vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: AceConsole-2.0
3 Revision: $Rev: 4621 $
4 Author(s): ckknight (ckknight@gmail.com)
5 cladhaire (cladhaire@gmail.com)
6 hyperactiveChipmunk (hyperactiveChipmunk@gmail.com)
7 Inspired By: AceChatCmd 1.x by Turan (<email here>)
8 Website: http://www.wowace.com/
9 Documentation: http://wiki.wowace.com/index.php/AceConsole-2.0
10 SVN: http://svn.wowace.com/root/trunk/Ace2/AceConsole-2.0
11 Description: Mixin to allow for input/output capabilities. This uses the
12 AceOptions data table format to determine input.
13 http://wiki.wowace.com/index.php/AceOptions_data_table
14 Dependencies: AceLibrary, AceOO-2.0
15 ]]
16  
17 local MAJOR_VERSION = "AceConsole-2.0"
18 local MINOR_VERSION = "$Revision: 4621 $"
19  
20 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
21 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
22  
23 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end
24  
25 -- localize --
26 local MAP_ONOFF = { [false] = "|cffff0000Off|r", [true] = "|cff00ff00On|r" }
27 local USAGE = "Usage"
28 local IS_CURRENTLY_SET_TO = "|cffffff7f%s|r is currently set to |cffffff7f[|r%s|cffffff7f]|r"
29 local IS_NOW_SET_TO = "|cffffff7f%s|r is now set to |cffffff7f[|r%s|cffffff7f]|r"
30 local IS_NOT_A_VALID_OPTION_FOR = "|cffffff7f%s|r is not a valid option for |cffffff7f%s|r"
31 local IS_NOT_A_VALID_VALUE_FOR = "|cffffff7f%s|r is not a valid value for |cffffff7f%s|r"
32 local NO_OPTIONS_AVAILABLE = "No options available"
33 local OPTION_HANDLER_NOT_FOUND = "Option handler |cffffff7f%q|r not found."
34 local OPTION_HANDLER_NOT_VALID = "Option handler not valid."
35 local OPTION_IS_DISABLED = "Option %q is disabled."
36 -- localize --
37  
38 local NONE = NONE or "None"
39  
40 local AceOO = AceLibrary("AceOO-2.0")
41 local AceEvent, AceHook
42  
43 local AceConsole = AceOO.Mixin { "Print", "CustomPrint", "RegisterChatCommand" }
44  
45 local _G = getfenv(0)
46  
47 local function print(text, name, r, g, b, frame, delay)
48 if not text or string.len(text) == 0 then
49 text = " "
50 end
51 if not name or name == AceConsole then
52 (frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, 1, delay or 5)
53 else
54 (frame or DEFAULT_CHAT_FRAME):AddMessage("|cffffff78" .. tostring(name) .. ":|r " .. text, r, g, b, 1, delay or 5)
55 end
56 end
57  
58 local tmp
59 function AceConsole:CustomPrint(r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
60 a1 = tostring(a1)
61 if string.find(a1, "%%") then
62 print(string.format(a1, tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20)), self, r, g, b, frame or self.printFrame, delay)
63 else
64 if not tmp then
65 tmp = {}
66 end
67 table.insert(tmp, a1)
68 table.insert(tmp, a2)
69 table.insert(tmp, a3)
70 table.insert(tmp, a4)
71 table.insert(tmp, a5)
72 table.insert(tmp, a6)
73 table.insert(tmp, a7)
74 table.insert(tmp, a8)
75 table.insert(tmp, a9)
76 table.insert(tmp, a10)
77 table.insert(tmp, a11)
78 table.insert(tmp, a12)
79 table.insert(tmp, a13)
80 table.insert(tmp, a14)
81 table.insert(tmp, a15)
82 table.insert(tmp, a16)
83 table.insert(tmp, a17)
84 table.insert(tmp, a18)
85 table.insert(tmp, a19)
86 table.insert(tmp, a20)
87 while tmp[table.getn(tmp)] == nil do
88 table.remove(tmp)
89 end
90 for k = 1, table.getn(tmp) do
91 tmp[k] = tostring(tmp[k])
92 end
93 print(table.concat(tmp, " "), self, r, g, b, frame or self.printFrame, delay)
94 for k,v in tmp do
95 tmp[k] = nil
96 end
97 table.setn(tmp, 0)
98 end
99 end
100  
101 function AceConsole:Print(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
102 AceConsole.CustomPrint(self, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
103 end
104  
105 local work
106 local argwork
107  
108 local function findTableLevel(self, options, chat, text, index, passTable)
109 if not index then
110 index = 1
111 if work then
112 for k,v in pairs(work) do
113 work[k] = nil
114 end
115 table.setn(work, 0)
116 for k,v in pairs(argwork) do
117 argwork[k] = nil
118 end
119 table.setn(argwork, 0)
120 else
121 work = {}
122 argwork = {}
123 end
124 local len = string.len(text)
125 local count
126 repeat
127 text, count = string.gsub(text, "(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[[^%]]-) (.-%]|h|r)", "%1\001%2")
128 until count == 0
129 text = string.gsub(text, "(%]|h|r)(|cff%x%x%x%x%x%x|Hitem:%d-:%d-:%d-:%d-|h%[)", "%1 %2")
130 for token in string.gfind(text, "([^%s]+)") do
131 local token = token
132 local num = tonumber(token)
133 if num then
134 token = num
135 else
136 token = string.gsub(token, "\001", " ")
137 end
138 table.insert(work, token)
139 end
140 end
141  
142 local path = chat
143 for i = 1, index - 1 do
144 path = path .. " " .. tostring(work[i])
145 end
146  
147 if type(options.args) == "table" then
148 local disabled, hidden = options.disabled, options.hidden
149 if hidden then
150 if type(hidden) == "function" then
151 hidden = hidden()
152 elseif type(hidden) == "string" then
153 local handler = options.handler or self
154 if type(handler[hidden]) ~= "function" then
155 AceConsole:error(OPTION_HANDLER_NOT_FOUND, hidden)
156 end
157 hidden = handler[hidden](handler)
158 end
159 end
160 if hidden then
161 disabled = true
162 elseif disabled then
163 if type(disabled) == "function" then
164 disabled = disabled()
165 elseif type(disabled) == "string" then
166 local handler = options.handler or self
167 if type(handler[disabled]) ~= "function" then
168 AceConsole:error(OPTION_HANDLER_NOT_FOUND, disabled)
169 end
170 disabled = handler[disabled](handler)
171 end
172 end
173 if not disabled then
174 local next = work[index] and string.lower(work[index])
175 if next then
176 for k,v in options.args do
177 local good = false
178 if string.lower(k) == next then
179 good = true
180 elseif type(v.aliases) == "table" then
181 for _,alias in ipairs(v.aliases) do
182 if string.lower(alias) == next then
183 good = true
184 break
185 end
186 end
187 elseif type(v.aliases) == "string" and string.lower(v.aliases) == next then
188 good = true
189 end
190 if good then
191 return findTableLevel(options.handler or self, v, chat, text, index + 1, options.pass and options or nil)
192 end
193 end
194 end
195 end
196 end
197 for i = index, table.getn(work) do
198 table.insert(argwork, work[i])
199 end
200 return options, path, argwork, options.handler or self, passTable, passTable and work[index - 1]
201 end
202  
203 local function validateOptionsMethods(self, options, position)
204 if type(options) ~= "table" then
205 return "Options must be a table.", position
206 end
207 self = options.handler or self
208 if options.type == "execute" then
209 if options.func and type(options.func) ~= "string" and type(options.func) ~= "function" then
210 return "func must be a string or function", position
211 end
212 if options.func and type(options.func) == "string" and type(self[options.func]) ~= "function" then
213 return string.format("%q is not a proper function", options.func), position
214 end
215 else
216 if options.get then
217 if type(options.get) ~= "string" and type(options.get) ~= "function" then
218 return "get must be a string or function", position
219 end
220 if type(options.get) == "string" and type(self[options.get]) ~= "function" then
221 return string.format("%q is not a proper function", options.get), position
222 end
223 end
224 if options.set then
225 if type(options.set) ~= "string" and type(options.set) ~= "function" then
226 return "set must be a string or function", position
227 end
228 if type(options.set) == "string" and type(self[options.set]) ~= "function" then
229 return string.format("%q is not a proper function", options.set), position
230 end
231 end
232 if options.validate and type(options.validate) ~= "table" then
233 if type(options.validate) ~= "string" and type(options.validate) ~= "function" then
234 return "validate must be a string or function", position
235 end
236 if type(options.validate) == "string" and type(self[options.validate]) ~= "function" then
237 return string.format("%q is not a proper function", options.validate), position
238 end
239 end
240 end
241 if options.disabled and type(options.disabled) == "string" and type(self[options.disabled]) ~= "function" then
242 return string.format("%q is not a proper function", options.disabled), position
243 end
244 if options.hidden and type(options.hidden) == "string" and type(self[options.hidden]) ~= "function" then
245 return string.format("%q is not a proper function", options.hidden), position
246 end
247 if options.type == "group" and type(options.args) == "table" then
248 for k,v in pairs(options.args) do
249 if type(v) == "table" then
250 local newposition
251 if position then
252 newposition = position .. ".args." .. k
253 else
254 newposition = "args." .. k
255 end
256 local err, pos = validateOptionsMethods(self, v, newposition)
257 if err then
258 return err, pos
259 end
260 end
261 end
262 end
263 end
264  
265 local function validateOptions(self, options, position, baseOptions, fromPass)
266 if not baseOptions then
267 baseOptions = options
268 end
269 if type(options) ~= "table" then
270 return "Options must be a table.", position
271 end
272 local kind = options.type
273 if type(kind) ~= "string" then
274 return '"type" must be a string.', position
275 elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" then
276 return '"type" must either be "range", "text", "group", "toggle", "execute", or "color".', position
277 end
278 if options.aliases then
279 if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then
280 return '"alias" must be a table or string', position
281 end
282 end
283 if not fromPass then
284 if kind == "execute" then
285 if type(options.func) ~= "string" and type(options.func) ~= "function" then
286 return '"func" must be a string or function', position
287 end
288 elseif kind == "range" or kind == "text" or kind == "toggle" then
289 if type(options.set) ~= "string" and type(options.set) ~= "function" then
290 return '"set" must be a string or function', position
291 end
292 if kind == "text" and options.get == false then
293 elseif type(options.get) ~= "string" and type(options.get) ~= "function" then
294 return '"get" must be a string or function', position
295 end
296 elseif kind == "group" and options.pass then
297 if options.pass ~= true then
298 return '"pass" must be either nil, true, or false', position
299 end
300 if not options.func then
301 if type(options.set) ~= "string" and type(options.set) ~= "function" then
302 return '"set" must be a string or function', position
303 end
304 if type(options.get) ~= "string" and type(options.get) ~= "function" then
305 return '"get" must be a string or function', position
306 end
307 elseif type(options.func) ~= "string" and type(options.func) ~= "function" then
308 return '"func" must be a string or function', position
309 end
310 end
311 else
312 if kind == "group" then
313 return 'cannot have "type" = "group" as a subgroup of a passing group', position
314 end
315 end
316 if options ~= baseOptions then
317 if type(options.desc) ~= "string" then
318 return '"desc" must be a string', position
319 elseif string.len(options.desc) == 0 then
320 return '"desc" cannot be a 0-length string', position
321 end
322 end
323 if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then
324 if options.cmdName then
325 if type(options.cmdName) ~= "string" then
326 return '"cmdName" must be a string or nil', position
327 elseif string.len(options.cmdName) == 0 then
328 return '"cmdName" cannot be a 0-length string', position
329 end
330 if type(options.guiName) ~= "string" then
331 return '"guiName" must be a string or nil', position
332 elseif string.len(options.guiName) == 0 then
333 return '"guiName" cannot be a 0-length string', position
334 end
335 else
336 if type(options.name) ~= "string" then
337 return '"name" must be a string', position
338 elseif string.len(options.name) == 0 then
339 return '"name" cannot be a 0-length string', position
340 end
341 end
342 end
343 if options.message and type(options.message) ~= "string" then
344 return '"message" must be a string or nil', position
345 end
346 if options.error and type(options.error) ~= "string" then
347 return '"error" must be a string or nil', position
348 end
349 if options.current and type(options.current) ~= "string" then
350 return '"current" must be a string or nil', position
351 end
352 if options.disabled then
353 if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then
354 return '"disabled" must be a function, string, or boolean', position
355 end
356 end
357 if options.hidden then
358 if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then
359 return '"hidden" must be a function, string, or boolean', position
360 end
361 end
362 if kind == "text" then
363 if type(options.validate) == "table" then
364 else
365 if type(options.usage) ~= "string" then
366 return '"usage" must be a string', position
367 elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then
368 return '"validate" must be a string or function', position
369 end
370 end
371 elseif kind == "range" then
372 if options.min or options.max then
373 if type(options.min) ~= "number" then
374 return '"min" must be a number', position
375 elseif type(options.max) ~= "number" then
376 return '"max" must be a number', position
377 elseif options.min >= options.max then
378 return '"min" must be less than "max"', position
379 end
380 end
381 if options.step then
382 if type(options.step) ~= "number" then
383 return '"step" must be a number', position
384 elseif options.step < 0 then
385 return '"step" must be nonnegative', position
386 end
387 end
388 if options.isPercent and options.isPercent ~= true then
389 return '"isPercent" must either be nil, true, or false', position
390 end
391 elseif kind == "toggle" then
392 if options.map then
393 if type(options.map) ~= "table" then
394 return '"map" must be a table', position
395 elseif type(options.map[true]) ~= "string" then
396 return '"map[true]" must be a string', position
397 elseif type(options.map[false]) ~= "string" then
398 return '"map[false]" must be a string', position
399 end
400 end
401 elseif kind == "color" then
402 if options.hasAlpha and options.hasAlpha ~= true then
403 return '"hasAlpha" must be nil, true, or false', position
404 end
405 elseif kind == "group" then
406 if options.pass and options.pass ~= true then
407 return '"pass" must be nil, true, or false', position
408 end
409 if type(options.args) ~= "table" then
410 return '"args" must be a table', position
411 end
412 for k,v in pairs(options.args) do
413 if type(k) ~= "string" then
414 return '"args" keys must be strings', position
415 end
416 if not string.find(k, "^%w+$") then
417 return string.format('"args" keys must be standard strings. %q is not appropriate.', k), position
418 end
419 if type(v) ~= "table" then
420 return '"args" values must be tables', position and position .. "." .. k or k
421 end
422 local newposition
423 if position then
424 newposition = position .. ".args." .. k
425 else
426 newposition = "args." .. k
427 end
428 local err, pos = validateOptions(self, v, newposition, baseOptions, options.pass)
429 if err then
430 return err, pos
431 end
432 end
433 end
434 end
435  
436 local colorTable
437 local colorFunc
438 local colorCancelFunc
439  
440 local order
441  
442 local function printUsage(self, handler, realOptions, options, path, args, quiet, filter)
443 if filter then
444 filter = "^" .. string.gsub(filter, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
445 end
446 local hidden, disabled = options.hidden, options.disabled
447 if hidden then
448 if type(hidden) == "function" then
449 hidden = hidden()
450 elseif type(hidden) == "string" then
451 if type(handler[handler]) ~= "function" then
452 AceConsole:error(OPTION_HANDLER_NOT_FOUND, handler)
453 end
454 hidden = handler[hidden](handler)
455 end
456 end
457 if hidden then
458 disabled = true
459 elseif disabled then
460 if type(disabled) == "function" then
461 disabled = disabled()
462 elseif type(disabled) == "string" then
463 if type(handler[disabled]) ~= "function" then
464 AceConsole:error(OPTION_HANDLER_NOT_FOUND, disabled)
465 end
466 disabled = handler[disabled](handler)
467 end
468 end
469 local kind = string.lower(options.type or "group")
470 if disabled then
471 print(string.format(OPTION_IS_DISABLED, path), realOptions.cmdName or realOptions.name or self)
472 elseif kind == "text" then
473 local var
474 if passTable then
475 if not passTable.get then
476 elseif type(passTable.get) == "function" then
477 var = passTable.get(passValue)
478 else
479 if type(handler[passTable.get]) ~= "function" then
480 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
481 end
482 var = handler[passTable.get](handler, passValue)
483 end
484 else
485 if not options.get then
486 elseif type(options.get) == "function" then
487 var = options.get()
488 else
489 if type(handler[options.get]) ~= "function" then
490 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
491 end
492 var = handler[options.get](handler)
493 end
494 end
495  
496 local usage
497 if type(options.validate) == "table" then
498 if filter then
499 if not order then
500 order = {}
501 end
502 for _,v in ipairs(options.validate) do
503 if string.find(k, filter) then
504 table.insert(order, k)
505 end
506 end
507 usage = "{" .. table.concat(order, " || ") .. "}"
508 for k in pairs(order) do
509 order[k] = nil
510 end
511 table.setn(order, 0)
512 else
513 usage = "{" .. table.concat(options.validate, " || ") .. "}"
514 end
515 else
516 usage = options.usage or "<value>"
517 end
518 if not quiet then
519 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage), realOptions.cmdName or realOptions.name or self)
520 end
521 if (passTable and passTable.get) or options.get then
522 print(string.format(options.current or IS_CURRENTLY_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)))
523 end
524 elseif kind == "range" then
525 local var
526 if passTable then
527 if type(passTable.get) == "function" then
528 var = passTable.get(passValue)
529 else
530 if type(handler[passTable.get]) ~= "function" then
531 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
532 end
533 var = handler[passTable.get](handler, passValue)
534 end
535 else
536 if type(options.get) == "function" then
537 var = options.get()
538 else
539 local handler = options.handler or self
540 if type(handler[options.get]) ~= "function" then
541 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
542 end
543 var = handler[options.get](handler)
544 end
545 end
546  
547 local usage
548 local min = options.min or 0
549 local max = options.max or 1
550 if options.isPercent then
551 min, max = min * 100, max * 100
552 var = tostring(var * 100) .. "%"
553 end
554 local bit = "-"
555 if min < 0 or max < 0 then
556 bit = " - "
557 end
558 usage = string.format("(%s%s%s)", min, bit, max)
559 if not quiet then
560 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage), realOptions.cmdName or realOptions.name or self)
561 end
562 print(string.format(options.current or IS_CURRENTLY_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)))
563 elseif kind == "group" then
564 local usage
565 if next(options.args) then
566 if not order then
567 order = {}
568 end
569 for k,v in pairs(options.args) do
570 if filter then
571 if string.find(k, filter) then
572 table.insert(order, k)
573 elseif type(v.aliases) == "table" then
574 for _,bit in ipairs(v.aliases) do
575 if string.find(v.aliases, filter) then
576 table.insert(order, k)
577 break
578 end
579 end
580 elseif type(v.aliases) == "string" then
581 if string.find(v.aliases, filter) then
582 table.insert(order, k)
583 end
584 end
585 else
586 table.insert(order, k)
587 end
588 end
589 table.sort(order)
590 if not quiet then
591 if options == realOptions then
592 if options.desc then
593 print(tostring(options.desc), realOptions.cmdName or realOptions.name or self)
594 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"))
595 elseif self.description or self.notes then
596 print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self)
597 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"))
598 else
599 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self)
600 end
601 else
602 if options.desc then
603 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self)
604 print(tostring(options.desc))
605 else
606 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, "{" .. table.concat(order, " || ") .. "}"), realOptions.cmdName or realOptions.name or self)
607 end
608 end
609 end
610 for _,k in ipairs(order) do
611 local v = options.args[k]
612 local hidden, disabled = v.hidden, v.disabled
613 if hidden then
614 if type(hidden) == "function" then
615 hidden = hidden()
616 elseif type(hidden) == "string" then
617 local handler = v.handler or self
618 if type(handler[hidden]) ~= "function" then
619 AceConsole:error(OPTION_HANDLER_NOT_FOUND, hidden)
620 end
621 hidden = handler[hidden](handler)
622 end
623 end
624 if hidden then
625 disabled = true
626 elseif disabled then
627 if type(disabled) == "function" then
628 disabled = disabled()
629 elseif type(disabled) == "string" then
630 local handler = v.handler or self
631 if type(handler[disabled]) ~= "function" then
632 AceConsole:error(OPTION_HANDLER_NOT_FOUND, disabled)
633 end
634 disabled = handler[disabled](handler)
635 end
636 end
637 if type(v.aliases) == "table" then
638 k = k .. " || " .. table.concat(v.aliases, " || ")
639 elseif type(v.aliases) == "string" then
640 k = k .. " || " .. v.aliases
641 end
642 if v.get and v.type ~= "group" and v.type ~= "pass" and v.type ~= "execute" then
643 local a1,a2,a3,a4
644 if type(v.get) == "function" then
645 if options.pass then
646 a1,a2,a3,a4 = v.get(k)
647 else
648 a1,a2,a3,a4 = v.get()
649 end
650 else
651 local handler = v.handler or self
652 if type(handler[v.get]) ~= "function" then
653 AceConsole:error(OPTION_HANDLER_NOT_FOUND, v.get)
654 end
655 if options.pass then
656 a1,a2,a3,a4 = handler[v.get](handler, k)
657 else
658 a1,a2,a3,a4 = handler[v.get](handler)
659 end
660 end
661 if v.type == "color" then
662 if v.hasAlpha then
663 if not a1 or not a2 or not a3 or not a4 then
664 s = NONE
665 else
666 s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a4*255, a1*255, a2*255, a3*255, a4*255, a1*255, a2*255, a3*255)
667 end
668 else
669 if not a1 or not a2 or not a3 then
670 s = NONE
671 else
672 s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", a1*255, a2*255, a3*255, a1*255, a2*255, a3*255)
673 end
674 end
675 elseif v.type == "toggle" then
676 if v.map then
677 s = tostring(v.map[a1 or false] or NONE)
678 else
679 s = tostring(MAP_ONOFF[a1 or false] or NONE)
680 end
681 elseif v.type == "range" then
682 if v.isPercent then
683 s = tostring(a1 * 100) .. "%"
684 else
685 s = tostring(a1)
686 end
687 else
688 s = tostring(a1 or NONE)
689 end
690 if not hidden then
691 if disabled then
692 local s = string.gsub(s, "|cff%x%x%x%x%x%x(.-)|r", "%1")
693 local desc = string.gsub(v.desc or NONE, "|cff%x%x%x%x%x%x(.-)|r", "%1")
694 print(string.format("|cffcfcfcf - %s: [%s]|r %s", k, s, desc))
695 else
696 print(string.format(" - |cffffff7f%s: [|r%s|cffffff7f]|r %s", k, s, v.desc or NONE))
697 end
698 end
699 else
700 if not hidden then
701 if disabled then
702 local desc = string.gsub(v.desc or NONE, "|cff%x%x%x%x%x%x(.-)|r", "%1")
703 print(string.format("|cffcfcfcf - %s: %s", k, desc))
704 else
705 print(string.format(" - |cffffff7f%s:|r %s", k, v.desc or NONE))
706 end
707 end
708 end
709 end
710 for k in pairs(order) do
711 order[k] = nil
712 end
713 table.setn(order, 0)
714 else
715 if options.desc then
716 desc = options.desc
717 print(string.format("|cffffff7f%s:|r %s", USAGE, path), realOptions.cmdName or realOptions.name or self)
718 print(tostring(options.desc))
719 elseif options == realOptions and (self.description or self.notes) then
720 print(tostring(self.description or self.notes), realOptions.cmdName or realOptions.name or self)
721 print(string.format("|cffffff7f%s:|r %s", USAGE, path))
722 else
723 print(string.format("|cffffff7f%s:|r %s", USAGE, path), realOptions.cmdName or realOptions.name or self)
724 end
725 print(self, NO_OPTIONS_AVAILABLE)
726 end
727 end
728 end
729  
730 local function handlerFunc(self, chat, msg, options)
731 if not msg then
732 msg = ""
733 else
734 msg = string.gsub(msg, "^%s*(.-)%s*$", "%1")
735 msg = string.gsub(msg, "%s+", " ")
736 end
737  
738 local realOptions = options
739 local options, path, args, handler, passTable, passValue = findTableLevel(self, options, chat, msg)
740  
741 local hidden, disabled = options.hidden, options.disabled
742 if hidden then
743 if type(hidden) == "function" then
744 hidden = hidden()
745 elseif type(hidden) == "string" then
746 if type(handler[hidden]) ~= "function" then
747 AceConsole:error(OPTION_HANDLER_NOT_FOUND, hidden)
748 end
749 hidden = handler[hidden](handler)
750 end
751 end
752 if hidden then
753 disabled = true
754 elseif disabled then
755 if type(disabled) == "function" then
756 disabled = disabled()
757 elseif type(disabled) == "string" then
758 if type(handler[disabled]) ~= "function" then
759 AceConsole:error(OPTION_HANDLER_NOT_FOUND, disabled)
760 end
761 disabled = handler[disabled](handler)
762 end
763 end
764 local kind = string.lower(options.type or "group")
765 if disabled then
766 print(string.format(OPTION_IS_DISABLED, path), realOptions.cmdName or realOptions.name or self)
767 elseif kind == "text" then
768 if table.getn(args) > 0 then
769 if (type(options.validate) == "table" and table.getn(args) > 1) or (type(options.validate) ~= "table" and not options.input) then
770 local arg = table.concat(args, " ")
771 for k,v in pairs(args) do
772 args[k] = nil
773 end
774 table.setn(args, 0)
775 table.insert(args, arg)
776 end
777 if options.validate then
778 local good
779 if type(options.validate) == "function" then
780 good = options.validate(unpack(args))
781 elseif type(options.validate) == "table" then
782 local arg = args[1]
783 arg = type(arg) == "string" and string.lower(arg) or arg
784 for _,v in ipairs(options.validate) do
785 if type(arg) == "string" then
786 if string.lower(v) == arg then
787 args[1] = v
788 good = true
789 break
790 end
791 elseif v == arg then
792 good = true
793 break
794 end
795 end
796 else
797 if type(handler[options.validate]) ~= "function" then
798 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.validate)
799 end
800 good = handler[options.validate](handler, unpack(args))
801 end
802 if not good then
803 local usage
804 if type(options.validate) == "table" then
805 usage = "{" .. table.concat(options.validate, " || ") .. "}"
806 else
807 usage = options.usage or "<value>"
808 end
809 print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, tostring(table.concat(args, " ")), path), realOptions.cmdName or realOptions.name or self)
810 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage))
811 return
812 end
813 end
814  
815 if passTable then
816 if type(passTable.set) == "function" then
817 passTable.set(passValue, unpack(args))
818 else
819 if type(handler[passTable.set]) ~= "function" then
820 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.set)
821 end
822 handler[passTable.set](handler, passTable.set, unpack(args))
823 end
824 else
825 if type(options.set) == "function" then
826 options.set(unpack(args))
827 else
828 if type(handler[options.set]) ~= "function" then
829 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.set)
830 end
831 handler[options.set](handler, unpack(args))
832 end
833 end
834 end
835  
836 if table.getn(args) > 0 then
837 local var
838 if passTable then
839 if not passTable.get then
840 elseif type(passTable.get) == "function" then
841 var = passTable.get(passValue)
842 else
843 if type(handler[passTable.get]) ~= "function" then
844 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
845 end
846 var = handler[passTable.get](handler, passValue)
847 end
848 else
849 if not options.get then
850 elseif type(options.get) == "function" then
851 var = options.get()
852 else
853 if type(handler[options.get]) ~= "function" then
854 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
855 end
856 var = handler[options.get](handler)
857 end
858 end
859 if (passTable and passTable.get) or options.get then
860 print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self)
861 end
862 else
863 printUsage(self, handler, realOptions, options, path, args)
864 end
865 elseif kind == "execute" then
866 if passTable then
867 if type(passFunc) == "function" then
868 set(passValue)
869 else
870 if type(handler[passFunc]) ~= "function" then
871 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passFunc)
872 end
873 handler[passFunc](handler, passValue)
874 end
875 else
876 if type(options.func) == "function" then
877 options.func()
878 else
879 local handler = options.handler or self
880 if type(handler[options.func]) ~= "function" then
881 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.func)
882 end
883 handler[options.func](handler)
884 end
885 end
886 elseif kind == "toggle" then
887 local var
888 if passTable then
889 if type(passTable.get) == "function" then
890 var = passTable.get(passValue)
891 else
892 if type(handler[passTable.get]) ~= "function" then
893 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
894 end
895 var = handler[passTable.get](handler, passValue)
896 end
897 if type(passTable.set) == "function" then
898 passTable.set(passValue, not var)
899 else
900 if type(handler[passTable.set]) ~= "function" then
901 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.set)
902 end
903 handler[passTable.set](handler, passValue, not var)
904 end
905 if type(passTable.get) == "function" then
906 var = passTable.get(passValue)
907 else
908 var = handler[passTable.get](handler, passValue)
909 end
910 else
911 local handler = options.handler or self
912 if type(options.get) == "function" then
913 var = options.get()
914 else
915 if type(handler[options.get]) ~= "function" then
916 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
917 end
918 var = handler[options.get](handler)
919 end
920 if type(options.set) == "function" then
921 options.set(not var)
922 else
923 if type(handler[options.set]) ~= "function" then
924 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.set)
925 end
926 handler[options.set](handler, not var)
927 end
928 if type(options.get) == "function" then
929 var = options.get()
930 else
931 var = handler[options.get](handler)
932 end
933 end
934  
935 print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), (options.map or MAP_ONOFF)[var or false] or NONE), realOptions.cmdName or realOptions.name or self)
936 elseif kind == "range" then
937 local arg
938 if table.getn(args) <= 1 then
939 arg = args[1]
940 else
941 arg = table.concat(args, " ")
942 end
943  
944 if arg then
945 local min = options.min or 0
946 local max = options.max or 1
947 local good = false
948 if type(arg) == "number" then
949 if options.isPercent then
950 arg = arg / 100
951 end
952  
953 if arg >= min and arg <= max then
954 good = true
955 end
956  
957 if type(options.step) == "number" and step > 0 then
958 local step = options.step
959 arg = math.floor((x - min) / step + 0.5) * step + min
960 if arg > max then
961 arg = max
962 elseif arg < min then
963 arg = min
964 end
965 end
966 end
967 if not good then
968 local usage
969 local min = options.min or 0
970 local max = options.max or 1
971 if options.isPercent then
972 min, max = min * 100, max * 100
973 end
974 local bit = "-"
975 if min < 0 or max < 0 then
976 bit = " - "
977 end
978 usage = string.format("(%s%s%s)", min, bit, max)
979 print(string.format(options.error or IS_NOT_A_VALID_VALUE_FOR, tostring(arg), path), realOptions.cmdName or realOptions.name or self)
980 print(string.format("|cffffff7f%s:|r %s %s", USAGE, path, usage))
981 return
982 end
983  
984 if passTable then
985 if type(passTable.set) == "function" then
986 passTable.set(passValue, arg)
987 else
988 if type(handler[passTable.set]) ~= "function" then
989 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.set)
990 end
991 handler[passTable.set](handler, passValue, arg)
992 end
993 else
994 if type(options.set) == "function" then
995 options.set(arg)
996 else
997 local handler = options.handler or self
998 if type(handler[options.set]) ~= "function" then
999 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.set)
1000 end
1001 handler[options.set](handler, arg)
1002 end
1003 end
1004 end
1005  
1006 if arg then
1007 local var
1008 if passTable then
1009 if type(passTable.get) == "function" then
1010 var = passTable.get(passValue)
1011 else
1012 if type(handler[passTable.get]) ~= "function" then
1013 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
1014 end
1015 var = handler[passTable.get](handler, passValue)
1016 end
1017 else
1018 if type(options.get) == "function" then
1019 var = options.get()
1020 else
1021 local handler = options.handler or self
1022 if type(handler[options.get]) ~= "function" then
1023 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
1024 end
1025 var = handler[options.get](handler)
1026 end
1027 end
1028  
1029 if var and options.isPercent then
1030 var = tostring(var * 100) .. "%"
1031 end
1032 print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), tostring(var or NONE)), realOptions.cmdName or realOptions.name or self)
1033 else
1034 printUsage(self, handler, realOptions, options, path, args)
1035 end
1036 elseif kind == "color" then
1037 if table.getn(args) > 0 then
1038 local r,g,b,a
1039 if table.getn(args) == 1 then
1040 local arg = tostring(args[1])
1041 if options.hasAlpha then
1042 if string.len(arg) == 8 and string.find(arg, "^%x*$") then
1043 r,g,b,a = tonumber(string.sub(arg, 1, 2), 16) / 255, tonumber(string.sub(arg, 3, 4), 16) / 255, tonumber(string.sub(arg, 5, 6), 16) / 255, tonumber(string.sub(arg, 7, 8), 16) / 255
1044 end
1045 else
1046 if string.len(arg) == 6 and string.find(arg, "^%x*$") then
1047 r,g,b = tonumber(string.sub(arg, 1, 2), 16) / 255, tonumber(string.sub(arg, 3, 4), 16) / 255, tonumber(string.sub(arg, 5, 6), 16) / 255
1048 end
1049 end
1050 elseif table.getn(args) == 4 and options.hasAlpha then
1051 local a1,a2,a3,a4 = args[1], args[2], args[3], args[4]
1052 if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and type(a4) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 and a4 <= 1 then
1053 r,g,b,a = a1,a2,a3,a4
1054 elseif (type(a1) == "number" or string.len(a1) == 2) and string.find(a1, "^%x*$") and (type(a2) == "number" or string.len(a2) == 2) and string.find(a2, "^%x*$") and (type(a3) == "number" or string.len(a3) == 2) and string.find(a3, "^%x*$") and (type(a4) == "number" or string.len(a4) == 2) and string.find(a4, "^%x*$") then
1055 r,g,b,a = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255, tonumber(a4, 16) / 255
1056 end
1057 elseif table.getn(args) == 3 and not options.hasAlpha then
1058 local a1,a2,a3 = args[1], args[2], args[3]
1059 if type(a1) == "number" and type(a2) == "number" and type(a3) == "number" and a1 <= 1 and a2 <= 1 and a3 <= 1 then
1060 r,g,b = a1,a2,a3
1061 elseif (type(a1) == "number" or string.len(a1) == 2) and string.find(a1, "^%x*$") and (type(a2) == "number" or string.len(a2) == 2) and string.find(a2, "^%x*$") and (type(a3) == "number" or string.len(a3) == 2) and string.find(a3, "^%x*$") then
1062 r,g,b = tonumber(a1, 16) / 255, tonumber(a2, 16) / 255, tonumber(a3, 16) / 255
1063 end
1064 end
1065 if not r then
1066 print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, table.concat(args, ' '), path), realOptions.cmdName or realOptions.name or self)
1067 print(string.format("|cffffff7f%s:|r %s {0-1} {0-1} {0-1}%s", USAGE, path, options.hasAlpha and " {0-1}" or ""))
1068 return
1069 end
1070 if passTable then
1071 if type(passTable.set) == "function" then
1072 passTable.set(passValue, r,g,b,a)
1073 else
1074 if type(handler[passTable.set]) ~= "function" then
1075 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.set)
1076 end
1077 handler[passTable.set](handler, passValue, r,g,b,a)
1078 end
1079 else
1080 if type(options.set) == "function" then
1081 options.set(r,g,b,a)
1082 else
1083 if type(handler[options.set]) ~= "function" then
1084 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.set)
1085 end
1086 handler[options.set](handler, r,g,b,a)
1087 end
1088 end
1089  
1090 local r,g,b,a
1091 if passTable then
1092 if type(passTable.get) == "function" then
1093 r,g,b,a = passTable.get(passValue)
1094 else
1095 if type(handler[passTable.get]) ~= "function" then
1096 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
1097 end
1098 r,g,b,a = handler[passTable.get](handler, passValue)
1099 end
1100 else
1101 if type(options.get) == "function" then
1102 r,g,b,a = options.get()
1103 else
1104 if type(handler[options.get]) ~= "function" then
1105 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
1106 end
1107 r,g,b,a = handler[options.get](handler)
1108 end
1109 end
1110  
1111 local s
1112 if type(r) == "number" and type(g) == "number" and type(b) == "number" then
1113 if options.hasAlpha and type(a) == "number" then
1114 s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255)
1115 else
1116 s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", r*255, g*255, b*255, r*255, g*255, b*255)
1117 end
1118 else
1119 s = NONE
1120 end
1121 print(string.format(options.message or IS_NOW_SET_TO, tostring(options.cmdName or options.name), s), realOptions.cmdName or realOptions.name or self)
1122 else
1123 local r,g,b,a
1124 if passTable then
1125 if type(passTable.get) == "function" then
1126 r,g,b,a = passTable.get(passValue)
1127 else
1128 if type(handler[passTable.get]) ~= "function" then
1129 AceConsole:error(OPTION_HANDLER_NOT_FOUND, passTable.get)
1130 end
1131 r,g,b,a = handler[passTable.get](handler, passValue)
1132 end
1133 else
1134 if type(options.get) == "function" then
1135 r,g,b,a = options.get()
1136 else
1137 if type(handler[options.get]) ~= "function" then
1138 AceConsole:error(OPTION_HANDLER_NOT_FOUND, options.get)
1139 end
1140 r,g,b,a = handler[options.get](handler)
1141 end
1142 end
1143  
1144 if not colorTable then
1145 colorTable = {}
1146 local t = colorTable
1147  
1148 if ColorPickerOkayButton then
1149 local ColorPickerOkayButton_OnClick = ColorPickerOkayButton:GetScript("OnClick")
1150 ColorPickerOkayButton:SetScript("OnClick", function()
1151 if ColorPickerOkayButton_OnClick then
1152 ColorPickerOkayButton_OnClick()
1153 end
1154 if t.active then
1155 ColorPickerFrame.cancelFunc = nil
1156 ColorPickerFrame.func = nil
1157 ColorPickerFrame.opacityFunc = nil
1158 local r,g,b,a
1159 if t.passValue then
1160 if type(t.get) == "function" then
1161 r,g,b,a = t.get(t.passValue)
1162 else
1163 if type(t.handler[t.get]) ~= "function" then
1164 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.get)
1165 end
1166 r,g,b,a = t.handler[t.get](t.handler, t.passValue)
1167 end
1168 else
1169 if type(t.get) == "function" then
1170 r,g,b,a = t.get()
1171 else
1172 if type(t.handler[t.get]) ~= "function" then
1173 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.get)
1174 end
1175 r,g,b,a = t.handler[t.get](t.handler)
1176 end
1177 end
1178 if r ~= t.r or g ~= t.g or b ~= t.b or (t.hasAlpha and a ~= t.a) then
1179 local s
1180 if type(r) == "number" and type(g) == "number" and type(b) == "number" then
1181 if t.hasAlpha and type(a) == "number" then
1182 s = string.format("|c%02x%02x%02x%02x%02x%02x%02x%02x|r", a*255, r*255, g*255, b*255, r*255, g*255, b*255, a*255)
1183 else
1184 s = string.format("|cff%02x%02x%02x%02x%02x%02x|r", r*255, g*255, b*255, r*255, g*255, b*255)
1185 end
1186 else
1187 s = NONE
1188 end
1189 print(string.format(t.message, tostring(t.name), s), t.realOptions.cmdName or t.realOptions.name or self)
1190 end
1191 for k,v in pairs(t) do
1192 t[k] = nil
1193 end
1194 end
1195 end)
1196 end
1197 else
1198 for k,v in pairs(colorTable) do
1199 colorTable[k] = nil
1200 end
1201 end
1202  
1203 if type(r) ~= "number" or type(g) ~= "number" or type(b) ~= "number" then
1204 r,g,b = 1, 1, 1
1205 end
1206 if type(a) ~= "number" then
1207 a = 1
1208 end
1209 local t = colorTable
1210 t.r = r
1211 t.g = g
1212 t.b = b
1213 if hasAlpha then
1214 t.a = a
1215 end
1216 t.realOptions = realOptions
1217 t.hasAlpha = options.hasAlpha
1218 t.handler = handler
1219 t.set = passTable and passTable.set or options.set
1220 t.get = passTable and passTable.get or options.get
1221 t.name = options.cmdName or options.name
1222 t.message = options.message or IS_NOW_SET_TO
1223 t.passValue = passValue
1224 t.active = true
1225  
1226 if not colorFunc then
1227 colorFunc = function()
1228 local r,g,b = ColorPickerFrame:GetColorRGB()
1229 if t.hasAlpha then
1230 local a = 1 - OpacitySliderFrame:GetValue()
1231 if type(t.set) == "function" then
1232 if t.passValue then
1233 t.set(t.passValue, r,g,b,a)
1234 else
1235 t.set(r,g,b,a)
1236 end
1237 else
1238 if type(t.handler[t.set]) ~= "function" then
1239 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.set)
1240 end
1241 if t.passValue then
1242 t.handler[t.set](t.handler, t.passValue, r,g,b,a)
1243 else
1244 t.handler[t.set](t.handler, r,g,b,a)
1245 end
1246 end
1247 else
1248 if type(t.set) == "function" then
1249 if t.passValue then
1250 t.set(t.passValue, r,g,b)
1251 else
1252 t.set(r,g,b)
1253 end
1254 else
1255 if type(t.handler[t.set]) ~= "function" then
1256 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.set)
1257 end
1258 if t.passValue then
1259 t.handler[t.set](t.handler, t.passValue, r,g,b)
1260 else
1261 t.handler[t.set](t.handler, r,g,b)
1262 end
1263 end
1264 end
1265 end
1266 end
1267  
1268 ColorPickerFrame.func = colorFunc
1269 ColorPickerFrame.hasOpacity = options.hasAlpha
1270 if options.hasAlpha then
1271 ColorPickerFrame.opacityFunc = ColorPickerFrame.func
1272 ColorPickerFrame.opacity = 1 - a
1273 end
1274 ColorPickerFrame:SetColorRGB(r,g,b)
1275  
1276 if not colorCancelFunc then
1277 colorCancelFunc = function()
1278 if t.hasAlpha then
1279 if type(t.set) == "function" then
1280 if t.passValue then
1281 t.set(t.passValue, t.r,t.g,t.b,t.a)
1282 else
1283 t.set(t.r,t.g,t.b,t.a)
1284 end
1285 else
1286 if type(t.handler[t.get]) ~= "function" then
1287 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.get)
1288 end
1289 if t.passValue then
1290 t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b,t.a)
1291 else
1292 t.handler[t.set](t.handler, t.r,t.g,t.b,t.a)
1293 end
1294 end
1295 else
1296 if type(t.set) == "function" then
1297 if t.passValue then
1298 t.set(t.passValue, t.r,t.g,t.b)
1299 else
1300 t.set(t.r,t.g,t.b)
1301 end
1302 else
1303 if type(t.handler[t.set]) ~= "function" then
1304 AceConsole:error(OPTION_HANDLER_NOT_FOUND, t.set)
1305 end
1306 if t.passValue then
1307 t.handler[t.set](t.handler, t.passValue, t.r,t.g,t.b)
1308 else
1309 t.handler[t.set](t.handler, t.r,t.g,t.b)
1310 end
1311 end
1312 end
1313 for k,v in pairs(t) do
1314 t[k] = nil
1315 end
1316 ColorPickerFrame.cancelFunc = nil
1317 ColorPickerFrame.func = nil
1318 ColorPickerFrame.opacityFunc = nil
1319 end
1320 end
1321  
1322 ColorPickerFrame.cancelFunc = colorCancelFunc
1323  
1324 ShowUIPanel(ColorPickerFrame)
1325 end
1326 elseif kind == "group" then
1327 if table.getn(args) == 0 then
1328 printUsage(self, handler, realOptions, options, path, args)
1329 else
1330 -- invalid argument
1331 print(string.format(options.error or IS_NOT_A_VALID_OPTION_FOR, args[1], path), realOptions.cmdName or realOptions.name or self)
1332 end
1333 end
1334 end
1335  
1336 local external
1337 function AceConsole:RegisterChatCommand(slashCommands, options, name)
1338 if type(slashCommands) ~= "table" and slashCommands ~= false then
1339 error(string.format("Bad argument #2 to `RegisterInputCommand' (expected table, got %s)", tostring(type(slashCommands))), 2)
1340 end
1341 if not slashCommands and type(name) ~= "string" then
1342 error(string.format("Bad argument #4 to `RegisterInputCommand' (expected string, got %s)", tostring(type(name))), 2)
1343 end
1344 if type(options) ~= "table" and type(options) ~= "function" and options ~= nil then
1345 error(string.format("Bad argument #3 to `RegisterInputCommand' (expected table, function, or nil, got %s)", tostring(type(options))), 2)
1346 end
1347 if name then
1348 if type(name) ~= "string" then
1349 error(string.format("Bad argument #4 to `RegisterInputCommand' (expected string or nil, got %s)", tostring(type(name))), 2)
1350 elseif not string.find(name, "^%w+$") or string.upper(name) ~= name or string.len(name) == 0 then
1351 error("Argument #4 must be an uppercase, letters-only string with at least 1 character", 2)
1352 end
1353 end
1354 if slashCommands then
1355 if table.getn(slashCommands) == 0 then
1356 error("Argument #2 must include at least one string")
1357 end
1358  
1359 for k,v in pairs(slashCommands) do
1360 if type(k) ~= "number" then
1361 error("All keys in argument #2 must be numbers", 2)
1362 end
1363 if type(v) ~= "string" then
1364 error("All values in argument #2 must be strings", 2)
1365 elseif not string.find(v, "^/[A-Za-z][A-Za-z0-9_]*$") then
1366 error("All values in argument #2 must be in the form of \"/word\"", 2)
1367 end
1368 end
1369 end
1370  
1371 if not options then
1372 options = {
1373 type = 'group',
1374 args = {},
1375 handler = self
1376 }
1377 end
1378  
1379 if type(options) == "table" then
1380 local err, position = validateOptions(self, options)
1381 if err then
1382 if position then
1383 error(position .. ": " .. err, 2)
1384 else
1385 error(err, 2)
1386 end
1387 end
1388  
1389 if not options.handler then
1390 options.handler = self
1391 end
1392  
1393 if options.handler == self and string.lower(options.type) == "group" then
1394 local class = self.class
1395 while class and class ~= AceOO.Class do
1396 if type(class.GetAceOptionsDataTable) == "function" then
1397 local t = class:GetAceOptionsDataTable()
1398 for k,v in pairs(t) do
1399 if type(options.args) ~= "table" then
1400 options.args = {}
1401 end
1402 if options.args[k] == nil then
1403 options.args[k] = v
1404 end
1405 end
1406 end
1407 local mixins = class.mixins
1408 if mixins then
1409 for mixin in pairs(mixins) do
1410 if type(mixin.GetAceOptionsDataTable) == "function" then
1411 local t = mixin:GetAceOptionsDataTable()
1412 for k,v in pairs(t) do
1413 if type(options.args) ~= "table" then
1414 options.args = {}
1415 end
1416 if options.args[k] == nil then
1417 options.args[k] = v
1418 end
1419 end
1420 end
1421 end
1422 end
1423 class = class.super
1424 end
1425 end
1426 end
1427  
1428 local chat
1429 if slashCommands then
1430 chat = slashCommands[1]
1431 else
1432 chat = _G["SLASH_"..name..1]
1433 end
1434  
1435 local handler
1436 if type(options) == "function" then
1437 handler = options
1438 else
1439 function handler(msg)
1440 handlerFunc(self, chat, msg, options)
1441 end
1442 end
1443  
1444 if not _G.SlashCmdList then
1445 _G.SlashCmdList = {}
1446 end
1447  
1448 if not name then
1449 repeat
1450 name = string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1) .. string.char(math.random(26) + string.byte('A') - 1)
1451 until not _G.SlashCmdList[name]
1452 end
1453  
1454 if slashCommands then
1455 if _G.SlashCmdList[name] then
1456 local i = 0
1457 while true do
1458 i = i + 1
1459 if _G["SLASH_"..name..i] then
1460 _G["SLASH_"..name..i] = nil
1461 else
1462 break
1463 end
1464 end
1465 end
1466  
1467 local i = 0
1468 for _,command in ipairs(slashCommands) do
1469 i = i + 1
1470 _G["SLASH_"..name..i] = command
1471 if string.lower(command) ~= command then
1472 i = i + 1
1473 _G["SLASH_"..name..i] = string.lower(command)
1474 end
1475 end
1476 end
1477 _G.SlashCmdList[name] = handler
1478 if self ~= AceConsole and self.slashCommand == nil then
1479 self.slashCommand = chat
1480 end
1481  
1482 if not AceEvent and AceLibrary:HasInstance("AceEvent-2.0") then
1483 external(AceConsole, "AceEvent-2.0", AceLibrary("AceEvent-2.0"))
1484 end
1485 if AceEvent then
1486 if not AceConsole.nextAddon then
1487 AceConsole.nextAddon = {}
1488 end
1489 AceConsole.nextAddon[self] = options
1490 if not self.playerLogin then
1491 AceConsole:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true)
1492 end
1493 end
1494  
1495 if not AceHook and AceLibrary:HasInstance("AceHook-2.0") then
1496 external(AceConsole, "AceHook-2.0", AceLibrary("AceHook-2.0"))
1497 end
1498  
1499 if AceHook then
1500 if not self.hooks then
1501 AceConsole:HookScript(ChatFrameEditBox, "OnTabPressed")
1502 AceConsole:Hook("ChatEdit_OnLoad")
1503 end
1504 end
1505  
1506 AceConsole.registry[name] = options
1507 end
1508  
1509 function AceConsole:PLAYER_LOGIN()
1510 self.playerLogin = true
1511 for addon, options in pairs(self.nextAddon) do
1512 local err, position = validateOptionsMethods(addon, options)
1513 if err then
1514 if position then
1515 error(tostring(addon) .. ": AceConsole: " .. position .. ": " .. err)
1516 else
1517 error(tostring(addon) .. ": AceConsole: " .. err)
1518 end
1519 end
1520 self.nextAddon[addon] = nil
1521 end
1522  
1523 self:RegisterChatCommand({ "/reload", "/rl", "/reloadui" }, ReloadUI, "RELOAD")
1524 local tmp
1525 self:RegisterChatCommand({ "/print" }, function(text)
1526 RunScript("local function func(...) for k,v in ipairs(arg) do arg[k] = tostring(v) end DEFAULT_CHAT_FRAME:AddMessage(table.concat(arg, ' ')) end func(" .. text .. ")")
1527 end, "PRINT")
1528 end
1529  
1530 function AceConsole:ChatEdit_OnLoad()
1531 AceConsole:HookScript(this, "OnTabPressed")
1532 end
1533  
1534 local function LCS(strings) --returns Least Common Substring
1535 local len = 0
1536 local numStrings = table.getn(strings)
1537  
1538 for _, s in strings do
1539 len = string.len(s) > len and string.len(s) or len
1540 end
1541  
1542 for i = 1, len do
1543 local c = string.sub(strings[1], i, i)
1544 for j = 2, numStrings do
1545 if string.sub(strings[j], i, i) ~= c then
1546 return string.sub(strings[1], 0, i-1)
1547 end
1548 end
1549 end
1550 return strings[1]
1551 end
1552  
1553 function AceConsole:OnTabPressed()
1554 --Get the position of the cursor
1555 local ost = this:GetScript("OnTextSet")
1556 if ost then this:SetScript("OnTextSet", nil) end
1557 this:Insert("\1")
1558 local pos = string.find(this:GetText(), "\1", 1) - 1
1559 this:HighlightText(pos, pos+1)
1560 this:Insert("\0")
1561 if ost then this:SetScript("OnTextSet", ost) end
1562  
1563 local text = this:GetText()
1564  
1565 local _, _, cmd = string.find(text, "^([%S]+)")
1566 if not cmd then return self.hooks[this].OnTabPressed.orig() end
1567  
1568 local left = string.find(string.sub(text, 0, pos), "[%S]+$") or string.len(cmd)
1569  
1570 local _, _, word = string.find(string.sub(text, left, pos), "^([%S]+)")
1571  
1572 local realOptions, validArgs, path, argwork
1573 if string.sub(cmd, 1, 1) == "/" then
1574 if left == 1 and word == cmd then
1575 return self.hooks[this].OnTabPressed.orig()
1576 else
1577 for name in pairs(SlashCmdList) do --global
1578 if AceConsole.registry[name] then
1579 local i = 0
1580 local scmd
1581 while true do
1582 i = i + 1
1583 scmd = _G["SLASH_"..name..i]
1584 if not scmd then break end
1585 if cmd == scmd then
1586 realOptions = AceConsole.registry[name]
1587 validArgs, path, argwork = findTableLevel(self, AceConsole.registry[name], cmd, string.sub(this:GetText(), string.len(cmd)+2, pos))
1588 end
1589 end
1590 end
1591 end
1592 end
1593 end
1594  
1595 if not validArgs then return self.hooks[this].OnTabPressed.orig() end
1596  
1597 if not validArgs.args then
1598 printUsage(self, validArgs.handler, realOptions, validArgs, path, argwork)
1599 else
1600 local matches = {}
1601 for arg in validArgs.args do
1602 if string.find(string.lower(arg), string.lower(word), nil, 1) == 1 then
1603 table.insert(matches, arg)
1604 end
1605 end
1606 local numMatches = table.getn(matches)
1607 if validArgs.type == "group" then
1608 if numMatches == 1 then
1609 this:HighlightText(left - 1, left + string.len(word))
1610 this:Insert(matches[1])
1611 this:Insert(" ")
1612 elseif numMatches > 1 then
1613 printUsage(self, validArgs.handler, realOptions, validArgs, path, argwork, true, LCS(matches))
1614 this:HighlightText(left - 1, left + string.len(word))
1615 this:Insert(LCS(matches))
1616 else
1617 printUsage(self, validArgs.handler, realOptions, validArgs, path, argwork)
1618 end
1619 end
1620 end
1621 end
1622  
1623 function external(self, major, instance)
1624 if major == "AceEvent-2.0" then
1625 if not AceEvent then
1626 AceEvent = instance
1627  
1628 AceEvent:embed(self)
1629 end
1630 elseif major == "AceHook-2.0" then
1631 if not AceHook then
1632 AceHook = instance
1633  
1634 AceHook:embed(self)
1635 end
1636 end
1637 end
1638  
1639 local function activate(self, oldLib, oldDeactivate)
1640 AceConsole = self
1641  
1642 self.super.activate(self, oldLib, oldDeactivate)
1643  
1644 if oldLib then
1645 self.registry = oldLib.registry
1646 self.nextAddon = oldLib.nextAddon
1647 end
1648 if not self.registry then
1649 self.registry = {}
1650 else
1651 for name,options in pairs(self.registry) do
1652 self:RegisterChatCommand(false, options, name)
1653 end
1654 end
1655  
1656 if oldDeactivate then
1657 oldDeactivate(oldLib)
1658 end
1659 end
1660  
1661 AceLibrary:Register(AceConsole, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
1662 AceConsole = AceLibrary(MAJOR_VERSION)