# -*- coding: utf-8 -*- # # Copyright (c) 2013-2019 by nils_2 # # a simple spell correction for a "misspelled" word # # This program 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. # # This program 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 this program. If not, see . # # 2019-07-16: nils_2, (freenode.#weechat) # 1.0 : fix bug when misspelled word don't have a suggestion (rafasc) # : fixed typo in /help text # # 2019-03-01: nils_2, (freenode.#weechat) # 0.9 : fix bug with auto popup 'spell_suggestion' item (StarlitGhost) # # 2019-02-24: nils_2, (freenode.#weechat) # 0.8.1: fix ValueError when a misspelled word don't have a suggestion and you move cursor in input_line # # 2019-02-08: nils_2, (freenode.#weechat) # 0.8 : add: make addword function shortkey compatible (ldlework) # : -> https://github.com/weechat/weechat/pull/1288 (WeeChat >=2.4) # : add: selected-suggestion color # : -> https://github.com/weechat/scripts/issues/203 # : support for "spell" plugin (WeeChat >=2.5) # : item "spell_suggest" renamed to "spell_suggestion" # : -> https://github.com/weechat/weechat/issues/1299 # # 2013-10-04: nils_2, (freenode.#weechat) # 0.7 : add: addword function (idea by Nei) # : localvar wasn't removed after /input return # # 2013-10-04: nils_2, (freenode.#weechat) # 0.6 : add: new option replace_mode # : add: support of /eval (weechat >= 0.4.2) # : fix: typo in help # # 2013-06-27: nils_2, (freenode.#weechat) # 0.5 : fix: bug with root input bar # # 2013-02-16: nils_2, (freenode.#weechat) # 0.4 : bug with empty localvar removed (reported by swimmer) # # 2013-01-31: nils_2, (freenode.#weechat) # 0.3 : using new info "aspell_dict" (weechat >= 0.4.1) # # 2013-01-25: nils_2, (freenode.#weechat) # 0.2 : make script compatible with Python 3.x # # 2012-01-13: nils_2, (freenode.#weechat) # 0.1 : - initial release - # # requires: WeeChat version >= 0.4.0 # better use latest stable or devel version : http://www.weechat.org/download/ # # # Development is currently hosted at # https://github.com/weechatter/weechat-scripts # try: import weechat, re #sys except Exception: print("This script must be run under WeeChat.") print("Get WeeChat now at: http://www.weechat.org/") quit() SCRIPT_NAME = "spell_correction" SCRIPT_AUTHOR = "nils_2 " SCRIPT_VERSION = "1.0" SCRIPT_LICENSE = "GPL" SCRIPT_DESC = "a spell correction script to use with spell/aspell plugin" OPTIONS = { 'auto_pop_up_item' : ('off','automatic pop-up suggestion item on a misspelled word'), 'auto_replace' : ('on','replaces misspelled word with selected suggestion, automatically. If you use "off" you will have to bind command "/%s replace" to a key' % SCRIPT_NAME), 'catch_input_completion' : ('on','will catch the input_complete commands [TAB-key]'), 'eat_input_char' : ('on','will eat the next char you type, after replacing a misspelled word'), 'suggest_item' : ('${white}%S${default}', 'item format (%S = suggestion, %D = dict). Colors are allowed with format "${color}". note: since WeeChat 0.4.2 content is evaluated, see /help eval.'), 'hide_single_dict' : ('on','will hide dict in item if you have a single dict for buffer only'), 'complete_near' : ('0','show suggestions item only if you are n-chars near the misspelled word (0 = off). Using \'replace_mode\' cursor has to be n-chars near misspelled word to cycle through suggestions.'), 'replace_mode' : ('off','misspelled word will be replaced directly by suggestions. Use option \'complete_near\' to specify range and item \'spell_suggestion\' to show possible suggestions.'), } Hooks = {'catch_input_completion': '', 'catch_input_return': ''} regex_color=re.compile('\$\{([^\{\}]+)\}') regex_optional_tags=re.compile('%\{[^\{\}]+\}') multiline_input = 0 plugin_name = "spell" # WeeChat >= 2.5 old_plugin_name = "aspell" # WeeChat < 2.5 # ================================[ weechat options & description ]=============================== def init_options(): for option,value in OPTIONS.items(): if not weechat.config_is_set_plugin(option): weechat.config_set_plugin(option, value[0]) OPTIONS[option] = value[0] else: OPTIONS[option] = weechat.config_get_plugin(option) weechat.config_set_desc_plugin(option, '%s (default: "%s")' % (value[1], value[0])) def toggle_refresh(pointer, name, value): global OPTIONS option = name[len('plugins.var.python.' + SCRIPT_NAME + '.'):] # get optionname OPTIONS[option] = value # save new value if OPTIONS['catch_input_completion'].lower() == "off": if Hooks['catch_input_completion']: weechat.unhook(Hooks['catch_input_completion']) Hooks['catch_input_completion'] = '' weechat.unhook(Hooks['catch_input_return']) Hooks['catch_input_return'] = '' elif OPTIONS['catch_input_completion'].lower() == "on": if not Hooks['catch_input_completion']: Hooks['catch_input_completion'] = weechat.hook_command_run('/input complete*', 'input_complete_cb', '') Hooks['catch_input_return'] = weechat.hook_command_run('/input return', 'input_return_cb', '') return weechat.WEECHAT_RC_OK # ================================[ hooks() ]=============================== # called from command and when TAB is pressed def auto_suggest_cmd_cb(data, buffer, args): arguments = args.split(' ') input_line = weechat.buffer_get_string(buffer, 'input') weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_input_line', '%s' % input_line) if args.lower() == 'replace': replace_misspelled_word(buffer) return weechat.WEECHAT_RC_OK # if not weechat.buffer_get_string(buffer,'localvar_spell_correction_suggest_item'): # return weechat.WEECHAT_RC_OK tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) if not position: position = -1 if arguments[0].lower() == 'addword' and len(arguments) >= 2: found_dicts = get_aspell_dict_for(buffer) if len(found_dicts.split(",")) == 1 and len(arguments) == 2: word = arguments[1] weechat.command("","/%s addword %s" % (plugin_name,word) ) elif arguments[1] in found_dicts.split(",") and len(arguments) == 3: word = arguments[2] weechat.command("","/%s addword %s %s" % (plugin_name,arguments[1],word)) # get localvar for misspelled_word and suggestions from buffer or return localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) if not localvar_aspell_suggest: return weechat.WEECHAT_RC_OK if arguments[0].lower() == 'addword' and len(arguments) == 1: found_dicts = get_aspell_dict_for(buffer) if not ":" in localvar_aspell_suggest and not "," in found_dicts: weechat.command("","/%s addword %s" % (plugin_name,localvar_aspell_suggest)) else: misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') weechat.command("","/%s addword %s" % (plugin_name,misspelled_word)) return weechat.WEECHAT_RC_OK if not ":" in localvar_aspell_suggest: return weechat.WEECHAT_RC_OK misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') aspell_suggestions = aspell_suggestions.replace('/',',') aspell_suggestion_list = aspell_suggestions.split(',') if len(aspell_suggestion_list) == 0: position = -1 weechat.bar_item_update('spell_correction') weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK # append an empty entry to suggestions to quit without changes. if OPTIONS['auto_replace'].lower() == "on": aspell_suggestion_list.append('') position = int(position) # cycle backwards through suggestions if args == '/input complete_previous' or args == 'previous': # position <= -1? go to last suggestion if position <= -1: position = len(aspell_suggestion_list)-1 position -= 1 # cycle forward through suggestions else: if position >= len(aspell_suggestion_list)-1: position = 0 else: position += 1 # 2 = TAB or command is called weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:%s' % ('2',str(position),aspell_suggestion_list[position])) weechat.bar_item_update('spell_correction') return weechat.WEECHAT_RC_OK # spell_correction_suggest_item: def show_spell_correction_item_cb (data, item, window): # check for root input bar! if not window: window = weechat.current_window() # weechat.buffer_get_string(buffer,'localvar_spell_correction_suggest_item'): buffer = weechat.window_get_pointer(window,"buffer") if buffer == '': return '' tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) if not position or not aspell_suggest_item: return '' config_spell_suggest_item = weechat.config_get_plugin('suggest_item') dict_found = search_dict(buffer,position) if dict_found: if config_spell_suggest_item: show_item = config_spell_suggest_item.replace('%S',aspell_suggest_item) show_item = show_item.replace('%D',dict_found) show_item = substitute_colors(show_item) return '%s' % (show_item) else: return aspell_suggest_item else: if config_spell_suggest_item: show_item = config_spell_suggest_item.replace('%S',aspell_suggest_item) if weechat.config_get_plugin('hide_single_dict').lower() == 'off': show_item = show_item.replace('%D',get_aspell_dict_for(buffer)) else: show_item = show_item.replace('%D','').rstrip() show_item = substitute_colors(show_item) return '%s' % (show_item) return aspell_suggest_item # if a suggestion is selected and you edit input line, then replace misspelled word! def input_text_changed_cb(data, signal, signal_data): global multiline_input if multiline_input == '1': return weechat.WEECHAT_RC_OK buffer = signal_data if not buffer: return weechat.WEECHAT_RC_OK tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) if not position or not aspell_suggest_item: cursor_pos = weechat.buffer_get_integer(buffer,'input_pos') if get_localvar_aspell_suggest(buffer) and cursor_pos >0: # save cursor position of misspelled word weechat.buffer_set(buffer, 'localvar_set_current_cursor_pos', '%s' % cursor_pos) else: saved_cursor_pos = weechat.buffer_get_string(buffer, 'localvar_current_cursor_pos') if saved_cursor_pos != '': if int(cursor_pos) > int(saved_cursor_pos) + int(OPTIONS['complete_near']) + 3: # +3 to be sure! delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK # 1 = cursor etc., 2 = TAB, 3 = replace_mode if tab_complete != '0': if not aspell_suggest_item: aspell_suggest_item = '' weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:%s' % ('0',position,aspell_suggest_item)) return weechat.WEECHAT_RC_OK if OPTIONS['auto_replace'].lower() == "on": replace_misspelled_word(buffer) return weechat.WEECHAT_RC_OK # weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:' % ('0','-1')) weechat.bar_item_update('spell_correction') weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK # also remove localvar_suggest_item def replace_misspelled_word(buffer): input_line = weechat.buffer_get_string(buffer, 'localvar_spell_correction_suggest_input_line') if not input_line: # remove spell_correction item weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_item', '') weechat.bar_item_update('spell_correction') weechat.bar_item_update('spell_suggestion') return if OPTIONS['eat_input_char'].lower() == 'off' or input_line == '': input_pos = weechat.buffer_get_integer(buffer,'input_pos') # check cursor position if len(input_line) < int(input_pos) or input_line[int(input_pos)-1] == ' ' or input_line == '': input_line = weechat.buffer_get_string(buffer, 'input') weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_input_line', '') localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) # localvar_aspell_suggest = word,word2/wort,wort2 if localvar_aspell_suggest: misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') aspell_suggestions = aspell_suggestions.replace('/',',') aspell_suggestion_list = aspell_suggestions.split(',') else: return tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) if not position or not aspell_suggest_item: return position = int(position) input_line = input_line.replace(misspelled_word, aspell_suggestion_list[position]) if input_line[-2:] == ' ': input_line = input_line.rstrip() input_line = input_line + ' ' weechat.buffer_set(buffer,'input',input_line) # set new cursor position. check if suggestion is longer or smaller than misspelled word input_pos = weechat.buffer_get_integer(buffer,'input_pos') + 1 length_misspelled_word = len(misspelled_word) length_suggestion_word = len(aspell_suggestion_list[position]) if length_misspelled_word < length_suggestion_word: difference = length_suggestion_word - length_misspelled_word new_position = input_pos + difference + 1 weechat.buffer_set(buffer,'input_pos',str(new_position)) weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_item', '') weechat.bar_item_update('spell_suggestion') weechat.bar_item_update('spell_correction') # ================================[ subroutines ]=============================== # get aspell dict for suggestion def search_dict(buffer,position): localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) dicts_found = localvar_aspell_suggest.count("/") if not dicts_found: return 0 # aspell.dict.full_name = en_GB,de_DE-neu # localvar_dict = en_GB,de_DE-neu dictionary = get_aspell_dict_for(buffer) if not dictionary: return 0 dictionary_list = dictionary.split(',') # more then one dict? if len(dictionary_list) > 1: undef,aspell_suggestions = localvar_aspell_suggest.split(':') dictionary = aspell_suggestions.split('/') words = 0 i = -1 for a in dictionary: i += 1 words += a.count(',')+1 if words > int(position): break return dictionary_list[i] # format of localvar aspell_suggest (using two dicts): diehs:die hs,die-hs,dies/dies,Diebs,Viehs def get_localvar_aspell_suggest(buffer): return weechat.buffer_get_string(buffer, 'localvar_%s_suggest' % plugin_name) def get_aspell_dict_for(buffer): # this should never happens, but to be sure. Otherwise WeeChat will crash if buffer == '': return '' if int(version) >= 0x00040100: return weechat.info_get("%s_dict" % plugin_name, buffer) # this is a "simple" work around and it only works for buffers with given dictionary # no fallback for partial name like "aspell.dict.irc". Get your hands on WeeChat 0.4.1 full_name = weechat.buffer_get_string(buffer,'full_name') return weechat.config_string(weechat.config_get('%s.dict.%s' % (plugin_name,weechat.buffer_get_string(buffer,'full_name')))) def substitute_colors(text): if int(version) >= 0x00040200: return weechat.string_eval_expression(text,{},{},{}) # substitute colors in output return re.sub(regex_color, lambda match: weechat.color(match.group(1)), text) def get_position_and_suggest_item(buffer): if weechat.buffer_get_string(buffer,'localvar_spell_correction_suggest_item'): tab_complete,position,aspell_suggest_item = weechat.buffer_get_string(buffer,'localvar_spell_correction_suggest_item').split(':',2) return (tab_complete,position,aspell_suggest_item) else: return ('', '', '') def aspell_suggest_cb(data, signal, signal_data): buffer = signal_data if OPTIONS['replace_mode'].lower() == 'on': localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) if localvar_aspell_suggest: # aspell says, suggested word is also misspelled. check out if we already have a suggestion list and don't use the new misspelled word! if weechat.buffer_get_string(buffer,'localvar_inline_suggestions'): return weechat.WEECHAT_RC_OK if not ":" in localvar_aspell_suggest: return weechat.WEECHAT_RC_OK misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') aspell_suggestions = aspell_suggestions.replace('/',',') weechat.buffer_set(buffer, 'localvar_set_inline_suggestions', '%s:%s:%s' % ('2','0',aspell_suggestions)) weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK if OPTIONS['auto_pop_up_item'].lower() == 'on': auto_suggest_cmd_cb('', buffer, '') weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_input_line', '') weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK def get_last_position_of_misspelled_word(misspelled_word, buffer): input_pos = weechat.buffer_get_integer(buffer,'input_pos') input_line = weechat.buffer_get_string(buffer, 'input') x = input_line.rfind(misspelled_word, 0, int(input_pos)) y = x + len(misspelled_word) return x, y, input_pos # this is a work-around for multiline def multiline_cb(data, signal, signal_data): global multiline_input multiline_input = signal_data # if multiline_input == '1': # buffer = weechat.window_get_pointer(weechat.current_window(),"buffer") # input_line = weechat.buffer_get_string(buffer, 'input') # else: # buffer = weechat.window_get_pointer(weechat.current_window(),"buffer") # input_line_bak = weechat.buffer_get_string(buffer, 'input') # if input_line != input_line_bak: # input_text_changed_cb('','',buffer) return weechat.WEECHAT_RC_OK # ================================[ hook_keys() ]=============================== # TAB key pressed? def input_complete_cb(data, buffer, command): # check if a misspelled word already exists! localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) if not localvar_aspell_suggest and not weechat.buffer_get_string(buffer,'localvar_inline_replace_mode'): return weechat.WEECHAT_RC_OK # first [TAB] on a misspelled word in "replace mode" if OPTIONS['replace_mode'].lower() == "on" and not weechat.buffer_get_string(buffer,'localvar_inline_replace_mode') and int(OPTIONS['complete_near']) >= 0: weechat.buffer_set(buffer, 'localvar_set_inline_replace_mode', '1') if not ":" in localvar_aspell_suggest: return weechat.WEECHAT_RC_OK misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') begin_last_position, end_last_position, input_pos = get_last_position_of_misspelled_word(misspelled_word, buffer) # maybe nick completion? if begin_last_position == -1: delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK if input_pos - end_last_position > int(OPTIONS['complete_near']): delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK aspell_suggestions = aspell_suggestions.replace('/',',') weechat.buffer_set(buffer, 'localvar_set_inline_suggestions', '%s:%s:%s' % ('2','0',aspell_suggestions)) weechat.buffer_set(buffer, 'localvar_set_save_position_of_word', '%s:%s' % (begin_last_position, end_last_position)) inline_suggestions = aspell_suggestions.split(',') input_line = weechat.buffer_get_string(buffer, 'input') input_line = input_line[:begin_last_position] + inline_suggestions[0] + input_line[end_last_position:] # input_line = input_line.replace(misspelled_word, inline_suggestions[0]) word_differ = 0 if len(misspelled_word) > len(inline_suggestions[0]): word_differ = len(misspelled_word) - len(inline_suggestions[0]) else: word_differ = len(inline_suggestions[0]) - len(misspelled_word) if input_line[-2:] == ' ': input_line = input_line.rstrip() input_line = input_line + ' ' weechat.buffer_set(buffer,'input',input_line) input_pos = int(input_pos) + word_differ weechat.buffer_set(buffer,'input_pos',str(input_pos)) weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK # after first [TAB] on a misspelled word in "replace mode" if OPTIONS['replace_mode'].lower() == "on" and weechat.buffer_get_string(buffer,'localvar_inline_replace_mode') == "1" and int(OPTIONS['complete_near']) >= 0: if not ":" in weechat.buffer_get_string(buffer,'localvar_inline_suggestions'): return weechat.WEECHAT_RC_OK tab_complete,position,aspell_suggest_items = weechat.buffer_get_string(buffer,'localvar_inline_suggestions').split(':',2) if not position or not aspell_suggest_items: weechat.buffer_set(buffer, 'localvar_del_inline_replace_mode', '') return weechat.WEECHAT_RC_OK inline_suggestions = aspell_suggest_items.split(',') position = int(position) previous_position = position # cycle backwards through suggestions if command == '/input complete_previous': # position <= -1? go to last suggestion if position <= -1: position = len(inline_suggestions)-1 else: position -= 1 # cycle forward through suggestions elif command == '/input complete_next': if position >= len(inline_suggestions)-1: position = 0 else: position += 1 begin_last_position, end_last_position, input_pos = get_last_position_of_misspelled_word(inline_suggestions[previous_position], buffer) if input_pos - end_last_position > int(OPTIONS['complete_near']): delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK input_line = weechat.buffer_get_string(buffer, 'input') input_line = input_line[:begin_last_position] + inline_suggestions[position] + input_line[end_last_position:] # input_line = input_line.replace(inline_suggestions[previous_position], inline_suggestions[position]) word_differ = 0 if len(inline_suggestions[previous_position]) > len(inline_suggestions[position]): word_differ = len(inline_suggestions[previous_position]) - len(inline_suggestions[position]) else: word_differ = len(inline_suggestions[position]) - len(inline_suggestions[previous_position]) if input_line[-2:] == ' ': input_line = input_line.rstrip() input_line = input_line + ' ' weechat.buffer_set(buffer,'input',input_line) input_pos = int(input_pos) + word_differ weechat.buffer_set(buffer,'input_pos',str(input_pos)) weechat.buffer_set(buffer, 'localvar_set_inline_suggestions', '%s:%s:%s' % ('2',str(position),aspell_suggest_items)) weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK if int(OPTIONS['complete_near']) > 0: if not ":" in localvar_aspell_suggest: weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') begin_last_position, end_last_position, input_pos = get_last_position_of_misspelled_word(misspelled_word, buffer) if input_pos - end_last_position > int(OPTIONS['complete_near']): weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:%s' % ('2',position,aspell_suggest_item)) auto_suggest_cmd_cb('', buffer, command) weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK def delete_localvar_replace_mode(buffer): if OPTIONS['replace_mode'].lower() == "on": weechat.buffer_set(buffer, 'localvar_del_inline_replace_mode', '') weechat.buffer_set(buffer, 'localvar_del_inline_suggestions', '') weechat.buffer_set(buffer, 'localvar_del_save_position_of_word', '') weechat.buffer_set(buffer, 'localvar_del_current_cursor_pos', '') weechat.bar_item_update('spell_suggestion') # if a suggestion is selected and you press [RETURN] replace misspelled word! def input_return_cb(data, signal, signal_data): buffer = signal tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) if not position or not aspell_suggest_item: delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK if OPTIONS['auto_replace'].lower() == "on" and aspell_suggest_item: replace_misspelled_word(buffer) delete_localvar_replace_mode(buffer) return weechat.WEECHAT_RC_OK # /input delete_* def input_delete_cb(data, signal, signal_data): buffer = signal delete_localvar_replace_mode(buffer) weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_item', '') weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_input_line', '') weechat.bar_item_update('spell_correction') weechat.bar_item_update('spell_suggestion') return weechat.WEECHAT_RC_OK # /input move_* (cursor position) def input_move_cb(data, signal, signal_data): buffer = signal if OPTIONS['replace_mode'].lower() == "on" and weechat.buffer_get_string(buffer,'localvar_inline_replace_mode') == "1": delete_localvar_replace_mode(buffer) weechat.buffer_set(buffer, 'localvar_del_spell_correction_suggest_item', '') return weechat.WEECHAT_RC_OK tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) if not localvar_aspell_suggest or not ":" in localvar_aspell_suggest: return weechat.WEECHAT_RC_OK misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') if not aspell_suggest_item in aspell_suggestions: aspell_suggestion_list = aspell_suggestions.split(',',1) weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:%s' % ('1',0,aspell_suggestion_list[0])) weechat.bar_item_update('spell_correction') return weechat.WEECHAT_RC_OK weechat.buffer_set(buffer, 'localvar_set_spell_correction_suggest_item', '%s:%s:%s' % ('1',position,aspell_suggest_item)) return weechat.WEECHAT_RC_OK def show_spell_suggestion_item_cb (data, item, window): buffer = weechat.window_get_pointer(window,"buffer") if buffer == '': return '' if OPTIONS['replace_mode'].lower() == "on": if not weechat.buffer_get_string(buffer,'localvar_inline_suggestions'): return '' tab_complete,position,aspell_suggest_items = weechat.buffer_get_string(buffer,'localvar_inline_suggestions').split(':',2) localvar_aspell_suggest = "dummy:%s" % aspell_suggest_items # return aspell_suggest_items else: tab_complete,position,aspell_suggest_item = get_position_and_suggest_item(buffer) localvar_aspell_suggest = get_localvar_aspell_suggest(buffer) # localvar_aspell_suggest = word,word2/wort,wort2 if localvar_aspell_suggest: try: misspelled_word,aspell_suggestions = localvar_aspell_suggest.split(':') except ValueError: # maybe no suggestion for misspelled word. then go back return '' aspell_suggestions_orig = aspell_suggestions aspell_suggestions = aspell_suggestions.replace('/',',') aspell_suggestion_list = aspell_suggestions.split(',') if not position: return '' if position == "-1": return aspell_suggestions_orig if int(position) < len(aspell_suggestion_list): reset_color = weechat.color('reset') color = weechat.color(weechat.config_color(weechat.config_get("%s.color.misspelled" % plugin_name))) new_word = aspell_suggestion_list[int(position)].replace(aspell_suggestion_list[int(position)],'%s%s%s' % (color, aspell_suggestion_list[int(position)], reset_color)) aspell_suggestion_list[int(position)] = new_word # replace word with colored word aspell_suggestions_orig = ','.join(map(str, aspell_suggestion_list)) else: return '' return aspell_suggestions_orig def window_switch_cb(data, signal, signal_data): weechat.bar_item_update('spell_correction') return weechat.WEECHAT_RC_OK def buffer_switch_cb(data, signal, signal_data): weechat.bar_item_update('spell_correction') return weechat.WEECHAT_RC_OK # ================================[ check for nick ]=============================== def weechat_nicklist_search_nick(buffer, nick): return weechat.nicklist_search_nick(buffer, "", nick) # ================================[ main ]=============================== if __name__ == "__main__": if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''): version = weechat.info_get("version_number", "") or 0 if int(version) < 0x00040000: weechat.prnt('','%s%s %s' % (weechat.prefix('error'),SCRIPT_NAME,': needs version 0.4.0 or higher')) weechat.command('','/wait 1ms /python unload %s' % SCRIPT_NAME) if int(version) < 0x02050000: plugin_name = old_plugin_name SCRIPT_HELP = """addword : add a word to personal aspell dictionary (does not work with multiple dicts) previous : to cycle though previous suggestion replace : to replace misspelled word Quick start: You should add script item "spell_correction" to a bar (i suggest using the input_bar). On an misspelled word, press TAB to cycle through suggestions. Press any key on suggestion to replace misspelled word with current displayed suggestion. Also check script options: /fset %(s)s IMPORTANT: "%(p)s.check.suggestions" option has to be set to a value >= 0 (default: -1 (off)). "%(p)s.color.misspelled" option is used to highlight current suggestion in "%(p)s_suggestion" item Using "%(p)s.check.real_time" the nick-completion will not work. All misspelled words in input_line have to be replaced first. """ %dict(p=plugin_name, s=SCRIPT_NAME) weechat.hook_command(SCRIPT_NAME, SCRIPT_DESC, 'addword ||previous||replace', SCRIPT_HELP+ '', 'previous|replace|addword', 'auto_suggest_cmd_cb', '') init_options() weechat.hook_command_run('/input delete_*', 'input_delete_cb', '') weechat.hook_command_run('/input move*', 'input_move_cb', '') weechat.hook_signal ('input_text_changed', 'input_text_changed_cb', '') # multiline workaround weechat.hook_signal('input_flow_free', 'multiline_cb', '') weechat.hook_signal ('%s_suggest' % plugin_name, 'aspell_suggest_cb', '') weechat.hook_signal ('buffer_switch', 'buffer_switch_cb','') weechat.hook_signal ('window_switch', 'window_switch_cb','') if OPTIONS['catch_input_completion'].lower() == "on": Hooks['catch_input_completion'] = weechat.hook_command_run('/input complete*', 'input_complete_cb', '') Hooks['catch_input_return'] = weechat.hook_command_run('/input return', 'input_return_cb', '') weechat.hook_config('plugins.var.python.' + SCRIPT_NAME + '.*', 'toggle_refresh', '') weechat.bar_item_new('spell_correction', 'show_spell_correction_item_cb', '') weechat.bar_item_new('spell_suggestion', 'show_spell_suggestion_item_cb', '')