Extracting info from a slash command
From WoWWiki
Contents |
The Concept
Lets say you have this nice addon you're creating, but you come to the point where just one argument on the slash command just isn't doing it. IE you need to use /myaddon my command goes here, rather then just /myaddon command. There are many ways you can solve this issue, but here's one very simple one I have found.
The Code
This requires two specific Functions. A 'Cmd/SubCmd' function, and an 'Argument' function (last one optional).
function MyAddon_GetCmd(msg) if msg then local a,b,c=strfind(msg, "(%S+)"); --contiguous string of non-space characters if a then return c, strsub(msg, b+2); else return ""; end end end function MyAddon_GetArgument(msg) if msg then local a,b=strfind(msg, "="); if a then return strsub(msg,1,a-1), strsub(msg, b+1); else return ""; end end end
How it Works
The way this works, is it first checks to see if a command was entered. If so, then it extracts just the first cmd/subcmd for return. This is very useful in recursively deep functions, IE:
/myaddon add user name=tigerheart
would be processed as:
msg = "add user name=tigerheart"; local Cmd, SubCmd = MyAddon_GetCmd(msg);
would return:
"add" as Cmd "user name=tigerheart" as SubCmd
so we send on the subcmd to the next processor for the "add" routines, which again will parse this as Cmd and SubCmd. This one parses:
"user" as Cmd "name=tigerheart" as SubCmd.
we now get to the final stage. This function will process the subcmd with 'GetArgument'. To call GetArgument you would do:
Argument, Answer = MyAddon_GetArgument(subcmd);
Which would return:
"name" as Argument "tigerheart" as Answer
Conclusion
I hope this helps, its come in very handy for my purposes. If you use this I would love if you could at least credit me in a comment somewhere.
My mod BattleInfo uses this actively, in a slightly modified form.
An Example
- Here's a simple example of how this is used, in context
function MyAddon_SlashHandler(msg) local Cmd, SubCmd = MyAddon_GetCmd(msg); --call to above function if (Cmd == "help") then MyAddon_DisplayHelp(); elseif (Cmd == "add") then MyAddon_AddUser(SubCmd); else MyAddon_DisplayHelp(); end; end; function MyAddon_AddUser(msg) local Cmd, SubCmd = MyAddon_GetCmd(msg); --call to above function if (Cmd == "user") then local Argument, Answer = MyAddon_GetArgument(SubCmd); --call to above function if (Argument == "name") then MyAddon_AnotherRoutine(Answer); end; end; end;
And so on, until you get what you need. This way you can split up each 'subcommand' into a separate function, quickly and easily. This also helps to modulize the code so it's easier to read, easer to debug, and later, to maintain.
Also, as for case-correction, Cmd will be converted to lower case, whereas subcmd is left untouched.
Enjoy,
Parsing Into Tables
If you want to put each word into a table, use gsub or string.gmatch.
With gmatch, use it as an iterator in a loop.
function MsgToTable( msg )
if not msg then return end
local t = {};
for w in string.gmatch( msg, "%S+" ) do
tinsert( t, w )
end
return t;
end
With gsub, pass an anonymous function as its 3rd argument.
function MsgToTable( msg )
if not msg then return end
local t = {};
gsub( msg, "%S+", function(w)
tinsert( t, w )
end)
return t;
end
Both functions return a table. Thus you can use it in an assignment statement. MyAddon_MsgTable = MsgToTable(msg);
