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

core: add modifier and infos to decode ANSI colors

New modifier:
- color_decode_ansi: convert ANSI colors to WeeChat colors (or remove colors).

New infos:
- color_ansi_regex: regex used to parse ANSI colors in a string
- color_term2rgb: convert a terminal color (0-255) to RGB
- color_rgb2term: convert a RGB color to terminal color (0-255)
This commit is contained in:
Sebastien Helleu
2014-03-15 11:06:30 +01:00
parent 9e659d9f2e
commit e38f437ad7
9 changed files with 357 additions and 29 deletions
+8 -2
View File
@@ -9132,12 +9132,12 @@ 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_command_auth +
_(WeeChat ≥ 0.4.1)_ |
@@ -9175,6 +9175,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 |
+10 -2
View File
@@ -9300,12 +9300,13 @@ 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_command_auth +
_(WeeChat ≥ 0.4.1)_ |
@@ -9343,6 +9344,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 |
+11 -2
View File
@@ -9356,15 +9356,17 @@ 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_command_auth +
@@ -9402,6 +9404,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 |
+11 -2
View File
@@ -9148,15 +9148,17 @@ 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)
| irc_command_auth +
_(WeeChat バージョン 0.4.1 以上で利用可)_ |
@@ -9192,6 +9194,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..") |
空文字列 |
-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,
+239
View File
@@ -100,6 +100,11 @@ int gui_color_term256[256] =
0xd0d0d0, 0xdadada, 0xe4e4e4, 0xeeeeee, /* 252-255 */
};
/* ANSI colors */
regex_t *gui_color_regex_ansi = NULL;
char *gui_color_ansi[8] =
{ "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" };
/*
* Searches for a color with configuration option name.
@@ -704,6 +709,216 @@ 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;
}
}
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).
@@ -1027,3 +1242,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;
}
}
+10 -2
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,9 +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 char *gui_color_decode (const char *string, const char *replacement);
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);
@@ -180,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) */
@@ -191,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);
+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"),