annotate Libs/AceConsole-3.0/AceConsole-3.0.lua @ 23:52973d00a183

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