annotate Libs/AceConsole-3.0/AceConsole-3.0.lua @ 0:98c6f55e6619

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