-
Notifications
You must be signed in to change notification settings - Fork 0
Miscellaneous Utility Functions
This section documents the miscellaneous helper functions provided by LibSFUtils. These utilities simplify common Lua tasks, provide safer function invocation, assist with argument handling, formatting, addon metadata, chat output, and several ESO-specific conveniences.
Creates an iterator for a variable argument list without requiring Lua 5.2's table.pack().
Unlike iterating over a temporary table directly, the iterator returns the current argument index, the argument value, and the total number of arguments on each iteration.
for index, value, total in sfutil.iter_args(...) do
...
end| Parameter | Description |
|---|---|
... |
Any number of arguments. |
An iterator function returning:
| Return | Description |
|---|---|
index |
Current argument index. |
value |
Current argument value. |
total |
Total number of arguments originally supplied. |
for i, value, total in sfutil.iter_args("a", 5, true) do
d(i, value, total)
endOutput
1 a 3
2 5 3
3 true 3
Creates a closure that binds a callback function to a specific self table and optionally pre-binds one or more leading arguments.
The returned function behaves like a partially applied function. When it is called, the bound arguments are supplied first, followed by any arguments passed to the returned function.
This is useful for:
- Registering callbacks that require a specific object as
self. - Creating event handlers with preconfigured arguments.
- Implementing partial function application.
local fn = sfutil.closure(callback, tblself, ...)| Parameter | Description |
|---|---|
callback |
Function to invoke when the closure is called. |
tblself |
Table passed as the first argument to callback. May be nil for normal functions. |
... |
Optional arguments to bind to the callback. These are inserted before the arguments supplied when the returned function is called. |
A function that calls:
callback(tblself, boundArgs..., runtimeArgs...)local update = sfutil.closure(MyObject.Update, MyObject)
update(10, 20)Equivalent to:
MyObject.Update(MyObject, 10, 20)local addFive = sfutil.closure(MyObject.AddValue, MyObject, 5)
addFive(10)Equivalent to:
MyObject.AddValue(MyObject, 5, 10)tblself may be nil when binding a regular function.
local greet = sfutil.closure(print, nil, "Hello")
greet("World")Equivalent to:
print("Hello", "World")- Bound arguments are supplied before any arguments provided when the returned function is invoked.
- The callback is not executed until the returned function is called.
- This function provides a simple form of partial application, allowing commonly used arguments to be fixed in advance.
- Intended for Lua 5.1 compatibility and does not require
table.pack().
Wraps an existing function so that all future calls are redirected through a wrapper function.
The wrapper receives the original function as its first argument, followed by the arguments supplied by the caller. This allows the wrapper to intercept, modify, extend, or completely replace the original function's behavior.
If no namespace is supplied, the function is assumed to exist in the global namespace (_G).
This utility is useful for:
- Hooking existing functions
- Logging or debugging function calls
- Profiling execution time
- Injecting additional behavior before or after a function executes
- Temporarily overriding existing implementations
This function is primarily intended for debugging as it likely does not play well with other addons!
Wrap a global function:
sfutil.WrapFunction(functionName, wrapper)Wrap a function in a table (namespace):
sfutil.WrapFunction(namespace, functionName, wrapper)| Parameter | Description |
|---|---|
namespace |
(Optional) Table containing the function to wrap. If omitted, _G is used. |
functionName |
Name of the function to wrap. |
wrapper |
Function that will replace the original function. It receives the original function as its first argument. |
function wrapper(originalFunction, ...)| Parameter | Description |
|---|---|
originalFunction |
The original function being wrapped. |
... |
Arguments passed by the caller. |
The wrapper may:
- Call the original function.
- Modify the arguments before calling it.
- Modify the return values.
- Skip calling the original function entirely.
Nothing.
The specified function is replaced with a wrapped version.
function SayHello(name)
d("Hello " .. name)
end
sfutil.WrapFunction("SayHello",
function(original, name)
d("Before")
original(name)
d("After")
end)
SayHello("Alice")Output:
Before
Hello Alice
After
MyAddon = {}
function MyAddon.Update(value)
d("Updating:", value)
end
sfutil.WrapFunction(MyAddon, "Update",
function(original, value)
d("Intercepted")
return original(value)
end)
MyAddon.Update(42)Output:
Intercepted
Updating: 42
The wrapper can alter the arguments before forwarding them.
sfutil.WrapFunction(MyAddon, "Update",
function(original, value)
return original(value * 2)
end)Calling
MyAddon.Update(10)actually invokes
original(20)The wrapper is not required to call the original function.
sfutil.WrapFunction("DangerousFunction",
function(original, ...)
d("DangerousFunction has been disabled.")
end)Every call to DangerousFunction() now prints a message without executing the original implementation.
- Wrapping affects all subsequent calls to the function.
- The original function is preserved only within the wrapper as the first parameter.
- Wrappers can modify arguments, return values, or completely replace the original behavior.
- Multiple calls to
WrapFunction()on the same function create nested wrappers, with the most recently installed wrapper executing first. - This utility is particularly useful for debugging, instrumentation, and extending third-party code without modifying its source.
- Function cannot be 'unwrapped'.
Executes a function inside pcall() and safely returns up to ten return values without creating a temporary table.
This version minimizes memory allocations and is useful for frequently called functions.
local ok, result1, result2 = sfutil.safeCall10(fn, ...)| Return | Description |
|---|---|
ok |
true if the call succeeded. |
| remaining | Up to ten return values from the function. |
On failure
false, errorMessagelocal ok, value = sfutil.safeCall10(MyFunction)Executes a function safely using pcall().
Unlike safeCall10(), this version preserves every return value by storing them temporarily in a table.
local ok, ... = sfutil.safeCall(fn, ...)| Return | Description |
|---|---|
ok |
Success flag. |
| remaining | All values returned by the function. |
local ok, a, b, c, d = sfutil.safeCall(MyFunction)Converts a boolean value into "true" or "false".
sfutil.bool2str(true)Returns
true
Converts a string representation into a boolean.
Accepted true values:
"true""1"
Everything else returns false.
sfutil.str2bool("true")Returns
truePerforms a stricter boolean test than Lua's built-in truthiness.
Returns true only for the following values:
true"true"1"1"
Everything else returns false.
sfutil.isTrue("1")Returns
trueReturns default only if value is nil.
Unlike Lua's or operator, false is preserved.
local enabled = sfutil.nilDefault(saved.enabled, false)Returns default if the value is either:
nil- an empty string
local name = sfutil.nilDefaultStr(userName, "Unknown")Creates or populates a table containing information about the current addon and player.
| Field | Description |
|---|---|
addonName |
Addon name. |
server |
Current world/server name. |
account |
Account display name. |
charId |
Character ID. |
charName |
Character name. |
fmtCharName |
Formatted character name. |
API |
Current ESO API version. |
local meta = sfutil.addonMeta("MyAddon")Converts a number of seconds into an HH:MM:SS string.
sfutil.secondsToClock(3665)Returns
01:01:05
Creates a colored prefix suitable for addon chat messages.
local prefix = sfutil.initSystemMsgPrefix("MyAddon")Produces something similar to
[MyAddon]
with color formatting applied.
Displays a colored message in the ESO system chat.
sfutil.systemMsg(prefix, "Settings loaded.")addonChatter is a lightweight chat message and debug output helper for ESO addons.
It provides:
- Consistent addon message prefixes.
- Colored normal messages.
- Colored debug messages.
- Runtime enabling and disabling of debug output.
- Slash command help display formatting.
addonChatter avoids repeated debug condition checks by replacing the debug function with an empty function when debugging is disabled.
Creates a new addon chat handler.
local chat = sfutil.addonChatter:New(addonName)| Parameter | Description |
|---|---|
addonName |
Name displayed in the chat message prefix. |
A new addonChatter object.
local chat = sfutil.addonChatter:New("MyAddon")The object is initialized with:
| Property | Default |
|---|---|
namecolor |
sfutil.hex.goldenrod |
normalcolor |
sfutil.hex.mocassin |
debugcolor |
sfutil.hex.ltskyblue |
isdbgon |
false |
Displays a normal addon message in ESO chat.
The message automatically receives the addon prefix and normal message color.
chat:systemMessage(...)chat:systemMessage("Settings loaded.")Output:
[MyAddon] Settings loaded.
Displays a debug message if debugging is enabled.
When debugging is disabled, the message is ignored.
chat:debugMsg(...)chat:debugMsg("Loading profile:", profileName)Enables debug output.
After calling this function:
chat.d(...)will output debug messages.
chat:enableDebug()
chat:debugMsg("Debug mode enabled.")Disables debug output.
Debug messages are discarded while disabled.
chat:disableDebug()Toggles the current debug state.
If debugging is enabled, it is disabled.
If debugging is disabled, it is enabled.
chat:toggleDebug()Returns the current debug state.
local enabled = chat:isDebugEnabled()| Value | Meaning |
|---|---|
true |
Debug output enabled. |
false |
Debug output disabled. |
if chat:isDebugEnabled() then
chat:debugMsg("Verbose logging active.")
endReturns the debug state as a string.
local state = chat:getDebugState()Either:
"true"
or
"false"
This is useful when displaying the state in chat or UI controls.
Changes the color used for normal messages.
chat:setNormalColor(color)chat:setNormalColor(sfutil.hex.white)Changes the color used for debug messages.
chat:setDebugColor(color)chat:setDebugColor(sfutil.hex.orange)The object contains a shortcut debug function:
chat.d(...)When debugging is disabled:
chat.d(...)does nothing.
When debugging is enabled:
chat.d(...)outputs a colored debug message.
This allows performance-sensitive code to avoid repeatedly checking the debug state.
Example:
chat.d("Current value:", value)instead of:
if chat:isDebugEnabled() then
chat:debugMsg("Current value:", value)
endA common addon pattern is:
local chat = sfutil.addonChatter:New("MyAddon")
chat:systemMessage("Initialized.")
chat:enableDebug()
chat.d("Loading saved variables.")For production releases:
chat:disableDebug()No additional checks are required because debug calls become no-ops.
addonChatter uses a function replacement technique for debug output:
Disabled:
self.d = function(...)
endEnabled:
self.d = function(...)
-- output message
endThis avoids a conditional check every time a debug message is generated.
This makes addonChatter suitable for addons where debug calls remain in production code but should have minimal runtime overhead.
slashHelp() displays a formatted list of addon slash commands in the ESO chat window.
It provides a simple way for an addon to present its available commands to users without each addon needing to implement its own formatting, coloring, and chat output handling.
Typical uses include:
- Responding to a
/addon helpcommand. - Displaying available addon commands.
- Providing in-game command documentation.
- Keeping command descriptions consistent with addon chat formatting.
chat:slashHelp(title, cmdstable)| Parameter | Type | Description |
|---|---|---|
title |
string | Title displayed above the command list. |
cmdstable |
table | Table containing slash command definitions. |
The command table should contain entries in the following format:
{
command,
description
}Example:
local commands =
{
{"/myaddon help", "Display available commands"},
{"/myaddon reset", "Reset settings"},
{"/myaddon debug", "Toggle debug mode"},
}Each entry contains:
| Index | Description |
|---|---|
[1] |
Slash command text. |
[2] |
Description displayed to the user. |
local chat = sfutil.addonChatter:New("MyAddon")
local commands =
{
{"/myaddon help", "Show this help message"},
{"/myaddon reload", "Reload saved variables"},
{"/myaddon reset", "Restore defaults"},
}
chat:slashHelp("MyAddon Commands", commands)Output:
[MyAddon] MyAddon Commands
/myaddon help = Show this help message
/myaddon reload = Reload saved variables
/myaddon reset = Restore defaults
The description field may contain an ESO string ID instead of a text string.
Example:
local commands =
{
{"/myaddon help", SI_MYADDON_HELP},
{"/myaddon reset", SI_MYADDON_RESET},
}When the description is a number, slashHelp() automatically converts it using:
GetString(description)This allows command descriptions to support localization.
A typical addon implementation:
local HELP_COMMANDS =
{
{"/myaddon help", "Show available commands"},
{"/myaddon debug", "Toggle debug messages"},
{"/myaddon reset", "Reset settings"},
}
SLASH_COMMANDS["/myaddon"] = function(command)
if command == "help" then
chat:slashHelp(
"MyAddon Commands",
HELP_COMMANDS
)
elseif command == "debug" then
chat:toggleDebug()
elseif command == "reset" then
ResetSettings()
else
chat:slashHelp(
"MyAddon Commands",
HELP_COMMANDS
)
end
endUsers can then enter:
/myaddon help
to display the command list.
slashHelp() performs the following operations:
- Displays the supplied title using
systemMessage(). - Iterates through the command table.
- Formats each command entry.
- Applies command and description colors.
- Sends each line to ESO chat.
Conceptually:
for _, command in pairs(cmdstable) do
display(
command[1],
command[2]
)
endEach command line is formatted as:
command = description
The command portion uses the command color:
sfutil.hex.tealThe description uses the normal message color:
self.normalcolorDefine the command list once and reuse it:
local COMMANDS =
{
{"/myaddon help", SI_MYADDON_HELP},
{"/myaddon config", SI_MYADDON_CONFIG},
{"/myaddon reset", SI_MYADDON_RESET},
}Then:
chat:slashHelp(
"MyAddon Commands",
COMMANDS
)This keeps the slash command implementation and user documentation synchronized.
All help output uses the same addon prefix and color scheme.
Command descriptions can use ESO string IDs.
Adding a new command only requires adding another table entry.
Example:
{
"/myaddon export", "Export settings"
}No additional formatting code is required.
-
slashHelp()expects each command entry to contain at least two values. - The command table may contain any number of entries.
- Descriptions may be normal strings or ESO string IDs.
- Commands are displayed in the iteration order returned by
pairs(). If a fixed display order is required, use an array andipairs()instead.
These utility functions provide convenient wrappers around many common Lua and ESO programming tasks, including:
- Safe function invocation
- Argument iteration
- Closure creation
- Function wrapping
- Boolean conversion
- Default value handling
- Addon metadata collection
- Time formatting
- System chat output
- Debug message management
They are intended to reduce boilerplate while providing consistent behavior throughout an addon.