summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2012-11-04 11:50:15 +0100
committerSebastien Helleu <flashcode@flashtux.org>2012-11-04 11:50:15 +0100
commit57d5afeda51be24f6dae13f4082fb91e90cdf3b2 (patch)
treec4c783a54600a1a5a960ae081d5ed032cca67f7e /src
parent9e94bfd48b9c17cacdc48f6c1e29dcde9fafaa6f (diff)
downloadweechat-57d5afeda51be24f6dae13f4082fb91e90cdf3b2.zip
aspell: add bar item "aspell_suggest": suggestions for misspelled word at cursor (task #12061) (patch from Nils Görs)
Diffstat (limited to 'src')
-rw-r--r--src/plugins/aspell/weechat-aspell-bar-item.c43
-rw-r--r--src/plugins/aspell/weechat-aspell-config.c25
-rw-r--r--src/plugins/aspell/weechat-aspell-config.h1
-rw-r--r--src/plugins/aspell/weechat-aspell-speller.c8
-rw-r--r--src/plugins/aspell/weechat-aspell.c164
5 files changed, 222 insertions, 19 deletions
diff --git a/src/plugins/aspell/weechat-aspell-bar-item.c b/src/plugins/aspell/weechat-aspell-bar-item.c
index c2be69c0b..bb2c78610 100644
--- a/src/plugins/aspell/weechat-aspell-bar-item.c
+++ b/src/plugins/aspell/weechat-aspell-bar-item.c
@@ -50,13 +50,53 @@ weechat_aspell_bar_item_dict (void *data, struct t_gui_bar_item *item,
window = weechat_current_window ();
buffer = weechat_window_get_pointer (window, "buffer");
-
if (buffer)
{
dict_list = weechat_aspell_get_dict (buffer);
if (dict_list)
return strdup (dict_list);
}
+
+ return NULL;
+}
+
+/*
+ * weechat_aspell_bar_item_suggest: bar item with aspell suggestions
+ */
+
+char *
+weechat_aspell_bar_item_suggest (void *data, struct t_gui_bar_item *item,
+ struct t_gui_window *window)
+{
+ struct t_gui_buffer *buffer;
+ const char *suggestions;
+ char str_delim[128], *suggestions2;
+
+ /* make C compiler happy */
+ (void) data;
+ (void) item;
+
+ if (!window)
+ window = weechat_current_window ();
+
+ buffer = weechat_window_get_pointer (window, "buffer");
+ if (buffer)
+ {
+ suggestions = weechat_buffer_get_string (buffer,
+ "localvar_aspell_suggest");
+ if (suggestions)
+ {
+ snprintf (str_delim, sizeof (str_delim),
+ "%s/%s",
+ weechat_color ("bar_delim"),
+ weechat_color ("bar_fg"));
+ suggestions2 = weechat_string_replace (suggestions, "/", str_delim);
+ if (suggestions2)
+ return suggestions2;
+ return strdup (suggestions);
+ }
+ }
+
return NULL;
}
@@ -68,4 +108,5 @@ void
weechat_aspell_bar_item_init ()
{
weechat_bar_item_new ("aspell_dict", &weechat_aspell_bar_item_dict, NULL);
+ weechat_bar_item_new ("aspell_suggest", &weechat_aspell_bar_item_suggest, NULL);
}
diff --git a/src/plugins/aspell/weechat-aspell-config.c b/src/plugins/aspell/weechat-aspell-config.c
index 0451810f8..ad359f5b6 100644
--- a/src/plugins/aspell/weechat-aspell-config.c
+++ b/src/plugins/aspell/weechat-aspell-config.c
@@ -46,6 +46,7 @@ struct t_config_option *weechat_aspell_config_check_default_dict;
struct t_config_option *weechat_aspell_config_check_during_search;
struct t_config_option *weechat_aspell_config_check_enabled;
struct t_config_option *weechat_aspell_config_check_real_time;
+struct t_config_option *weechat_aspell_config_check_suggestions;
struct t_config_option *weechat_aspell_config_check_word_min_length;
@@ -133,6 +134,22 @@ weechat_aspell_config_change_enabled (void *data, struct t_config_option *option
}
/*
+ * weechat_aspell_config_change_suggestions: called when number of suggestions
+ * is changed
+ */
+
+void
+weechat_aspell_config_change_suggestions (void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) data;
+ (void) option;
+
+ weechat_bar_item_update ("aspell_suggest");
+}
+
+/*
* weechat_aspell_config_dict_change: called when a dictionary is changed
*/
@@ -452,6 +469,14 @@ weechat_aspell_config_init ()
N_("real-time spell checking of words (slower, disabled by default: "
"words are checked only if there's delimiter after)"),
NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
+ weechat_aspell_config_check_suggestions = weechat_config_new_option (
+ weechat_aspell_config_file, ptr_section,
+ "suggestions", "integer",
+ N_("number of suggestions to display in bar item \"aspell_suggest\" "
+ "for each dictionary set in buffer (-1 = disable suggestions, "
+ "0 = display all possible suggestions in all languages)"),
+ NULL, -1, INT_MAX, "-1", NULL, 0,
+ NULL, NULL, &weechat_aspell_config_change_suggestions, NULL, NULL, NULL);
weechat_aspell_config_check_word_min_length = weechat_config_new_option (
weechat_aspell_config_file, ptr_section,
"word_min_length", "integer",
diff --git a/src/plugins/aspell/weechat-aspell-config.h b/src/plugins/aspell/weechat-aspell-config.h
index 11dc05920..b66c08434 100644
--- a/src/plugins/aspell/weechat-aspell-config.h
+++ b/src/plugins/aspell/weechat-aspell-config.h
@@ -31,6 +31,7 @@ extern struct t_config_option *weechat_aspell_config_check_default_dict;
extern struct t_config_option *weechat_aspell_config_check_during_search;
extern struct t_config_option *weechat_aspell_config_check_enabled;
extern struct t_config_option *weechat_aspell_config_check_real_time;
+extern struct t_config_option *weechat_aspell_config_check_suggestions;
extern struct t_config_option *weechat_aspell_config_check_word_min_length;
extern char **weechat_aspell_commands_to_check;
diff --git a/src/plugins/aspell/weechat-aspell-speller.c b/src/plugins/aspell/weechat-aspell-speller.c
index b5cbbd402..15e7e54cc 100644
--- a/src/plugins/aspell/weechat-aspell-speller.c
+++ b/src/plugins/aspell/weechat-aspell-speller.c
@@ -44,7 +44,7 @@ weechat_aspell_speller_exists (const char *lang)
{
struct AspellConfig *config;
AspellDictInfoList *list;
- AspellDictInfoEnumeration *el;
+ AspellDictInfoEnumeration *elements;
const AspellDictInfo *dict;
int rc;
@@ -52,9 +52,9 @@ weechat_aspell_speller_exists (const char *lang)
config = new_aspell_config ();
list = get_aspell_dict_info_list (config);
- el = aspell_dict_info_list_elements (list);
+ elements = aspell_dict_info_list_elements (list);
- while ((dict = aspell_dict_info_enumeration_next (el)))
+ while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL)
{
if (strcmp (dict->name, lang) == 0)
{
@@ -63,7 +63,7 @@ weechat_aspell_speller_exists (const char *lang)
}
}
- delete_aspell_dict_info_enumeration (el);
+ delete_aspell_dict_info_enumeration (elements);
delete_aspell_config (config);
return rc;
diff --git a/src/plugins/aspell/weechat-aspell.c b/src/plugins/aspell/weechat-aspell.c
index d689ee37f..cab034910 100644
--- a/src/plugins/aspell/weechat-aspell.c
+++ b/src/plugins/aspell/weechat-aspell.c
@@ -49,6 +49,7 @@ int aspell_enabled = 0;
struct t_gui_buffer *aspell_buffer_spellers = NULL;
char *aspell_last_modifier_string = NULL; /* last str. received by modifier */
+int aspell_last_buffer_input_pos = -1; /* last cursor position */
char *aspell_last_modifier_result = NULL; /* last str. built by modifier */
/*
@@ -385,7 +386,6 @@ weechat_aspell_iso_to_lang (const char *code)
return strdup ("Unknown");
}
-
/*
* weechat_aspell_iso_to_country: convert an aspell iso country code in its
* english full name
@@ -418,12 +418,12 @@ weechat_aspell_speller_list_dicts ()
char buffer[192];
struct AspellConfig *config;
AspellDictInfoList *list;
- AspellDictInfoEnumeration *el;
+ AspellDictInfoEnumeration *elements;
const AspellDictInfo *dict;
config = new_aspell_config();
list = get_aspell_dict_info_list (config);
- el = aspell_dict_info_list_elements (list);
+ elements = aspell_dict_info_list_elements (list);
weechat_printf (NULL, "");
weechat_printf (NULL,
@@ -431,7 +431,7 @@ weechat_aspell_speller_list_dicts ()
_( "%s dictionaries list:"),
ASPELL_PLUGIN_NAME);
- while ((dict = aspell_dict_info_enumeration_next (el)))
+ while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL)
{
country = NULL;
pos = strchr (dict->code, '_');
@@ -481,7 +481,7 @@ weechat_aspell_speller_list_dicts ()
free (country);
}
- delete_aspell_dict_info_enumeration (el);
+ delete_aspell_dict_info_enumeration (elements);
delete_aspell_config (config);
}
@@ -617,7 +617,6 @@ weechat_aspell_check_word (struct t_gui_buffer *buffer, const char *word)
{
struct t_aspell_speller *ptr_speller;
int rc;
-
rc = 0;
/* word too small? then do not check word */
@@ -654,6 +653,74 @@ weechat_aspell_check_word (struct t_gui_buffer *buffer, const char *word)
}
/*
+ * weechat_aspell_get_suggestions: get suggestions for a word
+ * A string is returned with format:
+ * "suggest1,suggest2,suggest3"
+ * Note: result (if not NULL) must be free()
+ * after use.
+ */
+
+char *
+weechat_aspell_get_suggestions (const char *word)
+{
+ struct t_aspell_speller *ptr_speller;
+ int size, max_suggestions, num_suggestions;
+ char *suggestions, *suggestions2;
+ const char *ptr_word;
+ const AspellWordList *list;
+ AspellStringEnumeration *elements;
+
+ max_suggestions = weechat_config_integer (weechat_aspell_config_check_suggestions);
+ if (max_suggestions < 0)
+ return NULL;
+
+ size = 1;
+ suggestions = malloc (size);
+ if (!suggestions)
+ return NULL;
+
+ suggestions[0] = '\0';
+ for (ptr_speller = weechat_aspell_spellers; ptr_speller;
+ ptr_speller = ptr_speller->next_speller)
+ {
+ list = aspell_speller_suggest (ptr_speller->speller, word, -1);
+ if (list)
+ {
+ elements = aspell_word_list_elements (list);
+ num_suggestions = 0;
+ while ((ptr_word = aspell_string_enumeration_next (elements)) != NULL)
+ {
+ size += strlen (ptr_word) + ((suggestions[0]) ? 1 : 0);
+ suggestions2 = realloc (suggestions, size);
+ if (!suggestions2)
+ {
+ free (suggestions);
+ delete_aspell_string_enumeration (elements);
+ return NULL;
+ }
+ suggestions = suggestions2;
+ if (suggestions[0])
+ strcat (suggestions, (num_suggestions == 0) ? "/" : ",");
+ strcat (suggestions, ptr_word);
+ num_suggestions++;
+ if ((max_suggestions >= 0) && (num_suggestions == max_suggestions))
+ break;
+ }
+ delete_aspell_string_enumeration (elements);
+ }
+ }
+
+ /* no suggestions found */
+ if (!suggestions[0])
+ {
+ free (suggestions);
+ return NULL;
+ }
+
+ return suggestions;
+}
+
+/*
* weechat_aspell_modifier_cb: modifier for input text
*/
@@ -664,10 +731,12 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
long unsigned int value;
struct t_gui_buffer *buffer;
char *result, *ptr_string, *pos_space, *ptr_end, save_end;
- const char *color_normal, *color_error;
+ char *word_for_suggestions, *old_suggestions, *suggestions;
+ const char *color_normal, *color_error, *ptr_suggestions;
int buffer_has_changed, utf8_char_int, char_size;
int length, index_result, length_word, word_ok;
int length_color_normal, length_color_error, rc;
+ int input_pos, current_pos, word_start_pos, word_end_pos;
/* make C compiler happy */
(void) data;
@@ -676,7 +745,7 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
if (!aspell_enabled)
return NULL;
- if (!string || !string[0])
+ if (!string)
return NULL;
rc = sscanf (modifier_data, "%lx", &value);
@@ -703,12 +772,14 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
/*
* for performance: return last string built if input string is the
- * same (for example user just change cursor position, or input text is
- * refreshed with same content)
+ * same and cursor position is the same (only if suggestions are enabled)
*/
+ input_pos = weechat_buffer_get_integer (buffer, "input_pos");
if (!buffer_has_changed
&& aspell_last_modifier_string
- && (strcmp (string, aspell_last_modifier_string) == 0))
+ && (strcmp (string, aspell_last_modifier_string) == 0)
+ && ((weechat_config_integer (weechat_aspell_config_check_suggestions) < 0)
+ || (input_pos == aspell_last_buffer_input_pos)))
{
return (aspell_last_modifier_result) ?
strdup (aspell_last_modifier_result) : NULL;
@@ -726,8 +797,11 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
aspell_last_modifier_result = NULL;
}
+ word_for_suggestions = NULL;
+
/* save last modifier string received */
aspell_last_modifier_string = strdup (string);
+ aspell_last_buffer_input_pos = input_pos;
color_normal = weechat_color ("bar_fg");
length_color_normal = strlen (color_normal);
@@ -777,6 +851,7 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
ptr_string = pos_space;
}
+ current_pos = 0;
while (ptr_string[0])
{
/* find start of word */
@@ -789,6 +864,7 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
memcpy (result + index_result, ptr_string, char_size);
index_result += char_size;
ptr_string += char_size;
+ current_pos++;
if (!ptr_string[0])
break;
utf8_char_int = weechat_utf8_char_int (ptr_string);
@@ -796,12 +872,17 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
if (!ptr_string[0])
break;
+ word_start_pos = current_pos;
+ word_end_pos = current_pos;
+
+ /* find end of word */
ptr_end = weechat_utf8_next_char (ptr_string);
utf8_char_int = weechat_utf8_char_int (ptr_end);
while (iswalnum (utf8_char_int) || (utf8_char_int == '\'')
|| (utf8_char_int == '-'))
{
ptr_end = weechat_utf8_next_char (ptr_end);
+ word_end_pos++;
if (!ptr_end[0])
break;
utf8_char_int = weechat_utf8_char_int (ptr_end);
@@ -834,7 +915,20 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
{
if ((save_end != '\0')
|| (weechat_config_integer (weechat_aspell_config_check_real_time)))
+ {
word_ok = weechat_aspell_check_word (buffer, ptr_string);
+ if (!word_ok && (input_pos >= word_start_pos))
+ {
+ /*
+ * if word is misspelled and that cursor is after
+ * the beginning of this word, save the word (we will
+ * look for suggestions after this loop)
+ */
+ if (word_for_suggestions)
+ free (word_for_suggestions);
+ word_for_suggestions = strdup (ptr_string);
+ }
+ }
else
word_ok = 1;
}
@@ -862,15 +956,55 @@ weechat_aspell_modifier_cb (void *data, const char *modifier,
ptr_end[0] = save_end;
ptr_string = ptr_end;
+ current_pos = word_end_pos + 1;
}
-
result[index_result] = '\0';
}
+ /* save old suggestions in buffer */
+ ptr_suggestions = weechat_buffer_get_string (buffer,
+ "localvar_aspell_suggest");
+ old_suggestions = (ptr_suggestions) ? strdup (ptr_suggestions) : NULL;
+
+ /* if there is a misspelled word, get suggestions and set them in buffer */
+ if (word_for_suggestions)
+ {
+ suggestions = weechat_aspell_get_suggestions (word_for_suggestions);
+ if (suggestions)
+ {
+ weechat_buffer_set (buffer, "localvar_set_aspell_suggest",
+ suggestions);
+ free (suggestions);
+ }
+ else
+ {
+ weechat_buffer_set (buffer, "localvar_del_aspell_suggest", "");
+ }
+ free (word_for_suggestions);
+ }
+ else
+ {
+ weechat_buffer_set (buffer, "localvar_del_aspell_suggest", "");
+ }
+
+ /* if suggestions have changed, update the bar item */
+ ptr_suggestions = weechat_buffer_get_string (buffer,
+ "localvar_aspell_suggest");
+ if ((old_suggestions && !ptr_suggestions)
+ || (!old_suggestions && ptr_suggestions)
+ || (old_suggestions && ptr_suggestions
+ && (strcmp (old_suggestions, ptr_suggestions) != 0)))
+ {
+ weechat_bar_item_update ("aspell_suggest");
+ }
+ if (old_suggestions)
+ free (old_suggestions);
+
if (!result)
return NULL;
aspell_last_modifier_result = strdup (result);
+
return result;
}
@@ -1053,8 +1187,9 @@ weechat_aspell_buffer_switch_cb (void *data, const char *signal,
(void) type_data;
(void) signal_data;
- /* refresh bar item "aspell_dict" (for root bars) */
+ /* refresh bar items (for root bars) */
weechat_bar_item_update ("aspell_dict");
+ weechat_bar_item_update ("aspell_suggest");
return WEECHAT_RC_OK;
}
@@ -1073,8 +1208,9 @@ weechat_aspell_window_switch_cb (void *data, const char *signal,
(void) type_data;
(void) signal_data;
- /* refresh bar item "aspell_dict" (for root bars) */
+ /* refresh bar items (for root bars) */
weechat_bar_item_update ("aspell_dict");
+ weechat_bar_item_update ("aspell_suggest");
return WEECHAT_RC_OK;
}