532 static GSList *lua_added_categories = NULL; |
532 static GSList *lua_added_categories = NULL; |
533 |
533 |
534 /// command function |
534 /// command function |
535 /// Function to handle newly registered command. |
535 /// Function to handle newly registered command. |
536 /// A: string (arguments) |
536 /// A: string (arguments) |
537 void lua_main_command_handler (char *args, lua_command_callback_t *cb) |
537 static void lua_main_command_handler (char *args, lua_command_callback_t *cb) |
538 { |
538 { |
539 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
539 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
540 lua_pushstring (cb->L, args); |
540 lua_pushstring (cb->L, args); |
541 if (lua_pcall (cb->L, 1, 0, 0)) { |
541 if (lua_pcall (cb->L, 1, 0, 0)) { |
542 scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1)); |
542 scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1)); |
543 lua_pop (cb->L, 1); |
543 lua_pop (cb->L, 1); |
544 } |
544 } |
|
545 } |
|
546 |
|
547 /// main.parse_args |
|
548 /// Function to parse command argument string. Returns table of strings. |
|
549 /// It can parse barewords (with escapes), double-quoted strings (with escapes) and single-quoted strings (without escapes). |
|
550 /// If args string ends with escape symbol, it is preserved. |
|
551 /// Arguments are separated only by whitespace, so, consequential quoted strings or barewords are one argument. |
|
552 /// Note: As for now, it does not preserve leading quote symbol for non-closed quoted strings. You should not rely on this behaviour. |
|
553 /// Examples: |
|
554 /// * ab\ cd\'e\\f\" |
|
555 /// * "ab cd'e\\f\"" |
|
556 /// * 'ab cd'\''e\f' |
|
557 /// * ab" cd'"'e\f' |
|
558 /// A: string |
|
559 /// R: table |
|
560 static int lua_main_parse_args (lua_State *L) |
|
561 { |
|
562 const char *args = luaL_checkstring (L, 1); |
|
563 const char *p = args; |
|
564 luaL_Buffer buf; |
|
565 |
|
566 lua_newtable (L); |
|
567 luaL_buffinit (L, &buf); |
|
568 while (*p) { |
|
569 if (*p == ' ') { |
|
570 ++p; |
|
571 continue; |
|
572 } |
|
573 if (*p == '"') { // soft quote |
|
574 const char *start = ++p; |
|
575 while (*p) { |
|
576 if (*p == '\\') { // escape symbol |
|
577 luaL_addlstring (&buf, start, p - start); |
|
578 start = ++p; |
|
579 if (*p) // skip symbol |
|
580 ++p; |
|
581 else // add last \ in line |
|
582 luaL_addchar (&buf, '\\'); |
|
583 } else if (*p == '"') // quotation end |
|
584 break; |
|
585 else |
|
586 ++p; |
|
587 } |
|
588 luaL_addlstring (&buf, start, p - start); |
|
589 if (*p) |
|
590 ++p; |
|
591 } else if (*p == '\'') { // no-escape quote |
|
592 const char *start = ++p; |
|
593 while (*p && *p != '\'') |
|
594 p++; |
|
595 luaL_addlstring (&buf, start, p - start); |
|
596 if (*p) |
|
597 ++p; |
|
598 } else { // bareword |
|
599 const char *start = p; |
|
600 while (*p) { |
|
601 if (*p == '\\') { |
|
602 luaL_addlstring (&buf, start, p - start); |
|
603 start = ++p; |
|
604 if (*p) // skip symbol |
|
605 ++p; |
|
606 else // add last \ in line |
|
607 luaL_addchar (&buf, '\\'); |
|
608 } else if (*p == ' ' || *p == '\'' || *p == '"') |
|
609 break; |
|
610 else |
|
611 ++p; |
|
612 } |
|
613 luaL_addlstring (&buf, start, p - start); |
|
614 } |
|
615 |
|
616 if ((!*p) || *p == ' ') { |
|
617 luaL_pushresult (&buf); |
|
618 luaL_ref (L, -2); |
|
619 luaL_buffinit (L, &buf); |
|
620 } |
|
621 } |
|
622 return 1; |
545 } |
623 } |
546 |
624 |
547 /// main.add_category |
625 /// main.add_category |
548 /// Adds completion category. |
626 /// Adds completion category. |
549 /// A: table (values are used as words for completion, optional) |
627 /// A: table (values are used as words for completion, optional) |