--- 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));