import mode, method, ispell from mode import Fundamental 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('text.word', self, lexer.y, lexer.x, s, None, parent, {}) else: token = Token('text.misspelled', self, lexer.y, lexer.x, s, None, parent, {}) token.color = lexer.get_color(token) lexer.x += len(s) yield token return class ContinuedRule(RegionRule): def __init__(self): RegionRule.__init__(self, r'cont', r'[a-zA-Z0-9_]+- *$', Grammar, r'^ *(?:[^ ]+|$)') class TextGrammar(Grammar): rules = [ PatternRule(r'text.link', r'[a-z]+://[^ ]*[^- .,;:]'), ContinuedRule(), WordRule(), PatternRule(r'text.punct', r'[^a-zA-Z0-9_]'), PatternRule(r'text.stuff', r'[a-zA-Z0-9_]+'), ] class TextWrapParagraph(method.WrapParagraph): pass class TextInsertSpace(method.Method): wrapper = TextWrapParagraph def execute(self, w, **vargs): cursor = w.logical_cursor() i = cursor.y if len(w.buffer.lines[i]) > self.wrapper.limit: self.wrapper().execute(w) w.insert_string_at_cursor(' ') 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 == 'text.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() class Text(Fundamental): name = 'Text' extensions = ['.txt'] grammar = TextGrammar actions = [LearnWord, TextInsertSpace, TextWrapParagraph] config = { 'text.margin': 78, } _bindings = { 'learn-word': ('C-c l',), 'text-insert-space': ('SPACE',), 'text-wrap-paragraph': ('M-q',), } colors = { 'text.link': ('cyan', 'default'), 'text.punct': ('default', 'default'), 'text.stuff': ('default', 'default'), 'text.word': ('default', 'default'), 'text.misspelled': ('red', 'default', 'bold'), } install = Text.install