Completion
* commands completion
* common hooks lua interface
* complete separation of features into modules
--- a/TODO Tue Feb 24 19:42:48 2009 +0200
+++ b/TODO Wed Feb 25 22:58:34 2009 +0200
@@ -3,7 +3,7 @@
finish roster list information
settings list?
non-setting settings?
-set package searching paths?
+mcabber_config_file uses option to set dir?
do uninitialization of commands and features with objects?
-debug module reloading issue
+help system accessors (needs major rewrite and planning)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/beep.lua Wed Feb 25 22:58:34 2009 +0200
@@ -0,0 +1,23 @@
+-- BEEPING ON ALL MESSAGES
+
+beep_enable = false
+
+-- FIXME: add generic cid generation routine
+boolean_cid = main.command ( 'beep',
+ function ( args )
+ local enable = yesno ( args )
+ if enable ~= nil then
+ beep_enable = enable
+ end
+ if beep_enable then
+ hooks_d['hook-message-in'].beep = main.beep
+ print ( "Beep on message is enabled" )
+ else
+ hooks_d['hook-message-in'].beep = nil
+ print ( "Beep on message is disabled" )
+ end
+ end, { 'enable', 'disable', 'yes', 'no', 'true', 'false', 'on', 'off' } )
+
+commands_help['beep'] = "[enable|disable|on|off|yes|no|true|false]\n\nEnables or disables beeping on all messages.\nIf state is omitted, prints current state."
+
+-- vim: se ts=4: --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/jobs.lua Wed Feb 25 22:58:34 2009 +0200
@@ -0,0 +1,73 @@
+--- JOBS
+
+delayed_jobs = {}
+
+-- may fail
+dopath 'saved_jobs.lua'
+
+function save_jobs ()
+ local h = io.open ( main.config_file ( 'saved_jobs.lua' ), "w" )
+ if not h then
+ print ( 'Cannot open jobs file for writing!' )
+ return
+ end
+ h:write ( "-- This is autogenerated file, do not edit it manually\n\ndelayed_jobs = {\n" );
+ for jid, more in pairs ( delayed_jobs ) do
+ h:write ( string.format ( "\t[%q] = {\n", jid ) )
+ for status, action in pairs ( more ) do
+ if action then -- remove fired jobs
+ h:write ( string.format ( "\t\t[%q] = %q,\n", status, action ) )
+ end
+ end
+ h:write ( "\t},\n" )
+ end
+ h:write ( "}\n" )
+ h:close ()
+end
+
+main.command ( 'delay',
+ function ( args )
+ args = parse_args ( args )
+ local who
+ if args.t then
+ who = args.t
+ args.t = nil
+ else
+ who = main.current_buddy ()
+ end
+ local stat = args[1]
+ args[1] = nil
+ delayed_jobs[who] = { }
+ delayed_jobs[who][stat] = 'say_to -q ' .. who .. ' ' .. rebuild_args_string ( args )
+ end )
+
+main.command ( 'job',
+ function ( args )
+ local action, jid, stat = args:match ( "(%w+)%s+(%w+)%s+(%w)" )
+ if action == 'del' then
+ delayed_jobs[jid][stat] = nil
+ else
+ print ( 'List of jobs:' )
+ for jid, jobs in pairs ( delayed_jobs ) do
+ for status, job in pairs ( jobs ) do
+ print ( ' - ' .. jid .. ' -> ' .. status .. ': ' .. job )
+ end
+ end
+ end
+ end, { "del" } )
+
+commands_help['delay'] = "[-t target_jid] status_letter message\n\nDelays sending a message to target jid (or current buddy) until it switches to specified status."
+commands_help['job'] = "[del jid status_letter]\n\nLists available jobs or deletes specified one."
+
+hooks_d['hook-status-change'].jobs =
+ function ( args )
+ if delayed_jobs[args.jid] and delayed_jobs[args.jid][args.new_status] then
+ main.run ( delayed_jobs[args.jid][args.new_status] )
+ delayed_jobs[args.jid][args.new_status] = nil
+ end
+ end
+
+hooks_d['hook-quit'].jobs = save_jobs
+
+
+-- vim: se ts=4: --
--- a/examples/marking.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/marking.lua Wed Feb 25 22:58:34 2009 +0200
@@ -60,8 +60,12 @@
print ( ' - ' .. jid )
end )
end
- end )
+ end, { 'clear', 'do' } )
commands_help['marked'] = "[clear | do mcabber_command]\n\nOperates on marked buddies. Without arguments prints list of marked jids.\nCommand should contain %s in place, where jid should be inserted."
+-- Ins
+-- TODO: check if ins already bound
+main.run ( 'bind 331 = lua mark_toggle ()' )
+
-- vim: se ts=4: --
--- a/examples/mcabberrc.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/mcabberrc.lua Wed Feb 25 22:58:34 2009 +0200
@@ -13,6 +13,7 @@
XEP-0077 In-Band Registration (only registration, but with data forms too)
XEP-0146 Remote commands requests
Jobs (actions, fired when some event occurs, now in one file, updated on exit)
+Room nicks completion
MPD status polling (can be turned off)
Beep on all messages, even on chatroom ones
Url saving to file (for urlview)
@@ -66,23 +67,8 @@
require 'lm'
--- OPTIONS, COMMON SUPPORT ROUTINES
-url_file = main.config_file ( 'urls.log' )
-transport_jids = { 'icq.jabber.kiev.ua', 'mrim.unixzone.org.ua' }
-beep_enable = false
-
--- XXX: to C?
-char2status = {
- f = 'free',
- o = 'online',
- a = 'away',
- d = 'dnd',
- n = 'notavail',
- i = 'invisible',
- ['_'] = 'offline',
- ['?'] = 'message',
-}
+-- COMMON SUPPORT ROUTINES
function shell_escape ( str )
if str then
@@ -178,6 +164,36 @@
return ret
end
+-- FIXME: get rid of this
+function rebuild_args_string ( tab )
+ local flags = nil
+ local args = nil
+ for k, v in pairs (tab) do
+ if type (k) == 'number' then
+ if args then
+ args = args .. ' ' .. v
+ else
+ args = v
+ end
+ else
+ if flags then
+ flags = flags .. ' ' .. '-' .. k .. ' ' .. v
+ else
+ flags = '-' .. k .. ' ' .. v
+ end
+ end
+ end
+ if flags and args then
+ return flags .. ' ' .. args
+ elseif flags then
+ return flags
+ elseif args then
+ return args
+ else
+ return ''
+ end
+end
+
-- COMMANDS
-- Help strings should not contain command, only arguments. This is necessary to support soft aliases.
@@ -199,20 +215,7 @@
main.command ( 's',
function ( args )
main.run ( ('status %s %s'):format ( args, mpd_getstatus () ) )
- end )
-main.command ( 'beep',
- function ( args )
- local enable = yesno ( args )
- if enable == nil then
- if beep_enable then
- print ( "Beep on message is enabled" )
- else
- print ( "Beep on message is disabled" )
- end
- else
- beep_enable = enable
- end
- end )
+ end, 0x10 )
main.command ( 'cmd',
function ( args )
local to = main.current_buddy ()
@@ -240,7 +243,7 @@
print ( list:sub ( 1, -3 ) )
print ( "For built-in mcabber commands see /help" )
end
- end )
+ end, 0x1 )
main.command ( 'reload',
function ( args )
dofile ( main.config_file ( 'mcabberrc.lua' ) )
@@ -258,6 +261,7 @@
print ( "Resource count: " .. count )
end )
+-- commands to allow leading smileys
for k, arg in ipairs ( { ')', '/', '(', 'D', '-/', 'S', '1', ']', '[' } ) do
main.command ( arg,
function ( args )
@@ -265,6 +269,60 @@
end )
end
+-- HOOKS
+
+hooks_d = {
+ ['hook-message-in'] = { },
+ ['hook-message-out'] = { },
+ ['hook-status-change'] = { },
+ ['hook-my-status-change'] = { },
+ ['hook-post-connect'] = { },
+ ['hook-pre-disconnect'] = { },
+ ['hook-start'] = { },
+ ['hook-quit'] = { },
+}
+
+-- hook:
+-- - hook-message-in
+-- jid
+-- groupchat
+-- message
+-- - hook-message-out
+-- jid
+-- message
+-- - hook-status-change
+-- jid
+-- resource
+-- new_status
+-- old_status
+-- message
+-- - hook-my-status-change
+-- new_status
+-- message
+-- - hook-post-connect
+-- - hook-pre-disconnect
+-- - hook-start
+-- - hook-quit
+function hook_handler ( args )
+ for mod, cb in pairs ( hooks_d[args.hook] ) do
+ if cb then
+ cb ( args )
+ end
+ end
+end
+
+-- SAVING URLS TO FILE
+
+dopath 'urls'
+
+-- TRANSPORTED BUDDIES AVAILABILITY INDICATION
+
+dopath 'transports'
+
+-- BEEPING ON ALL MESSAGES
+
+dopath 'beep'
+
-- MARKING
dopath 'marking'
@@ -295,171 +353,10 @@
-- JOBS
-delayed_jobs = {}
-
-dopath 'jobs.lua'
-
-function save_jobs ()
- local h = io.open ( main.config_file ( 'jobs.lua' ), "w" )
- if not h then
- print ( 'Cannot open jobs file for writing!' )
- return
- end
- h:write ( "-- This is autogenerated file, do not edit it manually\n\ndelayed_jobs = {\n" );
- for jid, more in pairs ( delayed_jobs ) do
- h:write ( string.format ( "\t[%q] = {\n", jid ) )
- for status, action in pairs ( more ) do
- if action then -- remove fired jobs
- h:write ( string.format ( "\t\t[%q] = %q,\n", status, action ) )
- end
- end
- h:write ( "\t},\n" )
- end
- h:write ( "}\n" )
- h:close ()
-end
-
-main.command ( 'delay',
- function ( args )
- args = parse_args ( args )
- local who
- if args.t then
- who = args.t
- args.t = nil
- else
- who = main.current_buddy ()
- end
- local stat = args[1]
- args[1] = nil
- delayed_jobs[who] = { }
- delayed_jobs[who][stat] =
- function ()
- main.run ( 'say_to -q ' .. who .. ' ' .. rebuild_args_string ( args ) )
- end
- end )
-
-main.command ( 'job',
- function ( args )
- local action, jid, stat = args:match ( "(%w+)%s+(%w+)%s+(%w)" )
- if action == 'del' then
- delayed_jobs[jid][stat] = nil
- else
- print ( 'List of jobs:' )
- for jid, jobs in pairs ( delayed_jobs ) do
- for status in pairs ( jobs ) do
- print ( ' - ' .. jid .. ' -> ' .. status )
- end
- end
- end
- end )
-
-commands_help['delay'] = "[-t target_jid] status_letter message\n\nDelays sending a message to target jid (or current buddy) until it switches to specified status."
-commands_help['job'] = "[del jid status_letter]\n\nLists available jobs or deletes specified one."
-
--- HOOKS
-
-ibb_handler_registered = false
-
--- Hard hooks, implemented in C
+dopath 'jobs'
--- hook:
--- - hook-message-in
--- jid
--- groupchat
--- message
--- - hook-message-out
--- jid
--- message
--- - hook-status-change
--- jid
--- resource
--- new_status
--- old_status
--- message
--- - hook-my-status-change
--- new_status
--- message
--- - hook-post-connect
--- - hook-pre-disconnect
--- - hook-start
--- - hook-quit
-function hook_handler ( args )
- if args.hook == 'hook-message-in' then
-
- -- beep on ALL messages, no matter, is it chat or something else.
- if beep_enable then
- main.beep ()
- end
-
- -- save urls to file from where urlview can get them...
- for url in args.message:gmatch ( "https?://[%w%p]+" ) do
- fd = io.open ( url_file, "a" )
- if fd then
- fd:write ( url .. "\n" )
- fd:close ()
- else
- print 'Cannot open urls log file'
- end
- end
-
- elseif args.hook == 'hook-status-change' then
+-- ROOM NICK COMPLETION
- -- delayed actions
- if delayed_jobs[args.jid] and delayed_jobs[args.jid][args.new_status] then
- delayed_jobs[args.jid][args.new_status] ()
- delayed_jobs[args.jid][args.new_status] = nil
- end
-
- -- transported buddies availability indication
- for k, jid in pairs ( transport_jids ) do
- if args.jid == jid then
- if args.new_status == '_' then
- main.run ( ("color roster * *@%s red"):format ( jid ) )
- main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
- else
- main.run ( ("color roster * *@%s white"):format ( jid ) )
- main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
- end
- end
- end
-
- elseif args.hook == 'hook-post-connect' then
-
- if mpd_enabled then
- mpd_callback ()
- end
-
- -- FIXME
- if not ibb_handler_registered then
- lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq', 'normal' )
- main.add_feature ( 'http://jabber.org/protocol/ibb' )
- ibb_handler_registered = true
- end
-
- elseif args.hook == 'hook-start' then
-
- -- XXX: for some reason, after module reloading, this is not working properly.
- for k, jid in pairs ( transport_jids ) do
- if not online ( jid ) then
- main.run ( ("color roster * *@%s red"):format ( jid ) )
- main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
- else
- main.run ( ("color roster * *@%s white"):format ( jid ) )
- main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
- end
- end
-
- elseif args.hook == 'hook-quit' then
-
- save_jobs ()
-
- -- FIXME
- if ibb_handler_registered then
- lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq' )
- end
-
- end
-end
-
+dopath 'room_priv'
-- The End -- vim: se ts=4: --
--- a/examples/mpd.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/mpd.lua Wed Feb 25 22:58:34 2009 +0200
@@ -103,6 +103,18 @@
mpd_enabled = false
+-- XXX: to C?
+char2status = {
+ f = 'free',
+ o = 'online',
+ a = 'away',
+ d = 'dnd',
+ n = 'notavail',
+ i = 'invisible',
+ ['_'] = 'offline',
+ ['?'] = 'message',
+}
+
function mpd_getstatus ()
if not mpd_enabled then
return ''
@@ -188,8 +200,16 @@
else
enable_mpd ( enable )
end
- end )
+ end, boolean_cid )
commands_help['mpd'] = "[enable|disable|on|off|yes|no|true|false]\n\nSets state of mpd string in your status.\nIf state is omitted, prints current state."
+-- XXX: why post-connect, why not start?
+hooks_d['hook-post-connect'].mpd =
+ function ( args )
+ if mpd_enabled then
+ mpd_callback ()
+ end
+ end
+
-- vim: se ts=4: --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/room_priv.lua Wed Feb 25 22:58:34 2009 +0200
@@ -0,0 +1,35 @@
+
+-- ROOM NICK COMPLETION
+
+room_cid = main.command ( 'priv',
+ function ( args )
+ main.run ( 'room privmsg ' .. args )
+ end, {} )
+
+commands_help['priv'] = "nick message\n\nSends private message to room participant. Nick completion available! ;)"
+
+registered_nicks = {}
+
+function register_nicks ()
+ for k, nick in pairs ( registered_nicks ) do
+ main.del_completion ( room_cid, nick )
+ end
+ local buddy = main.current_buddy ()
+ if buddy then
+ local info = main.buddy_info ( buddy )
+ if info then
+ registered_nicks = { }
+ if info.type == 'room' then
+ for nick, k in pairs ( info.resources ) do
+ main.add_completion ( room_cid, nick )
+ table.insert ( registered_nicks, nick )
+ end
+ end
+ end
+ end
+end
+
+main.run ( 'bind 338 = lua main.run ( "roster down" ); register_nicks ()' )
+main.run ( 'bind 339 = lua main.run ( "roster up" ); register_nicks ()' )
+
+-- vim: se ts=4: --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/transports.lua Wed Feb 25 22:58:34 2009 +0200
@@ -0,0 +1,33 @@
+-- TRANSPORTED BUDDIES AVAILABILITY INDICATION
+
+transport_jids = { 'icq.jabber.kiev.ua', 'mrim.unixzone.org.ua' }
+
+hooks_d['hook-status-change'].transports =
+ function ( args )
+ for k, jid in pairs ( transport_jids ) do
+ if args.jid == jid then
+ if args.new_status == '_' then
+ main.run ( ("color roster * *@%s red"):format ( jid ) )
+ main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
+ else
+ main.run ( ("color roster * *@%s white"):format ( jid ) )
+ main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
+ end
+ end
+ end
+ end
+
+hooks_d['hook-start'].transports =
+ function ( args )
+ for k, jid in pairs ( transport_jids ) do
+ if not online ( jid ) then
+ main.run ( ("color roster * *@%s red"):format ( jid ) )
+ main.run ( ("color roster dn_? *@%s red"):format ( jid ) )
+ else
+ main.run ( ("color roster * *@%s white"):format ( jid ) )
+ main.run ( ("color roster dn_? *@%s brightblack"):format ( jid ) )
+ end
+ end
+ end
+
+-- vim: se ts=4: --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/urls.lua Wed Feb 25 22:58:34 2009 +0200
@@ -0,0 +1,18 @@
+-- SAVING URLS TO FILE
+
+url_file = main.config_file ( 'urls.log' )
+
+hooks_d['hook-message-in'].urls =
+ function ( args )
+ for url in args.message:gmatch ( "https?://[%w%p]+" ) do
+ fd = io.open ( url_file, "a" )
+ if fd then
+ fd:write ( url .. "\n" )
+ fd:close ()
+ else
+ print 'Cannot open urls log file'
+ end
+ end
+ end
+
+-- vim: se ts=4: --
--- a/examples/xep0004.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/xep0004.lua Wed Feb 25 22:58:34 2009 +0200
@@ -1,5 +1,12 @@
forms = { }
+form_cid = 0
+
+function insert_form ( form )
+ table.insert ( forms, form )
+ main.add_completion ( form_cid, tostring(#forms) )
+ return #forms
+end
-- expects lm node x = { xmlns = 'jabber:x:data', type = 'form', ... }
-- returns form index in forms table, you can do whatever you want to upper level table, except exp and val fields.
@@ -77,8 +84,7 @@
end
field = field:next ()
end
- table.insert ( forms, form )
- return #forms
+ return insert_form ( form )
end
function form_set ( id, name, value )
@@ -99,7 +105,7 @@
end
end
-main.command ( 'form',
+form_cid = main.command ( 'form',
function ( args )
args = parse_args ( args )
local action = args[1]
@@ -133,6 +139,7 @@
end
elseif action == 'del' then
forms[tonumber(args[2])] = nil
+ main.del_completion ( form_cid, tostring(args[2]) )
elseif action == 'send' then
local form = forms[tonumber(args[2])]
if form then
@@ -144,7 +151,7 @@
print ( ' - ' .. tostring(id) .. ' ' .. form.title .. ' [' .. ( form.status or 'unknown' ) .. ']' )
end
end
- end )
+ end, { "del", "send" } )
commands_help['form'] = "[del form_id | send form_id | form_id [field_name {clear | [set] value}]\n\nWith bare form id prints info on that form.\nWith field name sets or clears field value. Set subcommand is optional, just to allow values, starting with 'clear'.\nWithout arguments prints form list."
--- a/examples/xep0047.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/xep0047.lua Wed Feb 25 22:58:34 2009 +0200
@@ -195,8 +195,22 @@
print ( sid .. ': ' .. ( data.name or '(not set)' ) .. ' [' .. data.status .. ']' )
end
end
- end )
+ end, { "send", "accept", "reject", "del" } )
commands_help['ibb'] = "[[-t target_jid] send filename | accept sid filename | reject sid filename | del sid]\n\nRequests, accepts or rejects sending file via in-band bytestream."
+hooks_d['hook-post-connect'].xep0047 =
+ function ( args )
+ lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq', 'normal' )
+ main.add_feature ( 'http://jabber.org/protocol/ibb' )
+ ibb_handler_registered = true
+ hooks_d['hook-post-connect'].xep0047 = nil
+ hooks_d['hook-quit'].xep0047 =
+ function ( args )
+ if ibb_handler_registered then
+ lm.connection.bless( main.connection () ):handler ( ibb_incoming_iq_handler, 'iq' )
+ end
+ end
+ end
+
-- vim: se ts=4: --
--- a/examples/xep0077.lua Tue Feb 24 19:42:48 2009 +0200
+++ b/examples/xep0077.lua Wed Feb 25 22:58:34 2009 +0200
@@ -20,8 +20,7 @@
end
field = field:next ()
end
- table.insert ( forms, form )
- return #forms
+ return insert_form ( form )
end
function format_iq_register ( fields )
@@ -146,13 +145,13 @@
main.command ( 'register',
function ( args )
local who
- if args[1] then
- who = rebuild_args_string ( args )
+ if args and args ~= '' then
+ who = args
else
who = full_current_jid ()
end
register_to ( who )
- end )
+ end, 0x2 )
main.command ( 'cancel',
function ( args )
@@ -163,7 +162,7 @@
who = full_current_jid ()
end
unregister_from ( who )
- end )
+ end, 0x2 )
commands_help['register'] = "[jid]\n\nSends registration request to jid (or current buddy). You, probably, then will need to fill and send some form."
commands_help['cancel'] = "[jid]\n\nSends registration cancellation request to jid (or current buddy). May require a form filling."
--- a/main.c Tue Feb 24 19:42:48 2009 +0200
+++ b/main.c Wed Feb 25 22:58:34 2009 +0200
@@ -20,6 +20,7 @@
#include "utils.h" // from_utf8, jidtodisp
#include "hooks.h" // hk_add_handler, hk_del_handler
#include "settings.h" // settings_set, settings_del, settings_get
+#include "compl.h" // compl_new_category, compl_add_category_word, compl_del_category_word
// global lua state object, necessary for uninitialization function
@@ -341,23 +342,69 @@
}
}
+/// main.add_completion
+/// Adds word to a completion list.
+/// A: integer (completion group id), string (word)
+static int lua_main_add_completion (lua_State *L)
+{
+ guint cid = luaL_checkinteger (L, 1);
+ const char *word = luaL_checkstring (L, 2);
+ compl_add_category_word (cid, word);
+}
+
+/// main.del_completion
+/// Removes word from a completion list.
+/// A: integer (completion group id), string (word)
+static int lua_main_del_completion (lua_State *L)
+{
+ guint cid = luaL_checkinteger (L, 1);
+ const char *word = luaL_checkstring (L, 2);
+ compl_del_category_word (cid, word);
+}
+
/// main.command
/// Associates or breaks association between mcabber command name and lua function.
/// To unregister command omit function argument.
-/// A: string (command name), command function (optional)
+/// If you specify a third argument, table (even empty), function will return completion group id or nothing.
+/// You can also specify an integer instead of table, then no new id will be registered.
+/// Note, that for now there are no way to unregister completion group, so, resources can be exausted easily.
+/// Also note, that it ignores keys in a completion table.
+/// A: string (command name), command function (optional), table (completions, optional)/integer (comletion group id, optional)
+/// R: integer (completion group id, optional) or nil
static int lua_main_command (lua_State *L)
{
const char *name = luaL_checkstring (L, 1);
lua_command_callback_t *cb;
if (lua_gettop (L) > 1) { // Register
+ guint cid = 0;
luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
+ if (lua_gettop (L) > 2) { // Completions provided
+ if (lua_type (L, 3) == LUA_TTABLE) {
+ cid = compl_new_category ();
+ if (cid) {
+ lua_pushnil (L);
+ while (lua_next (L, 3)) {
+ compl_add_category_word (cid, luaL_checkstring (L, -1));
+ lua_pop (L, 1);
+ }
+ }
+ } else
+ cid = luaL_checkinteger (L, 3);
+ }
+
cb = luaL_malloc (L, sizeof (lua_command_callback_t));
+ lua_pushvalue (L, 2);
cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
cb->L = L;
- cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb);
+ cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb);
lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name));
+
+ if (cid) {
+ lua_pushinteger (L, cid);
+ return 1;
+ }
} else { // Unregister
GSList *el = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) g_strcmp0);
@@ -546,7 +593,7 @@
if (lua_pcall (L, 0, 0, 0)) {
scr_LogPrint (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(lua, -1));
- lua_pop (L, -1);
+ lua_pop (L, 1);
return;
}
}
@@ -590,6 +637,8 @@
{ "option", lua_main_option },
{ "add_feature", lua_main_add_feature },
{ "del_feature", lua_main_del_feature },
+ { "add_completion",lua_main_add_completion},
+ { "del_completion",lua_main_del_completion},
{ "command", lua_main_command },
{ "print_info", lua_main_print_info },
{ "beep", lua_main_beep },