From 7c1d0a93302908fa56549d999871394ff191218c Mon Sep 17 00:00:00 2001 From: moculus Date: Thu, 5 Feb 2009 15:21:24 +0000 Subject: [PATCH] context header v0.1 --HG-- branch : pmacs2 --- application.py | 4 ++-- buffer/__init__.py | 11 ++++------- bufferlist.py | 12 ++++++++---- mode/__init__.py | 44 ++++++++++++++++++++++++++---------------- mode/python.py | 48 +++++++++++++++++++++++++++++++++++++++------- render.py | 8 ++++++-- tab.py | 40 ++++++++++++++++++++------------------ 7 files changed, 110 insertions(+), 57 deletions(-) diff --git a/application.py b/application.py index f1a325c..e6929bb 100755 --- a/application.py +++ b/application.py @@ -783,10 +783,10 @@ class Application(object): modename = w.mode.name() # draw the header - rstrs = w.mode.get_header(w) + rstrs = w.mode.get_header() assert len(rstrs) >= w.mode.header for j in range(0, w.mode.header): - rstrs[j].draw(self.win, slot.y_offset + j, slot.x_offset) + rstrs[j].draw(self.win, slot.y_offset + j, slot.x_offset, slot.width) # draw the actual slot self._draw_slot(i) diff --git a/buffer/__init__.py b/buffer/__init__.py index 727a1e0..b211393 100644 --- a/buffer/__init__.py +++ b/buffer/__init__.py @@ -368,14 +368,11 @@ class Buffer(object): self.delete(p1, p2, act, force) # random + def is_whitespace(self, y): + return regex.whitespace.match(self.lines[y]) def count_leading_whitespace(self, y): - line = self.lines[y] - m = regex.leading_whitespace.match(line) - if m: - return m.end() - else: - # should not happen - raise Exception, "iiiijjjj" + m = regex.leading_whitespace.match(self.lines[y]) + return m.end() # generic window functionality def forward(self, p): diff --git a/bufferlist.py b/bufferlist.py index 22c6779..d1b362b 100644 --- a/bufferlist.py +++ b/bufferlist.py @@ -13,9 +13,11 @@ class Slot(object): self.x_offset = x_offset if self.window is not None: self.window.set_size(self.width, self.height) + def reset(self): + self.window.set_size(self.width, self.height) def set(self, w): self.window = w - self.resize(self.height, self.width, self.y_offset, self.x_offset) + #self.resize(self.height, self.width, self.y_offset, self.x_offset) w.set_size(self.width, self.height) def unset(self): if not self.is_empty(): @@ -57,11 +59,13 @@ class BufferList(object): self.width = width self.fit_slots() - def is_window_visible(self, w): + def find_window_slot(self, w): for slot in self.slots: if w is slot.window: - return True - return False + return slot + return None + def is_window_visible(self, w): + return self.find_window_slot(w) is not None def is_buffer_visible(self, b): for slot in self.slots: if slot.window is not None and b is slot.window.buffer: diff --git a/mode/__init__.py b/mode/__init__.py index 3fb59fa..288c53b 100644 --- a/mode/__init__.py +++ b/mode/__init__.py @@ -101,18 +101,18 @@ class Fundamental(Handler): format = "%(flag)s %(bname)-18s (%(mname)s) %(indent)s %(cursor)s/%(mark)s %(perc)s" ## margins - def get_header(self): return self.get_setting('header') - def set_header(self, value): return self.set_setting('header', value) - header = property(get_header, set_header) - def get_footer(self): return self.get_setting('footer') - def set_footer(self, value): return self.set_setting('footer', value) - footer = property(get_footer, set_footer) - def get_lmargin(self): return self.get_setting('lmargin') - def set_lmargin(self, value): return self.set_setting('lmargin', value) - lmargin = property(get_lmargin, set_lmargin) - def get_rmargin(self): return self.get_setting('rmargin') - def set_rmargin(self, value): return self.set_setting('rmargin', value) - rmargin = property(get_rmargin, set_rmargin) + def _get_header(self): return self.get_setting('header') + def _set_header(self, value): return self.set_setting('header', value) + header = property(_get_header, _set_header) + def _get_footer(self): return self.get_setting('footer') + def _set_footer(self, value): return self.set_setting('footer', value) + footer = property(_get_footer, _set_footer) + def _get_lmargin(self): return self.get_setting('lmargin') + def _set_lmargin(self, value): return self.set_setting('lmargin', value) + lmargin = property(_get_lmargin, _set_lmargin) + def _get_rmargin(self): return self.get_setting('rmargin') + def _set_rmargin(self, value): return self.set_setting('rmargin', value) + rmargin = property(_get_rmargin, _set_rmargin) def install(cls, app): app.setmode(cls.modename.lower(), cls, paths=cls.paths, @@ -286,11 +286,23 @@ class Fundamental(Handler): # header def showing_header(self): return self.header != 0 - def enable_header(self): + def _enable_header(self): self.header = 1 - def disable_header(self): + def _disable_header(self): self.header = 0 + def enable_header(self): + self._enable_header() + self._slot_reset() + def disable_header(self): + self._disable_header() + self._slot_reset() + def _slot_reset(self): + w = self.window + slot = w.application.bufferlist.find_window_slot(w) + assert slot is not None + slot.reset() + # line numbers def showing_line_numbers(self): return self.lmargin != 0 @@ -301,10 +313,10 @@ class Fundamental(Handler): self.lmargin = 0 # headers and margins - def get_header(self, w): + def get_header(self): fg, bg = "default", "red" return [RenderString(s='header', attrs=color.build(fg, bg))] - def get_footer(self, w): + def get_footer(self): fg, bg = "default", "red" return [RenderString(s='footer', attrs=color.build(fg, bg))] def get_rmargin(self, w, y, x, ended=False, cont=False): diff --git a/mode/python.py b/mode/python.py index 2e64772..099cce1 100644 --- a/mode/python.py +++ b/mode/python.py @@ -1,6 +1,7 @@ import commands, os.path, string, sys, traceback import color, completer, context, default, mode, method, regex, tab, method.introspect from point import Point +from render import RenderString from lex import Grammar, PatternRule, RegionRule, OverridePatternRule from parse import Any, And, Or, Optional, Name, Match, Matchs @@ -157,12 +158,12 @@ class PythonTabber(tab.StackTabber): # we need to pop the indentation level over, unless last line was # also a continued line if self.continued: - self._opt_append('cont', currlvl) + self._opt_append('cont', currlvl, y) else: - self._opt_append('cont', currlvl + w) + self._opt_append('cont', currlvl + w, y) elif fqname == 'string.start': # while inside of a string, there is no indention leve - self._opt_append('string', None) + self._opt_append('string', None, y) elif fqname == 'string.end': # since we're done with the string, resume our indentation level self._opt_pop('string') @@ -183,25 +184,25 @@ class PythonTabber(tab.StackTabber): self.popped = True elif token.string in self.startlevel_names and self.is_leftmost_token(y, i): # we know we will indent exactly once - self._append(token.string, currlvl + w) + self._append(token.string, currlvl + w, y) elif token.string in ('elif', 'else') and self.is_leftmost_token(y, i): # we know we'll unindent at least to the first if/elif if not self.popped and not self.last_popped and self._peek_until('if', 'elif'): self._pop_until('if', 'elif') currlvl = self.get_curr_level() - self._append(token.string, currlvl + w) + self._append(token.string, currlvl + w, y) elif token.string == 'except' and self.is_leftmost_token(y, i): # we know we'll unindent at least to the first try if not self.popped and not self.last_popped: self._pop_until('try') currlvl = self.get_curr_level() - self._append(token.string, currlvl + w) + self._append(token.string, currlvl + w, y) elif token.string == 'finally' and self.is_leftmost_token(y, i): # we know we'll unindent at least to the first try/except if not self.popped and not self.last_popped: self._pop_until('try', 'except') currlvl = self.get_curr_level() - self._append(token.string, currlvl + w) + self._append(token.string, currlvl + w, y) return currlvl class PythonCheckSyntax(method.Method): @@ -575,6 +576,39 @@ class Python(mode.Fundamental): names['first'] = self.window.first.xy() return names + # xyz + def _enable_header(self): + self.header = 3 + def _disable_header(self): + self.header = 0 + def get_header(self): + fg, bg = "default", "red" + w = self.window + y = self.window.first.y + if self.window.first.x > 0: + y += 1 + lvl = self.tabber.get_level(y) + markers = self.tabber.record[y] + if w.buffer.is_whitespace(y): + ws = None + else: + ws = w.buffer.count_leading_whitespace(y) + + hs = [] + i = len(markers) - 1 + while i >= 0 and len(hs) < 3: + marker = markers[i] + i -= 1 + if marker.y == y: + continue + if ws and marker.level > ws: + continue + s = w.buffer.lines[marker.y][:w.width - 1] + hs.insert(0, RenderString(s=s, attrs=color.build(fg, bg))) + while len(hs) < 3: + hs.insert(0, RenderString(s='', attrs=color.build(fg, bg))) + return hs + def __init__(self, w): mode.Fundamental.__init__(self, w) self.add_bindings('close-paren', (')',)) diff --git a/render.py b/render.py index bed8e36..a5f992e 100644 --- a/render.py +++ b/render.py @@ -29,9 +29,13 @@ class RenderString(object): self.y = y self.x = x self.attrs = attrs - def draw(self, cwin, y, x): + def draw(self, cwin, y, x, x2=None): try: - cwin.addstr(self.y + y, self.x + x, self.string, self.attrs) + if x2: + s = '%-*s' % (x2 - x, self.string) + else: + s = self.string + cwin.addstr(self.y + y, self.x + x, s, self.attrs) except: v = (y, self.x, x, self.string, self.attrs) raise Exception, "cwin.addstr(%d, %d + %d, %r, %r) failed" % v diff --git a/tab.py b/tab.py index 201522c..fb0dd25 100644 --- a/tab.py +++ b/tab.py @@ -2,11 +2,12 @@ import regex, util from point import Point class Marker(object): - def __init__(self, name, level): + def __init__(self, name, level, y): self.name = name self.level = level + self.y = y def __repr__(self): - return '' % (self.name, self.level) + return '' % (self.name, self.level, self.y) class Tabber(object): wsre = regex.whitespace @@ -158,7 +159,7 @@ class StackTabber(Tabber): level = self.get_curr_level() + self.mode.tabwidth else: level = rtoken.x - self._append(token.string, level) + self._append(token.string, level, y) return currlvl def _handle_close_token(self, currlvl, y, i): token = self.get_token(y, i) @@ -180,8 +181,8 @@ class StackTabber(Tabber): return len(self.markers) > 0 def _empty(self): return len(self.markers) == 0 - def _append(self, name, level): - self.markers.append(Marker(name, level)) + def _append(self, name, level, y=None): + self.markers.append(Marker(name, level, y)) def _peek(self): if self.markers: return self.markers[-1] @@ -220,22 +221,23 @@ class StackTabber(Tabber): else: self.markers.pop(-1) - def _opt_append(self, name, level): + def _opt_append(self, name, level, y=None): if self.markers and self.markers[-1].name == name: pass else: - self._append(name, level) + self._append(name, level, y) def _opt_pop(self, *names): if self.markers and self.markers[-1].name in names: self.markers.pop(-1) class Marker2(object): - def __init__(self, name, type_, level): + def __init__(self, name, type_, level, y=None): self.name = name self.type_ = type_ self.level = level + self.y = y def __repr__(self): - return '' % (self.name, self.type_, self.level) + return '' % (self.name, self.type_, self.level, self.y) class StackTabber2(Tabber): open_tokens = {'delimiter': {'{': '}', '(': ')', '[': ']'}} @@ -307,9 +309,9 @@ class StackTabber2(Tabber): while self._nomatch(*names): self.stack.pop() - def _append(self, name, type_, level): + def _append(self, name, type_, level, y=None): self.stack.append(Marker2(name, type_, level)) - def _append_unless(self, name, type_, level): + def _append_unless(self, name, type_, level, y=None): if self._nomatch(name): self.stack.append(Marker2(name, type_, level)) def _peek(self): @@ -387,7 +389,7 @@ class StackTabber2(Tabber): if d is None or d != 1 and s not in d: if s not in self.close_scope_tokens.get(name, set()): nextlvl = self._get_next_level() - self._append_unless('continue', name, nextlvl) + self._append_unless('continue', name, nextlvl, y) #XYZYZYXYXY def _is_open_token(self, t): @@ -405,20 +407,20 @@ class StackTabber2(Tabber): level = self._get_next_level() else: level = tokens[i + 1].x + 1 - self._append(t.string, t.name, level) + self._append(t.string, t.name, level, y) def _handle_other_token(self, y, tokens, start, end, i, t): name, s = t.fqname(), t.string # handle "free" tokens (strings, heredocs, etc) if name in self.start_free_tokens: - self._append('free', name, None) + self._append('free', name, None, y) return elif name in self.end_free_tokens: self._pop('free') # handle macros if name in self.start_macro_tokens: - self._append('macro', name, 0) + self._append('macro', name, 0, y) if i == 0: self._save_curr_level() return @@ -439,17 +441,17 @@ class StackTabber2(Tabber): not top)): if self.continue_tokens: if s in self.continue_tokens.get(name, {}): - self._append_unless('continue', name, self._get_next_level()) + self._append_unless('continue', name, self._get_next_level(), y) elif self.nocontinue_tokens: d = self.nocontinue_tokens.get(name) if d is None or d != 1 and s not in d: - self._append_unless('continue', name, self._get_next_level()) + self._append_unless('continue', name, self._get_next_level(), y) if name == 'continuation': # handle explicit continuation - self._append_unless('continue', name, self._get_next_level()) + self._append_unless('continue', name, self._get_next_level(), y) elif s in self.control_tokens.get(name, {}): # handle control keywords if i == start: self._save_curr_level() - self._append_unless('control', name, self._get_next_level()) + self._append_unless('control', name, self._get_next_level(), y)