summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2017-12-29 21:59:29 +0100
committerSébastien Helleu <flashcode@flashtux.org>2018-01-06 14:07:50 +0100
commiteb542307609d3b2a66058640643c33d1dbc78a41 (patch)
treea161f5da06491960b4c17d9cfa9cf6a6af5bed89 /src
parent23ec371daea282e5c1148bb3bff0ed563977181a (diff)
downloadweechat-eb542307609d3b2a66058640643c33d1dbc78a41.zip
lua: add support of eval (issue #128)
Diffstat (limited to 'src')
-rw-r--r--src/plugins/lua/weechat-lua-api.c1
-rw-r--r--src/plugins/lua/weechat-lua.c273
-rw-r--r--src/plugins/lua/weechat-lua.h1
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,