import color, mode, method, ispell from lex import Token, Rule, PatternRule, RegionRule, Grammar class WordRule(PatternRule): def __init__(self): PatternRule.__init__(self, r'word', pattern=r"[a-zA-Z][a-zA-Z-\']*[a-zA-Z](?=$|[^a-zA-Z0-9-_])") def _spelled_ok(self, word): if ispell.can_spell(): speller = ispell.get_speller() return speller.check(word, caps=False, title=False) else: return True def lex(self, lexer, parent, m): if m: s = m.group(0) if self._spelled_ok(s): token = Token('word', self, lexer.y, lexer.x, s, None, parent, {}) else: token = Token('misspelled', self, lexer.y, lexer.x, s, None, parent, {}) token.color = lexer.get_color(token) lexer.x += len(s) yield token raise StopIteration class ContinuedRule(RegionRule): def __init__(self): RegionRule.__init__(self, r'cont', r'[a-zA-Z0-9_]+- *$', Grammar, r'^ *(?:[^ ]+|$)') class TextGrammar(Grammar): rules = [ ContinuedRule(), WordRule(), PatternRule(r'punct', r'[^a-zA-Z0-9_]'), PatternRule(r'stuff', r'[a-zA-Z0-9_]+'), ] class Text(mode.Fundamental): modename = 'Text' extensions=['.txt'] grammar = TextGrammar colors = { 'misspelled': ('red', 'default'), 'cont.start': ('default', 'default'), 'cont.end': ('default', 'default'), 'word': ('default', 'default'), 'punct': ('default', 'default'), 'stuff': ('default', 'default'), } def __init__(self, w): mode.Fundamental.__init__(self, w) self.add_action_and_bindings(LearnWord(), ('C-c l',)) self.add_action_and_bindings(TextInsertSpace(), ('SPACE',)) self.add_action_and_bindings(method.WrapParagraph(), ('M-q',)) class TextInsertSpace(method.Method): limit = 80 #wrapper = method.WrapParagraph wrapper = method.WrapParagraph2 def execute(self, w, **vargs): w.insert_string_at_cursor(' ') cursor = w.logical_cursor() i = cursor.y if len(w.buffer.lines[i]) > self.limit: self.wrapper().execute(w) class LearnWord(method.Method): def execute(self, w, **vargs): if not ispell.can_spell(): w.application.set_error('Spelling support is unavailable') return cursor = w.logical_cursor() word = None for token in w.buffer.highlights[w.mode.name()].tokens[cursor.y]: if (token.x <= cursor.x and token.end_x() > cursor.x and token.name == 'misspelled'): word = token.string if word is None: w.application.set_error('No misspelled word was found') return speller = ispell.get_speller() speller.learn(word) w.application.set_error("Added %r to personal dictionary" % (word)) # cheap way to relex just this word; there should really be a function w.insert_string_at_cursor(' ') w.left_delete() install = Text.install