1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-27 05:16:38 +02:00

exec: display output of commands in real time, add options -flush/-noflush in command /exec

This commit is contained in:
Sébastien Helleu
2014-04-03 11:55:04 +02:00
parent 936d5559f4
commit 7c55cbb38b
22 changed files with 391 additions and 285 deletions
+16 -2
View File
@@ -268,6 +268,14 @@ exec_command_parse_options (struct t_exec_cmd_options *cmd_options,
{
cmd_options->line_numbers = 0;
}
else if (weechat_strcasecmp (argv[i], "-flush") == 0)
{
cmd_options->flush = 1;
}
else if (weechat_strcasecmp (argv[i], "-noflush") == 0)
{
cmd_options->flush = 0;
}
else if (weechat_strcasecmp (argv[i], "-color") == 0)
{
if (i + 1 >= argc)
@@ -405,6 +413,7 @@ exec_command_run (struct t_gui_buffer *buffer,
cmd_options.new_buffer_clear = 0;
cmd_options.switch_to_buffer = 1;
cmd_options.line_numbers = -1;
cmd_options.flush = 1;
cmd_options.color = EXEC_COLOR_AUTO;
cmd_options.display_rc = 1;
cmd_options.ptr_command_name = NULL;
@@ -470,6 +479,8 @@ exec_command_run (struct t_gui_buffer *buffer,
weechat_hashtable_set (process_options, "stdin", "1");
if (cmd_options.detached)
weechat_hashtable_set (process_options, "detached", "1");
if (cmd_options.flush)
weechat_hashtable_set (process_options, "buffer_flush", "1");
/* set variables in new command (before running the command) */
new_exec_cmd->name = (cmd_options.ptr_command_name) ?
@@ -775,7 +786,7 @@ exec_command_init ()
N_("-list"
" || [-sh|-nosh] [-bg|-nobg] [-stdin|-nostdin] [-buffer <name>] "
"[-l|-o|-n|-nf] [-cl|-nocl] [-sw|-nosw] [-ln|-noln] "
"[-color ansi|auto|irc|weechat|strip] [-rc|-norc] "
"[-flush|-noflush] [-color ansi|auto|irc|weechat|strip] [-rc|-norc] "
"[-timeout <timeout>] [-name <name>] [-pipe <command>] "
"[-hsignal <name>] <command>"
" || -in <id> <text>"
@@ -814,6 +825,8 @@ exec_command_init ()
" -nosw: don't switch to the output buffer\n"
" -ln: display line numbers (default in new buffer only)\n"
" -noln: don't display line numbers\n"
" -flush: display output of command in real time (default)\n"
"-noflush: display output of command after its end\n"
" -color: action on ANSI colors in output:\n"
" ansi: keep ANSI codes as-is\n"
" auto: convert ANSI colors to WeeChat/IRC (default)\n"
@@ -863,7 +876,8 @@ exec_command_init ()
" /exec -pipe \"/print Machine uptime:\" uptime"),
"-list"
" || -sh|-nosh|-bg|-nobg|-stdin|-nostdin|-buffer|-l|-o|-n|-nf|"
"-cl|-nocl|-sw|-nosw|-ln|-noln|-color|-timeout|-name|-pipe|-hsignal|%*"
"-cl|-nocl|-sw|-nosw|-ln|-noln|-flush|-noflush|-color|-timeout|-name|"
"-pipe|-hsignal|%*"
" || -in|-inclose|-signal|-kill %(exec_commands_ids)"
" || -killall"
" || -set %(exec_commands_ids) stdin|stdin_close|signal"
+1
View File
@@ -34,6 +34,7 @@ struct t_exec_cmd_options
int new_buffer_clear; /* 1 to clear buffer before output */
int switch_to_buffer; /* switch to the output buffer */
int line_numbers; /* 1 to display line numbers */
int flush; /* 1 to flush lines immediately */
int color; /* what to do with ANSI colors */
int display_rc; /* 1 to display return code */
const char *ptr_command_name; /* name of command */
+185 -137
View File
@@ -114,7 +114,7 @@ struct t_exec_cmd *
exec_add ()
{
struct t_exec_cmd *new_exec_cmd, *ptr_exec_cmd;
int number;
int i, number;
/* find first available number */
number = (last_exec_cmd) ? last_exec_cmd->number + 1 : 0;
@@ -153,10 +153,12 @@ exec_add ()
new_exec_cmd->buffer_full_name = NULL;
new_exec_cmd->line_numbers = 0;
new_exec_cmd->display_rc = 0;
new_exec_cmd->out_size = 0;
new_exec_cmd->out = NULL;
new_exec_cmd->err_size = 0;
new_exec_cmd->err = NULL;
new_exec_cmd->output_line_nb = 0;
for (i = 0; i < 2; i++)
{
new_exec_cmd->output_size[i] = 0;
new_exec_cmd->output[i] = NULL;
}
new_exec_cmd->return_code = -1;
new_exec_cmd->pipe_command = NULL;
new_exec_cmd->hsignal = NULL;
@@ -195,27 +197,6 @@ exec_timer_delete_cb (void *data, int remaining_calls)
return WEECHAT_RC_OK;
}
/*
* Concatenates some text to stdout/stderr of a command.
*/
void
exec_concat_output (int *size, char **output, const char *text)
{
int length, new_size;
char *new_output;
length = strlen (text);
new_size = *size + length;
new_output = realloc (*output, new_size + 1);
if (!new_output)
return;
*output = new_output;
memcpy (*output + *size, text, length + 1);
*size = new_size;
}
/*
* Decodes colors in a string (from stdout/stderr).
*
@@ -258,19 +239,22 @@ exec_decode_color (struct t_exec_cmd *exec_cmd, const char *string)
}
/*
* Displays output of a command.
* Displays a line of output.
*/
void
exec_display_output (struct t_exec_cmd *exec_cmd,
struct t_gui_buffer *buffer, int out)
exec_display_line (struct t_exec_cmd *exec_cmd, struct t_gui_buffer *buffer,
int out, const char *line)
{
char *line_color, *line2, str_number[32], str_tags[1024];
int length;
/*
char *ptr_output, *ptr_line, *line, *line2, *pos;
char str_number[32], str_tags[1024];
int line_nb, length;
int length;
*/
ptr_output = (out) ? exec_cmd->out : exec_cmd->err;
if (!ptr_output)
if (!exec_cmd || !line)
return;
/*
@@ -280,99 +264,149 @@ exec_display_output (struct t_exec_cmd *exec_cmd,
if (exec_cmd->output_to_buffer && !exec_cmd->pipe_command && !buffer)
return;
ptr_line = ptr_output;
line_nb = 1;
while (ptr_line)
/* decode colors */
line_color = exec_decode_color (exec_cmd, line);
if (!line_color)
return;
exec_cmd->output_line_nb++;
if (exec_cmd->pipe_command)
{
/* ignore last empty line */
if (!ptr_line[0])
break;
/* search end of line */
pos = strchr (ptr_line, '\n');
line = (pos) ?
weechat_strndup (ptr_line, pos - ptr_line) : strdup (ptr_line);
if (!line)
break;
/* decode colors */
line2 = exec_decode_color (exec_cmd, line);
free (line);
if (!line2)
break;
line = line2;
if (exec_cmd->pipe_command)
if (strstr (exec_cmd->pipe_command, "$line"))
{
if (strstr (exec_cmd->pipe_command, "$line"))
/* replace $line by line content */
line2 = weechat_string_replace (exec_cmd->pipe_command,
"$line", line_color);
if (line2)
{
/* replace $line by line content */
line2 = weechat_string_replace (exec_cmd->pipe_command,
"$line", line);
if (line2)
{
weechat_command (buffer, line2);
free (line2);
}
weechat_command (buffer, line2);
free (line2);
}
else
{
/* add line at the end of command, after a space */
length = strlen (exec_cmd->pipe_command) + 1 + strlen (line) + 1;
line2 = malloc (length);
if (line2)
{
snprintf (line2, length, "%s %s", exec_cmd->pipe_command, line);
weechat_command (buffer, line2);
free (line2);
}
}
}
else if (exec_cmd->output_to_buffer)
{
if (exec_cmd->line_numbers)
{
length = 32 + strlen (line) + 1;
line2 = malloc (length);
if (line2)
{
snprintf (line2, length, "%d. %s", line_nb, line);
weechat_command (buffer, line2);
free (line2);
}
}
else
weechat_command (buffer, (line[0]) ? line : " ");
}
else
{
snprintf (str_number, sizeof (str_number), "%d", exec_cmd->number);
snprintf (str_tags, sizeof (str_tags),
"exec_%s,exec_cmd_%s",
(out) ? "stdout" : "stderr",
(exec_cmd->name) ? exec_cmd->name : str_number);
if (weechat_buffer_get_integer (buffer, "type") == 1)
/* add line at the end of command, after a space */
length = strlen (exec_cmd->pipe_command) + 1 + strlen (line_color) + 1;
line2 = malloc (length);
if (line2)
{
snprintf (str_number, sizeof (str_number), "%d. ", line_nb);
weechat_printf_y (buffer, -1,
"%s%s",
(exec_cmd->line_numbers) ? str_number : " ",
line);
}
else
{
snprintf (str_number, sizeof (str_number), "%d\t", line_nb);
weechat_printf_tags (buffer, str_tags,
"%s%s",
(exec_cmd->line_numbers) ? str_number : " \t",
line);
snprintf (line2, length,
"%s %s", exec_cmd->pipe_command, line_color);
weechat_command (buffer, line2);
free (line2);
}
}
}
else if (exec_cmd->output_to_buffer)
{
if (exec_cmd->line_numbers)
{
length = 32 + strlen (line_color) + 1;
line2 = malloc (length);
if (line2)
{
snprintf (line2, length,
"%d. %s", exec_cmd->output_line_nb, line_color);
weechat_command (buffer, line2);
free (line2);
}
}
else
weechat_command (buffer, (line_color[0]) ? line_color : " ");
}
else
{
snprintf (str_number, sizeof (str_number), "%d", exec_cmd->number);
snprintf (str_tags, sizeof (str_tags),
"exec_%s,exec_cmd_%s",
(out) ? "stdout" : "stderr",
(exec_cmd->name) ? exec_cmd->name : str_number);
if (weechat_buffer_get_integer (buffer, "type") == 1)
{
snprintf (str_number, sizeof (str_number),
"%d. ", exec_cmd->output_line_nb);
weechat_printf_y (buffer, -1,
"%s%s",
(exec_cmd->line_numbers) ? str_number : " ",
line_color);
}
else
{
snprintf (str_number, sizeof (str_number),
"%d\t", exec_cmd->output_line_nb);
weechat_printf_tags (buffer, str_tags,
"%s%s",
(exec_cmd->line_numbers) ? str_number : " \t",
line_color);
}
}
}
free (line);
line_nb++;
ptr_line = (pos) ? pos + 1 : NULL;
/*
* Concatenates some text to stdout/stderr of a command.
*/
void
exec_concat_output (struct t_exec_cmd *exec_cmd, struct t_gui_buffer *buffer,
int out, const char *text)
{
int length, new_size;
const char *ptr_text;
char *new_output, *pos, *line;
ptr_text = text;
/* if output is not sent as hsignal, display lines (ending with '\n') */
if (!exec_cmd->hsignal)
{
ptr_text = text;
while (ptr_text[0])
{
pos = strchr (ptr_text, '\n');
if (!pos)
break;
if (exec_cmd->output_size[out] > 0)
{
length = exec_cmd->output_size[out] + (pos - ptr_text) + 1;
line = malloc (length);
if (line)
{
memcpy (line, exec_cmd->output[out],
exec_cmd->output_size[out]);
memcpy (line + exec_cmd->output_size[out],
ptr_text, pos - ptr_text);
line[length - 1] = '\0';
}
}
else
line = weechat_strndup (ptr_text, pos - ptr_text);
if (!line)
break;
if (exec_cmd->output[out])
{
free (exec_cmd->output[out]);
exec_cmd->output[out] = NULL;
}
exec_cmd->output_size[out] = 0;
exec_display_line (exec_cmd, buffer, out, line);
free (line);
ptr_text = pos + 1;
}
}
/* concatenate ptr_text to output buffer */
length = strlen (ptr_text);
if (length > 0)
{
new_size = exec_cmd->output_size[out] + length;
new_output = realloc (exec_cmd->output[out], new_size + 1);
if (!new_output)
return;
exec_cmd->output[out] = new_output;
memcpy (exec_cmd->output[out] + exec_cmd->output_size[out],
ptr_text, length + 1);
exec_cmd->output_size[out] = new_size;
}
}
@@ -386,7 +420,7 @@ exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
struct t_gui_buffer *ptr_buffer;
struct t_hashtable *hashtable;
char str_number[32], *output;
int buffer_type;
int i, buffer_type;
if (exec_cmd->hsignal)
{
@@ -401,11 +435,11 @@ exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
snprintf (str_number, sizeof (str_number), "%d", exec_cmd->number);
weechat_hashtable_set (hashtable, "number", str_number);
weechat_hashtable_set (hashtable, "name", exec_cmd->name);
output = exec_decode_color (exec_cmd, exec_cmd->out);
output = exec_decode_color (exec_cmd, exec_cmd->output[EXEC_STDOUT]);
weechat_hashtable_set (hashtable, "out", output);
if (output)
free (output);
output = exec_decode_color (exec_cmd, exec_cmd->err);
output = exec_decode_color (exec_cmd, exec_cmd->output[EXEC_STDERR]);
weechat_hashtable_set (hashtable, "err", output);
if (output)
free (output);
@@ -419,8 +453,11 @@ exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
{
ptr_buffer = weechat_buffer_search ("==", exec_cmd->buffer_full_name);
exec_display_output (exec_cmd, ptr_buffer, 1);
exec_display_output (exec_cmd, ptr_buffer, 0);
/* display the last line of output (if not ending with '\n') */
exec_display_line (exec_cmd, ptr_buffer, EXEC_STDOUT,
exec_cmd->output[EXEC_STDOUT]);
exec_display_line (exec_cmd, ptr_buffer, EXEC_STDERR,
exec_cmd->output[EXEC_STDERR]);
/*
* display return code (only if command is not detached, if output is
@@ -477,6 +514,15 @@ exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
exec_cmd->pid = 0;
exec_cmd->end_time = time (NULL);
exec_cmd->return_code = return_code;
for (i = 0; i < 2; i++)
{
if (exec_cmd->output[i])
{
free (exec_cmd->output[i]);
exec_cmd->output[i] = NULL;
}
exec_cmd->output_size[i] = 0;
}
/* schedule a timer to remove the executed command */
if (weechat_config_integer (exec_config_command_purge_delay) >= 0)
@@ -496,6 +542,7 @@ exec_process_cb (void *data, const char *command, int return_code,
const char *out, const char *err)
{
struct t_exec_cmd *ptr_exec_cmd;
struct t_gui_buffer *ptr_buffer;
/* make C compiler happy */
(void) command;
@@ -516,17 +563,14 @@ exec_process_cb (void *data, const char *command, int return_code,
(err) ? strlen (err) : 0);
}
if (out)
if (out || err)
{
exec_concat_output (&ptr_exec_cmd->out_size,
&ptr_exec_cmd->out,
out);
}
if (err)
{
exec_concat_output (&ptr_exec_cmd->err_size,
&ptr_exec_cmd->err,
err);
ptr_buffer = weechat_buffer_search ("==",
ptr_exec_cmd->buffer_full_name);
if (out)
exec_concat_output (ptr_exec_cmd, ptr_buffer, EXEC_STDOUT, out);
if (err)
exec_concat_output (ptr_exec_cmd, ptr_buffer, EXEC_STDERR, err);
}
if (return_code == WEECHAT_HOOK_PROCESS_ERROR)
@@ -544,6 +588,8 @@ exec_process_cb (void *data, const char *command, int return_code,
void
exec_free (struct t_exec_cmd *exec_cmd)
{
int i;
if (!exec_cmd)
return;
@@ -566,10 +612,11 @@ exec_free (struct t_exec_cmd *exec_cmd)
free (exec_cmd->command);
if (exec_cmd->buffer_full_name)
free (exec_cmd->buffer_full_name);
if (exec_cmd->out)
free (exec_cmd->out);
if (exec_cmd->err)
free (exec_cmd->err);
for (i = 0; i < 2; i++)
{
if (exec_cmd->output[i])
free (exec_cmd->output[i]);
}
if (exec_cmd->pipe_command)
free (exec_cmd->pipe_command);
if (exec_cmd->hsignal)
@@ -619,10 +666,11 @@ exec_print_log ()
weechat_log_printf (" buffer_full_name. . . . : '%s'", ptr_exec_cmd->buffer_full_name);
weechat_log_printf (" line_numbers. . . . . . : %d", ptr_exec_cmd->line_numbers);
weechat_log_printf (" display_rc. . . . . . . : %d", ptr_exec_cmd->display_rc);
weechat_log_printf (" out_size. . . . . . . . : %d", ptr_exec_cmd->out_size);
weechat_log_printf (" out . . . . . . . . . . : '%s'", ptr_exec_cmd->out);
weechat_log_printf (" err_size. . . . . . . . : %d", ptr_exec_cmd->err_size);
weechat_log_printf (" err . . . . . . . . . . : '%s'", ptr_exec_cmd->err);
weechat_log_printf (" output_line_nb. . . . . : %d", ptr_exec_cmd->output_line_nb);
weechat_log_printf (" output_size[stdout] . . : %d", ptr_exec_cmd->output_size[EXEC_STDOUT]);
weechat_log_printf (" output[stdout]. . . . . : '%s'", ptr_exec_cmd->output[EXEC_STDOUT]);
weechat_log_printf (" output_size[stderr] . . : %d", ptr_exec_cmd->output_size[EXEC_STDERR]);
weechat_log_printf (" output[stderr]. . . . . : '%s'", ptr_exec_cmd->output[EXEC_STDERR]);
weechat_log_printf (" return_code . . . . . . : %d", ptr_exec_cmd->return_code);
weechat_log_printf (" pipe_command. . . . . . : '%s'", ptr_exec_cmd->pipe_command);
weechat_log_printf (" hsignal . . . . . . . . : '%s'", ptr_exec_cmd->hsignal);
+6 -4
View File
@@ -25,6 +25,9 @@
#define weechat_plugin weechat_exec_plugin
#define EXEC_PLUGIN_NAME "exec"
#define EXEC_STDOUT 0
#define EXEC_STDERR 1
enum t_exec_color
{
EXEC_COLOR_ANSI = 0,
@@ -56,10 +59,9 @@ struct t_exec_cmd
int display_rc; /* 1 if return code is displayed */
/* command output */
int out_size; /* number of bytes in stdout */
char *out; /* stdout of command */
int err_size; /* number of bytes in stderr */
char *err; /* stderr of command */
int output_line_nb; /* line number */
int output_size[2]; /* number of bytes in stdout/stderr */
char *output[2]; /* stdout/stderr of command */
int return_code; /* command return code */
/* pipe/hsignal */