mirror of
https://github.com/weechat/weechat.git
synced 2026-07-07 02:03:13 +02:00
core: add command /print
This commit is contained in:
@@ -20,12 +20,18 @@
|
||||
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* this define is needed for strptime() (not on OpenBSD) */
|
||||
#if !defined(__OpenBSD__)
|
||||
#define _XOPEN_SOURCE 700
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
@@ -4171,6 +4177,182 @@ COMMAND_CALLBACK(plugin)
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for command "/print": display text on a buffer.
|
||||
*/
|
||||
|
||||
COMMAND_CALLBACK(print)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
int i, escape, to_stdout, to_stderr;
|
||||
time_t date, date_now;
|
||||
struct tm tm_date;
|
||||
char *tags, *pos, *text, *text2, *error;
|
||||
const char *prefix;
|
||||
long value;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
|
||||
if (argc < 2)
|
||||
return WEECHAT_RC_OK;
|
||||
|
||||
ptr_buffer = buffer;
|
||||
date = 0;
|
||||
tags = NULL;
|
||||
prefix = NULL;
|
||||
escape = 0;
|
||||
to_stdout = 0;
|
||||
to_stderr = 0;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (string_strcasecmp (argv[i], "-buffer") == 0)
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
return WEECHAT_RC_ERROR;
|
||||
i++;
|
||||
ptr_buffer = gui_buffer_search_by_number_or_name (argv[i]);
|
||||
if (!ptr_buffer)
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-core") == 0)
|
||||
{
|
||||
ptr_buffer = NULL;
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-escape") == 0)
|
||||
{
|
||||
escape = 1;
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-date") == 0)
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
return WEECHAT_RC_ERROR;
|
||||
i++;
|
||||
if ((argv[i][0] == '-') || (argv[i][0] == '+'))
|
||||
{
|
||||
error = NULL;
|
||||
value = strtol (argv[i] + 1, &error, 10);
|
||||
if (!error || error[0])
|
||||
return WEECHAT_RC_ERROR;
|
||||
date = (argv[i][0] == '-') ?
|
||||
time (NULL) - value : time (NULL) + value;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = NULL;
|
||||
value = strtol (argv[i], &error, 10);
|
||||
if (error && !error[0])
|
||||
{
|
||||
date = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (&tm_date, 0, sizeof (struct tm));
|
||||
if (strchr (argv[i], '-'))
|
||||
{
|
||||
/* ISO 8601 (date/time) */
|
||||
if (strptime (argv[i], "%Y-%m-%dT%H:%M:%S", &tm_date))
|
||||
{
|
||||
if (tm_date.tm_year > 0)
|
||||
date = mktime (&tm_date);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* time only (use current date) */
|
||||
date_now = time (NULL);
|
||||
localtime_r (&date_now, &tm_date);
|
||||
if (strptime (argv[i], "%H:%M:%S", &tm_date))
|
||||
date = mktime (&tm_date);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-tags") == 0)
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
return WEECHAT_RC_ERROR;
|
||||
i++;
|
||||
tags = argv[i];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-action") == 0)
|
||||
{
|
||||
prefix = gui_chat_prefix[GUI_CHAT_PREFIX_ACTION];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-error") == 0)
|
||||
{
|
||||
prefix = gui_chat_prefix[GUI_CHAT_PREFIX_ERROR];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-join") == 0)
|
||||
{
|
||||
prefix = gui_chat_prefix[GUI_CHAT_PREFIX_JOIN];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-network") == 0)
|
||||
{
|
||||
prefix = gui_chat_prefix[GUI_CHAT_PREFIX_NETWORK];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-quit") == 0)
|
||||
{
|
||||
prefix = gui_chat_prefix[GUI_CHAT_PREFIX_QUIT];
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-stdout") == 0)
|
||||
{
|
||||
to_stdout = 1;
|
||||
}
|
||||
else if (string_strcasecmp (argv[i], "-stderr") == 0)
|
||||
{
|
||||
to_stderr = 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= argc)
|
||||
return WEECHAT_RC_OK;
|
||||
|
||||
if (to_stdout || to_stderr)
|
||||
{
|
||||
text = string_convert_escaped_chars (argv_eol[i]);
|
||||
if (text)
|
||||
{
|
||||
fprintf ((to_stdout) ? stdout : stderr, "%s", text);
|
||||
free (text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text = strdup (argv_eol[i]);
|
||||
if (text)
|
||||
{
|
||||
pos = NULL;
|
||||
if (!prefix)
|
||||
{
|
||||
pos = strstr (text, "\\t");
|
||||
if (pos)
|
||||
{
|
||||
pos[0] = '\t';
|
||||
memmove (pos + 1, pos + 2, strlen (pos + 2) + 1);
|
||||
}
|
||||
}
|
||||
text2 = (escape) ?
|
||||
string_convert_escaped_chars (text) : strdup (text);
|
||||
if (text2)
|
||||
{
|
||||
gui_chat_printf_date_tags (
|
||||
ptr_buffer, date, tags,
|
||||
"%s%s",
|
||||
(prefix) ? prefix : ((!prefix && !pos) ? "\t" : ""),
|
||||
text2);
|
||||
free (text2);
|
||||
}
|
||||
free (text);
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Displays a list of proxies.
|
||||
*/
|
||||
@@ -6912,6 +7094,53 @@ command_init ()
|
||||
" || reload %(plugins_names)"
|
||||
" || unload %(plugins_names)",
|
||||
&command_plugin, NULL);
|
||||
hook_command (
|
||||
NULL, "print",
|
||||
N_("display text on a buffer"),
|
||||
N_("[-buffer <number>|<name>] [-core] [-escape] [-date <date>] "
|
||||
"[-tags <tags>] [-action|-error|-join|-network|-quit] <text>"
|
||||
" || -stdout|-stderr <text>"),
|
||||
N_("-buffer: the buffer where text is displayed (default: current "
|
||||
"buffer)\n"
|
||||
" -core: alias of \"-buffer core.weechat\"\n"
|
||||
"-escape: interpret escaped chars (for example \\a, \\07, \\x07)\n"
|
||||
" -date: message date, format can be:\n"
|
||||
" -n: 'n' seconds before now\n"
|
||||
" +n: 'n' seconds in the future\n"
|
||||
" n: 'n' seconds since the Epoch (see man time)\n"
|
||||
" date/time (ISO 8601): yyyy-mm-ddThh:mm:ss, example: "
|
||||
"2014-01-19T04:32:55\n"
|
||||
" time: hh:mm:ss (example: 04:32:55)\n"
|
||||
" -tags: comma-separated list of tags (see /help filter for a list "
|
||||
"of tags most commonly used)\n"
|
||||
" text: text to display (prefix and message must be separated by "
|
||||
"\\t)\n"
|
||||
"-stdout: display text on stdout (not in a buffer)\n"
|
||||
"-stderr: display text on stderr (not in a buffer)\n"
|
||||
"\n"
|
||||
"The options -action ... -quit use the prefix defined in options "
|
||||
"\"weechat.look.prefix_*\".\n"
|
||||
"\n"
|
||||
"With options -stdout and -stderr, escaped chars are always "
|
||||
"interpreted.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
" display a reminder on core buffer with a highlight:\n"
|
||||
" /print -core -tags notify_highlight Reminder: buy milk\n"
|
||||
" display an error on core buffer:\n"
|
||||
" /print -core -error Some error here\n"
|
||||
" display message on core buffer with prefix \"abc\":\n"
|
||||
" /print -core abc\tThe message\n"
|
||||
" display a message on channel #weechat:\n"
|
||||
" /print -buffer irc.freenode.#weechat Message on #weechat\n"
|
||||
" send alert (BEL):\n"
|
||||
" /print -stderr \\a"),
|
||||
"-buffer %(buffers_numbers)|%(buffers_plugins_names)"
|
||||
" || -core|-escape|-date|-tags|-action|-error|-join|-network|-quit"
|
||||
" || -prefix"
|
||||
" || -stdout"
|
||||
" || -stderr",
|
||||
&command_print, NULL);
|
||||
hook_command (
|
||||
NULL, "proxy",
|
||||
N_("manage proxies"),
|
||||
|
||||
+110
-52
@@ -54,6 +54,11 @@
|
||||
#include "../plugins/plugin.h"
|
||||
|
||||
|
||||
#define IS_OCTAL_DIGIT(c) ((c >= '0') && (c <= '7'))
|
||||
#define HEX2DEC(c) (((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 : \
|
||||
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : \
|
||||
c - '0')
|
||||
|
||||
typedef uint32_t string_shared_count_t;
|
||||
|
||||
struct t_hashtable *string_hashtable_shared = NULL;
|
||||
@@ -623,74 +628,127 @@ string_strip (const char *string, int left, int right, const char *chars)
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts hex chars (\x??) to value.
|
||||
* Converts escaped chars to their value.
|
||||
*
|
||||
* Following escaped chars are supported:
|
||||
* \" double quote
|
||||
* \\ backslash
|
||||
* \a alert (BEL)
|
||||
* \b backspace
|
||||
* \e escape
|
||||
* \f form feed
|
||||
* \n new line
|
||||
* \r carriage return
|
||||
* \t horizontal tab
|
||||
* \v vertical tab
|
||||
* \0ooo octal value (ooo is 0 to 3 digits)
|
||||
* \xhh hexadecimal value (hh is 1 to 2 digits)
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
string_convert_hex_chars (const char *string)
|
||||
string_convert_escaped_chars (const char *string)
|
||||
{
|
||||
char *output, hex_str[8], *error;
|
||||
int pos_output;
|
||||
long number;
|
||||
const unsigned char *ptr_string;
|
||||
char *output;
|
||||
int pos_output, i, value;
|
||||
|
||||
/* the output length is always <= to string length */
|
||||
output = malloc (strlen (string) + 1);
|
||||
if (output)
|
||||
if (!output)
|
||||
return NULL;
|
||||
|
||||
pos_output = 0;
|
||||
ptr_string = (const unsigned char *)string;
|
||||
while (ptr_string && ptr_string[0])
|
||||
{
|
||||
pos_output = 0;
|
||||
while (string && string[0])
|
||||
if (ptr_string[0] == '\\')
|
||||
{
|
||||
if (string[0] == '\\')
|
||||
ptr_string++;
|
||||
switch (ptr_string[0])
|
||||
{
|
||||
string++;
|
||||
switch (string[0])
|
||||
{
|
||||
case '\\':
|
||||
output[pos_output++] = '\\';
|
||||
string++;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (isxdigit ((unsigned char)string[1])
|
||||
&& isxdigit ((unsigned char)string[2]))
|
||||
case '"':
|
||||
output[pos_output++] = '"';
|
||||
ptr_string++;
|
||||
break;
|
||||
case '\\':
|
||||
output[pos_output++] = '\\';
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'a': /* alert */
|
||||
output[pos_output++] = 7;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
output[pos_output++] = 8;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'e': /* escape */
|
||||
output[pos_output++] = 27;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'f': /* form feed */
|
||||
output[pos_output++] = 12;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'n': /* new line */
|
||||
output[pos_output++] = 10;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'r': /* carriage return */
|
||||
output[pos_output++] = 13;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
output[pos_output++] = 9;
|
||||
ptr_string++;
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
output[pos_output++] = 11;
|
||||
ptr_string++;
|
||||
break;
|
||||
case '0': /* octal value (0 to 3 digits expected) */
|
||||
value = 0;
|
||||
for (i = 0; (i < 3) && IS_OCTAL_DIGIT(ptr_string[i + 1]); i++)
|
||||
{
|
||||
value = (value * 8) + (ptr_string[i + 1] - '0');
|
||||
}
|
||||
output[pos_output++] = value;
|
||||
ptr_string += 1 + i;
|
||||
break;
|
||||
case 'x': /* hexadecimal value (1 to 2 digits expected) */
|
||||
case 'X':
|
||||
if (isxdigit (ptr_string[1]))
|
||||
{
|
||||
value = 0;
|
||||
for (i = 0; (i < 2) && isxdigit (ptr_string[i + 1]); i++)
|
||||
{
|
||||
snprintf (hex_str, sizeof (hex_str),
|
||||
"0x%c%c", string[1], string[2]);
|
||||
number = strtol (hex_str, &error, 16);
|
||||
if (error && !error[0])
|
||||
{
|
||||
output[pos_output++] = number;
|
||||
string += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = '\\';
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
}
|
||||
value = (value * 16) + HEX2DEC(ptr_string[i + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
output[pos_output++] = '\\';
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = string[0];
|
||||
string++;
|
||||
output[pos_output++] = value;
|
||||
ptr_string += 1 + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
output[pos_output++] = ptr_string[0];
|
||||
ptr_string++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
output[pos_output++] = '\\';
|
||||
output[pos_output++] = ptr_string[0];
|
||||
ptr_string++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
output[pos_output] = '\0';
|
||||
else
|
||||
{
|
||||
output[pos_output++] = ptr_string[0];
|
||||
ptr_string++;
|
||||
}
|
||||
}
|
||||
output[pos_output] = '\0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ extern char *string_expand_home (const char *path);
|
||||
extern char *string_remove_quotes (const char *string, const char *quotes);
|
||||
extern char *string_strip (const char *string, int left, int right,
|
||||
const char *chars);
|
||||
extern char *string_convert_hex_chars (const char *string);
|
||||
extern char *string_convert_escaped_chars (const char *string);
|
||||
extern char *string_mask_to_regex (const char *mask);
|
||||
extern const char *string_regex_flags (const char *regex, int default_flags,
|
||||
int *flags);
|
||||
|
||||
+1
-1
@@ -1666,7 +1666,7 @@ gui_input_insert (struct t_gui_buffer *buffer, const char *args)
|
||||
if (args)
|
||||
{
|
||||
gui_buffer_undo_snap (buffer);
|
||||
args2 = string_convert_hex_chars (args);
|
||||
args2 = string_convert_escaped_chars (args);
|
||||
gui_input_insert_string (buffer, (args2) ? args2 : args, -1);
|
||||
gui_input_text_changed_modifier_and_signal (buffer,
|
||||
1, /* save undo */
|
||||
|
||||
Reference in New Issue
Block a user