From bb50a613d7b19adb2be5ae3266d2f9601a816e26 Mon Sep 17 00:00:00 2001 From: moculus Date: Sun, 24 Jun 2007 02:49:13 +0000 Subject: [PATCH] lots of fixes and improvements --HG-- branch : pmacs2 --- application.py | 15 +++---- lex2.py | 6 --- method.py | 4 +- mode_mutt.py | 53 +++++++++++++---------- mode_text.py | 112 ++++++++++++++++++++++++++++++------------------- 5 files changed, 110 insertions(+), 80 deletions(-) diff --git a/application.py b/application.py index 35a7e1e..0e1f152 100755 --- a/application.py +++ b/application.py @@ -7,12 +7,13 @@ import util, window2 from point2 import Point # modes -#import mode, mode_c, mode_mini, mode_python, mode_nasm, mode_perl, mode_search -#import mode_replace, mode_xml, mode_console, mode_sh, mode_text, mode_which -#import mode_mutt, mode_sql, mode_javascript, mode_diff, mode_blame, mode_tt +#import #mode, mode_c, #mode_mini, #mode_python, mode_nasm, #mode_perl, #mode_search +#import #mode_replace, #mode_xml, mode_console, mode_sh, #mode_text, #mode_which +#import #mode_mutt, mode_sql, mode_javascript, mode_diff, #mode_blame, mode_tt import mode2 import mode_mini, mode_search, mode_replace, mode_blame, mode_which -import mode_python, mode_perl, mode_xml, mode_life +import mode_python, mode_perl, mode_xml +import mode_life, mode_text, mode_mutt def run(buffers, jump_to_line=None, init_mode=None): # save terminal state so we can restore it when the program exits @@ -92,11 +93,11 @@ class Application(object): 'replace': mode_replace.Replace, 'search': mode_search.Search, # 'sh': mode_sh.Sh, -# 'text': mode_text.Text, + 'text': mode_text.Text, 'which': mode_which.Which, 'xml': mode_xml.XML, 'life': mode_life.Life, -# 'mutt': mode_mutt.Mutt, + 'mutt': mode_mutt.Mutt, # 'sql': mode_sql.Sql, # 'javascript': mode_javascript.Javascript, # 'template': mode_tt.Template, @@ -118,7 +119,7 @@ class Application(object): '.pm': 'perl', '.t': 'perl', # '.c': 'c', -# '.txt': 'text', + '.txt': 'text', # '.s': 'nasm', # '.sh': 'sh', # '.bash': 'sh', diff --git a/lex2.py b/lex2.py index f1261db..bb689a4 100755 --- a/lex2.py +++ b/lex2.py @@ -120,12 +120,6 @@ class ContextPatternRule(PatternRule): else: return False -def xyz(x): - if hasattr(x, 'name'): - return x.name - else: - return x - class RegionRule(Rule): def __init__(self, name, start, grammar, end): assert valid_name_re.match(name), 'invalid name %r' % name diff --git a/method.py b/method.py index 0edd371..3a60880 100644 --- a/method.py +++ b/method.py @@ -605,7 +605,7 @@ class WrapLine(Method): limit = 80 def _execute(self, w, **vargs): cursor = w.logical_cursor() - old_cursor = cursor.copy() + old_cursor = cursor i = cursor.y move_old_cursor = old_cursor.x > self.limit @@ -634,7 +634,7 @@ class WrapParagraph(Method): limit = 80 wrapper = WrapLine def _execute(self, w, **vargs): - old_cursor = w.logical_cursor().copy() + old_cursor = w.logical_cursor() i = old_cursor.y while i < len(w.buffer.lines) - 1: if i < len(w.buffer.lines) and \ diff --git a/mode_mutt.py b/mode_mutt.py index 6a26548..17aeb3c 100644 --- a/mode_mutt.py +++ b/mode_mutt.py @@ -1,32 +1,41 @@ -import sets, sys +import color, mode2, method, mode_text +from lex2 import Grammar, PatternRule -import color, mode, lex, lex_mutt, method, mode_text +class MuttGrammar(Grammar): + rules = [ + PatternRule(name=r'header', pattern=r'^(?:From|To|Cc|Bcc|Subject|Reply-To|In-Reply-To|Delivered-To|Date):'), + PatternRule(name=r'quote1', pattern=r'^ *(?:(?: *>){3})*(?: *>){1}.*$'), + PatternRule(name=r'quote2', pattern=r'^ *(?:(?: *>){3})*(?: *>){2}.*$'), + PatternRule(name=r'quote3', pattern=r'^ *(?:(?: *>){3})*(?: *>){3}.*$'), + PatternRule(name=r'email', pattern=r'(?:^|(?<=[ :]))@\n ]+@(?:[^<>@\.\n ]+\.)*[^<>@\.\n ]+>?'), + PatternRule(name=r'url', pattern=r'(?:^|(?<= ))(?:http|https|ftp|sftp|file|smtp|smtps|torrent|news|jabber|irc|telnet)://(?:[^\.\n ]+\.)*[^\.\n ]+'), + mode_text.ContinuedRule(), + mode_text.WordRule(), + PatternRule(name=r'punct', pattern=r'[^a-zA-Z0-9_]'), + PatternRule(name=r'stuff', pattern=r'[a-zA-Z0-9_]+'), + ] -class Mutt(mode.Fundamental): +class Mutt(mode2.Fundamental): + grammar = MuttGrammar() def __init__(self, w): - mode.Fundamental.__init__(self, w) - + mode2.Fundamental.__init__(self, w) self.add_action_and_bindings(mode_text.LearnWord(), ('C-c l',)) self.add_action_and_bindings(MuttWrapParagraph(), ('M-q',)) self.add_action_and_bindings(MuttInsertSpace(), ('SPACE',)) - - self.grammar = lex_mutt.MuttGrammar() - #import lex_text - #self.grammar = lex_text.TextGrammar() - self.lexer = lex.Lexer(self.grammar) - - self.default_color = color.build('default', 'default') self.colors = { - 'header': color.build('green', 'default', 'bold'), - 'email': color.build('cyan', 'default', 'bold'), - 'url': color.build('cyan', 'default', 'bold'), - 'misspelled word': color.build('red', 'default', 'bold'), - 'misspelled continued word': color.build('red', 'default', 'bold'), - 'quote1': color.build('yellow', 'default', 'bold'), - 'quote2': color.build('cyan', 'default', 'bold'), - 'quote3': color.build('magenta', 'default', 'bold'), + 'header': color.build('green', 'default', 'bold'), + 'email': color.build('cyan', 'default', 'bold'), + 'url': color.build('cyan', 'default', 'bold'), + 'quote1': color.build('yellow', 'default', 'bold'), + 'quote2': color.build('cyan', 'default', 'bold'), + 'quote3': color.build('magenta', 'default', 'bold'), + 'misspelled': color.build('red', 'default'), + 'cont.start': color.build('default', 'default'), + 'cont.end': color.build('default', 'default'), + 'word': color.build('default', 'default'), + 'punct': color.build('default', 'default'), + 'stuff': color.build('default', 'default'), } - def name(self): return "Mutt" @@ -37,5 +46,5 @@ class MuttWrapParagraph(method.WrapParagraph): wrapper = MuttWrapLine class MuttInsertSpace(mode_text.TextInsertSpace): - limit = 72 + limit = 72 wrapper = MuttWrapParagraph diff --git a/mode_text.py b/mode_text.py index b4bb877..86c1b19 100644 --- a/mode_text.py +++ b/mode_text.py @@ -1,61 +1,87 @@ -import sets, sys +import color, mode2, method, ispell +from lex2 import Token, Rule, PatternRule, RegionRule, Grammar -import color, mode, lex, lex_text, method, ispell +class WordRule(PatternRule): + def __init__(self): + PatternRule.__init__(self, name=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 _match(self, lexer, parent, m): + s = m.group(0) + if self._spelled_ok(s): + token = Token('word', self, lexer.y, lexer.x, s, parent, {}) + else: + token = Token('misspelled', self, lexer.y, lexer.x, s, parent, {}) + lexer.add_token(token) + lexer.x += len(s) -class Text(mode.Fundamental): +class ContinuedRule(RegionRule): + def __init__(self): + RegionRule.__init__(self, name=r'cont', start=r'[a-zA-Z0-9_]+- *$', + grammar=Grammar(), end=r'^ *(?:[^ ]+|$)') + +class TextGrammar(Grammar): + rules = [ + ContinuedRule(), + WordRule(), + PatternRule(name=r'punct', pattern=r'[^a-zA-Z0-9_]'), + PatternRule(name=r'stuff', pattern=r'[a-zA-Z0-9_]+'), + ] + +class Text(mode2.Fundamental): + grammar = TextGrammar() def __init__(self, w): - mode.Fundamental.__init__(self, w) - + mode2.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',)) - - self.grammar = lex_text.TextGrammar() - self.lexer = lex.Lexer(self.grammar) - - self.default_color = color.build('default', 'default') self.colors = { - 'misspelled word': color.build('red', 'default', 'bold'), - 'misspelled continued word': color.build('red', 'default', 'bold'), + 'misspelled': color.build('red', 'default'), + 'cont.start': color.build('default', 'default'), + 'cont.end': color.build('default', 'default'), + 'word': color.build('default', 'default'), + 'punct': color.build('default', 'default'), + 'stuff': color.build('default', 'default'), } - def name(self): return "Text" class TextInsertSpace(method.Method): - limit = 80 - #wrapper = method.WrapLine + limit = 80 wrapper = method.WrapParagraph - def execute(self, window, **vargs): - window.insert_string(' ') - cursor = window.logical_cursor() + def execute(self, w, **vargs): + w.insert_string_at_cursor(' ') + cursor = w.logical_cursor() i = cursor.y - if len(window.buffer.lines[i]) > self.limit: - self.wrapper().execute(window) + if len(w.buffer.lines[i]) > self.limit: + self.wrapper().execute(w) class LearnWord(method.Method): - def execute(self, window, **vargs): - if window.mode.highlighter.tokens is None: - window.mode.highlighter.lex_buffer() - cursor = window.logical_cursor() - cursor_offset = window.get_cursor_offset() + def execute(self, w, **vargs): + if not ispell.can_spell(): + w.application.set_error('Spelling support is unavailable') + return - tok = None - for t in window.mode.highlighter.tokens: - if t.start <= cursor_offset and cursor_offset < t.end: - tok = t - break + 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 tok: - word = tok.string - if tok.name.startswith('all-caps'): - s = "%r is all-caps" % (word) - elif tok.name.startswith('misspelled'): - ispell.get_speller().learn(word) - window.mode.highlighter.invalidate_tokens() - s = "Added %r to personal dictionary" % (word) - else: - s = "%r is already in the dictionary" % (word) - else: - s = "No word to learn found" - window.application.set_error(s) + 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()