diff --git a/buffer/__init__.py b/buffer/__init__.py index b211393..a292329 100644 --- a/buffer/__init__.py +++ b/buffer/__init__.py @@ -70,6 +70,7 @@ class Buffer(object): self.settings = {} self.indentlvl = 4 self.writetabs = False + self.metadata = {} def _detect_nl_type(self, data): mac_c = len(self.mac_re.findall(data)) @@ -373,6 +374,17 @@ class Buffer(object): def count_leading_whitespace(self, y): m = regex.leading_whitespace.match(self.lines[y]) return m.end() + def detect_indent_level(self, y1, y2): + x = None + for y in range(y1, y2): + if self.is_whitespace(y): + continue + c = self.count_leading_whitespace(y) + if x is None: + x = c + else: + x = min(x, c) + return x or 0 # generic window functionality def forward(self, p): diff --git a/buffer/color.py b/buffer/color.py index 04a9070..63598a1 100644 --- a/buffer/color.py +++ b/buffer/color.py @@ -30,35 +30,36 @@ class ColorHighlighter(Highlighter): self.tokens[y].append(t) return len(s) - len(s2) def delete_token(self, y, i): - pass + del self.tokens[y][i] def relex(self, lines, y1, x1, y2, x2, token=None): - pass - def relex_del(self, lines, y1, x1, y2, x2): - pass + for y in range(y1, y2 + 1): + self.highlight_line(y, lines[y]) + + def highlight_line(self, y, line): + self.tokens[y] = [] + c = ['default', 'default'] + i = 0 + offset = 0 + while i < len(line): + m = self.color_re.search(line, i) + if m: + (j, k) = (m.start(), m.end()) + if j > i: + offset += self.append_token(y, i - offset, line[i:j], c) + fields = m.group(1).split(':') + c = [self.color_map.get(x, x) for x in fields] + offset += k - j + i = k + else: + offset += self.append_token(y, i - offset, line[i:], c) + break + def highlight(self, lines): if self.tokens: return - self.tokens = [[] for l in lines] - #self.tokens = [None] * len(lines) + self.tokens = [None] * len(lines) for y in range(0, len(lines)): - self.tokens[y] = [] - line = lines[y] - c = ['default', 'default'] - i = 0 - offset = 0 - while i < len(line): - m = self.color_re.search(line, i) - if m: - (j, k) = (m.start(), m.end()) - if j > i: - offset += self.append_token(y, i - offset, line[i:j], c) - fields = m.group(1).split(':') - c = [self.color_map.get(x, x) for x in fields] - offset += k - j - i = k - else: - offset += self.append_token(y, i - offset, line[i:], c) - break + self.highlight_line(y, lines[y]) class ColorDataBuffer(DataBuffer): btype = 'colordata' diff --git a/buffer/emul.py b/buffer/emul.py index 1a97aac..b851658 100644 --- a/buffer/emul.py +++ b/buffer/emul.py @@ -1,10 +1,12 @@ import fcntl, os, select, pty, threading from buffer import Buffer, ACT_NORM, ACT_NONE +#from buffer.color import ColorDataBuffer from term import XTerm from point import Point # evil evil evil evil evil +#class XTermBuffer(ColorDataBuffer, XTerm): class XTermBuffer(Buffer, XTerm): btype = 'term' modename = 'pipe' @@ -64,7 +66,6 @@ class XTermBuffer(Buffer, XTerm): def term_do_delete(self): self._w().delete_right() def term_handle_print(self, c): - #self._term_insert('%d ' % ord(c)) self._term_insert(c) def term_handle_ctl(self, c): n = ord(c) diff --git a/method/svn.py b/method/svn.py index 50db3db..238b97a 100644 --- a/method/svn.py +++ b/method/svn.py @@ -6,6 +6,51 @@ from point import Point from method import Method, Argument +class SvnException(Exception): + pass + +statuses = { + ' ': 'Unmodified', + 'A': 'Added', + 'C': 'Conflicted', + 'D': 'Deleted', + 'I': 'Ignored', + 'M': 'Modified', + 'R': 'Replaced', + 'X': 'External', + '?': 'Unknown', + '!': 'Missing', + '~': 'Obstructed', +} + +def get_status(path, base=None): + if base is None: base = os.getcwd() + os.path.sep + if path.startswith(base): path = path[len(base):] + + cmd = "svn status -v %r" % path + status, data = commands.getstatusoutput(cmd) + status = status >> 8 + + if status != 0: + raise SvnException("Problems with 'svn status': %d" % status) + + c = data[0] + status = statuses.get(c, 'Error (%s)' % c) + fields = data[6:].split() + + try: + rrev, lrev, lauthor, filename = fields + except: + raise Exception, '%r %r' % (fields, data[6:]) + + return { + 'svn-filename': filename, + 'svn-status': status, + 'svn-lrev': lrev, + 'svn-rrev': rrev, + 'svn-author': lauthor, + } + class SvnCommit(Method): '''diff the current file with the version in SVN''' args = [Argument("msg", type=type(""), prompt="Commit Message: ")] @@ -30,7 +75,10 @@ class SvnCommit(Method): for line in lines: m = self.regex.match(line) if m: - w.set_error("Committed [%s]" % (m.group(1))) + rev = m.group(1) + w.buffer.metadata['svn-lrev'] = rev + w.buffer.metadata['svn-rrev'] = rev + w.set_error("Committed [%s]" % rev) return except: pass @@ -76,6 +124,11 @@ class SvnStatus(Method): except: raise Exception, '%r %r' % (fields, data[6:]) + w.buffer.metadata['svn-filename'] = lrev + w.buffer.metadata['svn-status'] = lrev + w.buffer.metadata['svn-lrev'] = lrev + w.buffer.metadata['svn-rrev'] = lrev + w.buffer.metadata['svn-author'] = lrev w.set_error('%s %s %s/%s [%s]' % (filename, status, rrev, lrev, lauthor)) class SvnLog(Method): diff --git a/mode/python.py b/mode/python.py index f158245..4021531 100644 --- a/mode/python.py +++ b/mode/python.py @@ -1,9 +1,10 @@ -import commands, os.path, string, sys, traceback +import commands, os.path, re, 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 +from method import Method try: import bike @@ -401,6 +402,54 @@ class PythonBrmFindReferences(method.Method): else: w.set_error('%d references found' % n) +# commenting in python +class PythonCommentRegion(Method): + '''Prepend a comment to every line in the current buffer''' + commentc = '#' + def _execute(self, w, **vargs): + cursor = w.logical_cursor() + if cursor < w.mark: + p1 = cursor + p2 = w.mark + elif w.mark < cursor: + p1 = w.mark + p2 = cursor + else: + w.input_line = "Empty kill region" + return + + x = w.buffer.detect_indent_level(p1.y, p2.y) + for y in range(p1.y, p2.y): + c = self.commentc + if len(w.buffer.lines[y]) < x: + c += ' ' * (x - len(w.buffer.lines[y])) + w.buffer.insert_string(Point(x, y), c) + +class PythonUncommentRegion(Method): + '''Remove a comment from every line in the current buffer''' + commentre = re.compile('^( *)(#+)') + def _execute(self, w, **vargs): + cursor = w.logical_cursor() + if cursor < w.mark: + p1 = cursor + p2 = w.mark + elif w.mark < cursor: + p1 = w.mark + p2 = cursor + else: + w.input_line = "Empty kill region" + return + + x = w.buffer.detect_indent_level(p1.y, p2.y) + for y in range(p1.y, p2.y): + line = w.buffer.lines[y] + m = self.commentre.match(line) + if not m: + continue + s1, s2 = m.groups() + x1, x2 = len(s1), len(s1) + len(s2) + w.buffer.delete(Point(x1, y), Point(x2, y)) + class PythonNameCompleter(completer.Completer): def _get_dict(self, w): return w.buffer.method.old_window.mode.context.get_names() @@ -556,7 +605,8 @@ class Python(mode.Fundamental): lconfig = { 'ignore-suffix': ['.pyc'], } - actions = [PythonInitNames, PythonListNames, PythonGotoName, + actions = [PythonCommentRegion, PythonUncommentRegion, + PythonInitNames, PythonListNames, PythonGotoName, PythonGotoFunction, PythonGotoClass, PythonCheckSyntax, PythonDictCleanup, PythonSemanticComplete, PythonBrmFindReferences, PythonInsertTripleSquotes, PythonInsertTripleDquotes] @@ -616,6 +666,8 @@ class Python(mode.Fundamental): def __init__(self, w): mode.Fundamental.__init__(self, w) + self.add_bindings('python-comment-region', ('C-c #',)) + self.add_bindings('python-uncomment-region', ('C-u C-c #',)) self.add_bindings('close-paren', (')',)) self.add_bindings('close-brace', ('}',)) self.add_bindings('close-bracket', (']',))