diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2017-12-29 21:59:29 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2018-01-06 14:07:50 +0100 |
commit | eb542307609d3b2a66058640643c33d1dbc78a41 (patch) | |
tree | a161f5da06491960b4c17d9cfa9cf6a6af5bed89 | |
parent | 23ec371daea282e5c1148bb3bff0ed563977181a (diff) | |
download | weechat-eb542307609d3b2a66058640643c33d1dbc78a41.zip |
lua: add support of eval (issue #128)
-rw-r--r-- | src/plugins/lua/weechat-lua-api.c | 1 | ||||
-rw-r--r-- | src/plugins/lua/weechat-lua.c | 273 | ||||
-rw-r--r-- | src/plugins/lua/weechat-lua.h | 1 |
3 files changed, 229 insertions, 46 deletions
diff --git a/src/plugins/lua/weechat-lua-api.c b/src/plugins/lua/weechat-lua-api.c index 6ade90e84..81d7a1589 100644 --- a/src/plugins/lua/weechat-lua-api.c +++ b/src/plugins/lua/weechat-lua-api.c @@ -5128,6 +5128,7 @@ API_FUNC(upgrade_close) */ const struct luaL_Reg weechat_lua_api_funcs[] = { + { "__output__", weechat_lua_output }, API_DEF_FUNC(register), API_DEF_FUNC(plugin_get_name), API_DEF_FUNC(charset_set), diff --git a/src/plugins/lua/weechat-lua.c b/src/plugins/lua/weechat-lua.c index e211ba3ad..f5bc30195 100644 --- a/src/plugins/lua/weechat-lua.c +++ b/src/plugins/lua/weechat-lua.c @@ -52,6 +52,18 @@ int lua_eval_send_input = 0; int lua_eval_exec_commands = 0; struct t_gui_buffer *lua_eval_buffer = NULL; char *lua_eval_output = NULL; +#if LUA_VERSION_NUM >= 502 +#define LUA_LOAD "load" +#else +#define LUA_LOAD "loadstring" +#endif /* LUA_VERSION_NUM >= 502 */ +#define LUA_EVAL_SCRIPT \ + "function script_lua_eval(code)\n" \ + " assert(" LUA_LOAD "(code))()\n" \ + "end\n" \ + "\n" \ + "weechat.register('" WEECHAT_SCRIPT_EVAL_NAME "', '', '1.0', " \ + "'" WEECHAT_LICENSE "', 'Evaluation of script code', '', '')\n" struct t_plugin_script *lua_scripts = NULL; struct t_plugin_script *last_lua_script = NULL; @@ -59,6 +71,7 @@ struct t_plugin_script *lua_current_script = NULL; struct t_plugin_script *lua_registered_script = NULL; const char *lua_current_script_filename = NULL; lua_State *lua_current_interpreter = NULL; +char **lua_buffer_output = NULL; /* * string used to execute action "install": @@ -164,6 +177,95 @@ weechat_lua_tohashtable (lua_State *interpreter, int index, int size, } /* + * Flushes output. + */ + +void +weechat_lua_output_flush () +{ + const char *ptr_command; + char *command; + int length; + + if (!*lua_buffer_output[0]) + return; + + if (lua_eval_mode) + { + /* if there's no buffer, we catch the output, so there's no flush */ + if (!lua_eval_buffer) + return; + + if (lua_eval_send_input) + { + if (lua_eval_exec_commands) + ptr_command = *lua_buffer_output; + else + ptr_command = weechat_string_input_for_buffer (*lua_buffer_output); + if (ptr_command) + { + weechat_command (lua_eval_buffer, *lua_buffer_output); + } + else + { + length = 1 + strlen (*lua_buffer_output) + 1; + command = malloc (length); + if (command) + { + snprintf (command, length, "%c%s", + *lua_buffer_output[0], *lua_buffer_output); + weechat_command (lua_eval_buffer, + (command[0]) ? command : " "); + free (command); + } + } + } + else + { + weechat_printf (lua_eval_buffer, "%s", *lua_buffer_output); + } + } + else + { + /* script (no eval mode) */ + weechat_printf (NULL, + weechat_gettext ("%s: stdout/stderr: %s"), + LUA_PLUGIN_NAME, *lua_buffer_output); + } + + weechat_string_dyn_copy (lua_buffer_output, NULL); +} + +/* + * Redirection for stdout and stderr. + */ + +int +weechat_lua_output (lua_State *L) +{ + const char *msg, *ptr_msg, *ptr_newline; + char *message; + + if (lua_gettop (L) < 1) + return 0; + + msg = lua_tostring (L, -1); + ptr_msg = msg; + while ((ptr_newline = strchr (ptr_msg, '\n')) != NULL) + { + message = weechat_strndup (ptr_msg, ptr_newline - ptr_msg); + weechat_string_dyn_concat (lua_buffer_output, message); + if (message) + free (message); + weechat_lua_output_flush (); + ptr_msg = ++ptr_newline; + } + weechat_string_dyn_concat (lua_buffer_output, ptr_msg); + + return 0; +} + +/* * Executes a lua function. */ @@ -172,7 +274,7 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, const char *function, const char *format, void **argv) { void *ret_value; - int argc, i, *ret_i; + int argc, i, *ret_i, rc; lua_State *old_lua_current_interpreter; struct t_plugin_script *old_lua_current_script; @@ -213,7 +315,11 @@ weechat_lua_exec (struct t_plugin_script *script, int ret_type, ret_value = NULL; - if (lua_pcall (lua_current_interpreter, argc, 1, 0) == 0) + rc = lua_pcall (lua_current_interpreter, argc, 1, 0); + + weechat_lua_output_flush (); + + if (rc == 0) { if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) { @@ -370,22 +476,32 @@ struct t_plugin_script * weechat_lua_load (const char *filename, const char *code) { FILE *fp; - char *weechat_lua_code = { + char *lua_redirect_output = { + "function weechat_output_string(str)\n" + " weechat.__output__(str)\n" + "end\n" "weechat_outputs = {\n" - " write = function (self, str)\n" - " weechat.print(\"\", \"lua: stdout/stderr: \" .. str)\n" - " end\n" + " write = weechat_output_string\n" "}\n" "io.stdout = weechat_outputs\n" "io.stderr = weechat_outputs\n" + "io.write = weechat_output_string\n" + "print = weechat_output_string\n" }; - if ((fp = fopen (filename, "r")) == NULL) + fp = NULL; + + if (!code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: script \"%s\" not found"), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); - return NULL; + fp = fopen (filename, "r"); + if (!fp) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: script \"%s\" not found"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + filename); + return NULL; + } } if ((weechat_lua_plugin->debug >= 2) || !lua_quiet) @@ -406,7 +522,8 @@ weechat_lua_load (const char *filename, const char *code) weechat_gettext ("%s%s: unable to create new " "sub-interpreter"), weechat_prefix ("error"), LUA_PLUGIN_NAME); - fclose (fp); + if (fp) + fclose (fp); return NULL; } @@ -426,9 +543,9 @@ weechat_lua_load (const char *filename, const char *code) weechat_lua_api_consts); #ifdef LUA_VERSION_NUM - if (luaL_dostring (lua_current_interpreter, weechat_lua_code) != 0) + if (luaL_dostring (lua_current_interpreter, lua_redirect_output) != 0) #else - if (lua_dostring (lua_current_interpreter, weechat_lua_code) != 0) + if (lua_dostring (lua_current_interpreter, lua_redirect_output) != 0) #endif /* LUA_VERSION_NUM */ { weechat_printf (NULL, @@ -439,32 +556,63 @@ weechat_lua_load (const char *filename, const char *code) lua_current_script_filename = filename; - if (luaL_loadfile (lua_current_interpreter, filename) != 0) + if (code) { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to load file \"%s\""), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); - weechat_printf (NULL, - weechat_gettext ("%s%s: error: %s"), - weechat_prefix ("error"), LUA_PLUGIN_NAME, - lua_tostring (lua_current_interpreter, -1)); - lua_close (lua_current_interpreter); - fclose (fp); - return NULL; + /* execute code without reading file */ + if (luaL_loadstring (lua_current_interpreter, code) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to load code"), + weechat_prefix ("error"), LUA_PLUGIN_NAME); + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + lua_tostring (lua_current_interpreter, -1)); + lua_close (lua_current_interpreter); + return NULL; + } + } + else + { + /* read and execute code from file */ + if (luaL_loadfile (lua_current_interpreter, filename) != 0) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to load file \"%s\""), + weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + lua_tostring (lua_current_interpreter, -1)); + lua_close (lua_current_interpreter); + fclose (fp); + return NULL; + } } if (lua_pcall (lua_current_interpreter, 0, 0, 0) != 0) { - weechat_printf (NULL, - weechat_gettext ("%s%s: unable to execute file " - "\"%s\""), - weechat_prefix ("error"), LUA_PLUGIN_NAME, filename); + if (code) + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to execute code"), + weechat_prefix ("error"), LUA_PLUGIN_NAME); + } + else + { + weechat_printf (NULL, + weechat_gettext ("%s%s: unable to execute file " + "\"%s\""), + weechat_prefix ("error"), LUA_PLUGIN_NAME, + filename); + } weechat_printf (NULL, weechat_gettext ("%s%s: error: %s"), weechat_prefix ("error"), LUA_PLUGIN_NAME, lua_tostring (lua_current_interpreter, -1)); lua_close (lua_current_interpreter); - fclose (fp); + if (fp) + fclose (fp); /* if script was registered, remove it from list */ if (lua_current_script) @@ -477,7 +625,9 @@ weechat_lua_load (const char *filename, const char *code) return NULL; } - fclose (fp); + + if (fp) + fclose (fp); if (!lua_registered_script) { @@ -657,11 +807,40 @@ int weechat_lua_eval (struct t_gui_buffer *buffer, int send_to_buffer_as_input, int exec_commands, const char *code) { - /* TODO: implement lua eval */ - (void) buffer; - (void) send_to_buffer_as_input; - (void) exec_commands; - (void) code; + void *func_argv[1], *result; + + if (!lua_script_eval) + { + lua_quiet = 1; + lua_script_eval = weechat_lua_load (WEECHAT_SCRIPT_EVAL_NAME, + LUA_EVAL_SCRIPT); + lua_quiet = 0; + if (!lua_script_eval) + return 0; + } + + weechat_lua_output_flush (); + + lua_eval_mode = 1; + lua_eval_send_input = send_to_buffer_as_input; + lua_eval_exec_commands = exec_commands; + lua_eval_buffer = buffer; + + func_argv[0] = (char *)code; + result = weechat_lua_exec (lua_script_eval, + WEECHAT_SCRIPT_EXEC_IGNORE, + "script_lua_eval", + "s", func_argv); + /* result is ignored */ + if (result) + free (result); + + weechat_lua_output_flush (); + + lua_eval_mode = 0; + lua_eval_send_input = 0; + lua_eval_exec_commands = 0; + lua_eval_buffer = NULL; return 1; } @@ -799,10 +978,6 @@ weechat_lua_command_cb (const void *pointer, void *data, if (!weechat_lua_eval (buffer, send_to_buffer_as_input, exec_commands, ptr_code)) WEECHAT_COMMAND_ERROR; - /* TODO: implement /lua eval */ - weechat_printf (NULL, - "%sCommand \"/lua eval\" is not yet implemented", - weechat_prefix ("error")); } else WEECHAT_COMMAND_ERROR; @@ -858,17 +1033,18 @@ weechat_lua_info_eval_cb (const void *pointer, void *data, const char *info_name, const char *arguments) { - static const char *not_implemented = "not yet implemented"; - /* make C compiler happy */ (void) pointer; (void) data; (void) info_name; - (void) arguments; - return not_implemented; + weechat_lua_eval (NULL, 0, 0, (arguments) ? arguments : ""); + if (lua_eval_output) + free (lua_eval_output); + lua_eval_output = strdup (*lua_buffer_output); + weechat_string_dyn_copy (lua_buffer_output, NULL); - return NULL; + return lua_eval_output; } /* @@ -1030,6 +1206,11 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) ""); #endif /* LUA_VERSION */ + /* init stdout/stderr buffer */ + lua_buffer_output = weechat_string_dyn_alloc (256); + if (!lua_buffer_output) + return WEECHAT_RC_ERROR; + init.callback_command = &weechat_lua_command_cb; init.callback_completion = &weechat_lua_completion_cb; init.callback_hdata = &weechat_lua_hdata_cb; @@ -1074,7 +1255,7 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) free (lua_action_remove_list); if (lua_action_autoload_list) free (lua_action_autoload_list); - /* weechat_string_dyn_free (lua_buffer_output, 1); */ + weechat_string_dyn_free (lua_buffer_output, 1); if (lua_eval_output) free (lua_eval_output); diff --git a/src/plugins/lua/weechat-lua.h b/src/plugins/lua/weechat-lua.h index 8197391f9..0701c0ea3 100644 --- a/src/plugins/lua/weechat-lua.h +++ b/src/plugins/lua/weechat-lua.h @@ -50,6 +50,7 @@ extern struct t_hashtable *weechat_lua_tohashtable (lua_State *interpreter, int size, const char *type_keys, const char *type_values); +extern int weechat_lua_output (lua_State *L); extern void *weechat_lua_exec (struct t_plugin_script *script, int ret_type, const char *function, |