1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-29 14:26:39 +02:00

core: add options weechat.look.word_chars_{highlight|input} (closes #55, task #9459)

This commit is contained in:
Sébastien Helleu
2015-04-11 18:53:44 +02:00
parent c899254019
commit b2a68af077
26 changed files with 661 additions and 61 deletions
+177
View File
@@ -178,6 +178,8 @@ struct t_config_option *config_look_window_auto_zoom;
struct t_config_option *config_look_window_separator_horizontal;
struct t_config_option *config_look_window_separator_vertical;
struct t_config_option *config_look_window_title;
struct t_config_option *config_look_word_chars_highlight;
struct t_config_option *config_look_word_chars_input;
/* config, colors section */
@@ -292,6 +294,10 @@ int config_num_highlight_tags = 0;
char **config_plugin_extensions = NULL;
int config_num_plugin_extensions = 0;
char config_tab_spaces[TAB_MAX_WIDTH + 1];
struct t_config_look_word_char_item *config_word_chars_highlight = NULL;
int config_word_chars_highlight_count = 0;
struct t_config_look_word_char_item *config_word_chars_input = NULL;
int config_word_chars_input_count = 0;
/*
@@ -381,6 +387,131 @@ config_change_window_title (void *data, struct t_config_option *option)
}
}
/*
* Sets word chars array with a word chars option.
*/
void
config_set_word_chars (const char *str_word_chars,
struct t_config_look_word_char_item **word_chars,
int *word_chars_count)
{
char **items, *item, *item2, *ptr_item, *pos;
int i;
if (*word_chars)
{
free (*word_chars);
*word_chars = NULL;
}
*word_chars_count = 0;
if (!str_word_chars || !str_word_chars[0])
return;
items = string_split (str_word_chars, ",", 0, 0, word_chars_count);
if (!items)
{
*word_chars_count = 0;
return;
}
if (*word_chars_count == 0)
return;
*word_chars = malloc (
sizeof ((*word_chars)[0]) * (*word_chars_count));
if (!*word_chars)
return;
for (i = 0; i < *word_chars_count; i++)
{
/* init structure */
(*word_chars)[i].exclude = 0;
(*word_chars)[i].wc_class = (wctype_t)0;
(*word_chars)[i].char1 = 0;
(*word_chars)[i].char2 = 0;
ptr_item = items[i];
if ((ptr_item[0] == '!') && ptr_item[1])
{
(*word_chars)[i].exclude = 1;
ptr_item++;
}
if (strcmp (ptr_item, "*") != 0)
{
pos = strchr (ptr_item, '-');
if (pos && (pos > ptr_item) && pos[1])
{
/* range: char1 -> char2 */
/* char1 */
item = string_strndup (ptr_item, pos - ptr_item);
item2 = string_convert_escaped_chars (item);
(*word_chars)[i].char1 = utf8_wide_char (item2);
if (item)
free (item);
if (item2)
free (item2);
/* char2 */
item = strdup (pos + 1);
item2 = string_convert_escaped_chars (item);
(*word_chars)[i].char2 = utf8_wide_char (item2);
if (item)
free (item);
if (item2)
free (item2);
}
else
{
/* one char or wide character class */
(*word_chars)[i].wc_class = wctype (ptr_item);
if ((*word_chars)[i].wc_class == (wctype_t)0)
{
item = string_convert_escaped_chars (ptr_item);
(*word_chars)[i].char1 = utf8_wide_char (item);
(*word_chars)[i].char2 = (*word_chars)[i].char1;
if (item)
free (item);
}
}
}
}
string_free_split (items);
}
/*
* Callback for changes on option "weechat.look.word_chars_highlight".
*/
void
config_change_word_chars_highlight (void *data, struct t_config_option *option)
{
/* make C compiler happy */
(void) data;
(void) option;
config_set_word_chars (CONFIG_STRING(config_look_word_chars_highlight),
&config_word_chars_highlight,
&config_word_chars_highlight_count);
}
/*
* Callback for changes on option "weechat.look.word_chars_input".
*/
void
config_change_word_chars_input (void *data, struct t_config_option *option)
{
/* make C compiler happy */
(void) data;
(void) option;
config_set_word_chars (CONFIG_STRING(config_look_word_chars_input),
&config_word_chars_input,
&config_word_chars_input_count);
}
/*
* Callback for changes on options that require a refresh of buffers.
*/
@@ -2742,6 +2873,34 @@ config_weechat_init_options ()
"(note: content is evaluated, see /help eval)"),
NULL, 0, 0, "WeeChat ${info:version}", NULL, 0, NULL, NULL,
&config_change_window_title, NULL, NULL, NULL);
config_look_word_chars_highlight = config_file_new_option (
weechat_config_file, ptr_section,
"word_chars_highlight", "string",
N_("comma-separated list of chars (or range of chars) that are "
"considered part or words for highlights; "
"each item can be a single char, a range of chars (format: a-z), "
"a class of wide character (for example \"alnum\", "
"see man wctype); a \"!\" before the item makes it negative "
"(ie the char is NOT considered part of words); the value \"*\" "
"matches any char; unicode chars are allowed with the format "
"\\u1234, for example \\u00A0 for unbreakable space "
"(see /help print for supported formats)"),
NULL, 0, 0, "!\\u00A0,-,_,|,alnum", NULL, 0, NULL, NULL,
&config_change_word_chars_highlight, NULL, NULL, NULL);
config_look_word_chars_input = config_file_new_option (
weechat_config_file, ptr_section,
"word_chars_input", "string",
N_("comma-separated list of chars (or range of chars) that are "
"considered part or words for command line; "
"each item can be a single char, a range of chars (format: a-z), "
"a class of wide character (for example \"alnum\", "
"see man wctype); a \"!\" before the item makes it negative "
"(ie the char is NOT considered part of words); the value \"*\" "
"matches any char; unicode chars are allowed with the format "
"\\u1234, for example \\u00A0 for unbreakable space "
"(see /help print for supported formats)"),
NULL, 0, 0, "!\\u00A0,-,_,|,alnum", NULL, 0, NULL, NULL,
&config_change_word_chars_input, NULL, NULL, NULL);
/* palette */
ptr_section = config_file_new_section (weechat_config_file, "palette",
@@ -3525,6 +3684,10 @@ config_weechat_init ()
config_change_highlight_tags (NULL, NULL);
if (!config_plugin_extensions)
config_change_plugin_extension (NULL, NULL);
if (!config_word_chars_highlight)
config_change_word_chars_highlight (NULL, NULL);
if (!config_word_chars_input)
config_change_word_chars_input (NULL, NULL);
return rc;
}
@@ -3600,4 +3763,18 @@ config_weechat_free ()
config_plugin_extensions = NULL;
config_num_plugin_extensions = 0;
}
if (config_word_chars_highlight)
{
free (config_word_chars_highlight);
config_word_chars_highlight = NULL;
config_word_chars_highlight_count = 0;
}
if (config_word_chars_input)
{
free (config_word_chars_input);
config_word_chars_input = NULL;
config_word_chars_input_count = 0;
}
}
+15
View File
@@ -22,6 +22,7 @@
#define WEECHAT_CONFIG_H 1
#include <regex.h>
#include <wctype.h>
#include "wee-config-file.h"
struct t_gui_buffer;
@@ -105,6 +106,14 @@ enum t_config_look_save_layout_on_exit
CONFIG_LOOK_SAVE_LAYOUT_ON_EXIT_ALL,
};
struct t_config_look_word_char_item
{
char exclude; /* 1 if char is NOT a word char */
wctype_t wc_class; /* class of wide characters (wctype) */
wint_t char1; /* first char of range */
wint_t char2; /* second char of range */
};
extern struct t_config_file *weechat_config_file;
extern struct t_config_section *weechat_config_section_color;
extern struct t_config_section *weechat_config_section_proxy;
@@ -215,6 +224,8 @@ extern struct t_config_option *config_look_window_auto_zoom;
extern struct t_config_option *config_look_window_separator_horizontal;
extern struct t_config_option *config_look_window_separator_vertical;
extern struct t_config_option *config_look_window_title;
extern struct t_config_option *config_look_word_chars_highlight;
extern struct t_config_option *config_look_word_chars_input;
extern struct t_config_option *config_color_bar_more;
extern struct t_config_option *config_color_chat;
@@ -315,6 +326,10 @@ extern int config_num_highlight_tags;
extern char **config_plugin_extensions;
extern int config_num_plugin_extensions;
extern char config_tab_spaces[];
extern struct t_config_look_word_char_item *config_word_chars_highlight;
extern int config_word_chars_highlight_count;
extern struct t_config_look_word_char_item *config_word_chars_input;
extern int config_word_chars_input_count;
extern struct t_config_option *config_weechat_debug_get (const char *plugin_name);
extern int config_weechat_debug_set (const char *plugin_name,
+72 -15
View File
@@ -747,34 +747,91 @@ string_convert_escaped_chars (const char *string)
/*
* Checks if first char of string is a "word char".
*
* The word chars are customizable with options "weechat.look.word_chars_*".
*
* Returns:
* 1: first char is a word char
* 0: first char is not a word char
*/
int
string_is_word_char (const char *string)
string_is_word_char (const char *string,
struct t_config_look_word_char_item *word_chars,
int word_chars_count)
{
wint_t c = utf8_wide_char (string);
wint_t c;
int i, match;
c = utf8_wide_char (string);
if (c == WEOF)
return 0;
if (iswalnum (c))
return 1;
switch (c)
for (i = 0; i < word_chars_count; i++)
{
case '-':
case '_':
case '|':
return 1;
if (word_chars[i].wc_class != (wctype_t)0)
{
match = iswctype (c, word_chars[i].wc_class);
}
else
{
if ((word_chars[i].char1 == 0)
&& (word_chars[i].char2 == 0))
{
match = 1;
}
else
{
match = ((c >= word_chars[i].char1) &&
(c <= word_chars[i].char2));
}
}
if (match)
return (word_chars[i].exclude) ? 0 : 1;
}
/* not a 'word char' */
/* not a word char */
return 0;
}
/*
* Checks if first char of string is a "word char" (for highlight).
*
* The word chars for highlights are customizable with option
* "weechat.look.word_chars_highlight".
*
* Returns:
* 1: first char is a word char
* 0: first char is not a word char
*/
int
string_is_word_char_highlight (const char *string)
{
return string_is_word_char (string,
config_word_chars_highlight,
config_word_chars_highlight_count);
}
/*
* Checks if first char of string is a "word char" (for input).
*
* The word chars for input are customizable with option
* "weechat.look.word_chars_input".
*
* Returns:
* 1: first char is a word char
* 0: first char is not a word char
*/
int
string_is_word_char_input (const char *string)
{
return string_is_word_char (string,
config_word_chars_input,
config_word_chars_input_count);
}
/*
* Converts a mask (string with only "*" as wildcard) to a regex, paying
* attention to special chars in a regex.
@@ -1004,8 +1061,8 @@ string_has_highlight (const char *string, const char *highlight_words)
if (!match_pre)
match_pre = match - 1;
match_post = match + length;
startswith = ((match == msg) || (!string_is_word_char (match_pre)));
endswith = ((!match_post[0]) || (!string_is_word_char (match_post)));
startswith = ((match == msg) || (!string_is_word_char_highlight (match_pre)));
endswith = ((!match_post[0]) || (!string_is_word_char_highlight (match_post)));
if ((wildcard_start && wildcard_end) ||
(!wildcard_start && !wildcard_end &&
startswith && endswith) ||
@@ -1063,13 +1120,13 @@ string_has_highlight_regex_compiled (const char *string, regex_t *regex)
if (!startswith)
{
match_pre = utf8_prev_char (string, string + regex_match.rm_so);
startswith = !string_is_word_char (match_pre);
startswith = !string_is_word_char_highlight (match_pre);
}
endswith = 0;
if (startswith)
{
endswith = ((regex_match.rm_eo == (int)strlen (string))
|| !string_is_word_char (string + regex_match.rm_eo));
|| !string_is_word_char_highlight (string + regex_match.rm_eo));
}
if (startswith && endswith)
return 1;
+2 -1
View File
@@ -48,7 +48,8 @@ extern char *string_remove_quotes (const char *string, const char *quotes);
extern char *string_strip (const char *string, int left, int right,
const char *chars);
extern char *string_convert_escaped_chars (const char *string);
extern int string_is_word_char (const char *string);
extern int string_is_word_char_highlight (const char *string);
extern int string_is_word_char_input (const char *string);
extern char *string_mask_to_regex (const char *mask);
extern const char *string_regex_flags (const char *regex, int default_flags,
int *flags);
+8 -8
View File
@@ -814,19 +814,19 @@ gui_input_delete_previous_word (struct t_gui_buffer *buffer)
start = utf8_add_offset (buffer->input_buffer,
buffer->input_buffer_pos - 1);
string = start;
while (string && (string[0] == ' '))
while (string && !string_is_word_char_input (string))
{
string = utf8_prev_char (buffer->input_buffer, string);
}
if (string)
{
while (string && (string[0] != ' '))
while (string && string_is_word_char_input (string))
{
string = utf8_prev_char (buffer->input_buffer, string);
}
if (string)
{
while (string && (string[0] == ' '))
while (string && !string_is_word_char_input (string))
{
string = utf8_prev_char (buffer->input_buffer, string);
}
@@ -875,7 +875,7 @@ gui_input_delete_next_word (struct t_gui_buffer *buffer)
length_deleted = 0;
while (string[0])
{
if ((string[0] == ' ') && (string > start))
if (!string_is_word_char_input (string) && (string > start))
break;
string = utf8_next_char (string);
length_deleted++;
@@ -1087,13 +1087,13 @@ gui_input_move_previous_word (struct t_gui_buffer *buffer)
{
pos = utf8_add_offset (buffer->input_buffer,
buffer->input_buffer_pos - 1);
while (pos && (pos[0] == ' '))
while (pos && !string_is_word_char_input (pos))
{
pos = utf8_prev_char (buffer->input_buffer, pos);
}
if (pos)
{
while (pos && (pos[0] != ' '))
while (pos && string_is_word_char_input (pos))
{
pos = utf8_prev_char (buffer->input_buffer, pos);
}
@@ -1126,13 +1126,13 @@ gui_input_move_next_word (struct t_gui_buffer *buffer)
{
pos = utf8_add_offset (buffer->input_buffer,
buffer->input_buffer_pos);
while (pos[0] && (pos[0] == ' '))
while (pos[0] && !string_is_word_char_input (pos))
{
pos = utf8_next_char (pos);
}
if (pos[0])
{
while (pos[0] && (pos[0] != ' '))
while (pos[0] && string_is_word_char_input (pos))
{
pos = utf8_next_char (pos);
}