diff options
Diffstat (limited to 'ClientHamr/GuiLua/skang.lua')
-rw-r--r-- | ClientHamr/GuiLua/skang.lua | 289 |
1 files changed, 141 insertions, 148 deletions
diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua index 3baad4f..9efd03c 100644 --- a/ClientHamr/GuiLua/skang.lua +++ b/ClientHamr/GuiLua/skang.lua | |||
@@ -57,8 +57,7 @@ The old skang argument types are - | |||
57 | do -- Only I'm not gonna indent this. | 57 | do -- Only I'm not gonna indent this. |
58 | 58 | ||
59 | 59 | ||
60 | -- There is no ThingSpace, now it's all just in this table, and meta table. Predefined here coz moduleBegin references Thing. | 60 | -- There is no ThingSpace, or Stuff, now it's all just in this meta table. Predefined here coz moduleBegin references Thing. |
61 | things = {} | ||
62 | Thing = {} | 61 | Thing = {} |
63 | 62 | ||
64 | 63 | ||
@@ -124,13 +123,10 @@ moduleBegin = function (name, author, copyright, version, timestamp, skin, isLua | |||
124 | -- TODO - If there's no skin passed in, try to find the file skin .. '.skang' and load that instead. | 123 | -- TODO - If there's no skin passed in, try to find the file skin .. '.skang' and load that instead. |
125 | _M.DEFAULT_SKANG = skin | 124 | _M.DEFAULT_SKANG = skin |
126 | 125 | ||
127 | |||
128 | --_G[_M._NAME] = _M -- Stuff it into a global of the same name. | 126 | --_G[_M._NAME] = _M -- Stuff it into a global of the same name. |
129 | -- Not such a good idea to stomp on global name space. | 127 | -- Not such a good idea to stomp on global name space. |
130 | -- It's also redundant coz we get stored in package.loaded[_M._NAME] anyway. | 128 | -- It's also redundant coz we get stored in package.loaded[_M._NAME] anyway. |
131 | -- This is why module() is broken. | 129 | -- This is why module() is broken. |
132 | |||
133 | setmetatable(_M, Thing) | ||
134 | _M.savedEnvironment = savedEnvironment | 130 | _M.savedEnvironment = savedEnvironment |
135 | -- NOTE - setfenv() wont work if the environment it refers to is a C function. Worse, getfenv() returns the global environment, so we can't tell. | 131 | -- NOTE - setfenv() wont work if the environment it refers to is a C function. Worse, getfenv() returns the global environment, so we can't tell. |
136 | if isLua then | 132 | if isLua then |
@@ -142,6 +138,10 @@ moduleBegin = function (name, author, copyright, version, timestamp, skin, isLua | |||
142 | -- Next question, does this screw with the environment of the skang module? No it doesn't, coz that's set up at require 'skang' time. | 138 | -- Next question, does this screw with the environment of the skang module? No it doesn't, coz that's set up at require 'skang' time. |
143 | end | 139 | end |
144 | 140 | ||
141 | local thing = {} | ||
142 | thing.names = {name} | ||
143 | setmetatable(_M, thing) | ||
144 | |||
145 | print('Loaded module ' .. _M._NAME .. ' version ' .. _M.VERSION .. ', ' .. _M.COPYRIGHT .. '.\n ' .. _M.VERSION_DESC) | 145 | print('Loaded module ' .. _M._NAME .. ' version ' .. _M.VERSION .. ', ' .. _M.COPYRIGHT .. '.\n ' .. _M.VERSION_DESC) |
146 | 146 | ||
147 | return _M | 147 | return _M |
@@ -288,91 +288,6 @@ Other Thing things are - | |||
288 | --[[ TODO | 288 | --[[ TODO |
289 | NOTE that skang.thing{} doesn't care what other names you pass in, they all get assigned to the thing. | 289 | NOTE that skang.thing{} doesn't care what other names you pass in, they all get assigned to the thing. |
290 | 290 | ||
291 | Might be better to move skang.things.foo.value -> skang.values.module.foo | ||
292 | but keep skang.things.foo.* for the Thing metadata. | ||
293 | |||
294 | test.pre | ||
295 | skang.things.test | ||
296 | skang.things.test.foo | ||
297 | skang.things.pre_test.foo -> skang.things.test.foo | ||
298 | skang.values.test.foo | ||
299 | skang.values.pre_test.foo | ||
300 | |||
301 | thing:isValid(module) | ||
302 | skang.things[module][key]:isValid(module) | ||
303 | skang.things.test.foo:isValid(test) | ||
304 | isValid(thing, module) | ||
305 | local value = values[module._NAME][self.names[1] ] | ||
306 | |||
307 | __index(module, key) | ||
308 | local thing = things[module._NAME][key] | ||
309 | local value = values[module._NAME][key] | ||
310 | |||
311 | __newindex(module, key, value) | ||
312 | local thing = things[module._NAME][key] | ||
313 | local oldValue = values[module._NAME][key] | ||
314 | ... | ||
315 | values[module._NAME][key] = value | ||
316 | ... | ||
317 | if not thing:isValid(module) then | ||
318 | |||
319 | module(...) or module{...} | ||
320 | __call(module, ...) | ||
321 | |||
322 | new = function (module, name) | ||
323 | local result = {} | ||
324 | setmetatable(result, {__index=module}) | ||
325 | result._NAME = name | ||
326 | -- Loop through the Things in module. | ||
327 | for k, v in pairs(module.things) do | ||
328 | values[name][k] = values[module._NAME][k] | ||
329 | end | ||
330 | |||
331 | On the other hand, might be better to now think of modules as a type? | ||
332 | How much of OO are we willing to go with here? lol | ||
333 | In Lua 5.1 and LuaJIT (?) metatables have no __type. | ||
334 | What about userdata? We could hijack the type() function, and dig deeper if it's a userdata, or even if it's a Thing? | ||
335 | |||
336 | |||
337 | Things as a metatable field - | ||
338 | In this plan test.__something is short for metatable(test).__something. | ||
339 | |||
340 | C can set metatables to non table values. NOTE - values, not variables, so likely useless. | ||
341 | |||
342 | __index is used to look up things that don't exist in a table. | ||
343 | If table isn't actually a table, then use __index as well. | ||
344 | Actually, in that case, the environment is the "table". | ||
345 | Either way, if we get to __index, and it's a function, call the function. | ||
346 | If __index is not a function, then use __index as a table to start the lookup all over again. | ||
347 | |||
348 | __newindex is similar, it's used if table.key is nil, AND __newindex exists. | ||
349 | Otherwise, it just sets table.key. | ||
350 | Again, if __newindow is a table, then start the lookup all over again with that. | ||
351 | |||
352 | metatable(module).__thing | ||
353 | metatable(module).__stuff | ||
354 | metatable(module).__values | ||
355 | |||
356 | __thing is a table that is a Thing. It can be just a reference to a __thing elsewhere. | ||
357 | So module is free to be full of random variables that are anything. | ||
358 | If module.foo is a table, it can have it's own metatable(foo).__thing. | ||
359 | A table with __thing will use Thing as a proxy table via __index and __newindex, as it does now. | ||
360 | |||
361 | moduleBegin(test, ...) -> thing stuff goes into test.__thing | ||
362 | thing(test, 'foo', 'string' ...) -> thing stuff gous into thing; setmetatable(test, Thing); test.__stuff[foo] = thing; test.__values[foo] = default | ||
363 | thing(test, 'foo', 'table' ...) -> thing stuff goes into thing; setmetatable(foo, Thing); test.__stuff[foo] = thing; test.__values[foo] = {}; test.foo.__thing = thing | ||
364 | thing(test.foo, 'bar', ...) -> setmetatable(foo, Thing); foo.__stuff[bar] = thing; foo.__values[bar] = default | ||
365 | copy(test, 'c' -> c.__thing = test.__thing;, c.__stuff = test.__stuff; copy test.__values to c.__values; setmetatable(c, Thing) | ||
366 | test.foo -> test.__index(test, 'foo') -> test.__values[foo]; if that's nil, and test.__stuff[foo].__thing, then return an empty table instead? | ||
367 | test.foo = v -> test.__newindex(test, 'foo', v) -> test.__values[foo] = v; test.__stuff[foo]:isValid(test) -> local value = test.__values[ self.names[1] ] | ||
368 | Which should call self.__stuff[*]:isValid(self) | ||
369 | test.foo(a) -> test.__index(test, 'foo') -> test.__values[foo](a) | ||
370 | test.foo(a) -> test.__index(test, 'foo') -> test.__values[foo](a) (but it's not a function) -> test.__values[foo].__call(test.__values[foo], a) | ||
371 | Doesn't seem useful. | ||
372 | If test.foo is a table, with a __thing then that might be -> test.foo.__call(test.foo, a) -> could do something useful with this. | ||
373 | get(test.foo, 'help') -> return test.foo.__thing[help] | ||
374 | skang.thing{test, 'foo', required=true} -> test.__stuff[foo].required = true | ||
375 | |||
376 | 291 | ||
377 | Stuff - | 292 | Stuff - |
378 | test{'foo', key='blah', field0='something', field1=1, ...} -> skang.things.foo.key='blah' skang.things.foo.field='something' ... | 293 | test{'foo', key='blah', field0='something', field1=1, ...} -> skang.things.foo.key='blah' skang.things.foo.field='something' ... |
@@ -417,8 +332,48 @@ What about userdata? We could hijack the type() function, and dig deeper if it' | |||
417 | -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function. | 332 | -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function. |
418 | quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5) | 333 | quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5) |
419 | quitter:action('quit') | 334 | quitter:action('quit') |
335 | |||
336 | |||
337 | On the other hand, might be better to now think of modules as a type? | ||
338 | How much of OO are we willing to go with here? lol | ||
339 | In Lua 5.1 and LuaJIT (?) metatables have no __type. | ||
340 | What about userdata? We could hijack the type() function, and dig deeper if it's a userdata, or even if it's a Thing? | ||
341 | |||
342 | |||
343 | Things as a metatable field - | ||
344 | In this plan test.__something is short for metatable(test).__something. | ||
345 | |||
346 | C can set metatables to non table values. NOTE - values, not variables, so likely useless. | ||
347 | |||
348 | __index is used to look up things that don't exist in a table. | ||
349 | If table isn't actually a table, then use __index as well. | ||
350 | Actually, in that case, the environment is the "table". | ||
351 | Either way, if we get to __index, and it's a function, call the function. | ||
352 | If __index is not a function, then use __index as a table to start the lookup all over again. | ||
353 | |||
354 | __newindex is similar, it's used if table.key is nil, AND __newindex exists. | ||
355 | Otherwise, it just sets table.key. | ||
356 | Again, if __newindow is a table, then start the lookup all over again with that. | ||
357 | |||
358 | metatable(module).__stuff | ||
359 | metatable(module).__values | ||
360 | |||
361 | The Thing is stuffed in a metatable. It can be just a reference to an existing Thing elsewhere. | ||
362 | So module is free to be full of random variables that are anything. | ||
363 | If module.foo is a table, it can have it's own metatable(foo). | ||
364 | Such a table will use Thing as a proxy table via __index and __newindex, as it does now. | ||
365 | |||
366 | thing(test, 'foo', 'table' ...) -> setmetatable(thing, {__index=Thing}); thing stuff goes into thing; setmetatable(foo, thing); test.__stuff[foo] = thing; test.__values[foo] = {}; | ||
367 | thing(test.foo, 'bar', ...) -> setmetatable(thing, {__index=Thing}); setmetatable(foo, thing); foo.__stuff[bar] = thing; foo.__values[bar] = thing.default | ||
368 | test.foo -> test.__index(test, 'foo') -> test.__values[foo]; if that's nil, and test.__stuff[foo], then return an empty table instead? | ||
369 | test.foo(a) -> test.__index(test, 'foo') -> test.__values[foo](a) | ||
370 | test.foo(a) -> test.__index(test, 'foo') -> test.__values[foo](a) (but it's not a function) -> test.__values[foo].__call(test.__values[foo], a) | ||
371 | Doesn't seem useful. | ||
372 | If test.foo is a Thing then that might be -> test.foo.__call(test.foo, a) -> could do something useful with this. | ||
420 | ]] | 373 | ]] |
421 | 374 | ||
375 | |||
376 | |||
422 | -- Default things values. | 377 | -- Default things values. |
423 | -- help - help text describing this Thing. | 378 | -- help - help text describing this Thing. |
424 | -- default - the default value. This could be a funcion, making this a command. | 379 | -- default - the default value. This could be a funcion, making this a command. |
@@ -427,6 +382,7 @@ What about userdata? We could hijack the type() function, and dig deeper if it' | |||
427 | -- required - "boolean" to say if this thing is required. TODO - Maybe fold this into types somehow, or acl? | 382 | -- required - "boolean" to say if this thing is required. TODO - Maybe fold this into types somehow, or acl? |
428 | -- acl - Access Control List defining security restrains. | 383 | -- acl - Access Control List defining security restrains. |
429 | -- boss - the Thing or person that owns this Thing, otherwise it is self owned. | 384 | -- boss - the Thing or person that owns this Thing, otherwise it is self owned. |
385 | Thing.names = {'?'} | ||
430 | Thing.help = 'No description supplied.' | 386 | Thing.help = 'No description supplied.' |
431 | Thing.default = '' | 387 | Thing.default = '' |
432 | Thing.types = {'string'} | 388 | Thing.types = {'string'} |
@@ -451,41 +407,56 @@ end | |||
451 | Thing.things = {} -- The sub things this Thing has, for modules and Stuff. | 407 | Thing.things = {} -- The sub things this Thing has, for modules and Stuff. |
452 | Thing.errors = {} -- A list of errors returned by isValid(). | 408 | Thing.errors = {} -- A list of errors returned by isValid(). |
453 | 409 | ||
410 | Thing.__stuff = {} | ||
411 | Thing.__values = {} | ||
412 | |||
454 | Thing.isValid = function (self, module) -- Check if this Thing is valid, return resulting error messages in errors. | 413 | Thing.isValid = function (self, module) -- Check if this Thing is valid, return resulting error messages in errors. |
455 | -- Anything that overrides this method, should call this super method first. | 414 | -- Anything that overrides this method, should call this super method first. |
456 | local pre = rawget(module, 'pre') | 415 | local name = self.names[1] |
457 | if pre then pre = pre .. '_value' else pre = 'value' end | 416 | local modThing = getmetatable(module) |
458 | local value = self[pre] | 417 | local thing = modThing.__stuff[name] |
418 | local key = thing.names[1]; | ||
419 | local value = modThing.__values[key] | ||
420 | |||
459 | local t = type(value) | 421 | local t = type(value) |
460 | self.errors = {} | 422 | self.errors = {} |
461 | -- TODO - Naturally there should be formatting functions for stuffing Thing stuff into strings, and overridable output functions. | 423 | -- TODO - Naturally there should be formatting functions for stuffing Thing stuff into strings, and overridable output functions. |
462 | if 'nil' == t then | 424 | if 'nil' == t then |
463 | if self.required then table.insert(self.errors, module._NAME .. '.' .. self.names[1] .. ' is required!') end | 425 | if self.required then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' is required!') end |
464 | else | 426 | else |
465 | if self.types[1] ~= t then table.insert(self.errors, module._NAME .. '.' .. self.names[1] .. ' should be a ' .. self.types[1] .. ', but it is a ' .. type(value) .. '!') | 427 | if self.types[1] ~= t then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' should be a ' .. self.types[1] .. ', but it is a ' .. type(value) .. '!') |
466 | else | 428 | else |
467 | if 'number' == t then value = '' .. value end | 429 | if 'number' == t then value = '' .. value end |
468 | if ('number' == t) or ('string' == t) then | 430 | if ('number' == t) or ('string' == t) then |
469 | if 1 ~= string.find(value, '^' .. self.pattern .. '$') then table.insert(self.errors, module._NAME .. '.' .. self.names[1] .. ' does not match pattern "' .. self.pattern .. '"!') end | 431 | if 1 ~= string.find(value, '^' .. self.pattern .. '$') then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' does not match pattern "' .. self.pattern .. '"!') end |
470 | end | 432 | end |
471 | end | 433 | end |
472 | end | 434 | end |
435 | -- TODO - Should go through self.__stuff[*]:isValid(self) as well. | ||
473 | return #(self.errors) == 0 | 436 | return #(self.errors) == 0 |
474 | end | 437 | end |
475 | 438 | ||
476 | Thing.remove = function (self) -- Delete this Thing. | 439 | Thing.remove = function (self) -- Delete this Thing. |
477 | end | 440 | end |
478 | 441 | ||
442 | |||
479 | Thing.__index = function (module, key) | 443 | Thing.__index = function (module, key) |
480 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. | 444 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. |
481 | local pre = rawget(module, 'pre') | ||
482 | if pre then pre = pre .. '_value' else pre = 'value' end | ||
483 | local thing = things[key] | ||
484 | -- First see if this is a Thing. | ||
485 | -- TODO - Java skang called isValid() on get(). On the other hand, doesn't seem to call it on set(), but calls it on append(). | 445 | -- TODO - Java skang called isValid() on get(). On the other hand, doesn't seem to call it on set(), but calls it on append(). |
486 | -- Ah, it was doing isValid() on setStufflet(). | 446 | -- Ah, it was doing isValid() on setStufflet(). |
487 | -- TODO - Call thing.func() if it exists. | 447 | -- TODO - Call thing.func() if it exists. |
488 | if thing then return thing[pre] or thing.default end | 448 | |
449 | -- First see if this is a Thing. | ||
450 | local modThing = getmetatable(module) | ||
451 | |||
452 | if modThing then | ||
453 | local thing = modThing.__stuff[key] | ||
454 | |||
455 | if thing then | ||
456 | local name = thing.names[1]; | ||
457 | return modThing.__values[name] or thing.__stuff[name].default | ||
458 | end | ||
459 | end | ||
489 | 460 | ||
490 | -- Then see if we can inherit it from Thing. | 461 | -- Then see if we can inherit it from Thing. |
491 | thing = Thing[key] | 462 | thing = Thing[key] |
@@ -497,21 +468,16 @@ end | |||
497 | 468 | ||
498 | Thing.__newindex = function (module, key, value) | 469 | Thing.__newindex = function (module, key, value) |
499 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. | 470 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. |
500 | local pre = rawget(module, 'pre') | 471 | local modThing = getmetatable(module) |
501 | if pre then pre = pre .. '_value' else pre = 'value' end | ||
502 | local thing = things[key] | ||
503 | 472 | ||
504 | if thing then | 473 | if modThing then |
505 | -- local name = thing.names[1] | ||
506 | -- This is a proxy table, the values never exist in the real table. | 474 | -- This is a proxy table, the values never exist in the real table. |
507 | thing[pre] = value | 475 | local thing = modThing.__stuff[key] |
476 | local name = thing.names[1] | ||
477 | modThing.__values[name] = value | ||
508 | if 'function' == type(value) then | 478 | if 'function' == type(value) then |
509 | thing.func = value | 479 | thing.func = value |
510 | local types = '' | 480 | local types = '' |
511 | for i, v in ipairs(thing.types) do | ||
512 | if 1 ~= i then types = types .. v .. ', ' end | ||
513 | end | ||
514 | -- print(thing.module._NAME .. '.' .. name .. '(' .. types .. ') -> ' .. thing.help) | ||
515 | else | 481 | else |
516 | -- NOTE - invalid values are still stored, this is by design. | 482 | -- NOTE - invalid values are still stored, this is by design. |
517 | if not thing:isValid(module) then | 483 | if not thing:isValid(module) then |
@@ -519,7 +485,6 @@ Thing.__newindex = function (module, key, value) | |||
519 | print('ERROR - ' .. v) | 485 | print('ERROR - ' .. v) |
520 | end | 486 | end |
521 | end | 487 | end |
522 | -- print(thing.types[1] .. ' ' .. thing.module._NAME .. '.' .. name .. ' = ' .. (value or 'nil') .. ' -> ' .. thing.help) | ||
523 | -- TODO - Go through it's linked things and set them to. | 488 | -- TODO - Go through it's linked things and set them to. |
524 | end | 489 | end |
525 | else | 490 | else |
@@ -555,14 +520,28 @@ thing = function (names, ...) | |||
555 | local name = names[1] | 520 | local name = names[1] |
556 | local oldNames = {} | 521 | local oldNames = {} |
557 | 522 | ||
558 | -- No need to bitch and return if no names, this will crash for us. | 523 | -- TODO - Double check this comment - No need to bitch and return if no names, this will crash for us. |
559 | local thing = things[name] | 524 | local module = params.module or params[8] or getfenv(2) |
525 | local modThing = getmetatable(module) | ||
526 | if nil == modThing then | ||
527 | modThing = {} | ||
528 | setmetatable(module, modThing) | ||
529 | end | ||
530 | -- Coz at module creation time, Thing is an empty table, and setmetatable(modThing, {__index = Thing}) doesn't do the same thing. | ||
531 | -- Also, module might not be an actual module, this might be Stuff. | ||
532 | if nil == modThing.__stuff then | ||
533 | for k, v in pairs(Thing) do | ||
534 | modThing[k] = modThing[k] or v | ||
535 | end | ||
536 | end | ||
537 | local thing = modThing.__stuff[name] | ||
560 | if not thing then -- This is a new Thing. | 538 | if not thing then -- This is a new Thing. |
561 | new = true | 539 | new = true |
562 | thing = {} | 540 | thing = {} |
563 | -- Grab the environment of the calling function, so this new thing automatically becomes a global in it. | 541 | -- Grab the environment of the calling function, so this new thing automatically becomes a global in it. |
564 | thing.module = getfenv(2) | 542 | thing.module = module |
565 | thing.names = names | 543 | thing.names = names |
544 | setmetatable(thing, {__index = Thing}) | ||
566 | end | 545 | end |
567 | 546 | ||
568 | -- Pull out positional arguments. | 547 | -- Pull out positional arguments. |
@@ -573,7 +552,6 @@ thing = function (names, ...) | |||
573 | thing.required = params[5] or thing.required | 552 | thing.required = params[5] or thing.required |
574 | thing.acl = params[6] or thing.acl | 553 | thing.acl = params[6] or thing.acl |
575 | thing.boss = params[7] or thing.boss | 554 | thing.boss = params[7] or thing.boss |
576 | thing.module = params[8] or thing.module -- Mostly for things like C functions, where get/setfenv() wont do what we need. | ||
577 | 555 | ||
578 | -- Pull out named arguments. | 556 | -- Pull out named arguments. |
579 | for k, v in pairs(params) do | 557 | for k, v in pairs(params) do |
@@ -596,54 +574,69 @@ thing = function (names, ...) | |||
596 | if types then types = typ .. ',' .. types else types = typ end | 574 | if types then types = typ .. ',' .. types else types = typ end |
597 | thing.types = csv2table(types) | 575 | thing.types = csv2table(types) |
598 | 576 | ||
599 | if new then setmetatable(thing, Thing) end | ||
600 | |||
601 | -- Remove old names, then stash the Thing under all of it's new names. | 577 | -- Remove old names, then stash the Thing under all of it's new names. |
602 | for i, v in ipairs(oldNames) do | 578 | for i, v in ipairs(oldNames) do |
603 | thing.module.things[v] = nil | 579 | modThing.__stuff[v] = nil |
604 | things[v] = nil | ||
605 | end | 580 | end |
606 | for i, v in ipairs(thing.names) do | 581 | for i, v in ipairs(thing.names) do |
607 | thing.module.things[v] = thing | 582 | modThing.__stuff[v] = thing |
608 | things[v] = thing | ||
609 | end | 583 | end |
610 | 584 | ||
611 | -- This triggers the Thing.__newindex metamethod above. If nothing else, it triggers thing.isValid() | 585 | -- This triggers the Thing.__newindex metamethod above. If nothing else, it triggers thing.isValid() |
612 | if new then thing.module[name] = thing.default end | 586 | if new then module[name] = thing.default end |
613 | end | 587 | end |
614 | 588 | ||
615 | 589 | ||
616 | -- skang.new() Creats a new copy of a module. | 590 | copy = function (module, name) |
617 | --[[ | 591 | local result = {} |
618 | A module isn't exactly a thing, it has Thing as it's metatable though. | 592 | local thing = {} |
593 | local modThing = getmetatable(module) | ||
619 | 594 | ||
620 | local test = require 'test' | 595 | for k, v in pairs(Thing) do |
621 | skang.moduleBegin('test', ...) | 596 | thing[k] = v |
622 | setmetatable(test, Thing) | 597 | end |
623 | skang.thing('foo', ...) | ||
624 | setmetatable(test.module.things.foo, Thing) | ||
625 | test.module.things.foo = skang.things.foo | ||
626 | local tester = skang.new(test, 'pre') | ||
627 | 598 | ||
628 | skang.things.foo.value | 599 | thing.__values = {} |
629 | skang.things.foo.pre_value | 600 | for k, v in pairs(modThing.__values) do |
601 | thing.__values[k] = v | ||
602 | end | ||
630 | 603 | ||
604 | thing.__stuff = modThing.__stuff | ||
605 | thing.names = {name} | ||
606 | setmetatable(thing, {__index = Thing}) | ||
607 | setmetatable(result, thing) | ||
631 | 608 | ||
632 | ]] | 609 | return result |
633 | new = function (module, pre) | 610 | end |
634 | local result = {} | ||
635 | 611 | ||
636 | setmetatable(result, Thing) | ||
637 | result.pre = pre | ||
638 | -- Loop through the Things in thing | ||
639 | -- TODO - Will have to be a deeper copy if it's a Stuff? | ||
640 | for k, v in pairs(module.things) do | ||
641 | v[pre .. '_value'] = v.value | ||
642 | -- things[pre .. '_' .. k].module = result | ||
643 | end | ||
644 | 612 | ||
645 | return result | 613 | get = function (stuff, key, name) |
646 | end | 614 | local result |
615 | local thing = getmetatable(stuff) | ||
616 | if thing then | ||
617 | local this = thing.__stuff[key] | ||
618 | if this then result = this[name] end | ||
619 | end | ||
620 | return result | ||
621 | end | ||
622 | |||
623 | |||
624 | reset = function (stuff, key, name) | ||
625 | local thing = getmetatable(stuff) | ||
626 | if thing then | ||
627 | local this = thing.__stuff[key] | ||
628 | if this then this[name] = nil end | ||
629 | end | ||
630 | end | ||
631 | |||
632 | |||
633 | set = function (stuff, key, name, value) | ||
634 | local thing = getmetatable(stuff) | ||
635 | if thing then | ||
636 | local this = thing.__stuff[key] | ||
637 | if this then this[name] = value end | ||
638 | end | ||
639 | end | ||
647 | 640 | ||
648 | 641 | ||
649 | -- TODO - Some function stubs, for now. Fill them up later. | 642 | -- TODO - Some function stubs, for now. Fill them up later. |