main.c
changeset 34 8206d7cb1447
parent 33 db5396037b43
child 39 0d43f33243cc
--- a/main.c	Mon Mar 16 06:12:55 2009 +0200
+++ b/main.c	Mon Mar 16 18:54:16 2009 +0200
@@ -559,6 +559,7 @@
 
 typedef struct {
 	int        reference;
+	int        parse_args;
 	lua_State *L;
 } lua_command_callback_t;
 
@@ -566,21 +567,8 @@
 
 static GSList *lua_added_categories = NULL;
 
-/// command function
-/// Function to handle newly registered command.
-/// A: string (arguments)
-static void lua_main_command_handler (char *args, lua_command_callback_t *cb)
-{
-	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
-	lua_pushstring (cb->L, args);
-	if (lua_pcall (cb->L, 1, 0, 0)) {
-		scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
-		lua_pop (cb->L, 1);
-	}
-}
-
-/// main.parse_args
-/// Function to parse command argument string.
+// returns true if string contains errors - unclosed quotes or unvalued option
+/// command arguments table
 /// It can parse barewords (with escapes), double-quoted strings (with escapes), single-quoted strings (without escapes), options and arguments.
 /// Arguments are separated only by whitespace, so, consequential quoted strings or barewords are one argument.
 /// This strings are equal:
@@ -594,12 +582,9 @@
 /// * All options should be before any arguments. First non-option argument disables options recognizing.
 /// * EOL is a cutting edge, that can cut much earlier, than you expect. Non-closed quoted strings lose leading quote and option without value loses its leading minus.
 /// * Escape character just before EOL is preserved.
-/// A: string
-/// R: table
-static int lua_main_parse_args (lua_State *L)
+static int luaL_pushargs (lua_State *L, const char *args)
 {
-	const char  *args = luaL_checkstring (L, 1);
-	const char  *p    = args;
+	const char  *p       = args;
 	luaL_Buffer  buf;
 	int          option  = 0;
 	int          options = 1;
@@ -629,6 +614,8 @@
 			luaL_addlstring (&buf, start, p - start); // XXX: eats quote on eol
 			if (*p)
 				++p;
+			else
+				return 1;
 		} else if (*p == '\'') { // no-escape quote
 			const char *start = ++p;
 			while (*p && *p != '\'')
@@ -636,6 +623,8 @@
 			luaL_addlstring (&buf, start, p - start); // XXX: eats quote on eol
 			if (*p)
 				++p;
+			else
+				return 1;
 		} else { // bareword
 			const char *start = p;
 			while (*p) {
@@ -679,9 +668,41 @@
 			luaL_buffinit (L, &buf);
 		}
 	}
-	if (option)
+
+	if (option) {
 		luaL_ref (L, -2); // XXX: eats minus on eol
+		return 1;
+	}
 
+	return 0;
+}
+
+/// command function
+/// Function to handle newly registered command.
+/// Argument type passed depends on how command is registered.
+/// A: string (arguments) or command arguments table
+static void lua_main_command_handler (char *args, lua_command_callback_t *cb)
+{
+	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
+
+	if (cb->parse_args)
+		luaL_pushargs (cb->L, args);
+	else
+		lua_pushstring (cb->L, args);
+
+	if (lua_pcall (cb->L, 1, 0, 0)) {
+		scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1));
+		lua_pop (cb->L, 1);
+	}
+}
+
+/// main.parse_args
+/// Function to parse command argument string to command arguments table.
+/// A: string
+/// R: table
+static int lua_main_parse_args (lua_State *L)
+{
+	luaL_pushargs (L, luaL_checkstring (L, 1));
 	return 1;
 }
 
@@ -692,6 +713,7 @@
 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 ();
@@ -708,11 +730,13 @@
 		}
 	} else
 		cid = compl_new_category ();
+
 	if (cid) {
 		lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid);
 		lua_pushinteger (L, cid);
 	} else
 		lua_pushnil (L);
+
 	return 1;
 }
 
@@ -756,37 +780,44 @@
 /// You can also specify a string name (see completion type) instead of table, for non-builtin, you can just pass integer id.
 /// 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)/completion type (or integer comletion group id, optional)
+/// A: string (command name), command function (optional), boolean (parse args flag, optional), table (completions, optional)/completion type (or integer comletion group id, optional)
 /// R: completion type (integer completion group id or string for builtin types, optional)
 static int lua_main_command (lua_State *L)
-{
+{ // FIXME FIXME
 	const char             *name = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/
 	lua_command_callback_t *cb;
-	if (lua_gettop (L) > 1) { // Register
+	int                     top  = lua_gettop (L);
+	if (top > 1) { // Register
 		guint cid = 0;
+		int parse = 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_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid);
-					lua_pushnil (L);
-					while (lua_next (L, 3)) {
-						char *word = to_utf8 (luaL_checkstring (L, -1));
-						compl_add_category_word (cid, word);
-						lua_pop (L, 1);
-						g_free (word);
+		if (top > 2) { // parse flag provided
+			parse = lua_toboolean (L, 3);
+
+			if (top > 3) { // Completions provided
+				if (lua_type (L, 4) == LUA_TTABLE) {
+					cid = compl_new_category ();
+					if (cid) {
+						lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid);
+						lua_pushnil (L);
+						while (lua_next (L, 4)) {
+							char *word = to_utf8 (luaL_checkstring (L, -1));
+							compl_add_category_word (cid, word);
+							lua_pop (L, 1);
+							g_free (word);
+						}
 					}
-				}
-			} else
-				cid = luaL_checkenum (L, 3, lua_completion_type);
+				} else
+					cid = luaL_checkenum (L, 4, lua_completion_type);
+			}
 		}
 
 		cb = luaL_malloc (L, sizeof (lua_command_callback_t));
 		lua_pushvalue (L, 2);
-		cb->reference = luaL_ref (L, LUA_REGISTRYINDEX);
-		cb->L         = L;
+		cb->reference  = luaL_ref (L, LUA_REGISTRYINDEX);
+		cb->parse_args = parse;
+		cb->L          = L;
 		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));