Thread Tools Display Modes
08-06-13, 12:23 PM   #1
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
Removing slash commands

I was wondering how to remove a slash command once it has been added... I am making an addon that can take user supplied lua snippets and assign them to a slash command and want the option of having them be able to enable / disable the commands on the fly if they wish without needing to do a /reload

I was trying it by the following but it does not go away...

RunScript( ('SLASH_%s1 = nil'):format( cmdName ) )
RunScript( ('SlashCmdList["%s"] = nil'):format( cmdName ) )

cmdName gets made in addon by appending the addon name and the slash command (minus the slash)
the same as it is constructed during the creation of the slash command in the addon loaded event
  Reply With Quote
08-06-13, 02:09 PM   #2
Nibelheim
local roygbi-
 
Nibelheim's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 1,600
Originally Posted by Billtopia View Post
I was wondering how to remove a slash command once it has been added... I am making an addon that can take user supplied lua snippets and assign them to a slash command and want the option of having them be able to enable / disable the commands on the fly if they wish without needing to do a /reload

I was trying it by the following but it does not go away...

RunScript( ('SLASH_%s1 = nil'):format( cmdName ) )
RunScript( ('SlashCmdList["%s"] = nil'):format( cmdName ) )

cmdName gets made in addon by appending the addon name and the slash command (minus the slash)
the same as it is constructed during the creation of the slash command in the addon loaded event
I don't think you want the "" around the %s
  Reply With Quote
08-06-13, 02:19 PM   #3
Malsomnus
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Apr 2013
Posts: 203
I tried it with a specific command, and it didn't work, so I don't think the quotes are the problem. It's pretty weird though.
__________________
SanityCheck - If you've ever said the words "Sorry, I forgot" then you need this add-on.

Remember, every time you post a comment on an add-on, a kitten gets its wings!
  Reply With Quote
08-06-13, 02:21 PM   #4
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
It needs the quotes as it will be a string indexing the SlashCmdList table
the %s gets filled in with a string value from cmdName via the format
  Reply With Quote
08-06-13, 02:42 PM   #5
Nibelheim
local roygbi-
 
Nibelheim's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 1,600
Edit: I'm an idiot

What you want to remove from is not SlashCmdList, but hash_SlashCmdList. SlashCmdList is a temporary storage table and doesn't actually retain any data.
  Reply With Quote
08-06-13, 04:27 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,322
Actually, the problem is when you run a slash command, it takes all entries in SlashCmdList and moves them to its metatable. There are 3 steps that need to be done in order to unregister a slash command. Some unexpected results may occur if you don't clear all of the steps.
  • Clear all SLASH_* globals.
  • Clear the entry from SlashCmdList and its metatable.
  • Clear the entry from hash_SlashCmdList.

The following function should accomplish this.
Lua Code:
  1. function RemoveSlashToken(token)
  2.     local i=1;
  3.     while _G["SLASH_"..token..i]~=nil do
  4.         local slash=_G["SLASH_"..token..i];
  5.  
  6.         _G["SLASH_"..token..i]=nil;--   Removes SLASH_*
  7.         hash_SlashCmdList[slash]=nil;-- Removes from hash_SlashCmdList
  8.  
  9.         i=i+1;
  10.     end
  11.  
  12.     SlashCmdList[token]=nil;--  Removes from SlashCmdList
  13.     getmetatable(SlashCmdList).__index[token]=nil;--    Removes from metatable
  14. end
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
08-06-13, 04:31 PM   #7
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
Thanks... hash_SlashCmdList["/MYCOMMAND"] = nil
works fine... (I had to do a /dump on it to see how it was indexed)

I found nothing on the hash table when I was looking for a way to remove the commands... now I know lol

***************************

Oh no... another post as I was replying to the previous lol
but I guess I need more info anyways...

Should I just remove my own _G["SLASH_"] tokens or all of them? will I break something if I do? or does it not matter?

Last edited by Billtopia : 08-06-13 at 04:36 PM. Reason: another reply...
  Reply With Quote
08-06-13, 04:37 PM   #8
Nibelheim
local roygbi-
 
Nibelheim's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 1,600
Originally Posted by SDPhantom View Post
Actually, the problem is when you run a slash command, it takes all entries in SlashCmdList and moves them to its metatable. There are 3 steps that need to be done in order to unregister a slash command. Some unexpected results may occur if you don't clear all of the steps.
  • Clear all SLASH_* globals.
  • Clear the entry from SlashCmdList and its metatable.
  • Clear the entry from hash_SlashCmdList.
Neato. An interesting topic. Curiosity made me pop open ChatFrame.lua just to have a looksy at how Blizz handles slash commands.


Originally Posted by Billtopia View Post
Should I just remove my own _G["SLASH_"] tokens or all of them? will I break something if I do? or does it not matter?
Just your own. If you clear them all, any slash commands that haven't been moved to the hash table (this occurs when someone uses a slash command) will be lost.
  Reply With Quote
08-06-13, 04:39 PM   #9
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
nevermind... I see you are only clearing one, not all in the lua... so it is all of my own, not all

DOH!!!

Thanks for the help
  Reply With Quote
08-06-13, 06:49 PM   #10
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,322
Originally Posted by Nibelheim View Post
Neato. An interesting topic. Curiosity made me pop open ChatFrame.lua just to have a looksy at how Blizz handles slash commands.
They changed it in Cata 4.3, which broke SlashHelp at the time. Figures one change they make that doesn't offer any benefit breaks something useful.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
08-13-13, 04:36 PM   #11
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
Not sure if this helps, but I found a few functions in the SlashCmdList, while browsing through the source, that never got bound to a slash command. I wanted to change that, so I wrote this:

Code:
local errorsOff = "UI_ERRORS_OFF"

rawset(SlashCmdList, errorsOff, SlashCmdList[errorsOff])

_G["SLASH_"..errorsOff.."1"] = "/suppresserrors"
_G["SLASH_"..errorsOff.."2"] = "/se"

local errorsOn = "UI_ERRORS_ON"

rawset(SlashCmdList, errorsOn, SlashCmdList[errorsOn])

_G["SLASH_"..errorsOn.."1"] = "/restoreerrors"
_G["SLASH_"..errorsOn.."2"] = "/re"

ChatFrame_ImportAllListsToHash()
Using rawset lets me set the value directly without triggering the stuff that would prevent this from working as it looks like it should. Then, the call to ChatFrame_ImportAllListsToHash processes all the entries in SlashCmdList that aren't migrated into the hash_ version using the proper sequence of events to activate the slash commands.
  Reply With Quote
08-16-13, 12:32 PM   #12
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,322
Originally Posted by pelf View Post
Using rawset lets me set the value directly without triggering the stuff that would prevent this from working as it looks like it should.
Not exactly a solid explanation. You're talking of avoiding the __newindex metamethod in which if one exists, it would need to allow writing to the table or else break the slash command system. What's happening in the code is you're copying the function from the metatable and inserting it back into the table itself. This lets ChatFrame_ImportAllListsToHash() see the function and reprocess it. In the long run, rawset() isn't necessary as the following deceptively works fine as-is without the overhead of calling a global function.

Code:
SlashCmdList.UI_ERRORS_OFF=SlashCmdList.UI_ERRORS_OFF;
SlashCmdList.UI_ERRORS_ON=SlashCmdList.UI_ERRORS_ON;
Note since the indices don't exist, it pulls the functions from the metatable and creates the entry in the base table, not back into the metatable.





If you really wanted to bypass setting all the globals, you could just inject the function directly into hash.

Code:
hash_SlashCmdList["/ERROROFF"]=SlashCmdList.UI_ERRORS_OFF;
hash_SlashCmdList["/ERROFF"]=SlashCmdList.UI_ERRORS_OFF;

hash_SlashCmdList["/ERRORON"]=SlashCmdList.UI_ERRORS_ON;
hash_SlashCmdList["/ERRON"]=SlashCmdList.UI_ERRORS_ON;
Note the indices need to be in uppercase as all entered slash commands are checked this way.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 08-16-13 at 01:08 PM.
  Reply With Quote
08-16-13, 11:31 PM   #13
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
I knew someone wouldn't be able to resist giving a better explanation . I spent a while that night sifting through UI code to figure out how it expects slash commands to be added and I will admit that a good bit of it is a blur.

Thanks for expounding.
  Reply With Quote
08-19-13, 10:10 PM   #14
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,322
The previous version of the command system scanned SlashCmdList for command tokens in which to check the specific globals for a matching command. There was an included feature when it found a command, it loaded the command with a pointer to the command token's handler function into a cache table, hash_SlashCmdList. Further uses of that specific command would run the function from cache instead of running the scanner again.

The current version runs exclusively off of the mappings in hash_SlashCmdList and queries SlashCmdList for new entries using its metatable system for backwards compatibility when a slash command is executed. Note all slash commands are converted to uppercase before being inserted into hash_SlashCmdList. This helps with the case insensitivity of the command system. Using an index that is not all uppercase will not be recognized.

The scanner of the new command system is based off the fact when an entry is moved into the __index section of a metatable, it can still be accessed if referenced directly. Therefore command calls like SlashCmdList["Command_Token"]() will sill function as they always had. However, when the base table is iterated through with a for ... end loop, the entry will not be seen by the loop. This allows backwards compatibility as well as letting the new system see if any new commands had been added since the last time scanner had been run.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 08-19-13 at 10:19 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Removing slash commands

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off