1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-01 23:36:37 +02:00

Merge branch 'exec'

This commit is contained in:
Sebastien Helleu
2014-03-15 12:28:07 +01:00
46 changed files with 3223 additions and 86 deletions
+1
View File
@@ -71,6 +71,7 @@ OPTION(ENABLE_ALIAS "Enable Alias plugin" ON)
OPTION(ENABLE_ASPELL "Enable Aspell plugin" ON)
OPTION(ENABLE_ENCHANT "Enable Enchant lib for Aspell plugin" OFF)
OPTION(ENABLE_CHARSET "Enable Charset plugin" ON)
OPTION(ENABLE_EXEC "Enable Exec plugin" ON)
OPTION(ENABLE_FIFO "Enable FIFO plugin" ON)
OPTION(ENABLE_IRC "Enable IRC plugin" ON)
OPTION(ENABLE_LOGGER "Enable Logger plugin" ON)
+1
View File
@@ -15,6 +15,7 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
== Version 0.4.4 (under dev)
* core: add missing \0 at the end of stderr buffer in hook_process
* core: fix highlight problem with "(?-i)" and upper case letters in option
weechat.look.highlight (closes #24)
* core: use glibtoolize on Mac OS X (autotools) (closes #22)
+19
View File
@@ -104,6 +104,7 @@ AH_VERBATIM([HAVE_ASPELL_VERSION_STRING], [#undef HAVE_ASPELL_VERSION_STRING])
AH_VERBATIM([PLUGIN_ALIAS], [#undef PLUGIN_ALIAS])
AH_VERBATIM([PLUGIN_ASPELL], [#undef PLUGIN_ASPELL])
AH_VERBATIM([PLUGIN_CHARSET], [#undef PLUGIN_CHARSET])
AH_VERBATIM([PLUGIN_EXEC], [#undef PLUGIN_EXEC])
AH_VERBATIM([PLUGIN_FIFO], [#undef PLUGIN_FIFO])
AH_VERBATIM([PLUGIN_IRC], [#undef PLUGIN_IRC])
AH_VERBATIM([PLUGIN_LOGGER], [#undef PLUGIN_LOGGER])
@@ -131,6 +132,7 @@ AC_ARG_ENABLE(alias, [ --disable-alias turn off Alias plugin (de
AC_ARG_ENABLE(aspell, [ --disable-aspell turn off Aspell plugin (default=compiled)],enable_aspell=$enableval,enable_aspell=yes)
AC_ARG_ENABLE(enchant, [ --enable-enchant turn on Enchant lib for Aspell plugin (default=off)],enable_enchant=$enableval,enable_enchant=no)
AC_ARG_ENABLE(charset, [ --disable-charset turn off Charset plugin (default=compiled if found)],enable_charset=$enableval,enable_charset=yes)
AC_ARG_ENABLE(exec, [ --disable-exec turn off Exec plugin (default=compiled)],enable_exec=$enableval,enable_exec=yes)
AC_ARG_ENABLE(fifo, [ --disable-fifo turn off Fifo plugin (default=compiled)],enable_fifo=$enableval,enable_fifo=yes)
AC_ARG_ENABLE(irc, [ --disable-irc turn off IRC plugin (default=compiled)],enable_irc=$enableval,enable_irc=yes)
AC_ARG_ENABLE(logger, [ --disable-logger turn off Logger plugin (default=compiled)],enable_logger=$enableval,enable_logger=yes)
@@ -358,6 +360,18 @@ else
not_asked="$not_asked charset"
fi
# ---------------------------------- exec --------------------------------------
if test "x$enable_exec" = "xyes" ; then
EXEC_CFLAGS=""
EXEC_LFLAGS=""
AC_SUBST(EXEC_CFLAGS)
AC_SUBST(EXEC_LFLAGS)
AC_DEFINE(PLUGIN_EXEC)
else
not_asked="$not_asked exec"
fi
# ---------------------------------- fifo --------------------------------------
if test "x$enable_fifo" = "xyes" ; then
@@ -1117,6 +1131,7 @@ AM_CONDITIONAL(GUI_NCURSES, test "$enable_ncurses" = "yes")
AM_CONDITIONAL(PLUGIN_ALIAS, test "$enable_alias" = "yes")
AM_CONDITIONAL(PLUGIN_ASPELL, test "$enable_aspell" = "yes")
AM_CONDITIONAL(PLUGIN_CHARSET, test "$enable_charset" = "yes")
AM_CONDITIONAL(PLUGIN_EXEC, test "$enable_exec" = "yes")
AM_CONDITIONAL(PLUGIN_FIFO, test "$enable_fifo" = "yes")
AM_CONDITIONAL(PLUGIN_IRC, test "$enable_irc" = "yes")
AM_CONDITIONAL(PLUGIN_LOGGER, test "$enable_logger" = "yes")
@@ -1149,6 +1164,7 @@ AC_OUTPUT([Makefile
src/plugins/alias/Makefile
src/plugins/aspell/Makefile
src/plugins/charset/Makefile
src/plugins/exec/Makefile
src/plugins/fifo/Makefile
src/plugins/irc/Makefile
src/plugins/logger/Makefile
@@ -1192,6 +1208,9 @@ fi
if test "x$enable_charset" = "xyes"; then
listplugins="$listplugins charset"
fi
if test "x$enable_exec" = "xyes"; then
listplugins="$listplugins exec"
fi
if test "x$enable_fifo" = "xyes"; then
listplugins="$listplugins fifo"
fi
+1
View File
@@ -1,4 +1,5 @@
usr/lib/weechat/plugins/aspell.so
usr/lib/weechat/plugins/exec.so
usr/lib/weechat/plugins/fifo.so
usr/lib/weechat/plugins/guile.so
usr/lib/weechat/plugins/perl.so
+2 -2
View File
@@ -1395,8 +1395,8 @@ Farbtabelle für key[ctrl-c,c]:
| 11 | hell türkis | lightcyan
| 12 | hellblau | lightblue
| 13 | hell magenta | lightmagenta
| 14 | grau | gray
| 15 | hellgrau | white
| 14 | grau | darkgray
| 15 | hellgrau | gray
|===
Beispiel: Im Buffer wird "Hallo an alle!" ausgegeben. Dabei wird "Hallo" in fett und hellblau
+1
View File
@@ -88,6 +88,7 @@ plugin_list = {
'alias': '',
'aspell': 'o',
'charset': 'o',
'exec': 'o',
'fifo': 'o',
'irc': 'co',
'logger': 'o',
+27 -5
View File
@@ -1268,14 +1268,17 @@ This function is not available in scripting API.
_WeeChat ≥ 0.4.4._
Replace text in a string using a regular expression and replacement text.
Replace text in a string using a regular expression, replacement text and
optional callback.
Prototype:
[source,C]
----
char *weechat_string_replace_regex (const char *string, void *regex,
const char *replace, const char reference_char);
const char *replace, const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
----
Arguments:
@@ -1291,6 +1294,13 @@ Arguments:
** `$.*N`: match `N` (can be `+` or `0` to `99`), with all chars replaced by `*`
(the `*` char can be any char between space (32) and `~` (126))
* 'reference_char': the char used for reference to match (commonly '$')
* 'callback': an optional callback called for each reference in 'replace'
(except for matches replaced by a char); the callback must return:
** newly allocated string: it is used as replacement text (it is freed after
use)
** NULL: the text received in callback is used as replacement text (without
changes)
* 'callback_data': pointer given to callback when it is called
Return value:
@@ -1307,7 +1317,7 @@ if (weechat_string_regcomp (&my_regex, "([0-9]{4})-([0-9]{2})-([0-9]{2})",
REG_EXTENDED) == 0)
{
string = weechat_string_replace_regex ("date: 2014-02-14", &my_regex,
"$3/$2/$1", '$');
"$3/$2/$1", '$', NULL, NULL);
/* string == "date: 14/02/2014" */
if (string)
free (string);
@@ -9122,12 +9132,18 @@ List of modifiers used by WeeChat and plugins:
| irc_color_decode |
"1" to keep colors, "0" to remove colors |
Any string |
String with WeeChat color codes, or without color
String with IRC colors converted to WeeChat colors (or IRC colors removed)
| irc_color_encode |
"1" to keep colors, "0" to remove colors |
Any string |
String with IRC color codes, or without color
String with IRC colors (or IRC colors removed)
| irc_color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" to keep colors, "0" to remove colors |
Any string |
String with ANSI colors converted to IRC colors (or ANSI colors removed)
| irc_command_auth +
_(WeeChat ≥ 0.4.1)_ |
@@ -9165,6 +9181,12 @@ List of modifiers used by WeeChat and plugins:
fit in 512 bytes) |
New content of message
| color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" to keep colors, "0" to remove colors |
Any string |
String with ANSI colors converted to WeeChat colors (or ANSI colors removed)
| bar_condition_yyy ^(2)^ |
String with window pointer ("0x123..") |
Empty string |
+2 -2
View File
@@ -1377,8 +1377,8 @@ Color codes for key[ctrl-c,c] are:
| 11 | light cyan | lightcyan
| 12 | light blue | lightblue
| 13 | light magenta | lightmagenta
| 14 | gray | gray
| 15 | light gray | white
| 14 | gray | darkgray
| 15 | light gray | gray
|===
Example: display of "hello everybody!" with "hello" in light blue bold and
+31 -6
View File
@@ -1286,15 +1286,17 @@ Cette fonction n'est pas disponible dans l'API script.
_WeeChat ≥ 0.4.4._
Remplacer du texte dans une chaîne en utilisant une expression régulière et du
texte de remplacement.
Remplacer du texte dans une chaîne en utilisant une expression régulière, du
texte de remplacement et un "callback" optionnel.
Prototype :
[source,C]
----
char *weechat_string_replace_regex (const char *string, void *regex,
const char *replace, const char reference_char);
const char *replace, const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
----
Paramètres :
@@ -1314,6 +1316,14 @@ Paramètres :
caractère entre l'espace (32) et `~` (126))
* 'reference_char' : le caractère utilisé pour les références aux
correspondances (en général '$')
* 'callback' : un "callback" optionnel appelé pour chaque référence dans
'replace' (sauf pour les correspondances remplacées par un caractère); le
"callback" doit retourner :
** une chaîne nouvellement allouée : elle est utilisée en texte de remplacement
(elle est libérée après utilisation)
** NULL : le texte reçu dans le "callback" est utilisé comme texte de
remplacement (sans changement)
* 'callback_data' : pointeur donné au "callback" lorsqu'il est appelé
Valeur de retour :
@@ -1330,7 +1340,7 @@ if (weechat_string_regcomp (&my_regex, "([0-9]{4})-([0-9]{2})-([0-9]{2})",
REG_EXTENDED) == 0)
{
string = weechat_string_replace_regex ("date: 2014-02-14", &my_regex,
"$3/$2/$1", '$');
"$3/$2/$1", '$', NULL, NULL);
/* string == "date: 14/02/2014" */
if (string)
free (string);
@@ -9290,12 +9300,20 @@ Liste des modificateurs utilisés par WeeChat et les extensions :
| irc_color_decode |
"1" pour garder les couleurs, "0" pour les supprimer |
Toute chaîne |
Chaîne avec des codes couleur WeeChat, ou sans couleur
Chaîne avec les couleurs IRC converties en couleurs WeeChat (ou avec les
couleurs IRC supprimées)
| irc_color_encode |
"1" pour garder les couleurs, "0" pour les supprimer |
Toute chaîne |
Chaîne avec des codes couleur IRC, ou sans couleur
Chaîne avec les couleurs IRC (ou avec les couleurs IRC supprimées)
| irc_color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" pour garder les couleurs, "0" pour les supprimer |
Toute chaîne |
Chaîne avec les couleurs ANSI converties en couleurs IRC (ou avec les couleurs
ANSI supprimées)
| irc_command_auth +
_(WeeChat ≥ 0.4.1)_ |
@@ -9333,6 +9351,13 @@ Liste des modificateurs utilisés par WeeChat et les extensions :
automatique pour tenir dans les 512 octets) |
Nouveau contenu du message
| color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" pour garder les couleurs, "0" pour les supprimer |
Toute chaîne |
Chaîne avec les couleurs ANSI converties en couleurs WeeChat (ou avec les
couleurs ANSI supprimées)
| bar_condition_yyy ^(2)^ |
Chaîne avec un pointeur vers la fenêtre ("0x123..") |
Chaîne vide |
+2 -2
View File
@@ -1417,8 +1417,8 @@ Les codes couleur pour key[ctrl-c,c] sont :
| 11 | cyan clair | lightcyan
| 12 | bleu clair | lightblue
| 13 | violet clair | lightmagenta
| 14 | gris | gray
| 15 | gris clair | white
| 14 | gris | darkgray
| 15 | gris clair | gray
|===
Exemple : affichage de "bonjour tout le monde !" avec "bonjour" en bleu clair
+31 -5
View File
@@ -1302,14 +1302,17 @@ Questa funzione non è disponibile nelle API per lo scripting.
_WeeChat ≥ 0.4.4._
// TRANSLATION MISSING
Replace text in a string using a regular expression and replacement text.
Replace text in a string using a regular expression, replacement text and
optional callback.
Prototipo:
[source,C]
----
char *weechat_string_replace_regex (const char *string, void *regex,
const char *replace, const char reference_char);
const char *replace, const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
----
Argomenti:
@@ -1326,6 +1329,13 @@ Argomenti:
** `$.*N`: match `N` (can be `+` or `0` to `99`), with all chars replaced by `*`
(the `*` char can be any char between space (32) and `~` (126))
* 'reference_char': the char used for reference to match (commonly '$')
* 'callback': an optional callback called for each reference in 'replace'
(except for matches replaced by a char); the callback must return:
** newly allocated string: it is used as replacement text (it is freed after
use)
** NULL: the text received in callback is used as replacement text (without
changes)
* 'callback_data': pointer given to callback when it is called
Valore restituito:
@@ -1343,7 +1353,7 @@ if (weechat_string_regcomp (&my_regex, "([0-9]{4})-([0-9]{2})-([0-9]{2})",
REG_EXTENDED) == 0)
{
string = weechat_string_replace_regex ("date: 2014-02-14", &my_regex,
"$3/$2/$1", '$');
"$3/$2/$1", '$', NULL, NULL);
/* string == "date: 14/02/2014" */
if (string)
free (string);
@@ -9346,15 +9356,24 @@ List of modifiers used by WeeChat and plugins:
Qualsiasi stringa |
Stringa codificata da UTF-8 al set caratteri trovato per il plugin/buffer
// TRANSLATION MISSING
| irc_color_decode |
"1" per mantenere i colori, "0" per rimuovere i colori |
Qualsiasi stringa |
Stringa con i codici colori di Weechat, o senza colore
String with IRC colors converted to WeeChat colors (or IRC colors removed)
// TRANSLATION MISSING
| irc_color_encode |
"1" per mantenere i colori, "0" per rimuovere i colori |
Qualsiasi stringa |
Stringa con i codici colori IRC, o senza colore
String with IRC colors (or IRC colors removed)
// TRANSLATION MISSING
| irc_color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" per mantenere i colori, "0" per rimuovere i colori |
Qualsiasi stringa |
String with ANSI colors converted to IRC colors (or ANSI colors removed)
// TRANSLATION MISSING
| irc_command_auth +
@@ -9392,6 +9411,13 @@ List of modifiers used by WeeChat and plugins:
Contenuto del messaggio che sta per essere inviato al server IRC (dopo la divisione automatica da adattare in 512 byte) |
Nuovo contenuto del messaggio
// TRANSLATION MISSING
| color_decode_ansi +
_(WeeChat ≥ 0.4.4)_ |
"1" per mantenere i colori, "0" per rimuovere i colori |
Qualsiasi stringa |
String with ANSI colors converted to WeeChat colors (or ANSI colors removed)
| bar_condition_yyy ^(2)^ |
Stringa con puntatore alla finestra ("0x123..") |
Stringa vuota |
+2 -2
View File
@@ -1429,8 +1429,8 @@ I codici colore per key[ctrl-c,c] sono:
| 11 | azzurro chiaro | lightcyan
| 12 | blu chiaro | lightblue
| 13 | rosa chiaro | lightmagenta
| 14 | grigio | gray
| 15 | grigio chiaro | white
| 14 | grigio | darkgray
| 15 | grigio chiaro | gray
|===
Esempio: visualizza "ciao a tutti!" con "ciao" scritto in blu chiaro grassetto
+31 -5
View File
@@ -1269,14 +1269,17 @@ free (str);
_WeeChat バージョン 0.4.4 以上で利用可。_
// TRANSLATION MISSING
Replace text in a string using a regular expression and replacement text.
Replace text in a string using a regular expression, replacement text and
optional callback.
プロトタイプ:
[source,C]
----
char *weechat_string_replace_regex (const char *string, void *regex,
const char *replace, const char reference_char);
const char *replace, const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
----
引数:
@@ -1293,6 +1296,13 @@ char *weechat_string_replace_regex (const char *string, void *regex,
** `$.*N`: match `N` (can be `+` or `0` to `99`), with all chars replaced by `*`
(the `*` char can be any char between space (32) and `~` (126))
* 'reference_char': the char used for reference to match (commonly '$')
* 'callback': an optional callback called for each reference in 'replace'
(except for matches replaced by a char); the callback must return:
** newly allocated string: it is used as replacement text (it is freed after
use)
** NULL: the text received in callback is used as replacement text (without
changes)
* 'callback_data': pointer given to callback when it is called
戻り値:
@@ -1310,7 +1320,7 @@ if (weechat_string_regcomp (&my_regex, "([0-9]{4})-([0-9]{2})-([0-9]{2})",
REG_EXTENDED) == 0)
{
string = weechat_string_replace_regex ("date: 2014-02-14", &my_regex,
"$3/$2/$1", '$');
"$3/$2/$1", '$', NULL, NULL);
/* string == "date: 14/02/2014" */
if (string)
free (string);
@@ -9138,15 +9148,24 @@ WeeChat とプラグインが使う修飾子のリスト:
任意の文字列 |
UTF-8 からプラグインおよびバッファの文字セットにエンコードされた文字列
// TRANSLATION MISSING
| irc_color_decode |
色を保持する場合は "1"、削除する場合は "0" |
任意の文字列 |
WeeChat 色コードを含む文字列および含まない文字列
String with IRC colors converted to WeeChat colors (or IRC colors removed)
// TRANSLATION MISSING
| irc_color_encode |
色を保持する場合は "1"、削除する場合は "0" |
任意の文字列 |
IRC 色コードを含む文字列および含まない文字列
String with IRC colors (or IRC colors removed)
// TRANSLATION MISSING
| irc_color_decode_ansi +
_(WeeChat バージョン 0.4.4 以上で利用可)_ |
色を保持する場合は "1"、削除する場合は "0" |
任意の文字列 |
String with ANSI colors converted to IRC colors (or ANSI colors removed)
| irc_command_auth +
_(WeeChat バージョン 0.4.1 以上で利用可)_ |
@@ -9182,6 +9201,13 @@ WeeChat とプラグインが使う修飾子のリスト:
IRC サーバに送信するメッセージの内容 (512 バイトを超えないように自動分割した後) |
メッセージの新しい内容
// TRANSLATION MISSING
| color_decode_ansi +
_(WeeChat バージョン 0.4.4 以上で利用可)_ |
色を保持する場合は "1"、削除する場合は "0" |
任意の文字列 |
String with ANSI colors converted to WeeChat colors (or ANSI colors removed)
| bar_condition_yyy ^(2)^ |
ウィンドウへのポインタの文字列 ("0x123..") |
空文字列 |
+2 -2
View File
@@ -1379,8 +1379,8 @@ key[ctrl-c,c] 用の色コード:
| 11 | 明るい青緑色 | lightcyan
| 12 | 明るい青 | lightblue
| 13 | 明るい赤紫色 | lightmagenta
| 14 | 灰色 | gray
| 15 | 明るい灰色 | white
| 14 | 灰色 | darkgray
| 15 | 明るい灰色 | gray
|===
例: "こんにちは皆さん!" の "こんにちは" を太字の明るい青、"皆さん"
+2 -2
View File
@@ -1387,8 +1387,8 @@ Kody kolorów dla key[ctrl-c,c]:
| 11 | light cyan | lightcyan
| 12 | light blue | lightblue
| 13 | light magenta | lightmagenta
| 14 | gray | gray
| 15 | light gray | white
| 14 | gray | darkgray
| 15 | light gray | gray
|===
Przykład: wyświetlenie "hello everybody!" z pogrubionym jasno niebieskim "hello"
+10
View File
@@ -113,6 +113,16 @@
./src/plugins/aspell/weechat-aspell-speller.c
./src/plugins/aspell/weechat-aspell-speller.h
./src/plugins/charset/charset.c
./src/plugins/exec/exec.c
./src/plugins/exec/exec-buffer.c
./src/plugins/exec/exec-buffer.h
./src/plugins/exec/exec-command.c
./src/plugins/exec/exec-command.h
./src/plugins/exec/exec-completion.c
./src/plugins/exec/exec-completion.h
./src/plugins/exec/exec-config.c
./src/plugins/exec/exec-config.h
./src/plugins/exec/exec.h
./src/plugins/fifo/fifo.c
./src/plugins/fifo/fifo.h
./src/plugins/fifo/fifo-info.c
+10
View File
@@ -114,6 +114,16 @@ SET(WEECHAT_SOURCES
./src/plugins/aspell/weechat-aspell-speller.c
./src/plugins/aspell/weechat-aspell-speller.h
./src/plugins/charset/charset.c
./src/plugins/exec/exec.c
./src/plugins/exec/exec-buffer.c
./src/plugins/exec/exec-buffer.h
./src/plugins/exec/exec-command.c
./src/plugins/exec/exec-command.h
./src/plugins/exec/exec-completion.c
./src/plugins/exec/exec-completion.h
./src/plugins/exec/exec-config.c
./src/plugins/exec/exec-config.h
./src/plugins/exec/exec.h
./src/plugins/fifo/fifo.c
./src/plugins/fifo/fifo.h
./src/plugins/fifo/fifo-info.c
+60 -8
View File
@@ -1157,7 +1157,8 @@ COMMAND_CALLBACK(color)
{
char *str_alias, *str_rgb, *pos, *error;
char str_color[1024], str_command[1024];
long number;
long number, limit;
unsigned int rgb;
int i;
struct t_gui_color_palette *color_palette;
@@ -1302,6 +1303,46 @@ COMMAND_CALLBACK(color)
return WEECHAT_RC_OK;
}
/* convert terminal color to RGB color */
if (string_strcasecmp (argv[1], "term2rgb") == 0)
{
if (argc < 3)
return WEECHAT_RC_ERROR;
error = NULL;
number = strtol (argv[2], &error, 10);
if (!error || error[0] || (number < 0) || (number > 255))
return WEECHAT_RC_ERROR;
gui_chat_printf (NULL,
"%ld -> #%06x",
number,
gui_color_convert_term_to_rgb (number));
return WEECHAT_RC_OK;
}
/* convert RGB color to terminal color */
if (string_strcasecmp (argv[1], "rgb2term") == 0)
{
if (argc < 3)
return WEECHAT_RC_ERROR;
if (sscanf ((argv[2][0] == '#') ? argv[2] + 1 : argv[2], "%x", &rgb) != 1)
return WEECHAT_RC_ERROR;
if (rgb > 0xFFFFFF)
return WEECHAT_RC_ERROR;
limit = 256;
if (argc > 3)
{
error = NULL;
limit = strtol (argv[3], &error, 10);
if (!error || error[0] || (limit < 1) || (limit > 256))
return WEECHAT_RC_ERROR;
}
gui_chat_printf (NULL,
"#%06x -> %d",
rgb,
gui_color_convert_rgb_to_term (rgb, limit));
return WEECHAT_RC_OK;
}
return WEECHAT_RC_ERROR;
}
@@ -6612,16 +6653,25 @@ command_init ()
hook_command (
NULL, "color",
N_("define color aliases and display palette of colors"),
N_("alias <color> <name> || unalias <color> || reset || -o"),
N_(" alias: add an alias for a color\n"
"unalias: delete an alias\n"
" color: color number (greater than or equal to 0, max depends on "
N_("alias <color> <name>"
" || unalias <color>"
" || reset"
" || term2rgb <color>"
" || rgb2term <rgb> [<limit>]"
" || -o"),
N_(" alias: add an alias for a color\n"
" unalias: delete an alias\n"
" color: color number (greater than or equal to 0, max depends on "
"terminal, commonly 63 or 255)\n"
" name: alias name for color (for example: \"orange\")\n"
" reset: reset all color pairs (required when no more color pairs "
" name: alias name for color (for example: \"orange\")\n"
" reset: reset all color pairs (required when no more color pairs "
"are available if automatic reset is disabled, see option "
"weechat.look.color_pairs_auto_reset)\n"
" -o: send terminal/colors info to current buffer as input\n"
"term2rgb: convert a terminal color (0-255) to RGB color\n"
"rgb2term: convert a RGB color to terminal color (0-255)\n"
" limit: number of colors to use in terminal table (starting from "
"0); default is 256\n"
" -o: send terminal/colors info to current buffer as input\n"
"\n"
"Without argument, this command displays colors in a new buffer.\n"
"\n"
@@ -6633,6 +6683,8 @@ command_init ()
"alias %(palette_colors)"
" || unalias %(palette_colors)"
" || reset"
" || term2rgb"
" || rgb2term"
" || -o",
&command_color, NULL);
/*
+7 -7
View File
@@ -1607,15 +1607,15 @@ hook_process_child (struct t_hook *hook_process)
void
hook_process_send_buffers (struct t_hook *hook_process, int callback_rc)
{
int i, size;
int size;
/* add '\0' at end of stdout and stderr */
for (i = 0; i < 2; i++)
{
size = HOOK_PROCESS(hook_process, buffer_size[i]);
if (size > 0)
HOOK_PROCESS(hook_process, buffer[i])[size] = '\0';
}
size = HOOK_PROCESS(hook_process, buffer_size[HOOK_PROCESS_STDOUT]);
if (size > 0)
HOOK_PROCESS(hook_process, buffer[HOOK_PROCESS_STDOUT])[size] = '\0';
size = HOOK_PROCESS(hook_process, buffer_size[HOOK_PROCESS_STDERR]);
if (size > 0)
HOOK_PROCESS(hook_process, buffer[HOOK_PROCESS_STDERR])[size] = '\0';
/* send buffers to callback */
(void) (HOOK_PROCESS(hook_process, callback))
+37 -6
View File
@@ -1146,7 +1146,9 @@ string_replace (const char *string, const char *search, const char *replace)
char *
string_replace_regex_get_replace (const char *string, regmatch_t *regex_match,
int last_match, const char *replace,
const char reference_char)
const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data)
{
int length, length_current, length_add, match;
const char *ptr_replace, *ptr_add;
@@ -1200,8 +1202,26 @@ string_replace_regex_get_replace (const char *string, regmatch_t *regex_match,
}
if (regex_match[match].rm_so >= 0)
{
ptr_add = string + regex_match[match].rm_so;
length_add = regex_match[match].rm_eo - regex_match[match].rm_so;
if (callback)
{
temp = string_strndup (string + regex_match[match].rm_so,
regex_match[match].rm_eo - regex_match[match].rm_so);
if (temp)
{
modified_replace = (*callback) (callback_data, temp);
if (modified_replace)
{
ptr_add = modified_replace;
length_add = strlen (modified_replace);
}
free (temp);
}
}
if (!ptr_add)
{
ptr_add = string + regex_match[match].rm_so;
length_add = regex_match[match].rm_eo - regex_match[match].rm_so;
}
}
}
else if ((ptr_replace[1] == '.')
@@ -1300,6 +1320,11 @@ string_replace_regex_get_replace (const char *string, regmatch_t *regex_match,
* (the char '*' can be replaced by any char between space (32)
* and '~' (126))
*
* If the callback is not NULL, it is called for every reference to a match
* (except for matches replaced by a char).
* If not NULL, the string returned by the callback (which must have been newly
* allocated) is used and freed after use.
*
* Examples:
*
* string | regex | replace | result
@@ -1314,7 +1339,9 @@ string_replace_regex_get_replace (const char *string, regmatch_t *regex_match,
char *
string_replace_regex (const char *string, void *regex, const char *replace,
const char reference_char)
const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data)
{
char *result, *result2, *str_replace;
int length, length_replace, start_offset, i, rc, end, last_match;
@@ -1365,9 +1392,13 @@ string_replace_regex (const char *string, void *regex, const char *replace,
/* check if the regex matched the end of string */
end = !result[regex_match[0].rm_eo];
str_replace = string_replace_regex_get_replace (result, regex_match,
str_replace = string_replace_regex_get_replace (result,
regex_match,
last_match,
replace, reference_char);
replace,
reference_char,
callback,
callback_data);
length_replace = (str_replace) ? strlen (str_replace) : 0;
length = regex_match[0].rm_so + length_replace +
+3 -1
View File
@@ -59,7 +59,9 @@ extern int string_has_highlight_regex_compiled (const char *string,
extern int string_has_highlight_regex (const char *string, const char *regex);
extern char *string_replace_regex (const char *string, void *regex,
const char *replace,
const char reference_char);
const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
extern char **string_split (const char *string, const char *separators,
int keep_eol, int num_items_max, int *num_items);
extern char **string_split_shared (const char *string, const char *separators,
-17
View File
@@ -1539,20 +1539,3 @@ gui_color_dump ()
}
}
}
/*
* Ends GUI colors.
*/
void
gui_color_end ()
{
int i;
for (i = 0; i < GUI_COLOR_NUM_COLORS; i++)
{
gui_color_free (gui_color[i]);
}
gui_color_palette_free_structs ();
gui_color_free_vars ();
}
-1
View File
@@ -86,7 +86,6 @@ extern int gui_color_get_pair (int fg, int bg);
extern int gui_color_weechat_get_pair (int weechat_color);
extern void gui_color_pre_init ();
extern void gui_color_init ();
extern void gui_color_end ();
/* chat functions */
extern void gui_chat_calculate_line_diff (struct t_gui_window *window,
+380
View File
@@ -31,6 +31,7 @@
#include <signal.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>
#include "../core/weechat.h"
#include "../core/wee-config.h"
@@ -51,6 +52,65 @@ struct t_hashtable *gui_color_hash_palette_color = NULL;
struct t_hashtable *gui_color_hash_palette_alias = NULL;
struct t_weelist *gui_color_list_with_alias = NULL;
/* terminal colors */
int gui_color_term256[256] =
{
0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, /* 0-5 */
0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, /* 6-11 */
0x0000ff, 0xff00ff, 0x00ffff, 0xffffff, 0x000000, 0x00005f, /* 12-17 */
0x000087, 0x0000af, 0x0000d7, 0x0000ff, 0x005f00, 0x005f5f, /* 18-23 */
0x005f87, 0x005faf, 0x005fd7, 0x005fff, 0x008700, 0x00875f, /* 24-29 */
0x008787, 0x0087af, 0x0087d7, 0x0087ff, 0x00af00, 0x00af5f, /* 30-35 */
0x00af87, 0x00afaf, 0x00afd7, 0x00afff, 0x00d700, 0x00d75f, /* 36-41 */
0x00d787, 0x00d7af, 0x00d7d7, 0x00d7ff, 0x00ff00, 0x00ff5f, /* 42-47 */
0x00ff87, 0x00ffaf, 0x00ffd7, 0x00ffff, 0x5f0000, 0x5f005f, /* 48-53 */
0x5f0087, 0x5f00af, 0x5f00d7, 0x5f00ff, 0x5f5f00, 0x5f5f5f, /* 54-59 */
0x5f5f87, 0x5f5faf, 0x5f5fd7, 0x5f5fff, 0x5f8700, 0x5f875f, /* 60-65 */
0x5f8787, 0x5f87af, 0x5f87d7, 0x5f87ff, 0x5faf00, 0x5faf5f, /* 66-71 */
0x5faf87, 0x5fafaf, 0x5fafd7, 0x5fafff, 0x5fd700, 0x5fd75f, /* 72-77 */
0x5fd787, 0x5fd7af, 0x5fd7d7, 0x5fd7ff, 0x5fff00, 0x5fff5f, /* 78-83 */
0x5fff87, 0x5fffaf, 0x5fffd7, 0x5fffff, 0x870000, 0x87005f, /* 84-89 */
0x870087, 0x8700af, 0x8700d7, 0x8700ff, 0x875f00, 0x875f5f, /* 90-95 */
0x875f87, 0x875faf, 0x875fd7, 0x875fff, 0x878700, 0x87875f, /* 96-101 */
0x878787, 0x8787af, 0x8787d7, 0x8787ff, 0x87af00, 0x87af5f, /* 102-107 */
0x87af87, 0x87afaf, 0x87afd7, 0x87afff, 0x87d700, 0x87d75f, /* 108-113 */
0x87d787, 0x87d7af, 0x87d7d7, 0x87d7ff, 0x87ff00, 0x87ff5f, /* 114-119 */
0x87ff87, 0x87ffaf, 0x87ffd7, 0x87ffff, 0xaf0000, 0xaf005f, /* 120-125 */
0xaf0087, 0xaf00af, 0xaf00d7, 0xaf00ff, 0xaf5f00, 0xaf5f5f, /* 126-131 */
0xaf5f87, 0xaf5faf, 0xaf5fd7, 0xaf5fff, 0xaf8700, 0xaf875f, /* 132-137 */
0xaf8787, 0xaf87af, 0xaf87d7, 0xaf87ff, 0xafaf00, 0xafaf5f, /* 138-143 */
0xafaf87, 0xafafaf, 0xafafd7, 0xafafff, 0xafd700, 0xafd75f, /* 144-149 */
0xafd787, 0xafd7af, 0xafd7d7, 0xafd7ff, 0xafff00, 0xafff5f, /* 150-155 */
0xafff87, 0xafffaf, 0xafffd7, 0xafffff, 0xd70000, 0xd7005f, /* 156-161 */
0xd70087, 0xd700af, 0xd700d7, 0xd700ff, 0xd75f00, 0xd75f5f, /* 162-167 */
0xd75f87, 0xd75faf, 0xd75fd7, 0xd75fff, 0xd78700, 0xd7875f, /* 168-173 */
0xd78787, 0xd787af, 0xd787d7, 0xd787ff, 0xd7af00, 0xd7af5f, /* 174-179 */
0xd7af87, 0xd7afaf, 0xd7afd7, 0xd7afff, 0xd7d700, 0xd7d75f, /* 180-185 */
0xd7d787, 0xd7d7af, 0xd7d7d7, 0xd7d7ff, 0xd7ff00, 0xd7ff5f, /* 186-191 */
0xd7ff87, 0xd7ffaf, 0xd7ffd7, 0xd7ffff, 0xff0000, 0xff005f, /* 192-197 */
0xff0087, 0xff00af, 0xff00d7, 0xff00ff, 0xff5f00, 0xff5f5f, /* 198-203 */
0xff5f87, 0xff5faf, 0xff5fd7, 0xff5fff, 0xff8700, 0xff875f, /* 204-209 */
0xff8787, 0xff87af, 0xff87d7, 0xff87ff, 0xffaf00, 0xffaf5f, /* 210-215 */
0xffaf87, 0xffafaf, 0xffafd7, 0xffafff, 0xffd700, 0xffd75f, /* 216-221 */
0xffd787, 0xffd7af, 0xffd7d7, 0xffd7ff, 0xffff00, 0xffff5f, /* 222-227 */
0xffff87, 0xffffaf, 0xffffd7, 0xffffff, 0x080808, 0x121212, /* 228-233 */
0x1c1c1c, 0x262626, 0x303030, 0x3a3a3a, 0x444444, 0x4e4e4e, /* 234-239 */
0x585858, 0x626262, 0x6c6c6c, 0x767676, 0x808080, 0x8a8a8a, /* 240-245 */
0x949494, 0x9e9e9e, 0xa8a8a8, 0xb2b2b2, 0xbcbcbc, 0xc6c6c6, /* 246-251 */
0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee, /* 252-255 */
};
/* ANSI colors */
regex_t *gui_color_regex_ansi = NULL;
char *gui_color_ansi[16] =
{
/* 0-7 */
"black", "red", "green", "brown", "blue", "magenta", "cyan", "gray",
/* 8-15 */
"darkgray", "lightred", "lightgreen", "yellow", "lightblue", "lightmagenta",
"lightcyan", "white",
};
/*
* Searches for a color with configuration option name.
@@ -400,6 +460,68 @@ gui_color_get_custom (const char *color_name)
return color[index_color];
}
/*
* Converts a terminal color to its RGB value.
*
* Returns a RGB color as integer.
*/
int
gui_color_convert_term_to_rgb (int color)
{
if ((color < 0) || (color > 255))
return 0;
return gui_color_term256[color];
}
/*
* Converts a RGB color to the closest terminal color.
*
* Argument "limit" is the number of colors to check in the table of terminal
* colors (starting from 0). So for example 256 will return any of the 256
* colors, 16 will return a color between 0 and 15.
*
* Returns the closest terminal color (0-255).
*/
int
gui_color_convert_rgb_to_term (int rgb, int limit)
{
int i, r1, g1, b1, r2, g2, b2, diff, best_diff, best_color;
r1 = rgb >> 16;
g1 = (rgb >> 8) & 0xFF;
b1 = rgb & 0xFF;
best_diff = INT_MAX;
best_color = 0;
for (i = 0; i < limit; i++)
{
r2 = gui_color_term256[i] >> 16;
g2 = (gui_color_term256[i] >> 8) & 0xFF;
b2 = gui_color_term256[i] & 0xFF;
diff = ((r2 - r1) * (r2 - r1)) +
((g2 - g1) * (g2 - g1)) +
((b2 - b1) * (b2 - b1));
/* exact match! */
if (diff == 0)
return i;
if (diff < best_diff)
{
best_color = i;
best_diff = diff;
}
}
/* return the closest color */
return best_color;
}
/*
* Removes WeeChat color codes from a message.
*
@@ -593,6 +715,240 @@ gui_color_decode (const char *string, const char *replacement)
return (char *)out;
}
/*
* Converts ANSI color codes to WeeChat colors (or removes them).
*
* This callback is called by gui_color_decode_ansi, it must not be called
* directly.
*/
char *
gui_color_decode_ansi_cb (void *data, const char *text)
{
unsigned long keep_colors;
char *text2, **items, *output, str_color[128];
int i, length, num_items, value;
keep_colors = (unsigned long)data;
/* if we don't keep colors of if text is empty, just return empty string */
if (!keep_colors || !text || !text[0])
return strdup ("");
/* only sequences ending with 'm' are used, the others are discarded */
length = strlen (text);
if (text[length - 1] != 'm')
return strdup ("");
/* sequence "\33[m" resets color */
if (length < 4)
return strdup (gui_color_get_custom ("reset"));
text2 = NULL;
items = NULL;
output = NULL;
/* extract text between "\33[" and "m" */
text2 = string_strndup (text + 2, length - 3);
if (!text2)
goto end;
items = string_split (text2, ";", 0, 0, &num_items);
if (!items)
goto end;
output = malloc ((32 * num_items) + 1);
if (!output)
goto end;
output[0] = '\0';
for (i = 0; i < num_items; i++)
{
value = atoi (items[i]);
switch (value)
{
case 0: /* reset */
strcat (output, gui_color_get_custom ("reset"));
break;
case 1: /* bold */
strcat (output, gui_color_get_custom ("bold"));
break;
case 2: /* remove bold */
case 21:
case 22:
strcat (output, gui_color_get_custom ("-bold"));
break;
case 3: /* italic */
strcat (output, gui_color_get_custom ("italic"));
break;
case 4: /* underline */
strcat (output, gui_color_get_custom ("underline"));
break;
case 23: /* remove italic */
strcat (output, gui_color_get_custom ("-italic"));
break;
case 24: /* remove underline */
strcat (output, gui_color_get_custom ("-underline"));
break;
case 30: /* text color */
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
strcat (output,
gui_color_get_custom (gui_color_ansi[value - 30]));
break;
case 38: /* text color */
if (i + 1 < num_items)
{
switch (atoi (items[i + 1]))
{
case 2: /* RGB color */
if (i + 4 < num_items)
{
snprintf (str_color, sizeof (str_color),
"|%d",
gui_color_convert_rgb_to_term (
(atoi (items[i + 2]) << 16) |
(atoi (items[i + 3]) << 8) |
atoi (items[i + 4]),
256));
strcat (output, gui_color_get_custom (str_color));
i += 4;
}
break;
case 5: /* terminal color (0-255) */
if (i + 2 < num_items)
{
snprintf (str_color, sizeof (str_color),
"|%d", atoi (items[i + 2]));
strcat (output, gui_color_get_custom (str_color));
i += 2;
}
break;
}
}
break;
case 39: /* default text color */
strcat (output, gui_color_get_custom ("default"));
break;
case 40: /* background color */
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
snprintf (str_color, sizeof (str_color),
"|,%s",
gui_color_ansi[value - 40]);
strcat (output, gui_color_get_custom (str_color));
break;
case 48: /* background color */
if (i + 1 < num_items)
{
switch (atoi (items[i + 1]))
{
case 2: /* RGB color */
if (i + 4 < num_items)
{
snprintf (str_color, sizeof (str_color),
"|,%d",
gui_color_convert_rgb_to_term (
(atoi (items[i + 2]) << 16) |
(atoi (items[i + 3]) << 8) |
atoi (items[i + 4]),
256));
strcat (output, gui_color_get_custom (str_color));
i += 4;
}
break;
case 5: /* terminal color (0-255) */
if (i + 2 < num_items)
{
snprintf (str_color, sizeof (str_color),
"|,%d", atoi (items[i + 2]));
strcat (output, gui_color_get_custom (str_color));
i += 2;
}
break;
}
}
break;
case 49: /* default background color */
strcat (output, gui_color_get_custom (",default"));
break;
case 90: /* text color (bright) */
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
strcat (output,
gui_color_get_custom (gui_color_ansi[value - 90 + 8]));
break;
case 100: /* background color (bright) */
case 101:
case 102:
case 103:
case 104:
case 105:
case 106:
case 107:
snprintf (str_color, sizeof (str_color),
"|,%s",
gui_color_ansi[value - 100 + 8]);
strcat (output, gui_color_get_custom (str_color));
break;
}
}
end:
if (items)
string_free_split (items);
if (text2)
free (text2);
return (output) ? output : strdup ("");
}
/*
* Converts ANSI color codes to WeeChat colors (or removes them).
*
* Note: result must be freed after use.
*/
char *
gui_color_decode_ansi (const char *string, int keep_colors)
{
/* allocate/compile regex if needed (first call) */
if (!gui_color_regex_ansi)
{
gui_color_regex_ansi = malloc (sizeof (*gui_color_regex_ansi));
if (!gui_color_regex_ansi)
return NULL;
if (string_regcomp (gui_color_regex_ansi,
GUI_COLOR_REGEX_ANSI_DECODE,
REG_EXTENDED) != 0)
{
free (gui_color_regex_ansi);
gui_color_regex_ansi = NULL;
return NULL;
}
}
return string_replace_regex (string, gui_color_regex_ansi,
"$0", '$',
&gui_color_decode_ansi_cb,
(void *)((unsigned long)keep_colors));
}
/*
* Emphasizes a string or regular expression in a string (which can contain
* colors).
@@ -916,3 +1272,27 @@ gui_color_palette_free_structs ()
if (gui_color_list_with_alias)
weelist_free (gui_color_list_with_alias);
}
/*
* Ends GUI colors.
*/
void
gui_color_end ()
{
int i;
for (i = 0; i < GUI_COLOR_NUM_COLORS; i++)
{
gui_color_free (gui_color[i]);
}
gui_color_palette_free_structs ();
gui_color_free_vars ();
if (gui_color_regex_ansi)
{
regfree (gui_color_regex_ansi);
free (gui_color_regex_ansi);
gui_color_regex_ansi = NULL;
}
}
+11 -1
View File
@@ -138,6 +138,12 @@ enum t_gui_color_enum
#define GUI_COLOR_EXTENDED_MASK 0x00FFFFF
#define GUI_COLOR_EXTENDED_MAX 99999
#define GUI_COLOR_REGEX_ANSI_DECODE \
"\33(" \
"([()].)|" \
"([<>])|" \
"(\\[[0-9;?]*[A-Za-z]))"
/* color structure */
struct t_gui_color
@@ -169,7 +175,10 @@ extern const char *gui_color_search_config (const char *color_name);
extern int gui_color_attr_get_flag (char c);
extern void gui_color_attr_build_string (int color, char *str_attr);
extern const char *gui_color_get_custom (const char *color_name);
extern int gui_color_convert_term_to_rgb (int color);
extern int gui_color_convert_rgb_to_term (int rgb, int limit);
extern char *gui_color_decode (const char *string, const char *replacement);
extern char *gui_color_decode_ansi (const char *string, int keep_colors);
extern char *gui_color_emphasize (const char *string, const char *search,
int case_sensitive, regex_t *regex);
extern void gui_color_free (struct t_gui_color *color);
@@ -178,7 +187,7 @@ extern int gui_color_palette_get_alias (const char *alias);
extern struct t_gui_color_palette *gui_color_palette_get (int number);
extern void gui_color_palette_add (int number, const char *value);
extern void gui_color_palette_remove (int number);
extern void gui_color_palette_free_structs ();
extern void gui_color_end ();
/* color functions (GUI dependent) */
@@ -189,6 +198,7 @@ extern int gui_color_assign_by_diff (int *color, const char *color_name,
extern int gui_color_get_weechat_colors_number ();
extern int gui_color_get_term_colors ();
extern const char *gui_color_get_name (int num_color);
extern void gui_color_free_vars ();
extern void gui_color_init_weechat ();
extern void gui_color_display_terminal_colors ();
extern void gui_color_info_term_colors (char *buffer, int size);
+4
View File
@@ -72,6 +72,10 @@ IF(ENABLE_CHARSET)
ENDIF(ICONV_FOUND)
ENDIF(ENABLE_CHARSET)
IF(ENABLE_EXEC)
ADD_SUBDIRECTORY( exec )
ENDIF(ENABLE_EXEC)
IF(ENABLE_FIFO)
ADD_SUBDIRECTORY( fifo )
ENDIF(ENABLE_FIFO)
+8 -4
View File
@@ -51,6 +51,10 @@ if PLUGIN_CHARSET
charset_dir = charset
endif
if PLUGIN_EXEC
exec_dir = exec
endif
if PLUGIN_FIFO
fifo_dir = fifo
endif
@@ -103,10 +107,10 @@ if PLUGIN_XFER
xfer_dir = xfer
endif
SUBDIRS = . $(alias_dir) $(aspell_dir) $(charset_dir) $(fifo_dir) $(irc_dir) \
$(logger_dir) $(relay_dir) $(script_dir) $(perl_dir) $(python_dir) \
$(ruby_dir) $(lua_dir) $(tcl_dir) $(guile_dir) $(trigger_dir) \
$(xfer_dir)
SUBDIRS = . $(alias_dir) $(aspell_dir) $(charset_dir) $(exec_dir) $(fifo_dir) \
$(irc_dir) $(logger_dir) $(relay_dir) $(script_dir) $(perl_dir) \
$(python_dir) $(ruby_dir) $(lua_dir) $(tcl_dir) $(guile_dir) \
$(trigger_dir) $(xfer_dir)
EXTRA_DIST = CMakeLists.txt
+30
View File
@@ -0,0 +1,30 @@
#
# Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
#
# This file is part of WeeChat, the extensible chat client.
#
# WeeChat is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# WeeChat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
#
ADD_LIBRARY(exec MODULE
exec.c exec.h
exec-buffer.c exec-buffer.h
exec-command.c exec-command.h
exec-completion.c exec-completion.h
exec-config.c exec-config.h)
SET_TARGET_PROPERTIES(exec PROPERTIES PREFIX "")
TARGET_LINK_LIBRARIES(exec)
INSTALL(TARGETS exec LIBRARY DESTINATION ${LIBDIR}/plugins)
+40
View File
@@ -0,0 +1,40 @@
#
# Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
#
# This file is part of WeeChat, the extensible chat client.
#
# WeeChat is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# WeeChat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
#
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(EXEC_CFLAGS)
libdir = ${weechat_libdir}/plugins
lib_LTLIBRARIES = exec.la
exec_la_SOURCES = exec.c \
exec.h \
exec-buffer.c \
exec-buffer.h \
exec-command.c \
exec-command.h \
exec-completion.c \
exec-completion.h \
exec-config.c \
exec-config.h
exec_la_LDFLAGS = -module -no-undefined
exec_la_LIBADD = $(EXEC_LFLAGS)
EXTRA_DIST = CMakeLists.txt
+146
View File
@@ -0,0 +1,146 @@
/*
* exec-buffer.c - buffers with output of commands
*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "exec.h"
#include "exec-buffer.h"
#include "exec-command.h"
#include "exec-config.h"
/*
* Callback for user data in an exec buffer.
*/
int
exec_buffer_input_cb (void *data, struct t_gui_buffer *buffer,
const char *input_data)
{
char **argv, **argv_eol;
int argc;
/* make C compiler happy */
(void) data;
/* close buffer */
if (strcmp (input_data, "q") == 0)
{
weechat_buffer_close (buffer);
return WEECHAT_RC_OK;
}
argv = weechat_string_split (input_data, " ", 0, 0, &argc);
argv_eol = weechat_string_split (input_data, " ", 1, 0, NULL);
if (argv && argv_eol)
exec_command_run (buffer, argc, argv, argv_eol, 0);
if (argv)
weechat_string_free_split (argv);
if (argv_eol)
weechat_string_free_split (argv_eol);
return WEECHAT_RC_OK;
}
/*
* Callback called when an exec buffer is closed.
*/
int
exec_buffer_close_cb (void *data, struct t_gui_buffer *buffer)
{
/* make C compiler happy */
(void) data;
(void) buffer;
return WEECHAT_RC_OK;
}
/*
* Restore buffer callbacks (input and close) for buffers created by exec
* plugin.
*/
void
exec_buffer_set_callbacks ()
{
struct t_infolist *ptr_infolist;
struct t_gui_buffer *ptr_buffer;
const char *plugin_name;
ptr_infolist = weechat_infolist_get ("buffer", NULL, "");
if (ptr_infolist)
{
while (weechat_infolist_next (ptr_infolist))
{
ptr_buffer = weechat_infolist_pointer (ptr_infolist, "pointer");
plugin_name = weechat_infolist_string (ptr_infolist, "plugin_name");
if (ptr_buffer && plugin_name
&& (strcmp (plugin_name, EXEC_PLUGIN_NAME) == 0))
{
weechat_buffer_set_pointer (ptr_buffer, "close_callback",
&exec_buffer_close_cb);
weechat_buffer_set_pointer (ptr_buffer, "input_callback",
&exec_buffer_input_cb);
}
}
weechat_infolist_free (ptr_infolist);
}
}
/*
* Creates a new exec buffer for a command.
*/
struct t_gui_buffer *
exec_buffer_new (const char *name, int switch_to_buffer)
{
struct t_gui_buffer *new_buffer;
new_buffer = weechat_buffer_search (EXEC_PLUGIN_NAME, name);
if (new_buffer)
goto end;
new_buffer = weechat_buffer_new (name,
&exec_buffer_input_cb, NULL,
&exec_buffer_close_cb, NULL);
/* failed to create buffer ? then return */
if (!new_buffer)
return NULL;
weechat_buffer_set (new_buffer, "title", _("Executed commands"));
weechat_buffer_set (new_buffer, "localvar_set_type", "exec");
weechat_buffer_set (new_buffer, "localvar_set_no_log", "1");
weechat_buffer_set (new_buffer, "time_for_each_line", "0");
weechat_buffer_set (new_buffer, "input_get_unknown_commands", "0");
end:
if (switch_to_buffer)
weechat_buffer_set (new_buffer, "display", "1");
return new_buffer;
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_EXEC_BUFFER_H
#define __WEECHAT_EXEC_BUFFER_H 1
extern void exec_buffer_set_callbacks ();
extern struct t_gui_buffer *exec_buffer_new (const char *name,
int switch_to_buffer);
#endif /* __WEECHAT_EXEC_BUFFER_H */
+753
View File
@@ -0,0 +1,753 @@
/*
* exec-command.c - exec command
*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "exec.h"
#include "exec-buffer.h"
#include "exec-command.h"
#include "exec-config.h"
/*
* Displays a list of executed commands.
*/
void
exec_command_list ()
{
struct t_exec_cmd *ptr_exec_cmd;
char str_elapsed[32], str_time1[256], str_time2[256];
time_t elapsed_time;
struct tm *local_time;
weechat_printf (NULL, "");
if (!exec_cmds)
{
weechat_printf (NULL, _("No command is running"));
return;
}
weechat_printf (NULL, _("Commands:"));
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
elapsed_time = (ptr_exec_cmd->end_time == 0) ?
time (NULL) - ptr_exec_cmd->start_time :
ptr_exec_cmd->end_time - ptr_exec_cmd->start_time;
if (elapsed_time >= 3600)
{
snprintf (str_elapsed, sizeof (str_elapsed),
/* TRANSLATORS: format: hours + minutes, for example: 3h59 */
_("%dh%02d"),
elapsed_time / 3600,
elapsed_time % 3600);
}
else if (elapsed_time >= 60)
{
snprintf (str_elapsed, sizeof (str_elapsed),
/* TRANSLATORS: format: minutes + seconds, for example: 3m59 */
_("%dm%02d"),
elapsed_time / 60,
elapsed_time % 60);
}
else
{
snprintf (str_elapsed, sizeof (str_elapsed),
/* TRANSLATORS: format: seconds, for example: 59s */
_("%ds"),
elapsed_time);
}
if (ptr_exec_cmd->end_time == 0)
{
/* running command */
weechat_printf (NULL,
/* TRANSLATORS: %s before "ago" is elapsed time, for example: "3m59" */
_(" %s%s%s %d%s%s%s: %s\"%s%s%s\"%s (pid: %d, "
"started %s ago)"),
weechat_color (weechat_config_string (exec_config_color_flag_running)),
">>",
weechat_color ("reset"),
ptr_exec_cmd->number,
(ptr_exec_cmd->name) ? " (" : "",
(ptr_exec_cmd->name) ? ptr_exec_cmd->name : "",
(ptr_exec_cmd->name) ? ")" : "",
weechat_color ("chat_delimiters"),
weechat_color ("reset"),
ptr_exec_cmd->command,
weechat_color ("chat_delimiters"),
weechat_color ("reset"),
ptr_exec_cmd->pid,
str_elapsed);
}
else
{
/* process has ended */
local_time = localtime (&ptr_exec_cmd->start_time);
strftime (str_time1, sizeof (str_time1),
"%Y-%m-%d %H:%M:%S", local_time);
local_time = localtime (&ptr_exec_cmd->end_time);
strftime (str_time2, sizeof (str_time2),
"%Y-%m-%d %H:%M:%S", local_time);
weechat_printf (NULL,
" %s%s%s %d%s%s%s: %s\"%s%s%s\"%s (%s -> %s, %s)",
weechat_color (weechat_config_string (exec_config_color_flag_finished)),
"[]",
weechat_color ("reset"),
ptr_exec_cmd->number,
(ptr_exec_cmd->name) ? " (" : "",
(ptr_exec_cmd->name) ? ptr_exec_cmd->name : "",
(ptr_exec_cmd->name) ? ")" : "",
weechat_color ("chat_delimiters"),
weechat_color ("reset"),
ptr_exec_cmd->command,
weechat_color ("chat_delimiters"),
weechat_color ("reset"),
str_time1,
str_time2,
str_elapsed);
}
}
}
/*
* Searches a running command by id, and displays an error if command is not
* found or not running any more.
*
* Returns the command found, or NULL if not found or not running.
*/
struct t_exec_cmd *
exec_command_search_running_id (const char *id)
{
struct t_exec_cmd *ptr_exec_cmd;
ptr_exec_cmd = exec_search_by_id (id);
if (!ptr_exec_cmd)
{
weechat_printf (NULL, _("%s%s: command id \"%s\" not found"),
weechat_prefix ("error"), EXEC_PLUGIN_NAME, id);
return NULL;
}
if (!ptr_exec_cmd->hook)
{
weechat_printf (NULL,
_("%s%s: command with id \"%s\" is not running any "
"more"),
weechat_prefix ("error"), EXEC_PLUGIN_NAME, id);
return NULL;
}
return ptr_exec_cmd;
}
/*
* Parse command options.
*
* Returns:
* 1: options parsed successfully
* 0: error parsing options
*/
int
exec_command_parse_options (struct t_exec_cmd_options *cmd_options,
int argc, char **argv, int start_arg,
int set_command_index)
{
int i;
char *error;
for (i = start_arg; i < argc; i++)
{
if (weechat_strcasecmp (argv[i], "-sh") == 0)
{
cmd_options->use_shell = 1;
}
else if (weechat_strcasecmp (argv[i], "-nosh") == 0)
{
cmd_options->use_shell = 0;
}
else if (weechat_strcasecmp (argv[i], "-bg") == 0)
{
cmd_options->detached = 1;
}
else if (weechat_strcasecmp (argv[i], "-nobg") == 0)
{
cmd_options->detached = 0;
}
else if (weechat_strcasecmp (argv[i], "-stdin") == 0)
{
cmd_options->pipe_stdin = 1;
}
else if (weechat_strcasecmp (argv[i], "-nostdin") == 0)
{
cmd_options->pipe_stdin = 0;
}
else if (weechat_strcasecmp (argv[i], "-buffer") == 0)
{
if (i + 1 >= argc)
return 0;
i++;
cmd_options->ptr_buffer_name = argv[i];
cmd_options->ptr_buffer = weechat_buffer_search ("==", argv[i]);
if (cmd_options->ptr_buffer
&& (weechat_buffer_get_integer (cmd_options->ptr_buffer, "type") != 0))
{
/* only a buffer with formatted content is allowed */
return 0;
}
if (!cmd_options->ptr_buffer)
cmd_options->new_buffer = 1;
}
else if (weechat_strcasecmp (argv[i], "-l") == 0)
{
cmd_options->output_to_buffer = 0;
cmd_options->new_buffer = 0;
}
else if (weechat_strcasecmp (argv[i], "-o") == 0)
{
cmd_options->output_to_buffer = 1;
cmd_options->new_buffer = 0;
}
else if (weechat_strcasecmp (argv[i], "-n") == 0)
{
cmd_options->output_to_buffer = 0;
cmd_options->new_buffer = 1;
}
else if (weechat_strcasecmp (argv[i], "-sw") == 0)
{
cmd_options->switch_to_buffer = 1;
}
else if (weechat_strcasecmp (argv[i], "-nosw") == 0)
{
cmd_options->switch_to_buffer = 0;
}
else if (weechat_strcasecmp (argv[i], "-ln") == 0)
{
cmd_options->line_numbers = 1;
}
else if (weechat_strcasecmp (argv[i], "-noln") == 0)
{
cmd_options->line_numbers = 0;
}
else if (weechat_strcasecmp (argv[i], "-color") == 0)
{
if (i + 1 >= argc)
return 0;
i++;
cmd_options->color = exec_search_color (argv[i]);
if (cmd_options->color < 0)
return 0;
}
else if (weechat_strcasecmp (argv[i], "-rc") == 0)
{
cmd_options->display_rc = 1;
}
else if (weechat_strcasecmp (argv[i], "-norc") == 0)
{
cmd_options->display_rc = 0;
}
else if (weechat_strcasecmp (argv[i], "-timeout") == 0)
{
if (i + 1 >= argc)
return 0;
i++;
error = NULL;
cmd_options->timeout = strtol (argv[i], &error, 10);
if (!error || error[0])
return 0;
}
else if (weechat_strcasecmp (argv[i], "-name") == 0)
{
if (i + 1 >= argc)
return 0;
i++;
cmd_options->ptr_command_name = argv[i];
}
else
{
if (set_command_index)
{
cmd_options->command_index = i;
break;
}
else
return 0;
}
}
return 1;
}
/*
* Runs a command.
*
* Returns:
* WEECHAT_RC_OK: command run successfully
* WEECHAT_RC_ERROR: error running command
*/
int
exec_command_run (struct t_gui_buffer *buffer,
int argc, char **argv, char **argv_eol, int start_arg)
{
char str_buffer[512];
struct t_exec_cmd *new_exec_cmd;
struct t_exec_cmd_options cmd_options;
struct t_hashtable *process_options;
struct t_infolist *ptr_infolist;
struct t_gui_buffer *new_buffer;
/* parse command options */
cmd_options.command_index = -1;
cmd_options.use_shell = 1;
cmd_options.detached = 0;
cmd_options.pipe_stdin = 0;
cmd_options.timeout = 0;
cmd_options.ptr_buffer_name = NULL;
cmd_options.ptr_buffer = buffer;
cmd_options.output_to_buffer = 0;
cmd_options.new_buffer = 0;
cmd_options.switch_to_buffer = 1;
cmd_options.line_numbers = -1;
cmd_options.color = EXEC_COLOR_DECODE;
cmd_options.display_rc = 1;
cmd_options.ptr_command_name = NULL;
/* parse default options */
if (!exec_command_parse_options (&cmd_options,
exec_config_cmd_num_options,
exec_config_cmd_options,
0, 0))
{
weechat_printf (NULL,
_("%s%s: invalid options in option "
"exec.command.default_options"),
weechat_prefix ("error"), EXEC_PLUGIN_NAME);
return WEECHAT_RC_ERROR;
}
if (!exec_command_parse_options (&cmd_options, argc, argv, start_arg, 1))
return WEECHAT_RC_ERROR;
/* options "-bg" and "-o"/"-n" are incompatible */
if (cmd_options.detached
&& (cmd_options.output_to_buffer || cmd_options.new_buffer))
return WEECHAT_RC_ERROR;
/* command not found? */
if (cmd_options.command_index < 0)
return WEECHAT_RC_ERROR;
new_exec_cmd = exec_add ();
if (!new_exec_cmd)
return WEECHAT_RC_ERROR;
/* create hashtable for weechat_hook_process_hashtable() */
process_options = weechat_hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
if (!process_options)
{
exec_free (new_exec_cmd);
return WEECHAT_RC_ERROR;
}
/* automatically disable shell if we are downloading an URL */
if (strncmp (argv_eol[cmd_options.command_index], "url:", 4) == 0)
cmd_options.use_shell = 0;
if (cmd_options.use_shell)
{
/* command will be: sh -c "command arguments..." */
weechat_hashtable_set (process_options, "arg1", "-c");
weechat_hashtable_set (process_options, "arg2",
argv_eol[cmd_options.command_index]);
}
if (cmd_options.pipe_stdin)
weechat_hashtable_set (process_options, "stdin", "1");
if (cmd_options.detached)
weechat_hashtable_set (process_options, "detached", "1");
/* set variables in new command (before running the command) */
new_exec_cmd->name = (cmd_options.ptr_command_name) ?
strdup (cmd_options.ptr_command_name) : NULL;
new_exec_cmd->command = strdup (argv_eol[cmd_options.command_index]);
new_exec_cmd->detached = cmd_options.detached;
if (cmd_options.ptr_buffer_name && !cmd_options.ptr_buffer)
{
/* output in a new buffer using given name */
new_exec_cmd->output_to_buffer = 0;
snprintf (str_buffer, sizeof (str_buffer),
"exec.%s", cmd_options.ptr_buffer_name);
new_buffer = exec_buffer_new (str_buffer, cmd_options.switch_to_buffer);
if (new_buffer)
{
new_exec_cmd->buffer_full_name =
strdup (weechat_buffer_get_string (new_buffer, "full_name"));
}
}
else if (cmd_options.new_buffer)
{
/* output in a new buffer using automatic name */
if (new_exec_cmd->name)
{
snprintf (str_buffer, sizeof (str_buffer),
"exec.%s", new_exec_cmd->name);
}
else
{
snprintf (str_buffer, sizeof (str_buffer),
"exec.%d", new_exec_cmd->number);
}
new_buffer = exec_buffer_new (str_buffer, cmd_options.switch_to_buffer);
if (new_buffer)
{
new_exec_cmd->buffer_full_name =
strdup (weechat_buffer_get_string (new_buffer, "full_name"));
}
}
else if (cmd_options.ptr_buffer)
{
new_exec_cmd->buffer_full_name =
strdup (weechat_buffer_get_string (cmd_options.ptr_buffer,
"full_name"));
if (cmd_options.switch_to_buffer)
weechat_buffer_set (cmd_options.ptr_buffer, "display", "1");
}
if (cmd_options.ptr_buffer
&& (strcmp (weechat_buffer_get_string (cmd_options.ptr_buffer, "plugin"),
EXEC_PLUGIN_NAME) == 0))
{
cmd_options.output_to_buffer = 0;
cmd_options.new_buffer = 1;
}
new_exec_cmd->output_to_buffer = cmd_options.output_to_buffer;
new_exec_cmd->line_numbers = (cmd_options.line_numbers < 0) ?
cmd_options.new_buffer : cmd_options.line_numbers;
new_exec_cmd->color = cmd_options.color;
new_exec_cmd->display_rc = cmd_options.display_rc;
/* execute the command */
if (weechat_exec_plugin->debug >= 1)
{
weechat_printf (NULL, "%s: executing command: \"%s%s%s\"",
EXEC_PLUGIN_NAME,
(cmd_options.use_shell) ? "" : "sh -c '",
argv_eol[cmd_options.command_index],
(cmd_options.use_shell) ? "" : "'");
}
new_exec_cmd->hook = weechat_hook_process_hashtable (
(cmd_options.use_shell) ? "sh" : argv_eol[cmd_options.command_index],
process_options,
cmd_options.timeout * 1000,
&exec_process_cb,
new_exec_cmd);
if (new_exec_cmd->hook)
{
/* get PID of command */
ptr_infolist = weechat_infolist_get ("hook", new_exec_cmd->hook, NULL);
if (ptr_infolist)
{
if (weechat_infolist_next (ptr_infolist))
{
new_exec_cmd->pid = weechat_infolist_integer (ptr_infolist,
"child_pid");
}
weechat_infolist_free (ptr_infolist);
}
}
else
{
exec_free (new_exec_cmd);
weechat_printf (NULL,
_("%s%s: failed to run command \"%s\""),
weechat_prefix ("error"), EXEC_PLUGIN_NAME,
argv_eol[cmd_options.command_index]);
}
weechat_hashtable_free (process_options);
return WEECHAT_RC_OK;
}
/*
* Callback for command "/exec": manage executed commands.
*/
int
exec_command_exec (void *data, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
int i, length, count;
char *text;
struct t_exec_cmd *ptr_exec_cmd, *ptr_next_exec_cmd;
/* make C compiler happy */
(void) data;
(void) buffer;
/* list running commands */
if ((argc == 1)
|| ((argc == 2) && (weechat_strcasecmp (argv[1], "-list") == 0)))
{
exec_command_list ();
return WEECHAT_RC_OK;
}
/* send text to a running process */
if (weechat_strcasecmp (argv[1], "-in") == 0)
{
if (argc < 4)
return WEECHAT_RC_ERROR;
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
if (ptr_exec_cmd && ptr_exec_cmd->hook)
{
length = strlen (argv_eol[3]) + 1 + 1;
text = malloc (length);
if (text)
{
snprintf (text, length, "%s\n", argv_eol[3]);
weechat_hook_set (ptr_exec_cmd->hook, "stdin", text);
free (text);
}
}
return WEECHAT_RC_OK;
}
/* send text to a running process (if given), then close stdin */
if (weechat_strcasecmp (argv[1], "-inclose") == 0)
{
if (argc < 3)
return WEECHAT_RC_ERROR;
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
if (ptr_exec_cmd && ptr_exec_cmd->hook)
{
if (argc > 3)
{
length = strlen (argv_eol[3]) + 1 + 1;
text = malloc (length);
if (text)
{
snprintf (text, length, "%s\n", argv_eol[3]);
weechat_hook_set (ptr_exec_cmd->hook, "stdin", text);
free (text);
}
}
weechat_hook_set (ptr_exec_cmd->hook, "stdin_close", "1");
}
return WEECHAT_RC_OK;
}
/* send a signal to a running process */
if (weechat_strcasecmp (argv[1], "-signal") == 0)
{
if (argc < 4)
return WEECHAT_RC_ERROR;
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
if (ptr_exec_cmd)
weechat_hook_set (ptr_exec_cmd->hook, "signal", argv[3]);
return WEECHAT_RC_OK;
}
/* send a KILL signal to a running process */
if (weechat_strcasecmp (argv[1], "-kill") == 0)
{
if (argc < 3)
return WEECHAT_RC_ERROR;
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
if (ptr_exec_cmd)
weechat_hook_set (ptr_exec_cmd->hook, "signal", "kill");
return WEECHAT_RC_OK;
}
/* send a KILL signal to all running processes */
if (weechat_strcasecmp (argv[1], "-killall") == 0)
{
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
if (ptr_exec_cmd->hook)
{
weechat_hook_set (ptr_exec_cmd->hook, "signal", "kill");
}
}
return WEECHAT_RC_OK;
}
/* set a hook property */
if (weechat_strcasecmp (argv[1], "-set") == 0)
{
if (argc < 5)
return WEECHAT_RC_ERROR;
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
if (ptr_exec_cmd)
weechat_hook_set (ptr_exec_cmd->hook, argv[3], argv_eol[4]);
return WEECHAT_RC_OK;
}
/* delete terminated command(s) */
if (weechat_strcasecmp (argv[1], "-del") == 0)
{
if (argc < 3)
return WEECHAT_RC_ERROR;
if (weechat_strcasecmp (argv[2], "-all") == 0)
{
count = 0;
ptr_exec_cmd = exec_cmds;
while (ptr_exec_cmd)
{
ptr_next_exec_cmd = ptr_exec_cmd->next_cmd;
if (!ptr_exec_cmd->hook)
{
exec_free (ptr_exec_cmd);
count++;
}
ptr_exec_cmd = ptr_next_exec_cmd;
}
weechat_printf (NULL, _("%d commands removed"), count);
}
else
{
for (i = 2; i < argc; i++)
{
ptr_exec_cmd = exec_search_by_id (argv[i]);
if (ptr_exec_cmd)
{
if (ptr_exec_cmd->hook)
{
weechat_printf (NULL,
_("%s%s: command with id \"%s\" is still "
"running"),
weechat_prefix ("error"), EXEC_PLUGIN_NAME,
argv[i]);
}
else
{
exec_free (ptr_exec_cmd);
weechat_printf (NULL,
_("Command \"%s\" removed"), argv[i]);
}
}
else
{
weechat_printf (NULL,
_("%s%s: command id \"%s\" not found"),
weechat_prefix ("error"), EXEC_PLUGIN_NAME,
argv[i]);
}
}
}
return WEECHAT_RC_OK;
}
return exec_command_run (buffer, argc, argv, argv_eol, 1);
}
/*
* Hooks exec commands.
*/
void
exec_command_init ()
{
weechat_hook_command (
"exec",
N_("execute external commands"),
N_("-list"
" || [-sh|-nosh] [-bg|-nobg] [-stdin|-nostdin] [-buffer <name>] "
"[-l|-o|-n] |-sw|-nosw] [-ln|-noln] [-color off|decode|strip] "
"[-rc|-norc] [-timeout <timeout>] [-name <name>] <command>"
" || -in <id> <text>"
" || -inclose <id> [<text>]"
" || -signal <id> <signal>"
" || -kill <id>"
" || -killall"
" || -set <id> <property> <value>"
" || -del <id>|-all [<id>...]"),
N_(" -list: list commands\n"
" -sh: use the shell to execute the command (default)\n"
" -nosh: do not use the shell to execute the command (required if "
"the command has some unsafe data, for example the content of a "
"message from another user)\n"
" -bg: run process in background: do not display process output "
"neither return code (not compatible with option -o/-n)\n"
" -nobg: catch process output and display return code (default)\n"
" -stdin: create a pipe for sending data to the process (with "
"/exec -in)\n"
"-nostdin: do not create a pipe for stdin (default)\n"
" -buffer: display/send output of command on this buffer (if the "
"buffer is not found, a new buffer with name \"exec.exec.xxx\" is "
"created)\n"
" -l: display locally output of command on buffer (default)\n"
" -o: send output of command to the buffer "
"(not compatible with option -bg)\n"
" -n: display output of command in a new buffer (not compatible "
"with -bg)\n"
" -sw: switch to the output buffer (default)\n"
" -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"
" -color: action on ANSI colors in output:\n"
" off: keep ANSI codes as-is\n"
" decode: convert ANSI colors to WeeChat/IRC (default)\n"
" strip: remove ANSI colors\n"
" -rc: display return code (default)\n"
" -norc: don't display return code\n"
"-timeout: set a timeout for the command (in seconds)\n"
" -name: set a name for the command (to name it later with /exec)\n"
" command: the command to execute; if beginning with \"url:\", the "
"shell is disabled and the content of URL is downloaded and sent as "
"output\n"
" id: command identifier: either its number or name (if set "
"with \"-name xxx\")\n"
" -in: send text on standard input of process\n"
"-inclose: same a -in, but stdin is closed after (and text is "
"optional: without text, the stdin is just closed)\n"
" -signal: send a signal to the process; the signal can be an integer "
"or one of these names: hup, int, quit, kill, term, usr1, usr2\n"
" -kill: alias of \"-signal <id> kill\"\n"
"-killall: kill all running processes\n"
" -set: set a hook property (see function hook_set in plugin API "
"reference)\n"
"property: hook property\n"
" value: new value for hook property\n"
" -del: delete a terminated command\n"
" -all: delete all terminated commands\n"
"\n"
"Default options can be set in the option "
"exec.command.default_options."),
"-list"
" || -sh|-nosh|-bg|-nobg|-stdin|-nostdin|-buffer|-l|-o|-n|-sw|-nosw|"
"-ln|-noln|-color|-timeout|-name|%*"
" || -in|-inclose|-signal|-kill %(exec_commands_ids)"
" || -killall"
" || -set %(exec_commands_ids) stdin|stdin_close|signal"
" || -del %(exec_commands_ids)|-all %(exec_commands_ids)|%*",
&exec_command_exec, NULL);
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_EXEC_COMMAND_H
#define __WEECHAT_EXEC_COMMAND_H 1
struct t_exec_cmd_options
{
int command_index; /* index of command in arguments */
int use_shell; /* 1 to use shell (sh -c "command") */
int detached; /* 1 if detached (no output) */
int pipe_stdin; /* 1 to create a pipe for stdin */
int timeout; /* timeout (in seconds) */
const char *ptr_buffer_name; /* name of buffer */
struct t_gui_buffer *ptr_buffer; /* pointer to buffer */
int output_to_buffer; /* 1 if output is sent to buffer */
int new_buffer; /* output in a new buffer */
int switch_to_buffer; /* switch to the output buffer */
int line_numbers; /* 1 to display line numbers */
int color; /* what to do with ANSI colors */
int display_rc; /* 1 to display return code */
const char *ptr_command_name; /* name of command */
};
extern int exec_command_run (struct t_gui_buffer *buffer,
int argc, char **argv, char **argv_eol,
int start_arg);
extern void exec_command_init ();
#endif /* __WEECHAT_EXEC_COMMAND_H */
+73
View File
@@ -0,0 +1,73 @@
/*
* exec-completion.c - completion for exec commands
*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "exec.h"
/*
* Adds executed commands ids to completion list.
*/
int
exec_completion_commands_ids_cb (void *data, const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_exec_cmd *ptr_exec_cmd;
char str_number[32];
/* make C compiler happy */
(void) data;
(void) completion_item;
(void) buffer;
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
snprintf (str_number, sizeof (str_number), "%d", ptr_exec_cmd->number);
weechat_hook_completion_list_add (completion, str_number,
0, WEECHAT_LIST_POS_SORT);
if (ptr_exec_cmd->name)
{
weechat_hook_completion_list_add (completion, ptr_exec_cmd->name,
0, WEECHAT_LIST_POS_SORT);
}
}
return WEECHAT_RC_OK;
}
/*
* Hooks completions.
*/
void
exec_completion_init ()
{
weechat_hook_completion ("exec_commands_ids",
N_("ids (numbers and names) of executed commands"),
&exec_completion_commands_ids_cb, NULL);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_EXEC_COMPLETION_H
#define __WEECHAT_EXEC_COMPLETION_H 1
extern void exec_completion_init ();
#endif /* __WEECHAT_EXEC_COMPLETION_H */
+191
View File
@@ -0,0 +1,191 @@
/*
* exec-config.c - exec configuration options (file exec.conf)
*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "exec.h"
#include "exec-config.h"
struct t_config_file *exec_config_file = NULL;
/* exec config, command section */
struct t_config_option *exec_config_command_default_options;
struct t_config_option *exec_config_command_purge_delay;
/* exec config, color section */
struct t_config_option *exec_config_color_flag_running;
struct t_config_option *exec_config_color_flag_finished;
char **exec_config_cmd_options = NULL;
int exec_config_cmd_num_options = 0;
/*
* Callback for changes on option "exec.command.default_options".
*/
void
exec_config_change_command_default_options (void *data,
struct t_config_option *option)
{
/* make C compiler happy */
(void) data;
(void) option;
if (exec_config_cmd_options)
weechat_string_free_split (exec_config_cmd_options);
exec_config_cmd_options = weechat_string_split (
weechat_config_string (exec_config_command_default_options),
" ", 0, 0, &exec_config_cmd_num_options);
}
/*
* Reloads exec configuration file.
*/
int
exec_config_reload_cb (void *data, struct t_config_file *config_file)
{
/* make C compiler happy */
(void) data;
return weechat_config_reload (config_file);
}
/*
* Initializes exec configuration file.
*
* Returns:
* 1: OK
* 0: error
*/
int
exec_config_init ()
{
struct t_config_section *ptr_section;
exec_config_file = weechat_config_new (EXEC_CONFIG_NAME,
&exec_config_reload_cb, NULL);
if (!exec_config_file)
return 0;
/* command */
ptr_section = weechat_config_new_section (exec_config_file, "command",
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL);
if (!ptr_section)
{
weechat_config_free (exec_config_file);
return 0;
}
exec_config_command_default_options = weechat_config_new_option (
exec_config_file, ptr_section,
"default_options", "string",
N_("default options for command /exec (see /help exec); example: "
"\"-nosh -bg\" to run all commands in background (no output), and "
"without using the shell"),
NULL, 0, 0, "", NULL, 0, NULL, NULL,
&exec_config_change_command_default_options, NULL, NULL, NULL);
exec_config_command_purge_delay = weechat_config_new_option (
exec_config_file, ptr_section,
"purge_delay", "integer",
N_("delay for purging finished commands (in seconds, 0 = purge "
"commands immediately, -1 = never purge)"),
NULL, -1, 36000 * 24 * 30, "0", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL);
/* color */
ptr_section = weechat_config_new_section (exec_config_file, "color",
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL);
if (!ptr_section)
{
weechat_config_free (exec_config_file);
return 0;
}
exec_config_color_flag_running = weechat_config_new_option (
exec_config_file, ptr_section,
"flag_running", "color",
N_("text color for a running command flag (in exec buffer and "
"/exec -list)"),
NULL, 0, 0, "lightgreen", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL);
exec_config_color_flag_finished = weechat_config_new_option (
exec_config_file, ptr_section,
"flag_finished", "color",
N_("text color for a finished command flag (in exec buffer and "
"/exec -list)"),
NULL, 0, 0, "lightred", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL);
return 1;
}
/*
* Reads exec configuration file.
*/
int
exec_config_read ()
{
return weechat_config_read (exec_config_file);
}
/*
* Writes exec configuration file.
*/
int
exec_config_write ()
{
return weechat_config_write (exec_config_file);
}
/*
* Frees exec configuration.
*/
void
exec_config_free ()
{
weechat_config_free (exec_config_file);
if (exec_config_cmd_options)
{
weechat_string_free_split (exec_config_cmd_options);
exec_config_cmd_options = NULL;
exec_config_cmd_num_options = 0;
}
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_EXEC_CONFIG_H
#define __WEECHAT_EXEC_CONFIG_H 1
#define EXEC_CONFIG_NAME "exec"
#define EXEC_CONFIG_SECTION_EXEC "exec"
extern struct t_config_file *exec_config_file;
extern struct t_config_option *exec_config_command_default_options;
extern struct t_config_option *exec_config_command_purge_delay;
extern struct t_config_option *exec_config_color_flag_running;
extern struct t_config_option *exec_config_color_flag_finished;
extern char **exec_config_cmd_options;
extern int exec_config_cmd_num_options;
extern int exec_config_init ();
extern int exec_config_read ();
extern int exec_config_write ();
extern void exec_config_free ();
#endif /* __WEECHAT_EXEC_CONFIG_H */
+587
View File
@@ -0,0 +1,587 @@
/*
* exec.c - execution of external commands in WeeChat
*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "exec.h"
#include "exec-buffer.h"
#include "exec-command.h"
#include "exec-completion.h"
#include "exec-config.h"
WEECHAT_PLUGIN_NAME(EXEC_PLUGIN_NAME);
WEECHAT_PLUGIN_DESCRIPTION(N_("Execution of external commands in WeeChat"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
struct t_weechat_plugin *weechat_exec_plugin = NULL;
struct t_exec_cmd *exec_cmds = NULL; /* first executed command */
struct t_exec_cmd *last_exec_cmd = NULL; /* last executed command */
int exec_cmds_count = 0; /* number of executed commands */
char *exec_color_string[EXEC_NUM_COLORS] =
{ "off", "decode", "strip" };
/*
* Searches for a color action name.
*
* Returns index of color in enum t_exec_color, -1 if not found.
*/
int
exec_search_color (const char *color)
{
int i;
if (!color)
return -1;
for (i = 0; i < EXEC_NUM_COLORS; i++)
{
if (weechat_strcasecmp (exec_color_string[i], color) == 0)
return i;
}
/* color not found */
return -1;
}
/*
* Searches for an executed command by id, which can be a number or a name.
*
* Returns pointer to executed command found, NULL if not found.
*/
struct t_exec_cmd *
exec_search_by_id (const char *id)
{
struct t_exec_cmd* ptr_exec_cmd;
char *error;
long number;
error = NULL;
number = strtol (id, &error, 10);
if (!error || error[0])
number = -1;
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
/* check if number is matching */
if ((number >= 0) && (ptr_exec_cmd->number == (int)number))
return ptr_exec_cmd;
/* check if name is matching */
if (ptr_exec_cmd->name && (strcmp (ptr_exec_cmd->name, id) == 0))
return ptr_exec_cmd;
}
/* executed command not found */
return NULL;
}
/*
* Adds a command in list of executed commands.
*/
struct t_exec_cmd *
exec_add ()
{
struct t_exec_cmd *new_exec_cmd, *ptr_exec_cmd;
int number;
/* find first available number */
number = (last_exec_cmd) ? last_exec_cmd->number + 1 : 0;
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
if (ptr_exec_cmd->prev_cmd
&& (ptr_exec_cmd->number > ptr_exec_cmd->prev_cmd->number + 1))
{
number = ptr_exec_cmd->prev_cmd->number + 1;
break;
}
}
new_exec_cmd = malloc (sizeof (*new_exec_cmd));
if (!new_exec_cmd)
return NULL;
new_exec_cmd->prev_cmd = last_exec_cmd;
new_exec_cmd->next_cmd = NULL;
if (!exec_cmds)
exec_cmds = new_exec_cmd;
else
last_exec_cmd->next_cmd = new_exec_cmd;
last_exec_cmd = new_exec_cmd;
new_exec_cmd->number = number;
new_exec_cmd->name = NULL;
new_exec_cmd->hook = NULL;
new_exec_cmd->command = NULL;
new_exec_cmd->pid = 0;
new_exec_cmd->detached = 0;
new_exec_cmd->start_time = time (NULL);
new_exec_cmd->end_time = 0;
new_exec_cmd->output_to_buffer = 0;
new_exec_cmd->buffer_full_name = NULL;
new_exec_cmd->line_numbers = 0;
new_exec_cmd->display_rc = 0;
new_exec_cmd->stdout_size = 0;
new_exec_cmd->stdout = NULL;
new_exec_cmd->stderr_size = 0;
new_exec_cmd->stderr = NULL;
new_exec_cmd->return_code = -1;
exec_cmds_count++;
return new_exec_cmd;
}
/*
* Timer callback to delete a command.
*/
int
exec_timer_delete_cb (void *data, int remaining_calls)
{
struct t_exec_cmd *exec_cmd, *ptr_exec_cmd;
/* make C compiler happy */
(void) remaining_calls;
exec_cmd = (struct t_exec_cmd *)data;
if (!exec_cmd)
return WEECHAT_RC_OK;
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
if (ptr_exec_cmd == exec_cmd)
{
exec_free (ptr_exec_cmd);
break;
}
}
return WEECHAT_RC_OK;
}
/*
* Concatenates some text to stdout/stderr of a command.
*/
void
exec_command_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;
}
/*
* Displays output of a command.
*/
void
exec_command_display_output (struct t_exec_cmd *exec_cmd,
struct t_gui_buffer *buffer, int stdout)
{
char *ptr_output, *ptr_line, *line, *line2, *pos;
char str_number[32], str_tags[1024];
int line_nb, length;
ptr_output = (stdout) ? exec_cmd->stdout : exec_cmd->stderr;
if (!ptr_output)
return;
/*
* if output is sent to the buffer, the buffer must exist
* (we don't send output by default to core buffer)
*/
if (exec_cmd->output_to_buffer && !buffer)
return;
ptr_line = ptr_output;
line_nb = 1;
while (ptr_line)
{
/* 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;
if (exec_cmd->color != EXEC_COLOR_OFF)
{
line2 = weechat_hook_modifier_exec (
(exec_cmd->output_to_buffer) ?
"irc_color_decode_ansi" : "color_decode_ansi",
(exec_cmd->color == EXEC_COLOR_DECODE) ? "1" : "0",
line);
free (line);
if (!line2)
break;
line = line2;
}
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",
(stdout) ? "stdout" : "stderr",
(exec_cmd->name) ? exec_cmd->name : str_number);
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);
}
free (line);
line_nb++;
ptr_line = (pos) ? pos + 1 : NULL;
}
}
/*
* Ends a command.
*/
void
exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
{
struct t_gui_buffer *ptr_buffer;
ptr_buffer = weechat_buffer_search ("==", exec_cmd->buffer_full_name);
/* display stdout/stderr (if output to buffer, the buffer must exist) */
exec_command_display_output (exec_cmd, ptr_buffer, 1);
exec_command_display_output (exec_cmd, ptr_buffer, 0);
/*
* display return code (only if command is not detached and if output is
* NOT sent to buffer)
*/
if (!exec_cmd->detached && !exec_cmd->output_to_buffer
&& exec_cmd->display_rc)
{
if (return_code >= 0)
{
weechat_printf_tags (ptr_buffer, "exec_rc",
_("%s: end of command %d (\"%s\"), "
"return code: %d"),
EXEC_PLUGIN_NAME, exec_cmd->number,
exec_cmd->command, return_code);
}
else
{
weechat_printf_tags (ptr_buffer, "exec_rc",
_("%s: unexpected end of command %d "
"(\"%s\")"),
EXEC_PLUGIN_NAME, exec_cmd->number,
exec_cmd->command);
}
}
/* (re)set some variables after the end of command */
exec_cmd->hook = NULL;
exec_cmd->pid = 0;
exec_cmd->end_time = time (NULL);
exec_cmd->return_code = return_code;
/* schedule a timer to remove the executed command */
if (weechat_config_integer (exec_config_command_purge_delay) >= 0)
{
weechat_hook_timer (1 + (1000 * weechat_config_integer (exec_config_command_purge_delay)),
0, 1,
&exec_timer_delete_cb, exec_cmd);
}
}
/*
* Callback for hook process.
*/
int
exec_process_cb (void *data, const char *command, int return_code,
const char *out, const char *err)
{
struct t_exec_cmd *ptr_exec_cmd;
/* make C compiler happy */
(void) command;
ptr_exec_cmd = (struct t_exec_cmd *)data;
if (!ptr_exec_cmd)
return WEECHAT_RC_ERROR;
if (weechat_exec_plugin->debug >= 2)
{
weechat_printf (NULL,
"%s: process_cb: command=\"%s\", rc=%d, "
"out: %d bytes, err: %d bytes",
EXEC_PLUGIN_NAME,
ptr_exec_cmd->command,
return_code,
(out) ? strlen (out) : 0,
(err) ? strlen (err) : 0);
}
if (return_code == WEECHAT_HOOK_PROCESS_ERROR)
{
exec_end_command (ptr_exec_cmd, -1);
return WEECHAT_RC_OK;
}
if (out)
{
exec_command_concat_output (&ptr_exec_cmd->stdout_size,
&ptr_exec_cmd->stdout,
out);
}
if (err)
{
exec_command_concat_output (&ptr_exec_cmd->stderr_size,
&ptr_exec_cmd->stderr,
err);
}
if (return_code >= 0)
exec_end_command (ptr_exec_cmd, return_code);
return WEECHAT_RC_OK;
}
/*
* Deletes a command.
*/
void
exec_free (struct t_exec_cmd *exec_cmd)
{
if (!exec_cmd)
return;
/* remove command from commands list */
if (exec_cmd->prev_cmd)
(exec_cmd->prev_cmd)->next_cmd = exec_cmd->next_cmd;
if (exec_cmd->next_cmd)
(exec_cmd->next_cmd)->prev_cmd = exec_cmd->prev_cmd;
if (exec_cmds == exec_cmd)
exec_cmds = exec_cmd->next_cmd;
if (last_exec_cmd == exec_cmd)
last_exec_cmd = exec_cmd->prev_cmd;
/* free data */
if (exec_cmd->hook)
weechat_unhook (exec_cmd->hook);
if (exec_cmd->name)
free (exec_cmd->name);
if (exec_cmd->command)
free (exec_cmd->command);
if (exec_cmd->buffer_full_name)
free (exec_cmd->buffer_full_name);
if (exec_cmd->stdout)
free (exec_cmd->stdout);
if (exec_cmd->stderr)
free (exec_cmd->stderr);
free (exec_cmd);
exec_cmds_count--;
}
/*
* Deletes all commands.
*/
void
exec_free_all ()
{
while (exec_cmds)
{
exec_free (exec_cmds);
}
}
/*
* Prints exec infos in WeeChat log file (usually for crash dump).
*/
void
exec_print_log ()
{
struct t_exec_cmd *ptr_exec_cmd;
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
{
weechat_log_printf ("");
weechat_log_printf ("[exec command (addr:0x%lx)]", ptr_exec_cmd);
weechat_log_printf (" number. . . . . . . . . : %d", ptr_exec_cmd->number);
weechat_log_printf (" name. . . . . . . . . . : '%s'", ptr_exec_cmd->name);
weechat_log_printf (" hook. . . . . . . . . . : 0x%lx", ptr_exec_cmd->hook);
weechat_log_printf (" command . . . . . . . . : '%s'", ptr_exec_cmd->command);
weechat_log_printf (" pid . . . . . . . . . . : %d", ptr_exec_cmd->pid);
weechat_log_printf (" detached. . . . . . . . : %d", ptr_exec_cmd->detached);
weechat_log_printf (" start_time. . . . . . . : %ld", ptr_exec_cmd->start_time);
weechat_log_printf (" end_time. . . . . . . . : %ld", ptr_exec_cmd->end_time);
weechat_log_printf (" output_to_buffer. . . . : %d", ptr_exec_cmd->output_to_buffer);
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 (" stdout_size . . . . . . : %d", ptr_exec_cmd->stdout_size);
weechat_log_printf (" stdout. . . . . . . . . : '%s'", ptr_exec_cmd->stdout);
weechat_log_printf (" stderr_size . . . . . . : %d", ptr_exec_cmd->stderr_size);
weechat_log_printf (" stderr. . . . . . . . . : '%s'", ptr_exec_cmd->stderr);
weechat_log_printf (" return_code . . . . . . : %d", ptr_exec_cmd->return_code);
weechat_log_printf (" prev_cmd. . . . . . . . : 0x%lx", ptr_exec_cmd->prev_cmd);
weechat_log_printf (" next_cmd. . . . . . . . : 0x%lx", ptr_exec_cmd->next_cmd);
}
}
/*
* Callback for signal "debug_dump".
*/
int
exec_debug_dump_cb (void *data, const char *signal, const char *type_data,
void *signal_data)
{
/* make C compiler happy */
(void) data;
(void) signal;
(void) type_data;
if (!signal_data
|| (weechat_strcasecmp ((char *)signal_data, EXEC_PLUGIN_NAME) == 0))
{
weechat_log_printf ("");
weechat_log_printf ("***** \"%s\" plugin dump *****",
weechat_plugin->name);
exec_print_log ();
weechat_log_printf ("");
weechat_log_printf ("***** End of \"%s\" plugin dump *****",
weechat_plugin->name);
}
return WEECHAT_RC_OK;
}
/*
* Initializes exec plugin.
*/
int
weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
{
int i, upgrading;
weechat_plugin = plugin;
exec_command_init ();
if (!exec_config_init ())
return WEECHAT_RC_ERROR;
exec_config_read ();
/* hook some signals */
weechat_hook_signal ("debug_dump", &exec_debug_dump_cb, NULL);
/* hook completions */
exec_completion_init ();
/* look at arguments */
upgrading = 0;
for (i = 0; i < argc; i++)
{
if (weechat_strcasecmp (argv[i], "--upgrade") == 0)
{
upgrading = 1;
}
}
if (upgrading)
exec_buffer_set_callbacks ();
return WEECHAT_RC_OK;
}
/*
* Ends exec plugin.
*/
int
weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* make C compiler happy */
(void) plugin;
exec_config_write ();
exec_free_all ();
exec_config_free ();
return WEECHAT_RC_OK;
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WEECHAT_EXEC_H
#define __WEECHAT_EXEC_H 1
#include <time.h>
#define weechat_plugin weechat_exec_plugin
#define EXEC_PLUGIN_NAME "exec"
enum t_exec_color {
EXEC_COLOR_OFF = 0,
EXEC_COLOR_DECODE,
EXEC_COLOR_STRIP,
/* number of color actions */
EXEC_NUM_COLORS,
};
struct t_exec_cmd
{
/* command/process */
int number; /* command number */
char *name; /* name of command */
struct t_hook *hook; /* pointer to process hook */
char *command; /* command (with arguments) */
pid_t pid; /* process id */
int detached; /* 1 if command is detached */
time_t start_time; /* start time */
time_t end_time; /* end time */
/* display */
int output_to_buffer; /* 1 if output is sent to buffer */
char *buffer_full_name; /* buffer where output is displayed */
int line_numbers; /* 1 if lines numbers are displayed */
int color; /* what to do with ANSI colors */
int display_rc; /* 1 if return code is displayed */
/* command output */
int stdout_size; /* number of bytes in stdout */
char *stdout; /* stdout of command */
int stderr_size; /* number of bytes in stderr */
char *stderr; /* stderr of command */
int return_code; /* command return code */
struct t_exec_cmd *prev_cmd; /* link to previous command */
struct t_exec_cmd *next_cmd; /* link to next command */
};
extern struct t_weechat_plugin *weechat_exec_plugin;
extern struct t_exec_cmd *exec_cmds;
extern struct t_exec_cmd *last_exec_cmd;
extern int exec_cmds_count;
extern int exec_search_color (const char *color);
extern struct t_exec_cmd *exec_search_by_id (const char *id);
extern struct t_exec_cmd *exec_add ();
extern int exec_process_cb (void *data, const char *command, int return_code,
const char *out, const char *err);
extern void exec_free (struct t_exec_cmd *exec_cmd);
extern void exec_free_all ();
#endif /* __WEECHAT_EXEC_H */
+406 -2
View File
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <regex.h>
#include "../weechat-plugin.h"
#include "irc.h"
@@ -45,9 +46,29 @@ char *irc_color_to_weechat[IRC_NUM_COLORS] =
/* 11 */ "lightcyan",
/* 12 */ "lightblue",
/* 13 */ "lightmagenta",
/* 14 */ "gray",
/* 15 */ "white"
/* 14 */ "darkgray",
/* 15 */ "gray"
};
char irc_color_term2irc[IRC_COLOR_TERM2IRC_NUM_COLORS] =
{ /* term > IRC */
1, /* 0 1 (black) */
5, /* 1 5 (red) */
3, /* 2 3 (green) */
7, /* 3 7 (brown) */
2, /* 4 2 (blue) */
6, /* 5 6 (magenta) */
10, /* 6 10 (cyan) */
15, /* 7 15 (gray) */
14, /* 8 14 (darkgray) */
4, /* 9 4 (lightred) */
9, /* 10 9 (lightgreen) */
8, /* 11 8 (yellow) */
12, /* 12 12 (lightblue) */
13, /* 13 13 (lightmagenta) */
11, /* 14 11 (lightcyan) */
0, /* 15 0 (white) */
};
regex_t *irc_color_regex_ansi = NULL;
/*
@@ -361,6 +382,371 @@ irc_color_encode (const char *string, int keep_colors)
return (char *)out;
}
/*
* Converts a RGB color to IRC color.
*
* Returns a IRC color number (between 0 and 15), -1 if error.
*/
int
irc_color_convert_rgb2irc (int rgb)
{
char str_color[64], *error;
const char *info_color;
long number;
snprintf (str_color, sizeof (str_color),
"%d,%d",
rgb,
IRC_COLOR_TERM2IRC_NUM_COLORS);
info_color = weechat_info_get ("color_rgb2term", str_color);
if (!info_color || !info_color[0])
return -1;
error = NULL;
number = strtol (info_color, &error, 10);
if (!error || error[0]
|| (number < 0) || (number >= IRC_COLOR_TERM2IRC_NUM_COLORS))
{
return -1;
}
return irc_color_term2irc[number];
}
/*
* Converts a terminal color to IRC color.
*
* Returns a IRC color number (between 0 and 15), -1 if error.
*/
int
irc_color_convert_term2irc (int color)
{
char str_color[64], *error;
const char *info_color;
long number;
snprintf (str_color, sizeof (str_color), "%d", color);
info_color = weechat_info_get ("color_term2rgb", str_color);
if (!info_color || !info_color[0])
return -1;
error = NULL;
number = strtol (info_color, &error, 10);
if (!error || error[0] || (number < 0) || (number > 0xFFFFFF))
return -1;
return irc_color_convert_rgb2irc (number);
}
/*
* Replaces ANSI colors by IRC colors (or removes them).
*
* This callback is called by irc_color_decode_ansi, it must not be called
* directly.
*/
char *
irc_color_decode_ansi_cb (void *data, const char *text)
{
struct t_irc_color_ansi_state *ansi_state;
char *text2, **items, *output, str_color[128];
int i, length, num_items, value, color;
ansi_state = (struct t_irc_color_ansi_state *)data;
/* if we don't keep colors of if text is empty, just return empty string */
if (!ansi_state->keep_colors || !text || !text[0])
return strdup ("");
/* only sequences ending with 'm' are used, the others are discarded */
length = strlen (text);
if (text[length - 1] != 'm')
return strdup ("");
/* sequence "\33[m" resets color */
if (length < 4)
return strdup (weechat_color ("reset"));
text2 = NULL;
items = NULL;
output = NULL;
/* extract text between "\33[" and "m" */
text2 = weechat_strndup (text + 2, length - 3);
if (!text2)
goto end;
items = weechat_string_split (text2, ";", 0, 0, &num_items);
if (!items)
goto end;
output = malloc ((32 * num_items) + 1);
if (!output)
goto end;
output[0] = '\0';
for (i = 0; i < num_items; i++)
{
value = atoi (items[i]);
switch (value)
{
case 0: /* reset */
strcat (output, IRC_COLOR_RESET_STR);
ansi_state->bold = 0;
ansi_state->underline = 0;
ansi_state->italic = 0;
break;
case 1: /* bold */
if (!ansi_state->bold)
{
strcat (output, IRC_COLOR_BOLD_STR);
ansi_state->bold = 1;
}
break;
case 2: /* remove bold */
case 21:
case 22:
if (ansi_state->bold)
{
strcat (output, IRC_COLOR_BOLD_STR);
ansi_state->bold = 0;
}
break;
case 3: /* italic */
if (!ansi_state->italic)
{
strcat (output, IRC_COLOR_ITALIC_STR);
ansi_state->italic = 1;
}
break;
case 4: /* underline */
if (!ansi_state->underline)
{
strcat (output, IRC_COLOR_UNDERLINE_STR);
ansi_state->underline = 1;
}
break;
case 23: /* remove italic */
if (ansi_state->italic)
{
strcat (output, IRC_COLOR_ITALIC_STR);
ansi_state->italic = 0;
}
break;
case 24: /* remove underline */
if (ansi_state->underline)
{
strcat (output, IRC_COLOR_UNDERLINE_STR);
ansi_state->underline = 0;
}
break;
case 30: /* text color */
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
snprintf (str_color, sizeof (str_color),
"%c%02d",
IRC_COLOR_COLOR_CHAR,
irc_color_term2irc[value - 30]);
strcat (output, str_color);
break;
case 38: /* text color */
if (i + 1 < num_items)
{
switch (atoi (items[i + 1]))
{
case 2: /* RGB color */
if (i + 4 < num_items)
{
color = irc_color_convert_rgb2irc (
(atoi (items[i + 2]) << 16) |
(atoi (items[i + 3]) << 8) |
atoi (items[i + 4]));
if (color >= 0)
{
snprintf (str_color, sizeof (str_color),
"%c%02d",
IRC_COLOR_COLOR_CHAR,
color);
strcat (output, str_color);
}
i += 4;
}
break;
case 5: /* terminal color (0-255) */
if (i + 2 < num_items)
{
color = irc_color_convert_term2irc (atoi (items[i + 2]));
if (color >= 0)
{
snprintf (str_color, sizeof (str_color),
"%c%02d",
IRC_COLOR_COLOR_CHAR,
color);
strcat (output, str_color);
}
i += 2;
}
break;
}
}
break;
case 39: /* default text color */
snprintf (str_color, sizeof (str_color),
"%c15",
IRC_COLOR_COLOR_CHAR);
strcat (output, str_color);
break;
case 40: /* background color */
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
snprintf (str_color, sizeof (str_color),
"%c,%02d",
IRC_COLOR_COLOR_CHAR,
irc_color_term2irc[value - 40]);
strcat (output, str_color);
break;
case 48: /* background color */
if (i + 1 < num_items)
{
switch (atoi (items[i + 1]))
{
case 2: /* RGB color */
if (i + 4 < num_items)
{
color = irc_color_convert_rgb2irc (
(atoi (items[i + 2]) << 16) |
(atoi (items[i + 3]) << 8) |
atoi (items[i + 4]));
if (color >= 0)
{
snprintf (str_color, sizeof (str_color),
"%c,%02d",
IRC_COLOR_COLOR_CHAR,
color);
strcat (output, str_color);
}
i += 4;
}
break;
case 5: /* terminal color (0-255) */
if (i + 2 < num_items)
{
color = irc_color_convert_term2irc (atoi (items[i + 2]));
if (color >= 0)
{
snprintf (str_color, sizeof (str_color),
"%c,%02d",
IRC_COLOR_COLOR_CHAR,
color);
strcat (output, str_color);
}
i += 2;
}
break;
}
}
break;
case 49: /* default background color */
snprintf (str_color, sizeof (str_color),
"%c,01",
IRC_COLOR_COLOR_CHAR);
strcat (output, str_color);
break;
case 90: /* text color (bright) */
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
snprintf (str_color, sizeof (str_color),
"%c%02d",
IRC_COLOR_COLOR_CHAR,
irc_color_term2irc[value - 90 + 8]);
strcat (output, str_color);
break;
case 100: /* background color (bright) */
case 101:
case 102:
case 103:
case 104:
case 105:
case 106:
case 107:
snprintf (str_color, sizeof (str_color),
"%c,%02d",
IRC_COLOR_COLOR_CHAR,
irc_color_term2irc[value - 100 + 8]);
strcat (output, str_color);
break;
}
}
end:
if (items)
weechat_string_free_split (items);
if (text2)
free (text2);
return (output) ? output : strdup ("");
}
/*
* Replaces ANSI colors by IRC colors.
*
* If keep_colors == 0: removes any color/style in message otherwise keeps
* colors.
*
* Note: result must be freed after use.
*/
char *
irc_color_decode_ansi (const char *string, int keep_colors)
{
struct t_irc_color_ansi_state ansi_state;
/* allocate/compile regex if needed (first call) */
if (!irc_color_regex_ansi)
{
irc_color_regex_ansi = malloc (sizeof (*irc_color_regex_ansi));
if (!irc_color_regex_ansi)
return NULL;
if (weechat_string_regcomp (irc_color_regex_ansi,
weechat_info_get ("color_ansi_regex", NULL),
REG_EXTENDED) != 0)
{
free (irc_color_regex_ansi);
irc_color_regex_ansi = NULL;
return NULL;
}
}
ansi_state.keep_colors = keep_colors;
ansi_state.bold = 0;
ansi_state.underline = 0;
ansi_state.italic = 0;
return weechat_string_replace_regex (string, irc_color_regex_ansi,
"$0", '$',
&irc_color_decode_ansi_cb,
&ansi_state);
}
/*
* Callback for modifiers "irc_color_decode" and "irc_color_encode".
*
@@ -385,6 +771,9 @@ irc_color_modifier_cb (void *data, const char *modifier,
if (strcmp (modifier, "irc_color_encode") == 0)
return irc_color_encode (string, keep_colors);
if (strcmp (modifier, "irc_color_decode_ansi") == 0)
return irc_color_decode_ansi (string, keep_colors);
/* unknown modifier */
return NULL;
}
@@ -403,3 +792,18 @@ irc_color_for_tags (const char *color)
return weechat_string_replace (color, ",", ":");
}
/*
* Ends IRC colors.
*/
void
irc_color_end ()
{
if (irc_color_regex_ansi)
{
regfree (irc_color_regex_ansi);
free (irc_color_regex_ansi);
irc_color_regex_ansi = NULL;
}
}
+11
View File
@@ -59,6 +59,8 @@
#define IRC_COLOR_UNDERLINE_CHAR '\x1F' /* underlined text */
#define IRC_COLOR_UNDERLINE_STR "\x1F" /* [1F]...[1F] */
#define IRC_COLOR_TERM2IRC_NUM_COLORS 16
/* macros for WeeChat core and IRC colors */
#define IRC_COLOR_BAR_FG weechat_color("bar_fg")
@@ -92,11 +94,20 @@
#define IRC_COLOR_ITEM_LAG_COUNTING weechat_color(weechat_config_string(irc_config_color_item_lag_counting))
#define IRC_COLOR_ITEM_LAG_FINISHED weechat_color(weechat_config_string(irc_config_color_item_lag_finished))
struct t_irc_color_ansi_state
{
char keep_colors;
char bold;
char underline;
char italic;
};
extern char *irc_color_decode (const char *string, int keep_colors);
extern char *irc_color_encode (const char *string, int keep_colors);
extern char *irc_color_modifier_cb (void *data, const char *modifier,
const char *modifier_data,
const char *string);
extern char *irc_color_for_tags (const char *color);
extern void irc_color_end ();
#endif /* __WEECHAT_IRC_COLOR_H */
+3
View File
@@ -189,6 +189,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
/* modifiers */
weechat_hook_modifier ("irc_color_decode", &irc_color_modifier_cb, NULL);
weechat_hook_modifier ("irc_color_encode", &irc_color_modifier_cb, NULL);
weechat_hook_modifier ("irc_color_decode_ansi", &irc_color_modifier_cb, NULL);
/* hook completions */
irc_completion_init ();
@@ -281,5 +282,7 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
irc_redirect_end ();
irc_color_end ();
return WEECHAT_RC_OK;
}
+68 -1
View File
@@ -277,6 +277,25 @@ plugin_api_command (struct t_weechat_plugin *plugin,
free (command2);
}
/*
* Modifier to decode ANSI colors.
*/
char *
plugin_api_modifier_color_decode_ansi (void *data,
const char *modifier,
const char *modifier_data,
const char *string)
{
/* make C compiler happy */
(void) data;
(void) modifier;
return gui_color_decode_ansi (string,
(modifier_data && (strcmp (modifier_data, "1") == 0)) ?
1: 0);
}
/*
* Gets info about WeeChat.
*/
@@ -288,10 +307,11 @@ plugin_api_info_get_internal (void *data, const char *info_name,
time_t inactivity;
static char value[32], version_number[32] = { '\0' };
static char weechat_dir_absolute_path[PATH_MAX] = { '\0' };
int rgb, limit;
char *pos, *color;
/* make C compiler happy */
(void) data;
(void) arguments;
if (!info_name)
return NULL;
@@ -397,6 +417,43 @@ plugin_api_info_get_internal (void *data, const char *info_name,
snprintf (value, sizeof (value), "%d", gui_window_get_height ());
return value;
}
else if (string_strcasecmp (info_name, "color_ansi_regex") == 0)
{
return GUI_COLOR_REGEX_ANSI_DECODE;
}
else if (string_strcasecmp (info_name, "color_term2rgb") == 0)
{
if (arguments && arguments[0])
{
snprintf (value, sizeof (value),
"%d",
gui_color_convert_term_to_rgb (atoi (arguments)));
return value;
}
}
else if (string_strcasecmp (info_name, "color_rgb2term") == 0)
{
if (arguments && arguments[0])
{
limit = 256;
pos = strchr (arguments, ',');
if (pos)
{
color = string_strndup (arguments, pos - arguments);
if (!color)
return NULL;
rgb = atoi (color);
limit = atoi (pos + 1);
free (color);
}
else
rgb = atoi (arguments);
snprintf (value, sizeof (value),
"%d",
gui_color_convert_rgb_to_term (rgb, limit));
return value;
}
}
/* info not found */
return NULL;
@@ -1097,6 +1154,10 @@ plugin_api_infolist_free (struct t_infolist *infolist)
void
plugin_api_init ()
{
/* WeeChat core modifiers */
hook_modifier (NULL, "color_decode_ansi",
&plugin_api_modifier_color_decode_ansi, NULL);
/* WeeChat core info hooks */
hook_info (NULL, "version", N_("WeeChat version"), NULL,
&plugin_api_info_get_internal, NULL);
@@ -1141,6 +1202,12 @@ plugin_api_init ()
&plugin_api_info_get_internal, NULL);
hook_info (NULL, "term_height", N_("height of terminal"), NULL,
&plugin_api_info_get_internal, NULL);
hook_info (NULL, "color_ansi_regex", N_("regular expression to match ANSI escape codes"), NULL,
&plugin_api_info_get_internal, NULL);
hook_info (NULL, "color_term2rgb", N_("terminal color (0-255) converted to RGB color"), NULL,
&plugin_api_info_get_internal, NULL);
hook_info (NULL, "color_rgb2term", N_("RGB color converted to terminal color (0-255)"), NULL,
&plugin_api_info_get_internal, NULL);
/* WeeChat core infolist hooks */
hook_infolist (NULL, "bar", N_("list of bars"),
+2 -1
View File
@@ -213,7 +213,8 @@ trigger_callback_replace_regex (struct t_trigger *trigger,
value = weechat_string_replace_regex (ptr_value,
trigger->regex[i].regex,
replace_eval,
'$');
'$',
NULL, NULL);
if (value)
{
/* display debug info on trigger buffer */
+8 -4
View File
@@ -57,7 +57,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
#define WEECHAT_PLUGIN_API_VERSION "20140304-01"
#define WEECHAT_PLUGIN_API_VERSION "20140313-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -250,7 +250,9 @@ struct t_weechat_plugin
int (*string_has_highlight_regex) (const char *string, const char *regex);
char *(*string_replace_regex) (const char *string, void *regex,
const char *replace,
const char reference_char);
const char reference_char,
char *(*callback)(void *data, const char *text),
void *callback_data);
char **(*string_split) (const char *string, const char *separators,
int keep_eol, int num_items_max, int *num_items);
char **(*string_split_shell) (const char *string, int *num_items);
@@ -1017,9 +1019,11 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
#define weechat_string_has_highlight_regex(__string, __regex) \
weechat_plugin->string_has_highlight_regex(__string, __regex)
#define weechat_string_replace_regex(__string, __regex, __replace, \
__reference_char) \
__reference_char, __callback, \
__callback_data) \
weechat_plugin->string_replace_regex(__string, __regex, __replace, \
__reference_char)
__reference_char, __callback, \
__callback_data)
#define weechat_string_split(__string, __separator, __eol, __max, \
__num_items) \
weechat_plugin->string_split(__string, __separator, __eol, \
+1
View File
@@ -87,6 +87,7 @@ weechat_CONTENTS="
usr/lib/weechat/plugins/alias.dll
usr/lib/weechat/plugins/aspell.dll
usr/lib/weechat/plugins/charset.dll
usr/lib/weechat/plugins/exec.dll
usr/lib/weechat/plugins/fifo.dll
usr/lib/weechat/plugins/irc.dll
usr/lib/weechat/plugins/logger.dll