annotate Libs/AceConsole-3.0/AceConsole-3.0.lua @ 57:01b63b8ed811 v21

total rewrite to version 21
author yellowfive
date Fri, 05 Jun 2015 11:05:15 -0700
parents
children e635cd648e01
rev   line source
yellowfive@57 1 --- **AceConsole-3.0** provides registration facilities for slash commands.
yellowfive@57 2 -- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
yellowfive@57 3 -- to your addons individual needs.
yellowfive@57 4 --
yellowfive@57 5 -- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
yellowfive@57 6 -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
yellowfive@57 7 -- and can be accessed directly, without having to explicitly call AceConsole itself.\\
yellowfive@57 8 -- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
yellowfive@57 9 -- make into AceConsole.
yellowfive@57 10 -- @class file
yellowfive@57 11 -- @name AceConsole-3.0
yellowfive@57 12 -- @release $Id: AceConsole-3.0.lua 878 2009-11-02 18:51:58Z nevcairiel $
yellowfive@57 13 local MAJOR,MINOR = "AceConsole-3.0", 7
yellowfive@57 14
yellowfive@57 15 local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
yellowfive@57 16
yellowfive@57 17 if not AceConsole then return end -- No upgrade needed
yellowfive@57 18
yellowfive@57 19 AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
yellowfive@57 20 AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
yellowfive@57 21 AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
yellowfive@57 22
yellowfive@57 23 -- Lua APIs
yellowfive@57 24 local tconcat, tostring, select = table.concat, tostring, select
yellowfive@57 25 local type, pairs, error = type, pairs, error
yellowfive@57 26 local format, strfind, strsub = string.format, string.find, string.sub
yellowfive@57 27 local max = math.max
yellowfive@57 28
yellowfive@57 29 -- WoW APIs
yellowfive@57 30 local _G = _G
yellowfive@57 31
yellowfive@57 32 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
yellowfive@57 33 -- List them here for Mikk's FindGlobals script
yellowfive@57 34 -- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
yellowfive@57 35
yellowfive@57 36 local tmp={}
yellowfive@57 37 local function Print(self,frame,...)
yellowfive@57 38 local n=0
yellowfive@57 39 if self ~= AceConsole then
yellowfive@57 40 n=n+1
yellowfive@57 41 tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
yellowfive@57 42 end
yellowfive@57 43 for i=1, select("#", ...) do
yellowfive@57 44 n=n+1
yellowfive@57 45 tmp[n] = tostring(select(i, ...))
yellowfive@57 46 end
yellowfive@57 47 frame:AddMessage( tconcat(tmp," ",1,n) )
yellowfive@57 48 end
yellowfive@57 49
yellowfive@57 50 --- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
yellowfive@57 51 -- @paramsig [chatframe ,] ...
yellowfive@57 52 -- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
yellowfive@57 53 -- @param ... List of any values to be printed
yellowfive@57 54 function AceConsole:Print(...)
yellowfive@57 55 local frame = ...
yellowfive@57 56 if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
yellowfive@57 57 return Print(self, frame, select(2,...))
yellowfive@57 58 else
yellowfive@57 59 return Print(self, DEFAULT_CHAT_FRAME, ...)
yellowfive@57 60 end
yellowfive@57 61 end
yellowfive@57 62
yellowfive@57 63
yellowfive@57 64 --- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
yellowfive@57 65 -- @paramsig [chatframe ,] "format"[, ...]
yellowfive@57 66 -- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
yellowfive@57 67 -- @param format Format string - same syntax as standard Lua format()
yellowfive@57 68 -- @param ... Arguments to the format string
yellowfive@57 69 function AceConsole:Printf(...)
yellowfive@57 70 local frame = ...
yellowfive@57 71 if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
yellowfive@57 72 return Print(self, frame, format(select(2,...)))
yellowfive@57 73 else
yellowfive@57 74 return Print(self, DEFAULT_CHAT_FRAME, format(...))
yellowfive@57 75 end
yellowfive@57 76 end
yellowfive@57 77
yellowfive@57 78
yellowfive@57 79
yellowfive@57 80
yellowfive@57 81 --- Register a simple chat command
yellowfive@57 82 -- @param command Chat command to be registered WITHOUT leading "/"
yellowfive@57 83 -- @param func Function to call when the slash command is being used (funcref or methodname)
yellowfive@57 84 -- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
yellowfive@57 85 function AceConsole:RegisterChatCommand( command, func, persist )
yellowfive@57 86 if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
yellowfive@57 87
yellowfive@57 88 if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
yellowfive@57 89
yellowfive@57 90 local name = "ACECONSOLE_"..command:upper()
yellowfive@57 91
yellowfive@57 92 if type( func ) == "string" then
yellowfive@57 93 SlashCmdList[name] = function(input, editBox)
yellowfive@57 94 self[func](self, input, editBox)
yellowfive@57 95 end
yellowfive@57 96 else
yellowfive@57 97 SlashCmdList[name] = func
yellowfive@57 98 end
yellowfive@57 99 _G["SLASH_"..name.."1"] = "/"..command:lower()
yellowfive@57 100 AceConsole.commands[command] = name
yellowfive@57 101 -- non-persisting commands are registered for enabling disabling
yellowfive@57 102 if not persist then
yellowfive@57 103 if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
yellowfive@57 104 AceConsole.weakcommands[self][command] = func
yellowfive@57 105 end
yellowfive@57 106 return true
yellowfive@57 107 end
yellowfive@57 108
yellowfive@57 109 --- Unregister a chatcommand
yellowfive@57 110 -- @param command Chat command to be unregistered WITHOUT leading "/"
yellowfive@57 111 function AceConsole:UnregisterChatCommand( command )
yellowfive@57 112 local name = AceConsole.commands[command]
yellowfive@57 113 if name then
yellowfive@57 114 SlashCmdList[name] = nil
yellowfive@57 115 _G["SLASH_" .. name .. "1"] = nil
yellowfive@57 116 hash_SlashCmdList["/" .. command:upper()] = nil
yellowfive@57 117 AceConsole.commands[command] = nil
yellowfive@57 118 end
yellowfive@57 119 end
yellowfive@57 120
yellowfive@57 121 --- Get an iterator over all Chat Commands registered with AceConsole
yellowfive@57 122 -- @return Iterator (pairs) over all commands
yellowfive@57 123 function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
yellowfive@57 124
yellowfive@57 125
yellowfive@57 126 local function nils(n, ...)
yellowfive@57 127 if n>1 then
yellowfive@57 128 return nil, nils(n-1, ...)
yellowfive@57 129 elseif n==1 then
yellowfive@57 130 return nil, ...
yellowfive@57 131 else
yellowfive@57 132 return ...
yellowfive@57 133 end
yellowfive@57 134 end
yellowfive@57 135
yellowfive@57 136
yellowfive@57 137 --- Retreive one or more space-separated arguments from a string.
yellowfive@57 138 -- Treats quoted strings and itemlinks as non-spaced.
yellowfive@57 139 -- @param string The raw argument string
yellowfive@57 140 -- @param numargs How many arguments to get (default 1)
yellowfive@57 141 -- @param startpos Where in the string to start scanning (default 1)
yellowfive@57 142 -- @return Returns arg1, arg2, ..., nextposition\\
yellowfive@57 143 -- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
yellowfive@57 144 function AceConsole:GetArgs(str, numargs, startpos)
yellowfive@57 145 numargs = numargs or 1
yellowfive@57 146 startpos = max(startpos or 1, 1)
yellowfive@57 147
yellowfive@57 148 local pos=startpos
yellowfive@57 149
yellowfive@57 150 -- find start of new arg
yellowfive@57 151 pos = strfind(str, "[^ ]", pos)
yellowfive@57 152 if not pos then -- whoops, end of string
yellowfive@57 153 return nils(numargs, 1e9)
yellowfive@57 154 end
yellowfive@57 155
yellowfive@57 156 if numargs<1 then
yellowfive@57 157 return pos
yellowfive@57 158 end
yellowfive@57 159
yellowfive@57 160 -- quoted or space separated? find out which pattern to use
yellowfive@57 161 local delim_or_pipe
yellowfive@57 162 local ch = strsub(str, pos, pos)
yellowfive@57 163 if ch=='"' then
yellowfive@57 164 pos = pos + 1
yellowfive@57 165 delim_or_pipe='([|"])'
yellowfive@57 166 elseif ch=="'" then
yellowfive@57 167 pos = pos + 1
yellowfive@57 168 delim_or_pipe="([|'])"
yellowfive@57 169 else
yellowfive@57 170 delim_or_pipe="([| ])"
yellowfive@57 171 end
yellowfive@57 172
yellowfive@57 173 startpos = pos
yellowfive@57 174
yellowfive@57 175 while true do
yellowfive@57 176 -- find delimiter or hyperlink
yellowfive@57 177 local ch,_
yellowfive@57 178 pos,_,ch = strfind(str, delim_or_pipe, pos)
yellowfive@57 179
yellowfive@57 180 if not pos then break end
yellowfive@57 181
yellowfive@57 182 if ch=="|" then
yellowfive@57 183 -- some kind of escape
yellowfive@57 184
yellowfive@57 185 if strsub(str,pos,pos+1)=="|H" then
yellowfive@57 186 -- It's a |H....|hhyper link!|h
yellowfive@57 187 pos=strfind(str, "|h", pos+2) -- first |h
yellowfive@57 188 if not pos then break end
yellowfive@57 189
yellowfive@57 190 pos=strfind(str, "|h", pos+2) -- second |h
yellowfive@57 191 if not pos then break end
yellowfive@57 192 elseif strsub(str,pos, pos+1) == "|T" then
yellowfive@57 193 -- It's a |T....|t texture
yellowfive@57 194 pos=strfind(str, "|t", pos+2)
yellowfive@57 195 if not pos then break end
yellowfive@57 196 end
yellowfive@57 197
yellowfive@57 198 pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
yellowfive@57 199
yellowfive@57 200 else
yellowfive@57 201 -- found delimiter, done with this arg
yellowfive@57 202 return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
yellowfive@57 203 end
yellowfive@57 204
yellowfive@57 205 end
yellowfive@57 206
yellowfive@57 207 -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
yellowfive@57 208 return strsub(str, startpos), nils(numargs-1, 1e9)
yellowfive@57 209 end
yellowfive@57 210
yellowfive@57 211
yellowfive@57 212 --- embedding and embed handling
yellowfive@57 213
yellowfive@57 214 local mixins = {
yellowfive@57 215 "Print",
yellowfive@57 216 "Printf",
yellowfive@57 217 "RegisterChatCommand",
yellowfive@57 218 "UnregisterChatCommand",
yellowfive@57 219 "GetArgs",
yellowfive@57 220 }
yellowfive@57 221
yellowfive@57 222 -- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
yellowfive@57 223 -- @param target target object to embed AceBucket in
yellowfive@57 224 function AceConsole:Embed( target )
yellowfive@57 225 for k, v in pairs( mixins ) do
yellowfive@57 226 target[v] = self[v]
yellowfive@57 227 end
yellowfive@57 228 self.embeds[target] = true
yellowfive@57 229 return target
yellowfive@57 230 end
yellowfive@57 231
yellowfive@57 232 function AceConsole:OnEmbedEnable( target )
yellowfive@57 233 if AceConsole.weakcommands[target] then
yellowfive@57 234 for command, func in pairs( AceConsole.weakcommands[target] ) do
yellowfive@57 235 target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
yellowfive@57 236 end
yellowfive@57 237 end
yellowfive@57 238 end
yellowfive@57 239
yellowfive@57 240 function AceConsole:OnEmbedDisable( target )
yellowfive@57 241 if AceConsole.weakcommands[target] then
yellowfive@57 242 for command, func in pairs( AceConsole.weakcommands[target] ) do
yellowfive@57 243 target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
yellowfive@57 244 end
yellowfive@57 245 end
yellowfive@57 246 end
yellowfive@57 247
yellowfive@57 248 for addon in pairs(AceConsole.embeds) do
yellowfive@57 249 AceConsole:Embed(addon)
yellowfive@57 250 end