Vetinari's $HOME

xchat lua plugin

Introduction

Each script runs in it's own lua state. Currently no data can be passed from one script to another (except via commands). The base, table, io, string and math libs are loaded.

All scripts in the xchat dir (usually ~/.xchat2/) ending in .lua are autoloaded. After loading of all these scripts, the lua function xchat_register() in each script is called, it must return three strings: script name, description, version. If you load a script with /LOAD script.lua, the xchat_register() function is immediately called after loading.

After a script is registered (i.e. nothing was wrong in calling xchat_register()) the lua function xchat_init() is called. You should add your hooks here, open file descriptors, ... This is an optional call. If your script doesn't have an xchat_init() function, nothing bad happens.

Before unloading (just one script or the plugin) xchat_unload() is called if it exists. You must do cleanup stuff here, like closing all open file descriptors or removing menu entries (see http://xchat.org/docs/plugin20.html#menu). There is no need to unhook explicitly, as it's automa(t|g)ically done when unloading a script/the plugin.

Manually unloading of single scripts is supported with /UNLOAD script.lua.

All constants and functions of the xchat API are located in the table xchat.

One line lua scripts can be executed with the /LUA command, like in this (more or less usless ;-)) example:

 /LUA xchat.printf("my nick is %s", tostring(xchat.get_info("nick")))

This line is executed in it's own lua state. All xchat.hook_* are disabled for the /LUA command.

Download

In case you haven't done it already, you can get the latest version from here (0.7.1). Earlier versions are available via SVN from http://svn.ankh-morp.org:8080/xc_lua/

Predefined constants

Return values for callback functions

xchat.EAT_NONE

pass event along

xchat.EAT_XCHAT

don't let xchat see this event

xchat.EAT_PLUGIN

don't let other plugins see this event

xchat.EAT_ALL

don't let xchat and other plugins see this event

Priority of the event hook

xchat.PRI_HIGHEST
xchat.PRI_HIGH
xchat.PRI_NORM
xchat.PRI_LOW
xchat.PRI_LOWEST

Stripping color codes

for xchat.strip()

xchat.STRIP_COLOR

strip just colors

xchat.STRIP_ATTR

strip just attributes

xchat.STRIP_ALL

strip both

Setting tab color

for xchat.commandf("GUI COLOR %d", xchat.TAB_NEWMSG)

xchat.TAB_DEFAULT

set tab color to default color

xchat.TAB_NEWDATA

set tab color to "new data arrived"

xchat.TAB_NEWMSG

set tab color to "new messages"

xchat.TAB_HILIGHT

set tab color to "highlighted messages available"

Misc

xchat.ARCH

"Windows" or "Unix" ... depending on system :)

X-Chat API functions

xchat.hook_command()

Usage: xchat.hook_command(name, func_name, prio, help_str, data)

description

Adds a new /command. This allows your program to handle commands entered at the input box. To capture text without a / at the start (non-commands), you may hook a special name of "". i.e xchat.hook_command("", ...)

Starting from version 2.6.8, commands hooked that begin with a period (.) will be hidden in /HELP and /HELP -l.

return values

true... or false if something went wrong while registering hook

arguments
name (string)

the name of the new command

func_name (string)

the lua function to be called when command is entered

prio (number)

use one of the xchat.PRI_*, or nil for xchat.PRI_NORM

help_str (string)

help for the new command... use nil for no help

data (table)

table with strings, numbers and booleans, which will be passed to func_name as last argument.

xchat.hook_server()

Usage: xchat.hook_server(name, func_name, prio, data)

description

Registers a function to be called when a certain server event occurs. You can use this to trap PRIVMSG, NOTICE, PART, a server numeric etc... If you want to hook every line that comes from the IRC server, you may use the special name of RAW LINE.

return values

true... or false if something went wrong while registering

arguments
name (string)

the event name / numeric (yes, also as a string)

func_name (string)

the function to be called, when the event happens

prio (number)

one of the xchat.PRI_* constants (or nil for xchat.PRI_NORM)

data (table)

see xchat.hook_command()

Both (xchat.hook_command() and xchat.hook_server()) callback functions are called like

func_name()

Usage: func_name(word, word_eol, data)

description

your previously hooked callback function for hook_command() and hook_server(), you must return one of the xchat.EAT_* constants

return values

none

arguments
word (table)

the incoming line split into words (max 32)

word_eol (table)

for both see http://xchat.org/docs/plugin20.html#word

data (table)

the data table you passed to the hook_command() / hook_server() as 5th/4th arg

xchat.hook_print()

Usage: xchat.hook_print(name, func_name, prio, data)

description

Registers a function to trap any print events. The event names may be any available in the Advanced > Text Events window. There are also some extra special events you may hook using this function, see: http://xchat.org/docs/plugin20.html#xchat_hook_print

return values

true... or false if something went wrong while registering hook

arguments
name (string)

the name of the new command

func_name (string)

the lua function to be called when command is entered

prio (number)

use one of the xchat.PRI_*, or nil for xchat.PRI_NORM

data (table)

table with strings, numbers and booleans, which will be passed to func_name as last argument.

The callback function for this hook is called like

func_name()

Usage: func_name(word, data)

description

your previously hooked callback function for hook_print(), you must return one of the xchat.EAT_* constants

return values

none

arguments
word (table)

the incoming line split into words (max 32) (see http://xchat.org/docs/plugin20.html#word)

data (table)

the data table you passed to the hook_print() as 4th arg

xchat.hook_timer()

Usage: xchat.hook_timer(timeout, func_name, data)

description

Registers a function to be called every timeout milliseconds.

return values

the timer name (string) or false if something went wrong while setting up the timer. Use this timer name to unhook the timer (or return false from the timer func, see below).

arguments
timeout (number)

Timeout in milliseconds (1000 is 1 second).

func_name (string)

Callback function. This will be called every timeout milliseconds.

data (table)

see xchat.hook_command()

The callback for hook_timer() is called like

func_name()

Usage: func_name(data)

description

the callback function for the registered timer hook, return true to keep this timer going, false to stop it

return values

none

arguments
data (table)

the table you gave the hook_timer() as last argument

xchat.unhook()

Usage: xchat.unhook(name)

description

unhooks a previously hooked hook

return values

true if the hook existed, else false

arguments
name (string)

name of a registered hook (e.g. with xchat.hook_command("whois", ... ) you would unhook whois ... or the timer name returned from a xchat.hook_timer()).

xchat.event()

Usage: xchat.event()

description

returns the name of the currently running hook, i.e. the name of what you hooked with xchat.hook_server() or xchat.hook_print()

return values

the name of the hook

arguments
none

xchat.command()

Usage: xchat.command(command)

description

executes a command as if it were typed in xchat's input box.

return values

none

arguments
command (string)

command to execute, without the forward slash (/).

xchat.commandf()

Usage: xchat.commandf(fmt, arg1, ...)

description

executes a command as if it were typed in xchat's input box.... with string formatting. This command is implemented as

 function xchat.commandf(...)
     xchat.command(string.format(unpack(arg)))
 end
return values

none

arguments

like string.format()

xchat.print()

Usage: xchat.print(text)

description

Prints some text to the current tab/window.

return values

none

arguments
text (string)

the text to print

xchat.printf()

Usage: xchat.printf(fmt, arg1, ...)

description

Prints some formatted text to the current tab/window. This is implemented as

 function xchat.printf(...)
     xchat.print(string.format(unpack(arg)))
 end
return values

none

arguments

like string.format()

xchat.emit_print()

Usage: xchat.emit_print(event, text, [text2, ...])

description

Generates a print event. This can be any event found in the Preferences > Advanced > Text Events window. The number of parameters after the event must not be more than four (4), else you will raise a lua error.

Special care should be taken when calling this function inside a print callback (from xchat.hook_print()), as not to cause endless recursion.

return values

true on success, false on error

arguments
event (string)

the event name from the Preferences > Advanced > Text Events window

text (string)
text2 (string)

(string(s)): parameters for the given event

xchat.send_modes()

Usage: xchat.send_modes(targets, sign, mode [, modes_per_line])

description

Sends a number of channel mode changes to the current channel. For example, you can Op a whole group of people in one go. It may send multiple MODE lines if the request doesn't fit on one. Pass 0 for modes_per_line to use the current server's maximum possible (this is also the default).

This function should only be called while in a channel context.

return values

none

arguments

NOTE: the order of the arguments is not the same as in the C or perl API...

targets (table)

list of names (strings)

sign (string)

mode sign, i.e. + or -, only the first char of this is used (it is checked if it is really + or -)

mode (string)

mode char, i.e. o for opping, only the first char of this is used (checked if it's an ASCII char)

modes_per_line (number)

optional number of modes per line

xchat.find_context()

Usage: xchat.find_context(srv, chan)

description

Finds a context based on a channel and servername. If servname is nil, it finds any channel (or query) by the given name. If channel is nil, it finds the front-most tab/window of the given servname. If nil is given for both arguments, the currently focused tab/window will be returned.

Changed in 2.6.1. If servname is nil, it finds the channel (or query) by the given name in the same server group as the current context. If that doesn't exists then find any by the given name.

return values

context number (do not modify)

arguments
srv (string or nil)

server name

chan (string or nil)

channel / query name

xchat.get_context()

Usage: xchat.get_context()

description

Returns the current context for your plugin. You can use this later with xchat.set_context().

return values

context number ... do not modifiy

arguments

none

xchat.get_info()

Usage: xchat.get_info(id)

description

Returns information based on your current context.

return values

the requested string or nil on error

arguments
id (string)

the wanted information, for known values see http://xchat.org/docs/plugin20.html#xchat_get_info.

xchat.get_prefs(name)

description

Provides xchat's setting information (that which is available through the /set command). A few extra bits of information are available that don't appear in the /set list, currently they are:

state_cursor

Current input-box cursor position (characters, not bytes). Since 2.4.2.

id

Unique server id. Since 2.6.1.

return values

returns the string/number/boolean for the given config var or nil on error

arguments
name (string)

the wanted setting's name

xchat.set_context()

Usage: xchat.set_context(ctx)

description

Changes your current context to the one given.

return values

true or false

arguments
ctx (number)

the context (e.g. from xchat.get_context(), xchat.find_context())

xchat.nickcmp()

Usage: xchat.nickcmp(name1, name2)

description

Performs a nick name comparision, based on the current server connection. This might be a RFC1459 compliant string compare, or plain ascii (in the case of DALNet). Use this to compare channels and nicknames. The function works the same way as strcasecmp.

return values

number less than, equal to, or greater than zero if name1 is found, respectively, to be less than, to match, or be greater than name2.

arguments
name1 (string)

nick or channel name

name2 (string)

nick or channel name

xchat.strip()

Usage: xchat.strip(text, flags)

description

strips mIRC color codes and/or text attributes (bold, underlined etc) from the given string. This is implemented in lua for compatibility with older xchat versions (<= 2.4.1):

 function xchat.strip(str, flags)
     if flags == nil then
         flags = xchat.STRIP_ALL
     end
     local bits = xchat.bits(flags)
     if bits[1] then
         str = string.gsub(
                 string.gsub(str, "\3%d%d?,%d%d?", ""), 
             "\3%d%d?", "")
     end
     if bits[2] then
         -- bold, beep, reset, reverse, underline
         str = string.gsub(str, "[\2\7\15\22\31]", "")
     end
     return str
 end
return values

a "cleaned" string or nil on error

arguments
text (string)

string to strip

flags (number)

optional, defaults to xchat.STRIP_ALL: what to strip, use the xchat.STRIP_* values for this.

xchat.list_fields()

Usage: xchat.list_fields(name)

description

returns the possible keys for name as table

return values

a table, see above.

arguments
name (string)

name of the wanted list (channels, dcc, ignore, notify, users)

xchat.list_get()

Usage: xchat.list_get(name)

description

see http://xchat.org/docs/plugin20.html#lists

time_t values are stored as number. Example:

  os.date("%Y-%m-%d, %H:%M:%S", time_t_value)

pointers (channel -> context) as number... untested if this works, but should do the same way as xchat.get_context().

return values

a table with tables with all keys=Name, value=(Type)... or nil on error

arguments
name (string)

the wanted list, same valid as for xchat.list_fields(). Use

 chaninfo = xchat.list_get("channels")
 if chaninfo ~= nil then
     table.foreach(chaninfo,
         function(i, list)
             table.foreach(list,
                 function(k, v)
                     xchat.printf("k=%s, v=%s", k, v)
                 end
             )
         end
     )
 end

xchat.gettext()

Usage: xchat.gettext(msgid)

description

gives access to xchat's gettext. It looks up msgid in the message catalogs and returns the translated string according to the current locale.

Un*x only: If compiled without LXC_XCHAT_GETTEXT defined: xchat.gettext(msgid [,txtdomain]), where txtdomain is the catalog you want ot get the msg from (e.g. "libc").

return values

string with the translated msgid

arguments
msgid (string)

the string to be translated

Un*x only: If compiled without LXC_XCHAT_GETTEXT defined: txtdomain (string): the text domain to fetch the string from, see dgettext(3)

xchat.bits()

Usage: xchat.bits(flags)

description

returns a table of booleans if the bit at index is set Note: bits start counting at 0, so if you want bit 4, index is 5, for bit 0 index is 1, ...

return values

table of booleans

arguments
flags (number)

... from flags of xchat.list_get() -> channels, ignore, notify

Usage: see above in xchat.strip() or

 function has_whox(context)
     local chaninfo = xchat.list_get("channels")
     if chaninfo ~= nil then
         return table.foreach(chaninfo,
             function(i, list)
                 if context == list.context then
                     -- 'Has WHOX' is bit 4, which is the 5th bit
                     -- counting from 0
                     return xchat.bits(list.flags)[5]
                 end
             end
         )
     end
     return false
 end
 
 if has_whox(xchat.get_context()) then
     ...
 else
     ...

Compiling

NOTE: will wonly work with xchat >= 2.0.9, just tested on 2.6.8.

On debian Linux install

liblua50, liblua50-dev,
liblualib50, liblualib50-dev
lua50

and compile with

 gcc $( lua-config --include ) $( lua-config --libs --extralibs ) \
    -Wl,--export-dynamic -Wall -O1 -shared -fPIC \
    -I/path/to/your/xchat-plugin.h/dir \
    -o lua.so lua.c

...else:

 gcc -L/path/to/your/lualibs -llua50 -llualib50 -lm \
    -I/path/to/your/lua/includes/ \
    -Wl,--export-dynamic -Wall -O1 -shared -fPIC \
    -I/path/to/your/xchat-plugin.h/dir \
    -o lua.so lua.c

lua5.1 (debian etch, lenny):

 gcc -I/usr/include/lua5.1 -L/usr/lib  -l"lua5.1" \
    -Wl,--export-dynamic -Wall -O1 -shared -g -fPIC \
    -I/path/to/your/xchat-plugin.h/dir \
    -o lua.so lua.c

Finally, to install: copy the lua.so to the dir, where `xchat -p` wants it ;-)