Commands and init improvements
authorMyhailo Danylenko <isbear@ukrpost.net>
Tue, 24 Feb 2009 19:42:48 +0200
changeset 7 eb6d89bf1fbf
parent 6 90dceae3ed1f
child 8 fc9060b9b7cc
Commands and init improvements * 'lua' command in C * add_command and del_command merged * de-hardcoded initialization file name
examples/lua.rc
examples/marking.lua
examples/mcabberrc.lua
examples/mpd.lua
examples/xep0004.lua
examples/xep0030.lua
examples/xep0047.lua
examples/xep0077.lua
examples/xep0146.lua
main.c
--- a/examples/lua.rc	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/lua.rc	Tue Feb 24 19:42:48 2009 +0200
@@ -1,5 +1,8 @@
 
 # lua function name to be called on hooks invocation
 set lua_hook_function = hook_handler
+set lua_init_filename = ~/.mcabber/mcabberrc.lua
 load mcabber-lua
+# :(
+#lua dofile 'mcabberrc'
 
--- a/examples/marking.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/marking.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -42,7 +42,7 @@
 	marked_jids = {}
 end
 
-main.add_command ( 'marked',
+main.command ( 'marked',
 	function ( args )
 		local cmd = args:match ( "^%s*(%w+)" )
 		if cmd == 'clear' then
--- a/examples/mcabberrc.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/mcabberrc.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -55,8 +55,7 @@
 - bgread        - run command and read it's output in background
 - add_feature   - add string to feature list (for disco#info)
 - del_feature   - delete string from feature list
-- add_command   - adds mcabber command
-- del_command   - remove mcabber command
+- command       - adds/removes mcabber command
 
 --]]
 
@@ -183,7 +182,7 @@
 
 -- Help strings should not contain command, only arguments. This is necessary to support soft aliases.
 commands_help = {
-	file      = "filename\n\nSends file as a message. Just shorthand.",
+	post      = "filename\n\nSends file as a message. Just shorthand.",
 	s         = "status [message]\n\nSets your status, but takes into account mpd (if enabled).",
 	beep      = "[enable|disable|on|off|yes|no|true|false]\n\nEnables or disables beeping on all messages.\nIf state is omitted, prints current state.",
 	cmd       = "shell_command\n\nRuns shell command in background and sends output to current buddy.\nWorks asynchroneously, and may break long output in the middle of line",
@@ -193,19 +192,15 @@
 	count     = "\n\nPrints number of resources of current buddy. Useful to determine member count of large room."
 }
 
-main.add_command ( "lua",
-	function ( args )
-		assert ( loadstring ( args ) ) ()
-	end )
-main.add_command ( 'file',
+main.command ( 'post',
 	function ( args )
 		main.run ( 'say_to -f ' .. args .. ' .' )
 	end )
-main.add_command ( 's',
+main.command ( 's',
 	function ( args )
 		main.run ( ('status %s %s'):format ( args, mpd_getstatus () ) )
 	end )
-main.add_command ( 'beep',
+main.command ( 'beep',
 	function ( args )
 		local enable = yesno ( args )
 		if enable == nil then
@@ -218,7 +213,7 @@
 			beep_enable = enable
 		end
 	end )
-main.add_command ( 'cmd',
+main.command ( 'cmd',
 	function ( args )
 		local to = main.current_buddy ()
 		main.run ( ('send_to -q %q $ %s'):format ( to, args ) )
@@ -232,7 +227,7 @@
 				end
 			end )
 	end )
-main.add_command ( 'exthelp',
+main.command ( 'exthelp',
 	function ( args )
 		if commands_help[args] then
 			print ( "\n /" .. args .. ' ' .. commands_help[args] )
@@ -246,15 +241,15 @@
 			print ( "For built-in mcabber commands see /help" )
 		end
 	end )
-main.add_command ( 'reload',
+main.command ( 'reload',
 	function ( args )
 		dofile ( main.config_file ( 'mcabberrc.lua' ) )
 	end )
-main.add_command ( 'join!',
+main.command ( 'join!',
 	function ( args )
 		main.run ( 'room join ' .. main.current_buddy () )
 	end )
-main.add_command ( 'count',
+main.command ( 'count',
 	function ( args )
 		local count = 0
 		for resource in pairs ( main.buddy_info ( main.current_buddy () ).resources ) do
@@ -264,7 +259,7 @@
 	end )
 
 for k, arg in ipairs ( { ')', '/', '(', 'D', '-/', 'S', '1', ']', '[' } ) do
-	main.add_command ( arg,
+	main.command ( arg,
 		function ( args )
 			main.run ( 'say :' .. arg .. ' ' .. args )
 		end )
@@ -324,7 +319,7 @@
 	h:close ()
 end
 
-main.add_command ( 'delay',
+main.command ( 'delay',
 	function ( args )
 		args = parse_args ( args )
 		local who
@@ -343,7 +338,7 @@
 			end
 	end )
 
-main.add_command ( 'job',
+main.command ( 'job',
 	function ( args )
 		local action, jid, stat = args:match ( "(%w+)%s+(%w+)%s+(%w)" )
 		if action == 'del' then
--- a/examples/mpd.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/mpd.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -176,7 +176,7 @@
 	end
 end
 
-main.add_command ( 'mpd',
+main.command ( 'mpd',
 	function ( args )
 		local enable = yesno ( args )
 		if enable == nil then
--- a/examples/xep0004.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/xep0004.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -99,7 +99,7 @@
 	end
 end
 
-main.add_command ( 'form',
+main.command ( 'form',
 	function ( args )
 		args = parse_args ( args )
 		local action = args[1]
--- a/examples/xep0030.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/xep0030.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -53,7 +53,7 @@
 		end )
 end
 
-main.add_command ( 'disco',
+main.command ( 'disco',
 	function ( args )
 		args = parse_args ( args )
 		local who
--- a/examples/xep0047.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/xep0047.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -161,7 +161,7 @@
 		end )
 end
 
-main.add_command ( 'ibb',
+main.command ( 'ibb',
 	function ( args )
 		args = parse_args ( args )
 		if args[1] == 'send' then
--- a/examples/xep0077.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/xep0077.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -143,7 +143,7 @@
 		end )
 end
 
-main.add_command ( 'register',
+main.command ( 'register',
 	function ( args )
 		local who
 		if args[1] then
@@ -154,7 +154,7 @@
 		register_to ( who )
 	end )
 
-main.add_command ( 'cancel',
+main.command ( 'cancel',
 	function ( args )
 		local who
 		if args and args ~= '' then
--- a/examples/xep0146.lua	Tue Feb 24 09:14:00 2009 +0200
+++ b/examples/xep0146.lua	Tue Feb 24 19:42:48 2009 +0200
@@ -38,7 +38,7 @@
 		end )
 end
 
-main.add_command ( 'remote',
+main.command ( 'remote',
 	function ( args )
 		args = parse_args ( args )
 		local who
--- a/main.c	Tue Feb 24 09:14:00 2009 +0200
+++ b/main.c	Tue Feb 24 19:42:48 2009 +0200
@@ -10,15 +10,16 @@
 
 #include "config.h"
 #include "util.h"
-#include "logprint.h"  // scr_LogPrint
-#include "screen.h"    // scr_Beep, scr_WriteIncomingMessage
-#include "hbuf.h"      // HBB_PREFIX_INFO
-#include "commands.h"  // process_command, cmd_add, cmd_del
-#include "xmpp.h"      // xmpp_getstatus, xmpp_getstatusmsg, lconnection, xmpp_add_feature, xmpp_del_feature
-#include "roster.h"    // imstatus2char, foreach_buddy, buddy_*, current_buddy, BUDDATA, ROSTER_TYPE_*
-#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 "logprint.h"    // scr_LogPrint
+#include "screen.h"      // scr_Beep, scr_WriteIncomingMessage
+#include "hbuf.h"        // HBB_PREFIX_INFO
+#include "commands.h"    // process_command, cmd_add, cmd_del
+#include "xmpp.h"        // xmpp_getstatus, xmpp_getstatusmsg, lconnection
+#include "xmpp_helper.h" // xmpp_add_feature, xmpp_del_feature
+#include "roster.h"      // imstatus2char, foreach_buddy, buddy_*, current_buddy, BUDDATA, ROSTER_TYPE_*
+#include "utils.h"       // from_utf8, jidtodisp
+#include "hooks.h"       // hk_add_handler, hk_del_handler
+#include "settings.h"    // settings_set, settings_del, settings_get
 
 
 // global lua state object, necessary for uninitialization function
@@ -64,7 +65,7 @@
 	if (ret = luaL_loadfile (L, path))
 		scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1));
 	else if (ret = lua_pcall (lua, 0, LUA_MULTRET, 0))
-		scr_LogPrint(LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1));
+		scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1));
 	g_free (path);
 
 	if (ret)
@@ -213,7 +214,7 @@
 static int lua_main_roster (lua_State *L)
 {
 	lua_newtable (L);
-	foreach_buddy (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM, (void (*) (gpointer buddy, void *data))lua_rosterlist_callback, L);
+	foreach_buddy (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM, (void (*) (gpointer buddy, void *data)) lua_rosterlist_callback, L);
 	return 1;
 }
 
@@ -340,38 +341,36 @@
 	}
 }
 
-/// main.add_command
-/// Associates mcabber command name with lua function.
-/// A: string (command name), command function
-static int lua_main_add_command (lua_State *L)
+/// 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)
+static int lua_main_command (lua_State *L)
 {
 	const char             *name = luaL_checkstring (L, 1);
 	lua_command_callback_t *cb;
-	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
+	if (lua_gettop (L) > 1) { // Register
+		luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
 
-	cb = luaL_malloc (L, sizeof (lua_command_callback_t));
-	cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
-	cb->L         = L;
-	cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb);
-	lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name));
-	return 0;
-}
+		cb = luaL_malloc (L, sizeof (lua_command_callback_t));
+		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
+		cb->L         = L;
+		cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb);
 
-/// main.del_command
-/// Removes command from a list of commands.
-/// A: string (command name)
-static int lua_main_del_command (lua_State *L)
-{
-	const char             *name = luaL_checkstring (L, 1);
-	GSList                 *el   = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) strcmp);
-	lua_command_callback_t *cb   = cmd_del (name);
-	if (cb) {
-		luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
-		luaL_free (cb->L, cb);
-	}
-	if (el) {
-		g_free (el->data);
-		lua_added_commands = g_slist_delete_link (lua_added_commands, el);
+		lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name));
+	} else { // Unregister
+		GSList *el = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) g_strcmp0);
+
+		cb = cmd_del (name);
+		if (cb) {
+			luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
+			luaL_free (cb->L, cb);
+		}
+
+		if (el) {
+			g_free (el->data);
+			lua_added_commands = g_slist_delete_link (lua_added_commands, el);
+		}
 	}
 	return 0;
 }
@@ -448,8 +447,7 @@
 /// Function, that processes output from pipe in asynchroneous way.
 /// A: string (data) or nil (eof)
 /// R: boolean (false if reading should be terminated)
-static gboolean
-lua_bgread_callback (GIOChannel *source, GIOCondition condition, lua_bgread_callback_t *cb)
+static gboolean lua_bgread_callback (GIOChannel *source, GIOCondition condition, lua_bgread_callback_t *cb)
 {
 	int ret = TRUE;
 
@@ -538,6 +536,21 @@
 }
 #endif
 
+static void do_lua(char *arg, lua_State *L)
+{
+	if (luaL_loadbuffer (L, arg, strlen (arg), "line")) {
+		scr_LogPrint (LPRINT_LOGNORM, "lua: Compilation error: %s", lua_tostring (L, -1));
+		lua_pop (L, 1);
+		return;
+	}
+ 
+	if (lua_pcall (L, 0, 0, 0)) {
+		scr_LogPrint (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(lua, -1));
+		lua_pop (L, -1);
+		return;
+	}
+}
+
 static void lua_hook (hk_arg_t *args, lua_State *L)
 {
 	hk_arg_t *arg = args;
@@ -577,8 +590,7 @@
 	{ "option",        lua_main_option        },
 	{ "add_feature",   lua_main_add_feature   },
 	{ "del_feature",   lua_main_del_feature   },
-	{ "add_command",   lua_main_add_command   },
-	{ "del_command",   lua_main_del_command   },
+	{ "command",       lua_main_command       },
 	{ "print_info",    lua_main_print_info    },
 	{ "beep",          lua_main_beep          },
 	{ "run",           lua_main_run           },
@@ -593,8 +605,6 @@
 
 const gchar *g_module_check_init (GModule *module)
 {
-	char *initfile;
-
 	lua = lua_newstate (lua_alloc, NULL);
 	if (!lua) {
 		scr_LogPrint (LPRINT_LOGNORM, "lua: Initialization error");
@@ -608,25 +618,32 @@
 	lua_register (lua, "dopath", lua_global_dopath);
 	lua_register (lua, "print",  lua_global_print );
 
+	cmd_add ("lua", "", 0, 0, (void (*) (char *p)) do_lua, lua);
+
 #ifdef LLM_LOG_HANDLER
 	// FIXME: this should not be here.
 	lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL);
 #endif
-	
-	initfile = mcabber_config_filename ("mcabberrc.lua");
-	if (!initfile)
-		scr_LogPrint (LPRINT_LOGNORM, "lua: Cannot determine config file name");
-	else {
-		if (luaL_loadfile(lua, initfile)) {
-			scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1));
-			lua_pop (lua, 1);
-		} else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) {
-			scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1));
-			lua_pop (lua, 1);
-		} else
-			scr_LogPrint (LPRINT_LOGNORM, "Loaded mcabberrc.lua");
-		g_free (initfile);
+
+#if 1
+	{
+		char *initfile = expand_filename (settings_opt_get ("lua_init_filename"));
+		
+		if (!initfile)
+			scr_LogPrint (LPRINT_LOGNORM, "lua: Cannot determine config file name");
+		else {
+			if (luaL_loadfile(lua, initfile)) {
+				scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1));
+				lua_pop (lua, 1);
+			} else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) {
+				scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1));
+				lua_pop (lua, 1);
+			} else
+				scr_LogPrint (LPRINT_LOGNORM, "lua: Loaded %s", initfile);
+			g_free (initfile);
+		}
 	}
+#endif
 
 	hk_add_handler ((hk_handler_t) lua_hook, lua);
 
@@ -676,6 +693,8 @@
 		g_slist_free (lua_added_commands);
 		lua_added_commands = NULL;
 
+		cmd_del ("lua");
+
 		lua_close (lua);
 		lua = NULL;