dynamically-parsed nested regions seem to work!!!! holy shit!!!

--HG--
branch : pmacs2
This commit is contained in:
moculus 2007-07-17 11:14:21 +00:00
parent e691606a33
commit 81b84b24e1
5 changed files with 79 additions and 44 deletions

View File

@ -579,18 +579,6 @@ class Application(object):
x += slot.width
count += 1
def _get_token_color(self, w, token):
fqlist = token.fqlist()
c = w.mode.default_color
for j in range(0, len(fqlist)):
name = '.'.join(fqlist[j:])
if name in w.mode.colors:
c = w.mode.colors[name]
break
if DARK_BACKGROUND:
c |= curses.A_BOLD
return c
def _draw_slot_lit(self, i):
slot = self.bufferlist.slots[i]
w = slot.window
@ -617,12 +605,10 @@ class Application(object):
x_offset = max(token.x - x, 0)
assert x_offset <= slot.width, '%d <= %d' % (x_offset, slot.width)
c = self._get_token_color(w, token)
#s = token.string[s_offset:]
s = tstring[s_offset:]
token_done = x_offset + len(s) <= slot.width
token_wrap = x_offset + len(s) > slot.width
self.win.addstr(slot.offset + count, x_offset, s[:slot.width - x_offset], c)
self.win.addstr(slot.offset + count, x_offset, s[:slot.width - x_offset], token.color)
if token_wrap:
self.win.addch(slot.offset + count, slot.width, '\\', redattr)

View File

@ -7,11 +7,13 @@ sub foo {
unless 9 && 3;
}
#@@:heredoc:mode_sql.SqlGrammar
#@@:heredoc:mode_sql.Sql
my $s = <<EOT;
drop table foog;
select cast(plunk as timestamp) from blarg join plarg using(id_what) where x = 3;
EOT
#@@:string:mode_sql.Sql
my $foo = {
'drop table ',
'bar',

68
lex3.py
View File

@ -1,18 +1,18 @@
import re
import curses, re
import regex, util
from point2 import Point
class Token(object):
def __init__(self, name, rule, y, x, s, parent=None, matchd={}, link=None):
def __init__(self, name, rule, y, x, s, color=None, parent=None, matchd={}, link=None):
self.name = name
self.rule = rule
self.y = y
self.x = x
self.string = s
self.color = color
self.parent = parent
self.matchd = matchd
self.link = link
#self.loverride = None
assert parent is None or hasattr(parent, 'name'), 'oh no %r' % parent
def parents(self):
if self.parent is not None:
@ -43,7 +43,7 @@ class Token(object):
return '.'.join(names)
def copy(self):
return Token(self.name, self.rule, self.y, self.x, self.string,
self.parent, self.matchd)
self.color, self.parent, self.matchd, self.link)
def add_to_string(self, s):
self.string += s
def end_x(self):
@ -72,7 +72,8 @@ class Rule:
def lex(self, lexer, parent, match):
raise Exception, "not implemented"
def make_token(self, lexer, s, name, parent=None, matchd={}, link=None):
t = Token(name, self, lexer.y, lexer.x, s, parent, matchd, link)
t = Token(name, self, lexer.y, lexer.x, s, None, parent, matchd, link)
t.color = lexer.get_color(t)
lexer.x += len(s)
return t
def get_line(self, lexer):
@ -92,6 +93,8 @@ class PatternRule(Rule):
class NocasePatternRule(PatternRule):
reflags = re.IGNORECASE
class OverrideError(Exception):
pass
class OverridePatternRule(PatternRule):
def lex(self, lexer, parent, m):
if m:
@ -99,13 +102,16 @@ class OverridePatternRule(PatternRule):
if lexer.action == 'lex':
a = lexer.mode.window.application
try:
names = d['grammar'].split('.')
grammar = a.globals()[names.pop(0)]
names = d['mode'].split('.')
modecls = a.globals()[names.pop(0)]
for name in names:
grammar = getattr(grammar, name)
lexer.mode.gstack['%s.start' % d['token']] = grammar
except Exception:
#raise
modecls = getattr(modecls, name)
mode = modecls(None)
if hasattr(mode, 'grammar') and hasattr(mode, 'colors'):
lexer.mode.gstack['%s.start' % d['token']] = mode
else:
raise OverrideError, "argh: %r" % mode
except (KeyError, AttributeError, OverrideError):
pass
yield self.make_token(lexer, m.group(0), self.name, parent, d)
raise StopIteration
@ -211,14 +217,18 @@ class RegionRule(Rule):
fqname = toresume[0].fqname()
p = Point(toresume[0].x, toresume[0].y)
if fqname in lexer.mode.ghist and p in lexer.mode.ghist[fqname]:
grammar = lexer.mode.ghist[fqname][p]
mode = lexer.mode.ghist[fqname][p]
grammar = mode.grammar
elif fqname in lexer.mode.gstack:
grammar = lexer.mode.gstack[fqname]
mode = lexer.mode.gstack[fqname]
grammar = mode.grammar
lexer.mode.ghist.setdefault(fqname, {})
lexer.mode.ghist[fqname][p] = grammar
lexer.mode.ghist[fqname][p] = mode
del lexer.mode.gstack[fqname]
else:
mode = lexer.mode
grammar = self.pairs[i][0]
lexer.mstack.append(mode)
if self.pairs[i][1]:
stopre = re.compile(self.pairs[i][1] % matchd, self.reflags)
@ -242,6 +252,8 @@ class RegionRule(Rule):
matchd.update(tok.matchd)
else:
raise StopIteration
# this should have already gotten done by _lex
#lexer.mstack.pop(-1)
i += 1
# assuming we make it through all our grammars, and find the end-token,
# then we need to signal that we are done.
@ -286,6 +298,7 @@ class RegionRule(Rule):
null_t = None
# ok, now return the stop-token, and signal that we are
# done and no more input is to be consumed
lexer.mstack.pop(-1)
yield self.make_token(lexer, m.group(0), stopname,
parent, m.groupdict(), stopname)
done = True
@ -311,7 +324,8 @@ class RegionRule(Rule):
# we didn't find a match on a rule, so add this character to
# the current null token (creating a new one if necessary);
if not null_t:
null_t = Token('null', None, lexer.y, lexer.x, '', parent)
null_t = Token('null', None, lexer.y, lexer.x, '', None, parent)
null_t.color = lexer.get_color(null_t)
null_t.add_to_string(line[lexer.x])
lexer.x += 1
@ -334,6 +348,7 @@ grammar = Grammar()
class Lexer:
def __init__(self, mode, grammar):
self.mode = mode
self.mstack = []
self.grammar = grammar
self.y = 0
self.x = 0
@ -346,6 +361,7 @@ class Lexer:
self.y = y
self.x = x
self.lines = lines
self.mstack = []
self.mode.ghist = {}
self.mode.gstack = {}
for t in self._lex():
@ -357,7 +373,7 @@ class Lexer:
self.y = y
self.x = x
self.lines = lines
self.tokens = []
self.mstack = []
toresume = token.parents()
i = 1
@ -398,7 +414,8 @@ class Lexer:
if not m:
if self.x < len(line):
if null_t is None:
null_t = Token('null', None, self.y, self.x, '', parent)
null_t = Token('null', None, self.y, self.x, '', None, parent)
null_t.color = self.get_color(null_t)
null_t.add_to_string(line[self.x])
self.x += 1
if null_t:
@ -406,3 +423,20 @@ class Lexer:
self.y += 1
self.x = 0
raise StopIteration
def get_color(self, token):
fqlist = token.fqlist()
if self.mstack:
mode = self.mstack[-1]
else:
mode = self.mode
c = mode.default_color
for j in range(0, len(fqlist)):
name = '.'.join(fqlist[j:])
if name in mode.colors:
c = mode.colors[name]
break
#if DARK_BACKGROUND:
if True:
c |= curses.A_BOLD
return c

View File

@ -17,25 +17,37 @@ class Handler(object):
# handle adding and removing actions
def add_action(self, action):
if self.window is None:
return
if action.name in self.window.application.methods:
return
if action.name in self.window.application.methods:
raise Exception, "Action %r already found" % action.name
self.window.application.methods[action.name] = action
def del_action(self, name):
if self.window is None:
return
for binding in self.bindings.keys():
if self.bindings[binding] == name:
del self.bindings[binding]
def add_binding(self, name, sequence):
if self.window is None:
return
if name not in self.window.application.methods:
raise Exception, "No action called %r found" % name
self.bindings[sequence] = name
def add_bindings(self, name, sequences):
if self.window is None:
return
for sequence in sequences:
self.add_binding(name, sequence)
def del_binding(self, sequence):
if self.window is None:
return
del self.bindings[sequence]
def add_action_and_bindings(self, action, sequences):
if self.window is None:
return
self.add_action(action)
for sequence in sequences:
self.add_binding(action.name, sequence)

View File

@ -35,7 +35,7 @@ class PerlGrammar(Grammar):
RegionRule(r'endblock', r"^__END__|__DATA__ *$", Grammar, r''),
RegionRule(r'pod', r'^=[a-zA-Z0-9_]+', PodGrammar, r'^=cut'),
OverridePatternRule(r'comment', r'#@@:(?P<token>[.a-zA-Z0-9_]+):(?P<grammar>[.a-zA-Z0-9_]+) *$'),
OverridePatternRule(r'comment', r'#@@:(?P<token>[.a-zA-Z0-9_]+):(?P<mode>[.a-zA-Z0-9_]+) *$'),
PatternRule(r'comment', r'#.*$'),
RegionRule(r'string', r'"', StringGrammar, r'"'),
RegionRule(r'string', r"'", Grammar, r"'"),
@ -165,6 +165,7 @@ class Perl(mode2.Fundamental):
opentags = {'(': ')', '[': ']', '{': '}'}
closetokens = ('delimiter',)
closetags = {')': '(', ']': '[', '}': '{'}
def __init__(self, w):
mode2.Fundamental.__init__(self, w)