vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | if AceChatCmd then |
2 | PerfectRaid.AceChatCmd = AceChatCmd |
||
3 | else |
||
4 | local AceChatCmd = {} |
||
5 | PerfectRaid.AceChatCmd = AceChatCmd |
||
6 | |||
7 | local Ace = {} |
||
8 | |||
9 | function Ace:print(...) |
||
10 | local r,g,b,frame,delay |
||
11 | if( type(arg[1]) == "table" ) then |
||
12 | r,g,b,frame,delay = unpack(tremove(arg,1)) |
||
13 | end |
||
14 | (frame or DEFAULT_CHAT_FRAME):AddMessage(self.concat(arg),r,g,b,1,delay or 5) |
||
15 | end |
||
16 | |||
17 | function Ace.ParseWords(str, pat) |
||
18 | if( Ace.tostr(str) == "" ) then return {} end |
||
19 | local list = {} |
||
20 | for word in gfind(str, pat or "%S+") do |
||
21 | tinsert(list, word) |
||
22 | end |
||
23 | return list |
||
24 | end |
||
25 | |||
26 | local ACE_CMD = {} |
||
27 | ACE_CMD.OPT_HELP = "?" |
||
28 | ACE_CMD.OPT_HELP_DESC = "Display extra information about this addon." |
||
29 | ACE_CMD.OPT_STANDBY = "standby" |
||
30 | ACE_CMD.OPT_STANDBY_DESC = "Toggle the addon's standby mode." |
||
31 | ACE_CMD.OPT_REPORT = "report" |
||
32 | ACE_CMD.OPT_REPORT_DESC = "Display the status of all settings." |
||
33 | ACE_CMD.OPT_INVALID = "Invalid option '%s' entered." |
||
34 | ACE_CMD.OPT_LIST_ADDONS = "Addon List" |
||
35 | ACE_CMD.OPT_LOAD_IS_LOADED = "%s is already loaded." |
||
36 | ACE_CMD.OPT_LOAD_ERROR = "%s could not be loaded because it is %s." |
||
37 | ACE_CMD.OPT_LOAD_LOADED = "%s is now loaded." |
||
38 | ACE_CMD.OPT_AUTO_OFF_MSG = "%s will no longer be loaded on demand at game start." |
||
39 | ACE_CMD.ERROR = "|cffff6060[error]|r" |
||
40 | |||
41 | ACE_CMD.ADDON_NOTFOUND = "No addon named '%s' was found." |
||
42 | ACE_CMD.ADDON_ENABLED = "%s has been enabled. You must reload the game to load this addon." |
||
43 | ACE_CMD.ADDON_ENABLED_ALL = "All addons have been enabled. You must reload the game to load ".. |
||
44 | "previously unloaded addons." |
||
45 | ACE_CMD.ADDON_DISABLED = "%s has been disabled but will remain loaded until you reload the game." |
||
46 | ACE_CMD.ADDON_DISABLED_ALL = "All addons except Ace itself have been disabled but will remain loaded ".. |
||
47 | "until you reload the game." |
||
48 | |||
49 | ACE_CMD.PROFILE_ADDON_ADDED = "%s has been added. Active profile: %s." |
||
50 | ACE_CMD.PROFILE_ALL_ADDED = "All addons have been added. Active profile: %s." |
||
51 | ACE_CMD.PROFILE_ALL = "all" |
||
52 | ACE_CMD.PROFILE_NO_PROFILE = "%s has no profiling options available." |
||
53 | |||
54 | ACE_CMD.USAGE_ADDON_DESC = "|cffffff78[%s v%s]|r : %s" |
||
55 | ACE_CMD.USAGE_HEADER = "|cffffff78Usage:|r |cffd8c7ff%s|r %s" |
||
56 | ACE_CMD.USAGE_OPT_DESC = " - |cffffff78%s:|r %s" |
||
57 | ACE_CMD.USAGE_OPT_SEP = " | " |
||
58 | ACE_CMD.USAGE_OPT_OPEN = "[" |
||
59 | ACE_CMD.USAGE_OPT_CLOSE = "]" |
||
60 | ACE_CMD.USAGE_OPTION = "|cffd8c7ff%s %s|r %s" |
||
61 | ACE_CMD.USAGE_NOINFO = "No further information" |
||
62 | |||
63 | ACE_CMD.RESULT = "|cffffff78%s:|r %s" |
||
64 | |||
65 | ACE_CMD.REPORT_STATUS = "Status" |
||
66 | ACE_CMD.REPORT_LINE = "%s [|cfff5f530%s|r]" |
||
67 | ACE_CMD.REPORT_LINE_PRE = " - " |
||
68 | ACE_CMD.REPORT_LINE_INDENT = " " |
||
69 | |||
70 | ACE_CMD.REPORT_NO_VAL = "|cffc7c7c7no value|r" |
||
71 | |||
72 | |||
73 | -- Recursively iterate through the table and sub-tables until the entire table |
||
74 | -- structure is copied over. Note: I used to check whether the table was numerically |
||
75 | -- indexed and use two different for() loops, one with ipairs() and one without. I |
||
76 | -- did this because there seemed to be problems otherwise, but in rewriting this, I |
||
77 | -- haven't encountered any problems. |
||
78 | function Ace.CopyTable(into, from) |
||
79 | for key, val in from do |
||
80 | if( type(val) == "table" ) then |
||
81 | if( not into[key] ) then into[key] = {} end |
||
82 | Ace.CopyTable(into[key], val) |
||
83 | else |
||
84 | into[key] = val |
||
85 | end |
||
86 | end |
||
87 | |||
88 | if (getn(from)) then |
||
89 | table.setn(into, getn(from)) |
||
90 | end |
||
91 | |||
92 | return into |
||
93 | end |
||
94 | |||
95 | function Ace.GetTableKeys(tbl) |
||
96 | local t = {} |
||
97 | for key, val in pairs(tbl) do |
||
98 | tinsert(t, key) |
||
99 | end |
||
100 | return(t) |
||
101 | end |
||
102 | |||
103 | function Ace.TableFindKeyCaseless(tbl, key) |
||
104 | key = strlower(key) |
||
105 | for i, val in tbl do |
||
106 | if( strlower(i) == key ) then return i, val end |
||
107 | end |
||
108 | end |
||
109 | |||
110 | function Ace.TableFindByKeyValue(tbl, key, val, caseless) |
||
111 | if( not tbl ) then error("No table supplied to TableFindByKeyValue.", 2) end |
||
112 | for i, t in ipairs(tbl) do |
||
113 | if( (caseless and (strlower(t[key]) == strlower(val))) or (t[key] == val) ) then |
||
114 | return i, t |
||
115 | end |
||
116 | end |
||
117 | end |
||
118 | |||
119 | function Ace.concat(t,sep) |
||
120 | local msg = "" |
||
121 | if( getn(t) > 0 ) then |
||
122 | for key, val in ipairs(t) do |
||
123 | if( msg ~= "" and sep ) then msg = msg..sep end |
||
124 | msg = msg..Ace.tostr(val) |
||
125 | end |
||
126 | else |
||
127 | for key, val in t do |
||
128 | if( msg ~= "" and sep ) then msg = msg..sep end |
||
129 | msg = msg..key.."="..Ace.tostr(val) |
||
130 | end |
||
131 | end |
||
132 | return msg |
||
133 | end |
||
134 | |||
135 | function Ace.round(num) |
||
136 | return floor(Ace.tonum(num)+.5) |
||
137 | end |
||
138 | |||
139 | function Ace.sort(tbl, comp) |
||
140 | sort(tbl, comp) |
||
141 | return tbl |
||
142 | end |
||
143 | |||
144 | function Ace.strlen(str) |
||
145 | return strlen(str or "") |
||
146 | end |
||
147 | |||
148 | function Ace.tonum(val, base) |
||
149 | return tonumber((val or 0), base) or 0 |
||
150 | end |
||
151 | |||
152 | function Ace.tostr(val) |
||
153 | return tostring(val or "") |
||
154 | end |
||
155 | |||
156 | function Ace.toggle(val) |
||
157 | if( val ) then return FALSE end |
||
158 | return TRUE |
||
159 | end |
||
160 | |||
161 | function Ace.trim(str, opt) |
||
162 | if( (not opt) or (opt=="left" ) ) then str = gsub(str, "^%s*", "") end |
||
163 | if( (not opt) or (opt=="right") ) then str = gsub(str, "%s*$", "") end |
||
164 | return str |
||
165 | end |
||
166 | |||
167 | -- Object constructor |
||
168 | function AceChatCmd:new(commands,options) |
||
169 | self.__index = self |
||
170 | return setmetatable({_cmdList=commands,options=options}, self) |
||
171 | end |
||
172 | |||
173 | --[[--------------------------------------------------------------------------------- |
||
174 | Reporting Methods |
||
175 | ------------------------------------------------------------------------------------]] |
||
176 | |||
177 | function AceChatCmd:result(...) |
||
178 | Ace:print(self.app.disabled and ACE_ADDON_STANDBY.." " or "", |
||
179 | format(ACE_CMD.RESULT, self.app.name, Ace.concat(arg)) |
||
180 | ) |
||
181 | end |
||
182 | |||
183 | function AceChatCmd:msg(...) self:result(format(unpack(arg))) end |
||
184 | function AceChatCmd:error(...) self:result(ACE_CMD.ERROR.." ", format(unpack(arg))) end |
||
185 | function AceChatCmd:status(text, val, map) |
||
186 | if( map ) then val = map[val or 0] or val end |
||
187 | self:result(text, " ", ACE_TEXT_NOW_SET_TO, " ", |
||
188 | format(ACE_DISPLAY_OPTION, val or ACE_CMD.REPORT_NO_VAL) |
||
189 | ) |
||
190 | end |
||
191 | |||
192 | function AceChatCmd:report(hdr, def) |
||
193 | if( not def ) then def = hdr; hdr = nil end |
||
194 | Ace:print(hdr or format(ACE_CMD.RESULT, |
||
195 | self.app.name.." "..ACE_CMD.REPORT_STATUS, |
||
196 | self.app.disabled and ACE_ADDON_STANDBY or "" |
||
197 | ) |
||
198 | ) |
||
199 | for _, ref in ipairs(def) do |
||
200 | local val |
||
201 | if( ref.map ) then val = ref.map[ref.val or 0] |
||
202 | else val = ref.val |
||
203 | end |
||
204 | Ace:print( |
||
205 | (ref.indent |
||
206 | and (strrep(" ", strlen(ACE_CMD.REPORT_LINE_PRE)).. |
||
207 | strrep(ACE_CMD.REPORT_LINE_INDENT, ref.indent)) |
||
208 | or ACE_CMD.REPORT_LINE_PRE |
||
209 | ), |
||
210 | format(ACE_CMD.REPORT_LINE, ref.text, val or ACE_CMD.REPORT_NO_VAL) |
||
211 | ) |
||
212 | end |
||
213 | end |
||
214 | |||
215 | |||
216 | --[[--------------------------------------------------------------------------------- |
||
217 | Command Handling Methods |
||
218 | ------------------------------------------------------------------------------------]] |
||
219 | |||
220 | function AceChatCmd:FindCommand(cmd) |
||
221 | cmd = strlower(cmd) |
||
222 | for index in SlashCmdList do |
||
223 | local i, cmdString = 0 |
||
224 | repeat |
||
225 | i = i + 1 |
||
226 | cmdString = getglobal("SLASH_"..index..i) |
||
227 | if( strlower(cmdString or "") == cmd ) then return TRUE end |
||
228 | until( not cmdString ) |
||
229 | end |
||
230 | end |
||
231 | |||
232 | function AceChatCmd:Register(handler) |
||
233 | if( not self._cmdList ) then |
||
234 | error("Attempt to register command handler without defining commands.", 2) |
||
235 | end |
||
236 | if( self.registered ) then return end |
||
237 | |||
238 | local slashID = strupper(self.app.name).."_CMD" |
||
239 | |||
240 | SlashCmdList[slashID] = function(msg) self:ProcessCommand(msg) end |
||
241 | local i = 0 |
||
242 | for index, cmd in self._cmdList do |
||
243 | if( not self:FindCommand(cmd) ) then |
||
244 | if( not self.commands ) then self.commands = {} end |
||
245 | i = i + 1 |
||
246 | tinsert(self.commands, cmd) |
||
247 | setglobal("SLASH_"..slashID..i, cmd) |
||
248 | end |
||
249 | end |
||
250 | |||
251 | self.handler = handler or self |
||
252 | |||
253 | if( not self.options ) then self.options = {} end |
||
254 | |||
255 | if( self.handler.Report ) then |
||
256 | tinsert(self.options, 1, { |
||
257 | option = ACE_CMD.OPT_REPORT, |
||
258 | desc = ACE_CMD.OPT_REPORT_DESC, |
||
259 | method = "Report" |
||
260 | } |
||
261 | ) |
||
262 | end |
||
263 | |||
264 | if( self.app.Enable ) then |
||
265 | tinsert(self.options, 1, { |
||
266 | option = ACE_CMD.OPT_STANDBY, |
||
267 | desc = format(ACE_CMD.OPT_STANDBY_DESC, self.app.name), |
||
268 | method = "ToggleStandBy" |
||
269 | } |
||
270 | ) |
||
271 | end |
||
272 | |||
273 | tinsert(self.options, 1, {option = ACE_CMD.OPT_HELP, desc = ACE_CMD.OPT_HELP_DESC}) |
||
274 | |||
275 | -- Create a closure for printing option lines, since it's done so much |
||
276 | self.printOpt = function(l,t) Ace:print(format(ACE_CMD.USAGE_OPT_DESC,l,t)) end |
||
277 | self.registered = TRUE |
||
278 | end |
||
279 | |||
280 | function AceChatCmd:ProcessCommand(msg) |
||
281 | msg = Ace.trim(msg or "") |
||
282 | |||
283 | if( strfind(strlower(msg), ACE_CMD.OPT_HELP) == 1 ) then |
||
284 | self:DisplayAddonInfo(self.options) |
||
285 | return |
||
286 | elseif( msg ~= "" ) then |
||
287 | return self:ProcessOptions(self.options, msg, self.handler, self.handler.CommandHandler) |
||
288 | elseif( self.handler.CommandHandler ) then |
||
289 | self.handler.CommandHandler(self.handler, msg) |
||
290 | return |
||
291 | end |
||
292 | |||
293 | self:DisplayUsage() |
||
294 | end |
||
295 | |||
296 | function AceChatCmd:ProcessOptions(list, msg, handler, method, opttext) |
||
297 | local _, _, cmd = strfind(strlower(msg), "(%S+)") |
||
298 | local args = gsub(msg, cmd.."%s*", "") |
||
299 | |||
300 | local i = Ace.TableFindByKeyValue(list, "option", cmd, TRUE) |
||
301 | if( i ) then |
||
302 | local opt = list[i] |
||
303 | if( opt.args and (args ~= "") and |
||
304 | self:ProcessOptions(opt.args, |
||
305 | args, |
||
306 | opt.handler or handler, |
||
307 | opt.method or method, |
||
308 | opttext and opttext.." "..opt.option or opt.option |
||
309 | ) |
||
310 | ) then |
||
311 | return TRUE |
||
312 | elseif( opt.method and ((args ~= "") or (not opt.input)) and |
||
313 | (strlower(args) ~= ACE_CMD.OPT_HELP) |
||
314 | ) then |
||
315 | handler = opt.handler or handler |
||
316 | handler[opt.method](handler, args) |
||
317 | return TRUE |
||
318 | elseif( opt.input and (args == "") or (opt.args and (not method)) or |
||
319 | (strlower(args) == ACE_CMD.OPT_HELP) |
||
320 | ) then |
||
321 | self:OptionHeader(opt, opttext) |
||
322 | self:DisplayArgUsage(opt) |
||
323 | return TRUE |
||
324 | end |
||
325 | elseif( ((cmd or "") ~= "") and (cmd ~= ACE_CMD.OPT_HELP) and (not method) ) then |
||
326 | self:result(format(ACE_CMD.OPT_INVALID, cmd)) |
||
327 | return TRUE |
||
328 | end |
||
329 | end |
||
330 | |||
331 | |||
332 | --[[--------------------------------------------------------------------------------- |
||
333 | Usage Display Methods |
||
334 | ------------------------------------------------------------------------------------]] |
||
335 | |||
336 | function AceChatCmd:DisplayAddonInfo() |
||
337 | self:CommandHeader() |
||
338 | if( self.commands ) then |
||
339 | self.printOpt(ACE_TEXT_COMMANDS, Ace.concat(self.commands, " | ")) |
||
340 | end |
||
341 | if( self.app.author ) then self.printOpt(ACE_TEXT_AUTHOR, self.app.author) end |
||
342 | if( self.app.releaseDate ) then self.printOpt(ACE_TEXT_RELEASED, self.app.releaseDate) end |
||
343 | if( self.app.email ) then self.printOpt(ACE_TEXT_EMAIL, self.app.email) end |
||
344 | if( self.app.website ) then self.printOpt(ACE_TEXT_WEBSITE, self.app.website) end |
||
345 | end |
||
346 | |||
347 | function AceChatCmd:OptionHeader(option, opttext) |
||
348 | local args |
||
349 | if( option.args ) then |
||
350 | args = self:ConcatOptions(option.args, ACE_CMD.USAGE_OPT_SEP) |
||
351 | end |
||
352 | if( not args ) then |
||
353 | args = "- "..(option.desc or ACE_CMD.USAGE_NOINFO) |
||
354 | end |
||
355 | Ace:print(format(ACE_CMD.USAGE_OPTION, |
||
356 | self.commands[1], |
||
357 | opttext and opttext.." "..option.option or option.option, |
||
358 | args |
||
359 | ) |
||
360 | ) |
||
361 | end |
||
362 | |||
363 | function AceChatCmd:DisplayArgUsage(option) |
||
364 | if( not option.args ) then return end |
||
365 | for _, arg in ipairs(option.args) do |
||
366 | self.printOpt(arg.option, arg.desc) |
||
367 | end |
||
368 | end |
||
369 | |||
370 | function AceChatCmd:DisplayUsage() |
||
371 | self:CommandHeader() |
||
372 | |||
373 | if( getn(self.options) < 1 ) then return end |
||
374 | |||
375 | Ace:print(format(ACE_CMD.USAGE_HEADER, |
||
376 | self.commands[1], |
||
377 | self:ConcatOptions(self.options, ACE_CMD.USAGE_OPT_SEP) |
||
378 | ) |
||
379 | ) |
||
380 | |||
381 | -- Have to print the lines one at a time or risk it getting too large for the |
||
382 | -- print buffer. |
||
383 | for _, opt in ipairs(self.options) do |
||
384 | self.printOpt(opt.option, opt.desc) |
||
385 | end |
||
386 | end |
||
387 | |||
388 | function AceChatCmd:CommandHeader() |
||
389 | Ace:print(self.app.disabled and ACE_ADDON_STANDBY.." " or "", |
||
390 | format(ACE_CMD.USAGE_ADDON_DESC, |
||
391 | self.app.name, |
||
392 | self.app.version, |
||
393 | self.app.description |
||
394 | ) |
||
395 | ) |
||
396 | end |
||
397 | |||
398 | function AceChatCmd:ConcatOptions(options, sep) |
||
399 | local str = "" |
||
400 | for _, opt in options do |
||
401 | if( (str ~= "") and sep ) then str = str..sep end |
||
402 | str = str..opt.option |
||
403 | end |
||
404 | return str |
||
405 | end |
||
406 | end |