diff options
author | Philipp Hörist <philipp@hoerist.com> | 2018-10-14 19:56:04 +0300 |
---|---|---|
committer | Philipp Hörist <philipp@hoerist.com> | 2018-10-14 20:04:33 +0300 |
commit | 85d42a76fbdd67a16918565b87922b978a462ed2 (patch) | |
tree | 5c3c1578535de8a7915336961f1dc628ef46d7d7 /acronyms_expander | |
parent | 6976a840b35debd0040e56e74a173fe0cceba2a1 (diff) |
[acronyms] Complete rewrite of the plugin
Diffstat (limited to 'acronyms_expander')
-rw-r--r-- | acronyms_expander/acronyms | 69 | ||||
-rw-r--r-- | acronyms_expander/acronyms.py | 70 | ||||
-rw-r--r-- | acronyms_expander/acronyms_expander.py | 214 |
3 files changed, 182 insertions, 171 deletions
diff --git a/acronyms_expander/acronyms b/acronyms_expander/acronyms deleted file mode 100644 index 7cbe8e5..0000000 --- a/acronyms_expander/acronyms +++ /dev/null @@ -1,69 +0,0 @@ -{"afaik": "as far as I know", -"afaict": "as far as I can tell", -"afk": "away from keyboard", -"atm": "at the moment", -"bbiab": "be back in a bit", -"bbiaf": "be back in a few (minutes)", -"bbl": "be back later", -"bbs": "be back soon", -"b/c": "because", -"bf": "boyfriend", -"bfo": "blinding flash of the obvious", -"brb": "be right back", -"bsod": "blue screen of death", -"btw": "by the way", -"ciao": "Italian for goodbye", -"ctrn": "can't talk right now", -"cul8r": "see you later", -"cya": "see ya", -"dhtb": "don't have the bandwidth", -"f2f": "face to face", -"fubar": "fucked up beyond all recognition", -"fwiw": "for what it's worth", -"fyi": "for your information", -"gmta": "great minds think alike", -"iam": "in a meeting", -"ianal": "I am not a lawyer", -"ihmb": "I hate my boss", -"iirc": "if I recall correctly", -"imho": "in my humble opinion", -"imo": "in my opinion", -"iow": "in other words", -"irl": "in real life", -"<g>": "grin", -"*g*": "grin", -"gf": "girlfriend", -"gmta": "great minds think alike", -"g2g": "got to go", -"jid": "jabber identifier", -"j/k": "just kidding", -"ok": "okay", -"lol": "laugh out loud", -"l8r": "later", -"msg": "message", -"n/m": "never mind", -"n/p": "no problem", -"oAo": "over and out!", -"omg": "oh my god", -"oob": "out of band", -"otoh": "on the other hand", -"oww": "oops, wrong window!", -"otp": "on the phone", -"pita": "pain in the ass", -"pov": "point of view", -"pw": "password", -"rotfl": "rolling on the floor laughing", -"rsn": "real soon now", -"rtfm": "read the friendly manual", -"slap": "sounds like a plan", -"thx": "thanks", -"tia": "thanks in advance", -"tla": "three-letter arconym", -"ttfn": "ta ta for now", -"ttyl": "talk to you later", -"wb": "welcome back", -"wfm": "works for me", -"wtf": "what the fuck?!", -"wtg": "way to go!", -"xfer": "transfer", -"ymmv": "your mileage may vary",} diff --git a/acronyms_expander/acronyms.py b/acronyms_expander/acronyms.py new file mode 100644 index 0000000..f49bc26 --- /dev/null +++ b/acronyms_expander/acronyms.py @@ -0,0 +1,70 @@ +DEFAULT_DATA = { + "afaik": "as far as I know", + "afaict": "as far as I can tell", + "afk": "away from keyboard", + "atm": "at the moment", + "bbiab": "be back in a bit", + "bbiaf": "be back in a few (minutes)", + "bbl": "be back later", + "bbs": "be back soon", + "b/c": "because", + "bf": "boyfriend", + "bfo": "blinding flash of the obvious", + "brb": "be right back", + "bsod": "blue screen of death", + "btw": "by the way", + "ciao": "Italian for goodbye", + "ctrn": "can't talk right now", + "cul8r": "see you later", + "cya": "see ya", + "dhtb": "don't have the bandwidth", + "f2f": "face to face", + "fubar": "fucked up beyond all recognition", + "fwiw": "for what it's worth", + "fyi": "for your information", + "iam": "in a meeting", + "ianal": "I am not a lawyer", + "ihmb": "I hate my boss", + "iirc": "if I recall correctly", + "imho": "in my humble opinion", + "imo": "in my opinion", + "iow": "in other words", + "irl": "in real life", + "<g>": "grin", + "*g*": "grin", + "gf": "girlfriend", + "gmta": "great minds think alike", + "g2g": "got to go", + "jid": "jabber identifier", + "j/k": "just kidding", + "ok": "okay", + "lol": "laugh out loud", + "l8r": "later", + "msg": "message", + "n/m": "never mind", + "n/p": "no problem", + "oAo": "over and out!", + "omg": "oh my god", + "oob": "out of band", + "otoh": "on the other hand", + "oww": "oops, wrong window!", + "otp": "on the phone", + "pita": "pain in the ass", + "pov": "point of view", + "pw": "password", + "rotfl": "rolling on the floor laughing", + "rsn": "real soon now", + "rtfm": "read the friendly manual", + "slap": "sounds like a plan", + "thx": "thanks", + "tia": "thanks in advance", + "tla": "three-letter arconym", + "ttfn": "ta ta for now", + "ttyl": "talk to you later", + "wb": "welcome back", + "wfm": "works for me", + "wtf": "what the fuck?!", + "wtg": "way to go!", + "xfer": "transfer", + "ymmv": "your mileage may vary", +} diff --git a/acronyms_expander/acronyms_expander.py b/acronyms_expander/acronyms_expander.py index 983a43c..ea55cfa 100644 --- a/acronyms_expander/acronyms_expander.py +++ b/acronyms_expander/acronyms_expander.py @@ -1,114 +1,124 @@ -# -*- coding: utf-8 -*- - -## This file is part of Gajim. -## -## Gajim 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; version 3 only. -## -## Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>. -## - -''' -Acronyms expander plugin. - -:author: Mateusz Biliński <mateusz@bilinski.it> -:since: 9th June 2008 -:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it> -:license: GPL -''' - -import os - -from gi.repository import GObject +# Copyright (C) 2008 Mateusz Biliński <mateusz AT bilinski.it> +# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com> +# +# This file is part of Acronyms Expander. +# +# Acronyms Expander 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; version 3 only. +# +# Acronyms Expander 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 Acronyms Expander. If not, see <http://www.gnu.org/licenses/>. + +import json +import logging +from pathlib import Path + +from gi.repository import GLib + +from gajim.common import configpaths from gajim.plugins import GajimPlugin -from gajim.plugins.helpers import log, log_calls +from gajim.plugins.plugins_i18n import _ -# Since Gajim 1.1.0 _() has to be imported -try: - from gajim.common.i18n import _ -except ImportError: - pass +from acronyms_expander.acronyms import DEFAULT_DATA + +log = logging.getLogger('gajim.plugin_system.acronyms') -class AcronymsExpanderPlugin(GajimPlugin): - @log_calls('AcronymsExpanderPlugin') +class AcronymsExpanderPlugin(GajimPlugin): def init(self): self.description = _('Replaces acronyms (or other strings) ' - 'with given expansions/substitutes.') + 'with given expansions/substitutes.') self.config_dialog = None - self.gui_extension_points = { - 'chat_control_base': (self.connect_with_chat_control_base, - self.disconnect_from_chat_control_base) - } - - self.config_default_values = { - 'INVOKER': (' ', ''), - 'ACRONYMS': ({'/slap': '/me slaps', - 'PS-': 'plug-in system', - 'G-': 'Gajim', - 'GNT-': 'https://dev.gajim.org/gajim/gajim/issues', - 'GW-': 'https://dev.gajim.org/gajim/gajim/wikis/home', - }, - ''), + 'chat_control_base': (self._connect, self._disconnect) } - if 'ACRONYMS' not in self.config: - myAcronyms = self.get_own_acronyms_list() - self.config['ACRONYMS'].update(myAcronyms) - - @log_calls('AcronymsExpanderPlugin') - def get_own_acronyms_list(self): - data_file = self.local_file_path('acronyms') - if not os.path.isfile(data_file): - return {} - data = open(data_file, 'r', encoding='utf-8') - acronyms = eval(data.read()) - data.close() + self._invoker = ' ' + self._acronyms = self._load_acronyms() + self._replace_in_progress = False + self._handler_ids = {} + + @staticmethod + def _load_acronyms(): + try: + path = Path(configpaths.get('PLUGINS_DATA')) / 'acronyms' + except KeyError: + # PLUGINS_DATA was added in 1.0.99.1 + return DEFAULT_DATA + + if not path.exists(): + return DEFAULT_DATA + + with open(path / 'acronyms', 'r') as file: + acronyms = json.load(file) return acronyms - @log_calls('AcronymsExpanderPlugin') - def textbuffer_live_acronym_expander(self, tb): - """ - @param tb gtk.TextBuffer - """ - #assert isinstance(tb,gtk.TextBuffer) - ACRONYMS = self.config['ACRONYMS'] - INVOKER = self.config['INVOKER'] - t = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), True) - #log.debug('%s %d'%(t, len(t))) - if t and t[-1] == INVOKER: - #log.debug('changing msg text') - base, sep, head=t[:-1].rpartition(INVOKER) - log.debug('%s | %s | %s'%(base, sep, head)) - if head in ACRONYMS: - head = ACRONYMS[head] - #log.debug('head: %s'%(head)) - t = ''.join((base, sep, head, INVOKER)) - #log.debug("setting text: '%s'"%(t)) - GObject.idle_add(tb.set_text, t) - - @log_calls('AcronymsExpanderPlugin') - def connect_with_chat_control_base(self, chat_control): - d = {} - tv = chat_control.msg_textview - tb = tv.get_buffer() - h_id = tb.connect('changed', self.textbuffer_live_acronym_expander) - d['h_id'] = h_id - - chat_control.acronyms_expander_plugin_data = d - - return True - - @log_calls('AcronymsExpanderPlugin') - def disconnect_from_chat_control_base(self, chat_control): - d = chat_control.acronyms_expander_plugin_data - tv = chat_control.msg_textview - tv.get_buffer().disconnect(d['h_id']) + @staticmethod + def _save_acronyms(acronyms): + path = Path(configpaths.get('PLUGINS_DATA')) / 'acronyms' + with open(path / 'acronyms', 'w') as file: + json.dump(acronyms, file) + + def _on_buffer_changed(self, _textview, buffer_): + if self._replace_in_progress: + return + + if buffer_.get_char_count() < 2: + return + # Get iter at cursor + insert_iter = buffer_.get_iter_at_mark(buffer_.get_insert()) + + if insert_iter.get_offset() < 2: + # We need at least 2 chars and an invoker + return + + # Get last char + insert_iter.backward_char() + if insert_iter.get_char() != self._invoker: + log.debug('"%s" not an invoker', insert_iter.get_char()) + return + + # Get to the start of the last word + word_start_iter = insert_iter.copy() + word_start_iter.backward_word_start() + + # Get last word and cut invoker + last_word = word_start_iter.get_slice(insert_iter).strip() + + substitute = self._acronyms.get(last_word) + if substitute is None: + log.debug('%s not an acronym', last_word) + return + + # Replace + word_end_iter = word_start_iter.copy() + word_end_iter.forward_word_end() + GLib.idle_add(self._replace_text, + buffer_, + word_start_iter, + word_end_iter, + substitute) + + def _replace_text(self, buffer_, start, end, substitute): + self._replace_in_progress = True + buffer_.delete(start, end) + buffer_.insert(start, substitute) + self._replace_in_progress = False + + def _connect(self, chat_control): + textview = chat_control.msg_textview + handler_id = textview.connect('text-changed', self._on_buffer_changed) + self._handler_ids[id(textview)] = handler_id + + def _disconnect(self, chat_control): + textview = chat_control.msg_textview + handler_id = self._handler_ids.get(id(textview)) + if handler_id is not None: + textview.disconnect(handler_id) + del self._handler_ids[id(textview)] |