diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2012-11-04 11:50:15 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2012-11-04 11:50:15 +0100 |
commit | 57d5afeda51be24f6dae13f4082fb91e90cdf3b2 (patch) | |
tree | c4c783a54600a1a5a960ae081d5ed032cca67f7e /src | |
parent | 9e94bfd48b9c17cacdc48f6c1e29dcde9fafaa6f (diff) | |
download | weechat-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.c | 43 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-config.c | 25 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-config.h | 1 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-speller.c | 8 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell.c | 164 |
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; } |