improvements to the big 3: c, python, perl

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-09-21 05:15:33 +00:00
parent bbe7bee4c5
commit b4d9a69663
3 changed files with 87 additions and 29 deletions

View File

@ -1,6 +1,6 @@
import os, re import os, re
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
import color, default, method, method.shell, mode, tab import color, context, default, method, method.shell, mode, tab
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
from mode.python import StringGrammar from mode.python import StringGrammar
@ -9,7 +9,7 @@ from mode.python import StringGrammar
class MacroGrammar(Grammar): class MacroGrammar(Grammar):
rules = [ rules = [
PatternRule('name', r'(?:(?<=#define )) *[a-zA-Z_][a-zA-Z0-9_]*'), PatternRule('name', r'(?:(?<=#define )) *[a-zA-Z_][a-zA-Z0-9_]*'),
PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=|\^=|>>=|<<=|\*\*=|\|="),
PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"),
PatternRule(r"delimiter", r"->|\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=|\?"), PatternRule(r"delimiter", r"->|\.|\(|\)|\[|\]|{|}|@|,|:|`|;|=|\?"),
PatternRule(r"integer", r"-?(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"), PatternRule(r"integer", r"-?(?:0(?![x0-9])|[1-9][0-9]*|0[0-7]+|0[xX][0-9a-fA-F]+)[lL]?"),
@ -38,6 +38,7 @@ class CGrammar(Grammar):
PatternRule(r'function', r'[a-zA-Z_][a-zA-Z0-9_]*(?= *\()'), PatternRule(r'function', r'[a-zA-Z_][a-zA-Z0-9_]*(?= *\()'),
PatternRule(r'builtin', r"(?:NULL|TRUE|FALSE)"), PatternRule(r'builtin', r"(?:NULL|TRUE|FALSE)"),
PatternRule(r'c_type', r'[a-zA-Z_][a-zA-Z0-9_]*(?= +[a-zA-Z_])'),
PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"), PatternRule(r'identifier', r"[a-zA-Z_][a-zA-Z0-9_]*"),
PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="), PatternRule(r"unop", r"\+=|-=|\*=|/=|//=|%=|&=\|\^=|>>=|<<=|\*\*="),
PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"), PatternRule(r'binop', r"\+|<>|<<|<=|<|-|>>|>=|>|\*\*|&|\*|\||/|\^|==|//|~|!=|%"),
@ -97,7 +98,7 @@ class CTabber(tab.StackTabber):
self._opt_pop('cont') self._opt_pop('cont')
token = self.get_token(y, i) token = self.get_token(y, i)
if token.string == '{': if token.string == '{':
self._pop_while('cond', 'cont') self._pop_while('cond', 'cont', 'case')
if self.is_leftmost_token(y, i): if self.is_leftmost_token(y, i):
currlvl = self.get_curr_level() currlvl = self.get_curr_level()
tab.StackTabber._handle_open_token(self, currlvl, y, i) tab.StackTabber._handle_open_token(self, currlvl, y, i)
@ -105,11 +106,13 @@ class CTabber(tab.StackTabber):
def _handle_close_token(self, currlvl, y, i): def _handle_close_token(self, currlvl, y, i):
w = self.mode.tabwidth w = self.mode.tabwidth
self._opt_pop('cont') self._opt_pop('cont')
currlvl = tab.StackTabber._handle_close_token(self, currlvl, y, i)
token = self.get_token(y, i) token = self.get_token(y, i)
if token.string == '}':
self._opt_pop('case')
currlvl = tab.StackTabber._handle_close_token(self, currlvl, y, i)
if self.is_rightmost_token(y, i): if self.is_rightmost_token(y, i):
if token.string == '}': if token.string == '}':
self._pop_while('cond', 'cont') self._pop_while('cond', 'cont', 'case')
elif self._has_markers() and self._peek_name() == 'cond': elif self._has_markers() and self._peek_name() == 'cond':
pass pass
else: else:
@ -198,6 +201,54 @@ class CMake(method.shell.Exec):
self._doit(w, w.buffer.path, w.application.config['c.make-cmd'], self._doit(w, w.buffer.path, w.application.config['c.make-cmd'],
cmdname='c-make') cmdname='c-make')
class CContext(context.Context):
def _regen_stack(self, y):
if y > 0 and self.namelines[y - 1][1]:
return list(self.namelines[y - 1][1])
else:
return []
def _build_name_map(self, y1, y2, last, curr, stack):
blen = len(self.mode.window.buffer.lines)
highlights = self.mode.window.get_highlighter()
i = y1
starting = curr and not bool(stack)
while i < y2:
if not starting and not stack:
curr = None
g = highlights.tokens[i]
if not stack and len(g) > 2 and g[0].name in ('c_type', 'keyword'):
g2 = [x for x in g if x.name != 'spaces']
j = 0
while j < len(g2) - 1 and g2[j].name in ('keyword', 'c_type'):
j += 1
if j < len(g2) and g2[j].name == 'function':
curr = g2[j].string
starting = True
if curr is not None and curr not in self.names:
self.names[curr] = i
if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen:
y2 += 1
m = self.mode
for t in g:
if t.name == 'delimiter' and t.string == '{':
stack.append(t.string)
starting = False
elif t.name == 'delimiter' and t.string == '}':
if not stack:
# we are totally hosed. start over. ugh.
#self.build_name_map()
raise Exception, "we're totally hosed"
return
stack.pop(-1)
if curr:
self.namelines[i] = (curr, tuple(stack))
i += 1
class C(mode.Fundamental): class C(mode.Fundamental):
modename = 'C' modename = 'C'
extensions = ['.c', '.h', '.cpp'] extensions = ['.c', '.h', '.cpp']
@ -230,6 +281,7 @@ class C(mode.Fundamental):
'header': ('green', 'default', 'bold'), 'header': ('green', 'default', 'bold'),
'structname': ('yellow', 'default', 'bold'), 'structname': ('yellow', 'default', 'bold'),
'enumname': ('yellow', 'default', 'bold'), 'enumname': ('yellow', 'default', 'bold'),
'c_type': ('green', 'default', 'bold'),
} }
config = { config = {
'c.syntax-cmd': "gcc -x c -fsyntax-only %(path)s", 'c.syntax-cmd': "gcc -x c -fsyntax-only %(path)s",
@ -238,6 +290,15 @@ class C(mode.Fundamental):
'c.make-rel-dir': True, 'c.make-rel-dir': True,
} }
actions = [CCheckSyntax, CMake] actions = [CCheckSyntax, CMake]
format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(func)s]"
def get_status_names(self):
names = mode.Fundamental.get_status_names(self)
c = self.window.logical_cursor()
names['func'] = self.get_line_function(c.y)
return names
def __init__(self, w): def __init__(self, w):
mode.Fundamental.__init__(self, w) mode.Fundamental.__init__(self, w)
self.add_bindings('close-paren', (')',)) self.add_bindings('close-paren', (')',))
@ -245,5 +306,15 @@ class C(mode.Fundamental):
self.add_bindings('close-bracket', (']',)) self.add_bindings('close-bracket', (']',))
self.add_bindings('c-check-syntax', ('C-c s',)) self.add_bindings('c-check-syntax', ('C-c s',))
self.add_bindings('c-make', ('C-c C-c',)) self.add_bindings('c-make', ('C-c C-c',))
self.context = CContext(self)
self.functions = None
self.funclines = None
def get_functions(self):
return self.context.get_names()
def get_function_names(self):
return self.context.get_name_list()
def get_line_function(self, y):
return self.context.get_line_name(y)
install = C.install install = C.install

View File

@ -743,20 +743,12 @@ class Perl(mode.Fundamental):
completers = { completers = {
'perlfunction': PerlFunctionCompleter(), 'perlfunction': PerlFunctionCompleter(),
} }
format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s [%(func)s]" format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(func)s]"
#format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s" #format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s"
def get_status_names(self): def get_status_names(self):
w = self.window names = mode.Fundamental.get_status_names(self)
c = w.logical_cursor() c = self.window.logical_cursor()
names = { names['func'] = self.get_line_function(c.y)
'bname': w.buffer.name(),
'mname': self.name(),
'flag': self._get_flag(),
'perc': self._get_perc(),
'cursor': '(%d,%d)' % (c.y + 1, c.x + 1),
'mark': self._get_mark(),
'func': self.get_line_function(c.y),
}
return names return names
def __init__(self, w): def __init__(self, w):
mode.Fundamental.__init__(self, w) mode.Fundamental.__init__(self, w)

View File

@ -481,20 +481,15 @@ class Python(mode.Fundamental):
"pythonfunction": PythonFunctionCompleter(), "pythonfunction": PythonFunctionCompleter(),
"pythonclass": PythonClassCompleter(), "pythonclass": PythonClassCompleter(),
} }
format = "%(flag)s %(bname)-18s (%(mname)s) %(cursor)s/%(mark)s %(perc)s [%(name)s]"
format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s [%(name)s]"
def get_status_names(self): def get_status_names(self):
w = self.window names = mode.Fundamental.get_status_names(self)
c = w.logical_cursor() c = self.window.logical_cursor()
names = { names['name'] = self.context.get_line_name(c.y)
'bname': w.buffer.name(),
'mname': self.name(),
'flag': self._get_flag(),
'perc': self._get_perc(),
'cursor': '(%d,%d)' % (c.y + 1, c.x + 1),
'mark': self._get_mark(),
'name': self.context.get_line_name(c.y),
}
return names return names
def __init__(self, w): def __init__(self, w):
mode.Fundamental.__init__(self, w) mode.Fundamental.__init__(self, w)
self.add_bindings('close-paren', (')',)) self.add_bindings('close-paren', (')',))