aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ClientHamr/GuiLua/skang.lua244
1 files changed, 120 insertions, 124 deletions
diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua
index 0ba16cb..418cd10 100644
--- a/ClientHamr/GuiLua/skang.lua
+++ b/ClientHamr/GuiLua/skang.lua
@@ -52,12 +52,79 @@ The old skang argument types are -
52]] 52]]
53 53
54 54
55
56-- Wrapping the entire module in do .. end helps if people just join a bunch of modules together, which apparently is popular. 55-- Wrapping the entire module in do .. end helps if people just join a bunch of modules together, which apparently is popular.
57-- By virtue of the fact we are stuffing our result into package.loaded[], just plain running this works as "loading the module". 56-- By virtue of the fact we are stuffing our result into package.loaded[], just plain running this works as "loading the module".
58do -- Only I'm not gonna indent this. 57do -- Only I'm not gonna indent this.
59 58
60 59
60-- There is no ThingSpace, now it's all just in this table, and meta table. Predefined here coz moduleBegin references Thing.
61things = {}
62Thing = {}
63
64
65-- Trying to capture best practices here for creating modules, especially since module() is broken and deprecated.
66moduleBegin = function (name, author, copyright, version, timestamp, skin)
67 local _M = {} -- This is what we return to require().
68 local level = 2
69
70 package.loaded[name] = _M -- Stuff the result into where require() can find it, instead of returning it at the end.
71 -- Returning it at the end does the same thing.
72 -- This is so that we can have all the module stuff at the top, in this function.
73 -- Should do this before any further require(), so that circular references don't blow out.
74
75 -- Save the callers environment.
76 local savedEnvironment = getfenv(level)
77
78 -- Clone the environment into _M, so the module can access everything as usual after the setfenv() below.
79 --[[ TODO - Check if this also clones _G or _ENV. And see if it leaks stuff in either direction.
80 local _G = _G -- Only sets a local _G for this function.
81 _M._G = _G -- This clone loop might do this, but we don't want to be able to access the old _G from outside via this leak.
82 In Lua 5.1 at least, _G was special. In 5.2, _ENV sorta replaces setfenv(), but no idea if this clone loop stomps on that.
83 ]]
84 for k, v in pairs(savedEnvironment) do
85 _M[k] = v
86 end
87
88 _M._M = _M -- So that references to _M below the setfenv() actually go to the real _M.
89 _M._NAME = name
90 _M._PACKAGE = string.gsub(_M._NAME, "[^.]*$", "") -- Strip the name down to the package name.
91
92 -- TODO - Should parse in an entire copyright message, and strip that down into bits, to put back together.
93 _M.AUTHOR = author
94 _M.COPYRIGHT = copyright .. ' ' .. author
95 -- TODO - Translate the version number into a version string.
96 _M.VERSION = version .. ' lookup version here ' .. timestamp
97 -- TODO - If there's no skin passed in, try to find the file skin .. '.skang' and load that instead.
98 _M.DEFAULT_SKANG = skin
99
100
101 --_G[_M._NAME] = _M -- Stuff it into a global of the same name.
102 -- Not such a good idea to stomp on global name space.
103 -- It's also redundant coz we get stored in package.loaded[_M._NAME] anyway.
104 -- This is why module() is broken.
105
106 setmetatable(_M, Thing)
107 _M.savedEnvironment = savedEnvironment
108 -- setfenv() sets the environment for the FUNCTION, stack level deep.
109 -- The number is the stack level -
110 -- 0 running thread, 1 current function, 2 function that called this function, etc
111 setfenv(level, _M) -- Use the result for the modules internal global environment, so they don't need to qualify internal names.
112 -- Dunno if this causes problems with the do ... end style of joining modules. It does. So we need to restore in moduleEnd().
113 -- 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.
114
115 return _M
116end
117
118-- Restore the environment.
119moduleEnd = function (module)
120 setfenv(2, module.savedEnvironment)
121end
122
123-- Call this now so that from now on, this is like any other module.
124local _M = moduleBegin('skang', 'David Seikel', '2014', '0.0', '2014-03-19 19:01:00')
125
126
127
61--[[ Thing package 128--[[ Thing package
62 129
63matrix-RAD had Thing as the base class of everything. Lua doesn't have 130matrix-RAD had Thing as the base class of everything. Lua doesn't have
@@ -119,38 +186,31 @@ Other Thing things are -
119 Actually, not sure matrix-RAD solved that either. lol 186 Actually, not sure matrix-RAD solved that either. lol
120]] 187]]
121 188
189Thing.action = 'nada' -- An optional action to perform.
190Thing.tell = '' -- The skang command that created this Thing.
122 191
123-- There is no ThingSpace, now it's just in this table - 192Thing.append = function (self,data) -- Append to the value of this Thing.
124things = 193 end
125{
126}
127
128Thing =
129{
130 action = 'nada', -- An optional action to perform.
131 tell = '', -- The skang command that created this Thing.
132 194
133 append = function (self,data) -- Append to the value of this Thing. 195Thing.isValid = function (self) -- Check if this Thing is valid, return resulting error messages in errors.
134 end,
135 isValid = function (self) -- Check if this Thing is valid, return resulting error messages in errors.
136 self.errors = {} 196 self.errors = {}
137 -- TODO - Should check for required, matching mask, matching type, etc. 197 -- TODO - Should check for required, matching mask, matching type, etc.
138 return true 198 return true
139 end, 199 end
140 remove = function (self) -- Delete this Thing.
141 end,
142 200
143 errors = {}, -- A list of errors returned by isValid(). 201Thing.remove = function (self) -- Delete this Thing.
202 end
144 203
145 isReadOnly = false, -- Is this Thing read only? 204Thing.errors = {} -- A list of errors returned by isValid().
146 isServer = false, -- Is this Thing server side?
147 isStub = false, -- Is this Thing a stub?
148 isStubbed = false, -- Is this Thing stubbed elsewhere?
149 205
150 hasCrashed = 0, -- How many times this Thing has crashed. 206Thing.isReadOnly = false -- Is this Thing read only?
207Thing.isServer = false -- Is this Thing server side?
208Thing.isStub = false -- Is this Thing a stub?
209Thing.isStubbed = false -- Is this Thing stubbed elsewhere?
151 210
211Thing.hasCrashed = 0 -- How many times this Thing has crashed.
152 212
153 __index = function (table, key) 213Thing.__index = function (table, key)
154 -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. 214 -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist.
155 local thing = things[key] 215 local thing = things[key]
156 216
@@ -158,7 +218,7 @@ Thing =
158 if thing then 218 if thing then
159 local result = nil 219 local result = nil
160 if key ~= thing.names[1] then 220 if key ~= thing.names[1] then
161 result = table[thing.names[1] ] 221 result = table[thing.names[1] ] -- This might be recursive.
162 end 222 end
163 return result or thing.default 223 return result or thing.default
164 end 224 end
@@ -169,14 +229,14 @@ Thing =
169 229
170 -- If all else fails, return nil. 230 -- If all else fails, return nil.
171 return nil 231 return nil
172 end, 232 end
173
174 233
175 __newindex = function (table, key, value) 234Thing.__newindex = function (table, key, value)
176 local thing = things[key] 235 local thing = things[key]
177 236
178 if thing then 237 if thing then
179 local name = thing.names[1] 238 local name = thing.names[1]
239 rawset(table, name, value) -- Only stuff it under the first name, the rest are left as nil.
180 if 'function' == type(value) then 240 if 'function' == type(value) then
181 thing.func = value 241 thing.func = value
182 local types = '' 242 local types = ''
@@ -189,114 +249,22 @@ Thing =
189 print(thing.types[1] .. ' ' .. thing.module._NAME .. '.' .. name .. ' = ' .. (value or 'nil') .. ' -> ' .. thing.help) 249 print(thing.types[1] .. ' ' .. thing.module._NAME .. '.' .. name .. ' = ' .. (value or 'nil') .. ' -> ' .. thing.help)
190 -- TODO - Go through it's linked things and set them to. 250 -- TODO - Go through it's linked things and set them to.
191 end 251 end
192 rawset(table, name, value)
193 else 252 else
194 rawset(table, key, value) 253 rawset(table, key, value) -- Stuff it normally.
195 end 254 end
196 end, 255 end
197
198 256
199 -- TODO - Seemed like a good idea at the time, but do we really need it? 257 -- TODO - Seemed like a good idea at the time, but do we really need it?
200-- __call = function (func, ...) 258--Thing.__call = function (func, ...)
201-- return func.func(...) 259-- return func.func(...)
202-- end, 260-- end
203}
204
205
206-- Trying to capture best practices here for creating modules, especially since module() is broken and deprecated.
207moduleBegin = function (name, author, copyright, version, timestamp, skin)
208 local _M = {} -- This is what we return to require().
209 local level = 2
210
211 package.loaded[name] = _M -- Stuff the result into where require() can find it, instead of returning it at the end.
212 -- Returning it at the end does the same thing.
213 -- This is so that we can have all the module stuff at the top, in this function.
214 -- Should do this before any further require(), so that circular references don't blow out.
215 261
216 -- Save the callers environment.
217 local savedEnvironment = getfenv(level)
218
219 -- Clone the environment into _M, so the module can access everything as usual after the setfenv() below.
220 --[[ TODO - Check if this also clones _G or _ENV. And see if it leaks stuff in either direction.
221 local _G = _G -- Only sets a local _G for this function.
222 _M._G = _G -- This clone loop might do this, but we don't want to be able to access the old _G from outside via this leak.
223 In Lua 5.1 at least, _G was special. In 5.2, _ENV sorta replaces setfenv(), but no idea if this clone loop stomps on that.
224 ]]
225 for k, v in pairs(savedEnvironment) do
226 _M[k] = v
227 end
228
229 _M._M = _M -- So that references to _M below the setfenv() actually go to the real _M.
230 _M._NAME = name
231 _M._PACKAGE = string.gsub(_M._NAME, "[^.]*$", "") -- Strip the name down to the package name.
232
233 -- TODO - Should parse in an entire copyright message, and strip that down into bits, to put back together.
234 _M.AUTHOR = author
235 _M.COPYRIGHT = copyright .. ' ' .. author
236 -- TODO - Translate the version number into a version string.
237 _M.VERSION = version .. ' lookup version here ' .. timestamp
238 -- TODO - If there's no skin passed in, try to find the file skin .. '.skang' and load that instead.
239 _M.DEFAULT_SKANG = skin
240
241
242 --_G[_M._NAME] = _M -- Stuff it into a global of the same name.
243 -- Not such a good idea to stomp on global name space.
244 -- It's also redundant coz we get stored in package.loaded[_M._NAME] anyway.
245 -- This is why module() is broken.
246
247 setmetatable(_M, Thing)
248 _M.savedEnvironment = savedEnvironment
249 -- setfenv() sets the environment for the FUNCTION, stack level deep.
250 -- The number is the stack level -
251 -- 0 running thread, 1 current function, 2 function that called this function, etc
252 setfenv(level, _M) -- Use the result for the modules internal global environment, so they don't need to qualify internal names.
253 -- Dunno if this causes problems with the do ... end style of joining modules. It does. So we need to restore in moduleEnd().
254 -- 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.
255
256 return _M
257end
258
259-- Restore the environment.
260moduleEnd = function (module)
261 setfenv(2, module.savedEnvironment)
262end
263
264-- Call this now so that from now on, this is like any other module.
265local _M = moduleBegin('skang', 'David Seikel', '2014', '0.0', '2014-03-19 19:01:00')
266
267
268--[[ TODO - It might be worth it to combine parameters and commands, since in Lua, functions are first class types like numbers and strings.
269 Merging widgets might work to. B-)
270 This does make the entire "Things with the same name link automatically" deal work easily, since they ARE the same Thing.
271
272 Parameter gets a type, which might help since Lua is untyped, versus Java being strongly typed.
273 Widgets get a type as well, which would be label, button, edit, grid, etc.
274 A grid could even have sub types - grid,number,string,button,date. B-)
275
276 Required commands makes no sense, but can just be ignored.
277 A required widget might mean that the window HAS to have one.
278
279 Default for a command would be the actual function.
280 Default being a function makes this Thing a command.
281 Default for a widget could be the default creation arguments - '"Press me", 1, 1, 10, 50'
282
283 skang.thing(_M, 'foo,s,fooAlias', 'Foo is a bar, not the drinking type.', function () print('foo') end, nil, '"button", "The foo :"' 1, 1, 10, 50')
284 myButton = skang.widget('foo') -- Gets the default widget creation arguments.
285 myButton:colour(1, 2, 3, 4)
286 myEditor = skang.widget('foo', "edit", "Edit foo :", 5, 15, 10, 100)
287 myEditor:colour(1, 2, 3, 4, 5, 6, 7, 8)
288 myButton = 'Not default' -- myEditor and _M.foo change to. Though now _M.foo is a command, not a parameter, so maybe don't change that.
289 -- Though the 'quit' Thing could have a function that does quitting, this is just an example of NOT linking to a Thing.
290 -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function.
291 quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5)
292 quitter:action('quit')
293]]
294 262
295-- skang.thing() stashes the default value into _M['bar'], and the details into things['bar']. 263-- skang.thing() stashes the default value into _M['bar'], and the details into things['bar'].
296-- names - a comma seperated list of names, aliasas, and shortcuts. The first one is the official name. 264-- names - a comma seperated list of names, aliasas, and shortcuts. The first one is the official name.
297-- help - help text describing this Thing. 265-- help - help text describing this Thing.
298-- default - the default value. This could be a funcion, making this a command. 266-- default - the default value. This could be a funcion, making this a command.
299-- types - a comma separated list of types. The first is the type of the Thing itself, the rest are for multi value Things. Or argument types for functions. 267-- types - a comma separated list of types. The first is the type of the Thing itself, the rest are for multi value Things. Or argument types for commands.
300-- widget - default widget command arguments for creating this Thing as a widget. 268-- widget - default widget command arguments for creating this Thing as a widget.
301-- required - "boolean" to say if this thing is required. TODO - Maybe fold this into types somehow, or acl? 269-- required - "boolean" to say if this thing is required. TODO - Maybe fold this into types somehow, or acl?
302-- acl - Access Control List defining security restrains. 270-- acl - Access Control List defining security restrains.
@@ -336,6 +304,34 @@ thing = function (module, names, help, default, types, widget, required, acl, bo
336 module[name] = default 304 module[name] = default
337end 305end
338 306
307--[[ TODO - It might be worth it to combine parameters and commands, since in Lua, functions are first class types like numbers and strings.
308 Merging widgets might work to. B-)
309 This does make the entire "Things with the same name link automatically" deal work easily, since they ARE the same Thing.
310
311 Parameter gets a type, which might help since Lua is untyped, versus Java being strongly typed.
312 Widgets get a type as well, which would be label, button, edit, grid, etc.
313 A grid could even have sub types - grid,number,string,button,date. B-)
314
315 Required commands makes no sense, but can just be ignored.
316 A required widget might mean that the window HAS to have one.
317
318 Default for a command would be the actual function.
319 Default being a function makes this Thing a command.
320 Default for a widget could be the default creation arguments - '"Press me", 1, 1, 10, 50'
321
322 skang.thing(_M, 'foo,s,fooAlias', 'Foo is a bar, not the drinking type.', function () print('foo') end, nil, '"button", "The foo :"' 1, 1, 10, 50')
323 myButton = skang.widget('foo') -- Gets the default widget creation arguments.
324 myButton:colour(1, 2, 3, 4)
325 myEditor = skang.widget('foo', "edit", "Edit foo :", 5, 15, 10, 100)
326 myEditor:colour(1, 2, 3, 4, 5, 6, 7, 8)
327 myButton = 'Not default' -- myEditor and _M.foo change to. Though now _M.foo is a command, not a parameter, so maybe don't change that.
328 -- Though the 'quit' Thing could have a function that does quitting, this is just an example of NOT linking to a Thing.
329 -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function.
330 quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5)
331 quitter:action('quit')
332]]
333
334
339-- TODO - Some function stubs, for now. Fill them up later. 335-- TODO - Some function stubs, for now. Fill them up later.
340nada = function () end 336nada = function () end
341 337