Completion and settings improvements
authorMyhailo Danylenko <isbear@ukrpost.net>
Tue, 03 Mar 2009 23:15:04 +0200
changeset 14 ff13ba17fb6d
parent 13 0b716ba23b03
child 15 b224cbc7b8be
Completion and settings improvements * settings list can be obtained * bindings accessor * aliases accessor * unregisterging of completion categories
TODO
main.c
--- a/TODO	Sun Mar 01 18:35:43 2009 +0200
+++ b/TODO	Tue Mar 03 23:15:04 2009 +0200
@@ -1,7 +1,6 @@
 
 print should allow other types to be printed
 finish roster list information
-settings list?
 non-setting settings?
 mcabber_config_file uses option to set dir?
 do uninitialization of commands and features with objects?
@@ -10,4 +9,5 @@
 in mcabber add hook/call to also handle room status changes
 well, so, mcabber will pass all arguments to hooks in utf. but do we really need to convert names to utf?
 use glib filename charset conversion functions?
+toggle routine should handle multiple status toggles.
 
--- a/main.c	Sun Mar 01 18:35:43 2009 +0200
+++ b/main.c	Tue Mar 03 23:15:04 2009 +0200
@@ -127,33 +127,132 @@
 	return 0;
 }
 
+// expects table on top
+static void lua_options_callback (char *key, char *value, lua_State *L)
+{
+	char *loc = from_utf8 (key);
+	lua_pushstring (L, loc);
+	g_free (loc);
+	loc = from_utf8 (value);
+	lua_pushstring (L, loc);
+	g_free (loc);
+	lua_settable (L, -3);
+}
+
 /// main.option
 /// Sets or gets value of mcabber option.
 /// You can specify nil as a value to delete option.
-/// XXX: Should we do types here?
-/// A: string (option name), string (value, optional)
+/// If you omit option name, it returns hash table of all options.
+/// A: string (option name, optional), string (value, optional)
 /// R: string (value, optional)
 static int lua_main_option (lua_State *L)
 {
-	char *name = to_utf8 (luaL_checkstring (L, 1));
-	if (lua_gettop (L) > 1) { // Set
-		if (lua_type (L, 2) == LUA_TNIL) // Unset
-			settings_del (SETTINGS_TYPE_OPTION, name);
-		else { // Set
-			char *value = to_utf8 (luaL_checkstring (L, 2));
-			settings_set (SETTINGS_TYPE_OPTION, name, value);
-			g_free (value);
+	int top = lua_gettop (L);
+	if (top > 0) {
+		char *name = to_utf8 (luaL_checkstring (L, 1));
+		if (top > 1) { // Set
+			if (lua_type (L, 2) == LUA_TNIL) // Unset
+				settings_del (SETTINGS_TYPE_OPTION, name);
+			else { // Set
+				char *value = to_utf8 (luaL_checkstring (L, 2));
+				settings_set (SETTINGS_TYPE_OPTION, name, value);
+				g_free (value);
+			}
+			g_free (name);
+			return 0;
+		} else { // Get
+			char *value = from_utf8 (settings_get (SETTINGS_TYPE_OPTION, name));
+			if (value) {
+				lua_pushstring (L, value);
+				g_free (value);
+			} else
+				lua_pushnil (L);
+			g_free (name);
+			return 1;
 		}
-		g_free (name);
-		return 0;
-	} else { // Get
-		char *value = from_utf8 (settings_get (SETTINGS_TYPE_OPTION, name));
-		if (value) {
-			lua_pushstring (L, value);
-			g_free (value);
-		} else
-			lua_pushnil (L);
-		g_free (name);
+	} else { // List
+		lua_newtable (L);
+		settings_foreach (SETTINGS_TYPE_OPTION, (void (*)(char *key, char *val, void *ud)) lua_options_callback, L);
+		return 1;
+	}
+}
+
+/// main.alias
+/// Sets or gets alias.
+/// You can specify nil as a command to delete alias.
+/// If you omit alias name, it will return hash table of all aliases.
+/// A: string (alias name, optional), string (command, optional)
+/// R: string (command, optional)
+static int lua_main_alias (lua_State *L)
+{
+	int top = lua_gettop (L);
+	if (top > 0) {
+		char *name = to_utf8 (luaL_checkstring (L, 1));
+		if (top > 1) { // Set
+			if (lua_type (L, 2) == LUA_TNIL) { // Unset
+				settings_del (SETTINGS_TYPE_ALIAS, name);
+				compl_del_category_word (COMPL_CMD, name);
+			} else { // Set
+				char *value = to_utf8 (luaL_checkstring (L, 2));
+				if (!settings_get (SETTINGS_TYPE_ALIAS, name))
+					compl_add_category_word (COMPL_CMD, name);
+				settings_set (SETTINGS_TYPE_ALIAS, name, value);
+				g_free (value);
+			}
+			g_free (name);
+			return 0;
+		} else { // Get
+			char *value = from_utf8 (settings_get (SETTINGS_TYPE_ALIAS, name));
+			if (value) {
+				lua_pushstring (L, value);
+				g_free (value);
+			} else
+				lua_pushnil (L);
+			g_free (name);
+			return 1;
+		}
+	} else { // List
+		lua_newtable (L);
+		settings_foreach (SETTINGS_TYPE_ALIAS, (void (*)(char *key, char *val, void *ud)) lua_options_callback, L);
+		return 1;
+	}
+}
+
+/// main.bind
+/// Sets or gets alias.
+/// You can specify nil as a command to unbind key.
+/// If you omit keycode, it will return hash table of all bindings.
+/// A: string (keycode, optional), string (command, optional)
+/// R: string (command, optional)
+static int lua_main_alias (lua_State *L)
+{
+	int top = lua_gettop (L);
+	if (top > 0) {
+		// just to be sure...
+		char *name = to_utf8 (luaL_checkstring (L, 1));
+		if (top > 1) { // Set
+			if (lua_type (L, 2) == LUA_TNIL) // Unset
+				settings_del (SETTINGS_TYPE_BINDING, name);
+			else { // Set
+				char *value = to_utf8 (luaL_checkstring (L, 2));
+				settings_set (SETTINGS_TYPE_BINDING, name, value);
+				g_free (value);
+			}
+			g_free (name);
+			return 0;
+		} else { // Get
+			char *value = from_utf8 (settings_get (SETTINGS_TYPE_BINDING, name));
+			if (value) {
+				lua_pushstring (L, value);
+				g_free (value);
+			} else
+				lua_pushnil (L);
+			g_free (name);
+			return 1;
+		}
+	} else { // List
+		lua_newtable (L);
+		settings_foreach (SETTINGS_TYPE_BINDING, (void (*)(char *key, char *val, void *ud)) lua_options_callback, L);
 		return 1;
 	}
 }
@@ -430,6 +529,8 @@
 
 static GSList *lua_added_commands = NULL;
 
+static GSList *lua_added_categories = NULL;
+
 /// command function
 /// Function to handle newly registered command.
 /// A: string (arguments)
@@ -443,6 +544,48 @@
 	}
 }
 
+/// main.add_category
+/// Adds completion category.
+/// A: table (values are used as words for completion, optional)
+/// R: integer (category id, in fact completion type) or nil
+static int lua_main_add_category (lua_State *L)
+{
+	guint cid;
+	if (lua_gettop (L) > 0)
+		luaL_argcheck (L, lua_type (L, 1) == LUA_TTABLE, 1, "table expected");
+		cid = compl_new_category ();
+		if (cid) {
+			lua_pushnil (L);
+			while (lua_next (L, 3)) {
+				char *word = to_utf8 (luaL_checkstring (L, -1));
+				if (word) {
+					compl_add_category_word (cid, word);
+					g_free (word);
+				}
+				lua_pop (L, 1);
+			}
+		}
+	} else
+		cid = compl_new_category ();
+	if (cid) {
+		lua_added_categories = g_slist_prepend (lua_added_categories, (gpoiner) cid);
+		lua_pushinteger (L, cid);
+	} else
+		lua_pushnil (L);
+	return 1;
+}
+
+/// main.del_category
+/// Removes completion category.
+/// A: integer (category id)
+static int lua_main_del_category (lua_State *L)
+{
+	guint cid = luaL_checkinteger (L, 1);
+	compl_del_category (cid);
+	lua_added_categories = g_slist_remove (lua_added_categories, (gpointer) cid);
+	return 0;
+}
+
 /// main.add_completion
 /// Adds word to a completion list.
 /// A: integer (completion group id), string (word)
@@ -486,6 +629,7 @@
 			if (lua_type (L, 3) == LUA_TTABLE) {
 				cid = compl_new_category ();
 				if (cid) {
+					lua_added_categories = g_slist_prepend (lua_added_categories, (gpoiner) cid);
 					lua_pushnil (L);
 					while (lua_next (L, 3)) {
 						char *word = to_utf8 (luaL_checkstring (L, -1));
@@ -746,8 +890,12 @@
 	reg ( connection )
 	reg ( log )
 	reg ( option )
+	reg ( alias )
+	reg ( binding )
 	reg ( add_feature )
 	reg ( del_feature )
+	reg ( add_category )
+	reg ( del_category )
 	reg ( add_completion )
 	reg ( del_completion )
 	reg ( command )
@@ -836,6 +984,11 @@
 	g_free (name);
 }
 
+static void lua_categories_destroy (guint id, gpointer ignore)
+{
+	compl_del_category (id);
+}
+
 void g_module_unload (GModule *module)
 {
 	if (lua) {
@@ -855,6 +1008,10 @@
 		g_slist_free (lua_added_commands);
 		lua_added_commands = NULL;
 
+		g_slist_foreach (lua_added_categories, (GFunc) lua_categories_destroy, NULL);
+		g_slist_free (lua_added_categories);
+		lua_added_categories = NULL;
+
 		cmd_del ("lua");
 
 		lua_close (lua);