Lua script extensions
MUSHclient has some scripting extensions which are only available to Lua scripting. This page describes them.
Lua "sandbox"
To help block out dangerous functions, for example:
Into this you can place code that disables some 'dangerous' functions (like 'os') by setting them to nil.
The code in this box is executed every time the Lua script engine is instantiated, in other words for every world, and every plugin.
You can modify the sandbox code to remove all restrictions, add more, or fine-tune them to your requirements. For example, if you wanted to use os.date and os.time (and others), but not os.execute, os.remove or os.rename, you could use:
'print' function
To make it easier to use Lua examples in MUSHclient, the function "print" is defined to effectively call the world "Note" function. However, unlike Note, print adds a space between each argument (like the Lua "print" does).
eg.
world functions available from global scope
Although the normal MUSHclient script functions are defined in the "world" table, MUSHclient adds a metatable to the _G table and uses the __index entry to make the script functions available at global scope.
Put another way, you can either write:
If you wish to change the behaviour of an inbuilt script function you must replace the world.XXX version (eg. change world.Note) rather than simply replacing the global version.
'check' function
Many script functions return error codes (see the error_code table described below). A quick way of checking that the function has succeeded is to wrap the 'check' function around it.
For example, instead of:
Constants
To make it easier to write scripts, MUSHclient's Lua interface has various built-in tables of constants.
Trigger flags for AddTrigger
These are in the 'trigger_flag' table.
These are in the 'alias_flag' table.
These are in the 'timer_flag' table.
These are in the 'custom_colour' table.
These are in the 'error_code' table.
You can use these to check individual error codes.
eg.
Error codes - map error codes to descriptions
These are in the 'error_desc' table.
You can use these to give meaningful error messages.
eg.
These are in the 'colour_names' table.
You can use these to look up colour names (eg. "red") and find the corresponding RGB value.
Extended colour codes - map colour selector numbers to RGB values
These are in the 'extended_colours' table.
You can use these to see what the RGB equivalent is for the 256 extended colours (keyed by 0 to 255).
Send-to codes - map scripted "send" names to a number
These are in the 'sendto' table.
You can use these to make functions like DoAfterSpecial more self-documenting. For example, instead of sending to '12', you can send to 'sendto.script'.
eg.
These are in the 'miniwin' table.
You can use these to make functions like WindowCreate, WindowRectOp, WindowCircleOp etc. more self-documenting. For example, instead of doing WindowRectOp action 1, you can use 'miniwin.rect_frame'.
eg.
progress
This provides functionality for displaying a "progress" dialog box during lengthy operations.
First you create the progress dialog with:
progress.new (description)
That returns a userdata item that you can then use in subsequent operations:
Lua "sandbox"
To help block out dangerous functions, for example:
os.execute "del mushclient.exe"
... MUSHclient has a 'preliminary script' box in its Global Preferences -> Lua section. Into this you can place code that disables some 'dangerous' functions (like 'os') by setting them to nil.
The code in this box is executed every time the Lua script engine is instantiated, in other words for every world, and every plugin.
You can modify the sandbox code to remove all restrictions, add more, or fine-tune them to your requirements. For example, if you wanted to use os.date and os.time (and others), but not os.execute, os.remove or os.rename, you could use:
os.execute = nil -- no executing OS commands
os.remove = nil -- no removing files
os.rename = nil -- no renaming files
'print' function
To make it easier to use Lua examples in MUSHclient, the function "print" is defined to effectively call the world "Note" function. However, unlike Note, print adds a space between each argument (like the Lua "print" does).
eg.
Note "hello, world"
print "hello, world" --> does the same thing
Note (1, 2, 3) --> 123
print (1, 2, 3) --> 1 2 3
world functions available from global scope
Although the normal MUSHclient script functions are defined in the "world" table, MUSHclient adds a metatable to the _G table and uses the __index entry to make the script functions available at global scope.
Put another way, you can either write:
world.Note "hello, world" --> calls Note function in world table
Note "hello, world" --> does the same thing
Both methods call the world.Note script function.If you wish to change the behaviour of an inbuilt script function you must replace the world.XXX version (eg. change world.Note) rather than simply replacing the global version.
'check' function
Many script functions return error codes (see the error_code table described below). A quick way of checking that the function has succeeded is to wrap the 'check' function around it.
For example, instead of:
DoAfter (10, "eat food")
you could do this:
check (DoAfter (10, "eat food"))
This raises an error (and shows the appropriate error message) if the function fails. Note that this is not relevant to all functions, only those which are documented to return eOK on success, and some other code on failure.
Constants
To make it easier to write scripts, MUSHclient's Lua interface has various built-in tables of constants.
Trigger flags for AddTrigger
These are in the 'trigger_flag' table.
print (trigger_flag.OmitFromOutput) --> 4
Trigger flags for AddAliasThese are in the 'alias_flag' table.
print (alias_flag.AliasQueue) --> 4096
Trigger flags for AddTimerThese are in the 'timer_flag' table.
print (timer_flag.OneShot) --> 4
Custom colour flags for AddTriggerThese are in the 'custom_colour' table.
print (custom_colour.NoChange) --> -1
Error codes - map error names to numbersThese are in the 'error_code' table.
You can use these to check individual error codes.
eg.
if AddTimer (blah blah blah) ==
error_code.eTimerAlreadyExists then
error ("That timer already exists")
end
print (error_code.eBadRegularExpression) --> 30021
Also see above about the 'check' function.Error codes - map error codes to descriptions
These are in the 'error_desc' table.
You can use these to give meaningful error messages.
eg.
status = AddTimer ("a", 0, 0, 0, 0, 0)
if status ~= error_code.eOK then
error (error_desc [status]) --> Time given to AddTimer is invalid
end
Colour names - map colour picker names to RGB valuesThese are in the 'colour_names' table.
You can use these to look up colour names (eg. "red") and find the corresponding RGB value.
Extended colour codes - map colour selector numbers to RGB values
These are in the 'extended_colours' table.
You can use these to see what the RGB equivalent is for the 256 extended colours (keyed by 0 to 255).
Send-to codes - map scripted "send" names to a number
These are in the 'sendto' table.
You can use these to make functions like DoAfterSpecial more self-documenting. For example, instead of sending to '12', you can send to 'sendto.script'.
eg.
DoAfterSpecial (5, "Sound ('ding.wav')", sendto.script)
Miniwindow constantsThese are in the 'miniwin' table.
You can use these to make functions like WindowCreate, WindowRectOp, WindowCircleOp etc. more self-documenting. For example, instead of doing WindowRectOp action 1, you can use 'miniwin.rect_frame'.
eg.
WindowRectOp (win, miniwin.rect_frame, 20, 20, 70, 70, ColourNameToRGB("blue"))
progress
This provides functionality for displaying a "progress" dialog box during lengthy operations.
First you create the progress dialog with:
progress.new (description)
That returns a userdata item that you can then use in subsequent operations:
dlg:status (msg) --> set a status message (eg. "processing 'foo' ")
dlg:range (low, high) --> sets the range of operations (eg. 1 to 100)
dlg:position (pos) --> sets where we are in the range (eg. 80)
dlg:checkcancel () --> returns true if the user clicked on the cancel button
dlg:setstep (amount) --> sets the step amount (eg. 5)
dlg:step () --> increase the position by the step amount
dlg:close () --> dismiss the progress dialog
Example of use:
local dlg = progress.new ("Loading things ...")
dlg:range (0, 3) --> 3 steps
dlg:setstep (1) --> step 1 per step
dlg:status ("Processing foo") --> first step
dlg:step ()
-- do something lengthy here
dlg:status ("Processing bar") --> second step
dlg:step ()
-- do something lengthy here
dlg:status ("Processing fruit") --> third step
dlg:step ()
-- do something lengthy here
dlg:close () --> all done
The dialog box is a "modal" dialog, so make sure you arrange to close it, even on a script error, or it will lock out attempts to use the GUI interface. If necessary, use "pcall" on whatever it is you do while the dialog is open.Topics
- Lua LPEG library
- Lua PCRE regular expression functions
- Lua SQLite (database) interface
- Lua base functions
- Lua bc (big number) functions
- Lua bit manipulation functions
- Lua coroutine functions
- Lua debug functions
- Lua io functions
- Lua math functions
- Lua os functions
- Lua package functions
- Lua string functions
- Lua syntax
- Lua table functions
- Lua utilities
- Scripting callbacks - plugins
- Scripting functions list
- Scripting