diff --git a/IDEAS b/IDEAS index 5f38283..3131e0e 100644 --- a/IDEAS +++ b/IDEAS @@ -1,3 +1,8 @@ +2009/07/11: + +Redo mode detection so that it uses regexes not words. Then fix all the modes +that want #! detection. + 2009/05/05: Either give buffers direct access to the application object, or make the diff --git a/application.py b/application.py index 678365f..05849df 100755 --- a/application.py +++ b/application.py @@ -405,10 +405,12 @@ class Application(object): return self.mini_buffer is not None def open_mini_buffer(self, prompt, cb, method=None, tabber=None, modename=None, startvalue=None, queue='default'): + parentw = self.bufferlist.slots[self.active_slot].window if self.mini_buffer_is_open(): self.close_mini_buffer() self.mini_prompt = prompt - self.mini_buffer = MiniBuffer(cb, self, method, tabber, modename, queue) + self.mini_buffer = MiniBuffer(cb, self, method, tabber, modename, queue, + parentw) try: w = self.x - 1 - len(self.mini_prompt) - 1 window.Window(self.mini_buffer, self, height=1, width=w) diff --git a/buffer/__init__.py b/buffer/__init__.py index 9743cbc..8cdd57f 100644 --- a/buffer/__init__.py +++ b/buffer/__init__.py @@ -685,14 +685,14 @@ class FileBuffer(Buffer): try: data = self.make_string() if self.windows[0].mode.savetabs: - data = data.replace(" ", "\t").encode(self.codec) - - data = self.write_filter(data) + data = data.replace(" ", "\t") + data = self.write_filter(data.encode(self.codec)) f2 = self._open_file_w(self.path, preserve=False) f2.write(self.bytemark + data) f2.close() - except Exception, e: + #except Exception, e: + except NameError, e: if exists: shutil.copyfile(temp_path, self.path) raise e else: diff --git a/buffer/emul.py b/buffer/emul.py index 5e714de..06bb699 100644 --- a/buffer/emul.py +++ b/buffer/emul.py @@ -159,7 +159,9 @@ class XTermBuffer(Buffer, XTerm): self._towrite = self._towrite[n:] self._lock.release() if efd: - raise Exception, "exception is ready: %s" % repr(efd) + self.term_receive(repr(efd)) + #raise Exception, "exception is ready: %s" % repr(efd) + pass except OSError: pass except TypeError: diff --git a/minibuffer.py b/minibuffer.py index ebee996..da73812 100644 --- a/minibuffer.py +++ b/minibuffer.py @@ -14,7 +14,7 @@ class MiniBuffer(buffer.Buffer): return mini # the callback function should take one argument (window) def __init__(self, func, app, method=None, tabber=None, modename=None, - queue=None): + queue=None, parentw=None): buffer.Buffer.__init__(self) self.app = app self.callback = func @@ -22,6 +22,7 @@ class MiniBuffer(buffer.Buffer): self.tabber = tabber self.modename = modename self.queue = queue + self.parentw = parentw def name(self): return "*Minibuffer*" diff --git a/mode/consolemini.py b/mode/consolemini.py index 1e65217..0733ef5 100644 --- a/mode/consolemini.py +++ b/mode/consolemini.py @@ -93,11 +93,12 @@ class ConsoleCancel(Method): w.application.close_completion_buffer() class ConsoleClear(Method): def execute(self, w, **vargs): - a = w.application - if not a.has_buffer_name('*Console*'): - raise Exception, "No console found!" - b = a.bufferlist.get_buffer_by_name('*Console*') - b.clear() + #a = w.application + #if not a.has_buffer_name('*Console*'): + # raise Exception, "No console found!" + #b = a.bufferlist.get_buffer_by_name('*Console*') + #b.clear() + w.buffer.parentw.buffer.clear() class ConsoleHistoryPrev(Method): def execute(self, w, **vargs): diff --git a/mode/mutt.py b/mode/mutt.py index 45a1f97..49e17fa 100644 --- a/mode/mutt.py +++ b/mode/mutt.py @@ -17,7 +17,7 @@ rules = [ ] class HeaderGrammar(Grammar): - rules = [PatternRule('header', '^[^ ].*:')] + rules + rules = [PatternRule('header', '^[^ ][^:]*:')] + rules class BodyGrammar(Grammar): rules = rules class MuttGrammar(Grammar): rules = [RegionRule('mutt', '^', HeaderGrammar, '^\n$', BodyGrammar, '')] diff --git a/mode/perl.py b/mode/perl.py index 2923bb0..a22f253 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -698,7 +698,8 @@ class PerlContext(context.Context): class Perl(Fundamental): name = 'Perl' extensions = ['.pl', '.pm', '.pod'] - detection = ['perl'] + #detection = ['perl'] + detection = [re.compile('^#!(?:.+/)?perl')] tabbercls = PerlTabber2 grammar = PerlGrammar commentc = '#' diff --git a/mode/python.py b/mode/python.py index f053119..b11a4f6 100644 --- a/mode/python.py +++ b/mode/python.py @@ -61,7 +61,7 @@ class PythonGrammar(Grammar): RegionRule('string', 'u?"', StringGrammar2, '"'), RegionRule('string', "u?'", StringGrammar1, "'"), - PatternRule('delimiter', r'\(|\)|\[|\]|{|}|@|,|:|\.|`|=|;|\+=|-=|\*=|/=|//=|%=|&=|\|=|\^=|>>=|<<=|\*\*='), + PatternRule('delimiter', r'\(|\)|\[|\]|{|}|,|:|\.|`|=|;|\+=|-=|\*=|/=|//=|%=|&=|\|=|\^=|>>=|<<=|\*\*='), PatternRule(r"python.integer", r"(?[.a-zA-Z0-9_]+):(?P[.a-zA-Z0-9_]+) *$'), PatternRule('comment', '#.*$'), PatternRule('continuation', r'\\\n$'), - PatternRule('decorator', '@[a-zA-Z_][a-zA-Z0-9_]*'), + PatternRule('python.decorator', '@[a-zA-Z_][a-zA-Z0-9_]*'), PatternRule('spaces', ' +'), PatternRule('eol', r'\n$'), ] @@ -335,7 +335,8 @@ class PythonSemanticComplete(method.introspect.TokenComplete): a = w.application a.methods['ipython-path-start'].execute(w, switch=False) - name = buffer.IperlBuffer.create_name(w.buffer) + #name = buffer.IperlBuffer.create_name(w.buffer) + name = buffer.IpythonBuffer.create_name(w.buffer) b = a.get_buffer_by_name(name) line = w.buffer.lines[t.y] @@ -560,7 +561,8 @@ class Python(mode.Fundamental): ''' name = 'Python' extensions = ['.py'] - detection = ['python'] + #detection = ['python'] + detection = [re.compile('^#!(?:.+/)python')] tabbercls = PythonTabber grammar = PythonGrammar opentokens = ('delimiter',) diff --git a/mode/sh.py b/mode/sh.py index fcc0f4e..18e0a6f 100644 --- a/mode/sh.py +++ b/mode/sh.py @@ -1,3 +1,5 @@ +import re + import commands from tab import StackTabber from mode import Fundamental @@ -190,7 +192,8 @@ class Sh(Fundamental): paths = ['/etc/profile'] basenames = ['.bashrc', '.bash_profile', '.profile'] extensions = ['.bash', '.sh'] - detection = ['sh', 'bash'] + #detection = ['sh', 'bash'] + detection = [re.compile('^#!(?:.+/)sh'), re.compile('^#!(?:.+/)bash')] grammar = ShGrammar tabbercls = ShTabber opentokens = ('delimiter', 'sh_reserved', 'case.start') diff --git a/mode/xml.py b/mode/xml.py index b0e3738..d4b7a48 100644 --- a/mode/xml.py +++ b/mode/xml.py @@ -1,50 +1,55 @@ +import re + import color, method, mode from lex import Grammar, Rule, PatternRule, RegionRule, PatternMatchRule class StringGrammar1(Grammar): rules = [ - PatternRule(r'data', r'[^"&]+'), - PatternRule(r'escaped', r'&[a-z]+;'), + PatternRule('data', '[^"&]+'), + PatternRule('escaped', '&[a-z]+;'), ] class StringGrammar2(Grammar): rules = [ - PatternRule(r'data', r"[^'&]+"), - PatternRule(r'escaped', r'&[a-z]+;'), + PatternRule('data', r"[^'&]+"), + PatternRule('escaped', '&[a-z]+;'), ] class CDataGrammar(Grammar): - rules = [PatternRule(r'data', r'(?:[^\]]|\](?!\])|\]\](?!>))+')] + rules = [PatternRule('data', r'(?:[^\]]|\](?!\])|\]\](?!>))+')] class CommentGrammar(Grammar): - rules = [PatternRule(r'data', r'(?:[^-]|-(?!-)|--(?!>))+')] -class MetadataGrammar(Grammar): - rules = [PatternRule(r'data', r'(?:[^?]|\?(?!>))+')] - + rules = [PatternRule('data', '(?:[^-]|-(?!-)|--(?!>))+')] class TagGrammar(Grammar): rules = [ - PatternRule(r'attrname', r'[a-zA-Z_][a-zA-Z0-9_]+(?==)'), - PatternRule(r'namespace', r'[a-zA-Z_]+(?=:)'), - PatternRule(r'name', r'[a-zA-Z_][a-zA-Z0-9_]*'), - PatternRule(r'delimiter', r'[:/=]'), - RegionRule(r'string', r'"', StringGrammar1, r'"'), - RegionRule(r'string', r"'", StringGrammar2, r"'"), - PatternRule(r'spaces', r' +'), - PatternRule(r'eol', r'\n'), + PatternRule('attrname', '[a-zA-Z_][a-zA-Z0-9_]+(?==)'), + PatternRule('namespace', '[a-zA-Z_]+(?=:)'), + PatternRule('name', '[a-zA-Z_][a-zA-Z0-9_]*'), + PatternRule('delimiter', '[:/=]'), + RegionRule('string', '"', StringGrammar1, '"'), + RegionRule('string', "'", StringGrammar2, "'"), + PatternRule('spaces', ' +'), + PatternRule('eol', r'\n'), ] +class MetadataGrammar(Grammar): + rules = [PatternRule('meta', r'\?(?:xml)?')] + TagGrammar.rules +class DoctypeGrammar(Grammar): + rules = [PatternRule('doctype', '!DOCTYPE')] + TagGrammar.rules class XMLGrammar(Grammar): rules = [ # TODO: how does cdata work again? - PatternRule(r'data', r'[^<& \n]+'), - PatternRule(r'spaces', r' +'), - PatternRule(r'xml.entity', r'&[a-z]+;'), - PatternRule(r'eol', r'\n'), - PatternMatchRule('x', r'(<)(/)([a-zA-Z_][a-zA-Z0-9_]*)(>)', + PatternRule('data', r'[^<& \n]+'), + PatternRule('spaces', ' +'), + PatternRule('xml.entity', '&[a-z]+;'), + PatternRule('eol', r'\n'), + PatternMatchRule('x', '(<)(/)([a-zA-Z_][a-zA-Z0-9_]*)(>)', 'xml.tag.start', 'xml.tag.delimiter', 'xml.tag.name', 'xml.tag.end'), - RegionRule(r'xml.tag', r'<(?![\?!])', TagGrammar, r'/?>'), - RegionRule(r'comment', r''), - RegionRule(r'xml.metadata', r'<\?', MetadataGrammar, r'\?>'), - RegionRule(r'xml.cdata', r''), + RegionRule('xml.tag', r'<(?![\?!])', TagGrammar, '/?>'), + RegionRule('xml.tag', r'<(?![\?!])', TagGrammar, '/?>'), + RegionRule('comment', ''), + RegionRule('xml.tag', r'<(?=\?)', MetadataGrammar, r'\?>'), + RegionRule('xml.tag', '<(?!!)', DoctypeGrammar, '>'), + RegionRule('xml.cdata', r''), ] class XmlValidate(method.shell.Exec): @@ -84,20 +89,20 @@ class XmlCreateCdata(method.Method): class XML(mode.Fundamental): name = 'XML' extensions = ['.xml', '.xml.in', '.xsl', '.xsd'] + detection = [re.compile(r'^<\?xml')] grammar = XMLGrammar colors = { - 'xml.metadata.start': ('magenta', 'default', 'bold'), - 'xml.metadata.data': ('magenta', 'default', 'bold'), - 'xml.metadata.end': ('magenta', 'default', 'bold'), - 'xml.tag.start': ('default', 'default', 'bold'), - 'xml.tag.namespace': ('magenta', 'default', 'bold'), - 'xml.tag.name': ('blue', 'default', 'bold'), - 'xml.tag.attrname': ('cyan', 'default', 'bold'), - 'xml.tag.end': ('default', 'default', 'bold'), - 'xml.entity': ('magenta', 'default', 'bold'), - 'xml.cdata.start': ('magenta', 'default', 'bold'), - 'xml.cdata.data': ('green', 'default', 'bold'), - 'xml.cdata.end': ('magenta', 'default', 'bold'), + 'xml.tag.meta': ('magenta', 'default', 'bold'), + 'xml.tag.doctype': ('magenta', 'default', 'bold'), + 'xml.tag.start': ('default', 'default', 'bold'), + 'xml.tag.namespace': ('magenta', 'default', 'bold'), + 'xml.tag.name': ('blue', 'default', 'bold'), + 'xml.tag.attrname': ('cyan', 'default', 'bold'), + 'xml.tag.end': ('default', 'default', 'bold'), + 'xml.entity': ('magenta', 'default', 'bold'), + 'xml.cdata.start': ('magenta', 'default', 'bold'), + 'xml.cdata.data': ('green', 'default', 'bold'), + 'xml.cdata.end': ('magenta', 'default', 'bold'), } actions = [XmlValidate, XmlCreateTag, XmlCreateComment, XmlCreateCdata] _bindings = { diff --git a/window.py b/window.py index b48f381..afed9f5 100644 --- a/window.py +++ b/window.py @@ -64,11 +64,11 @@ class Window(object): mode_name = regex.auto_mode_emacs.search(firstline).group(1) elif regex.auto_mode_vi.search(firstline): mode_name = regex.auto_mode_vi.search(firstline).group(1) - elif firstline.startswith('#!'): - line = b.lines[0] - for word in a.mode_detection: - if word in line: - mode_name = a.mode_detection[word] + else: + for (r, name) in a.mode_detection.items(): + if r.match(b.lines[0]): + mode_name = name + break cls = a.modes.get(mode_name, a.modes['fundamental']) self.set_mode(cls(self))