From ad71553553b1511dff0ed277762a5b3b236a25f0 Mon Sep 17 00:00:00 2001 From: moculus Date: Sat, 8 Nov 2008 15:30:04 +0000 Subject: [PATCH] refactors --HG-- branch : pmacs2 --- application.py | 76 +++++++++-------- buffer/__init__.py | 2 +- buffer/emul.py | 4 +- completer.py | 4 +- method/__init__.py | 26 +----- method/buffers.py | 2 +- method/cvs.py | 2 +- method/help.py | 2 +- method/introspect.py | 2 +- method/move.py | 2 +- method/search.py | 2 +- method/shell.py | 2 +- method/svn.py | 2 +- mode/__init__.py | 43 +++++----- mode/brm.py | 2 +- mode/elisp.py | 2 +- mode/erlang.py | 2 +- mode/haskell.py | 2 +- mode/lisp.py | 2 +- mode/ocaml.py | 2 +- mode/perl.py | 2 +- mode/python.py | 2 +- mode/replace.py | 2 +- mode/scheme.py | 2 +- mode/search.py | 2 +- mode/shellmini.py | 2 +- window.py | 194 +++++++++++++++++++++++-------------------- 27 files changed, 197 insertions(+), 192 deletions(-) diff --git a/application.py b/application.py index 0df7c56..880a575 100755 --- a/application.py +++ b/application.py @@ -8,37 +8,11 @@ import bufferlist, color, completer, keyinput, method, minibuffer, mode import util, window from point import Point -def run(buffers, jump_to_line=None, init_mode=None): - # save terminal state so we can restore it when the program exits - attr = termios.tcgetattr(sys.stdin) - keyinput.disable_control_chars() - - retval = 1 - try: - retval = curses.wrapper(run_app, buffers, jump_to_line, init_mode) - except: - traceback.print_exc() - - # restore terminal state - termios.tcsetattr(sys.stdin, termios.TCSANOW, attr) - return retval - -def run_app(stdscr, buffers, jump_to_line=None, init_mode=None): - curses.def_shell_mode() - a = Application(stdscr, buffers, jump_to_line, init_mode) - a.run() - -MAX_ERROR_DISPLAY = 128 -KILL_RING_LIMIT = 128 -WORD_LETTERS = list(string.letters + string.digits) -ERROR_TIMEOUT = -1 -#ERROR_TIMEOUT = 2 - class Application(object): def __init__(self, stdscr, buffers=[], jump_to_line=None, init_mode=None): # initalize curses primitives self.stdscr = stdscr - (self.y, self.x) = self.stdscr.getmaxyx() + self.y, self.x = self.stdscr.getmaxyx() # initialize some basic stuff # a highlighted_range contains three things: (window, start_p, end_p) @@ -51,7 +25,15 @@ class Application(object): self.mini_prompt = "" self.error_string = "" self.error_timestamp = None + self.need_draw = True self.input = keyinput.Handler() + + # some constants + self.error_timeout = -1 + self.max_error_len = 192 + self.max_num_kills = 64 + self.def_word_letters = string.letters + string.digits + # let's prepopulate some default token colors self.token_colors = { 'comment': ('red', 'default', 'bold'), @@ -544,7 +526,8 @@ class Application(object): self.kill_ring[-1] = self.kill_ring[-1] + s else: self.kill_ring.append(s) - if KILL_RING_LIMIT and len(self.kill_ring) > KILL_RING_LIMIT: + #if KILL_RING_LIMIT and len(self.kill_ring) > KILL_RING_LIMIT: + if self.max_num_kills and len(self.kill_ring) > self.max_num_kills: self.kill_ring.pop(0) def pop_kill(self): return self.kill_ring.pop(-1) @@ -605,16 +588,22 @@ class Application(object): while i == curses.KEY_RESIZE: i = self.win.getch() self.resize_event() + self.need_draw = True err = '' try: self.input.parse(i) except Exception, e: err = str(e) - while len(self.input.tokens): + + if self.input.tokens: + self.need_draw = True + while self.input.tokens: t = self.input.tokens.pop(0) self.active_window().mode.handle_token(t) - self.draw(err) + if self.need_draw: + self.draw(err) + self.need_draw = False # clear the error line; it might look confusing to the user try: @@ -667,8 +656,8 @@ class Application(object): self.resize_event() if err: self.set_error(err) - if self.error_timestamp is not None and ERROR_TIMEOUT > 0 and \ - time.time() - self.error_timestamp > ERROR_TIMEOUT: + if self.error_timestamp is not None and self.error_timeout > 0 and \ + time.time() - self.error_timestamp > self.error_timeout: self.clear_error() (y, x) = self.stdscr.getmaxyx() if y != self.y or x != self.x: @@ -861,10 +850,10 @@ class Application(object): def get_minibuffer_lines(self): lines, lines2 = [], [] if self.error_string: - if len(self.error_string) < MAX_ERROR_DISPLAY: + if len(self.error_string) < self.max_error_len: s = self.error_string else: - s = self.error_string[:MAX_ERROR_DISPLAY] + '...' + s = self.error_string[:self.max_error_len] + '...' elif self.mini_buffer_is_open(): s = self.mini_prompt + self.mini_buffer.lines[0] lines2 = self.mini_buffer.lines[1:] @@ -895,6 +884,11 @@ def open_plain_file(path, name=None, binary=False): else: raise Exception, "can't open %r; unsupported file type" % path +def run_app(stdscr, buffers, jump_to_line=None, init_mode=None): + curses.def_shell_mode() + a = Application(stdscr, buffers, jump_to_line, init_mode) + a.run() + if __name__ == "__main__": ciphers = { 'none': open_plain_file, @@ -986,5 +980,17 @@ if __name__ == "__main__": paths.add(path) names.add(name) + # save terminal state so we can restore it when the program exits + attr = termios.tcgetattr(sys.stdin) + keyinput.disable_control_chars() + # ok, now run our app - run(buffers, opts.goto, opts.mode) + retval = 1 + try: + retval = curses.wrapper(run_app, buffers, opts.goto, opts.mode) + except: + traceback.print_exc() + + # restore terminal state + termios.tcsetattr(sys.stdin, termios.TCSANOW, attr) + sys.exit(retval) diff --git a/buffer/__init__.py b/buffer/__init__.py index d8d7d1a..a749830 100644 --- a/buffer/__init__.py +++ b/buffer/__init__.py @@ -1,4 +1,4 @@ -import codecs, datetime, grp, md5, os, pwd, re, sets, shutil, stat, string +import codecs, datetime, grp, md5, os, pwd, re, shutil, stat, string import fcntl, select, pty, threading import aes, dirutil, regex, highlight, lex, term from point import Point diff --git a/buffer/emul.py b/buffer/emul.py index 76bbeec..b28bb76 100644 --- a/buffer/emul.py +++ b/buffer/emul.py @@ -10,9 +10,10 @@ class XTermBuffer(Buffer, XTerm): modename = 'pipe' termtype = 'xterm' #termtype = 'vt100' - def __init__(self, cmd, args, name=None): + def __init__(self, app, cmd, args, name=None): XTerm.__init__(self) Buffer.__init__(self) + self.application = app self._name = name or '*XTerm*' self._pid, self._pty = pty.fork() if self._pid == 0: @@ -102,6 +103,7 @@ class XTermBuffer(Buffer, XTerm): if ifd: data = os.read(ifd[0], 1024) self.term_receive(data) + self.application.need_draw = True if ofd: self._lock.acquire() n = os.write(ofd[0], self._towrite) diff --git a/completer.py b/completer.py index dfce5a6..bf5826f 100644 --- a/completer.py +++ b/completer.py @@ -1,4 +1,4 @@ -import glob, os, pwd, sets +import glob, os, pwd import method, util def find_common_string(candidates): @@ -78,7 +78,7 @@ class CommandCompleter(Completer): def get_candidates(self, s, w=None): path = os.getenv('PATH') path_dirs = path.split(':') - candidates = sets.Set() + candidates = set() for d in path_dirs: if (not os.path.isdir(d) or not os.access(d, os.R_OK)): continue diff --git a/method/__init__.py b/method/__init__.py index d7bc32d..85b46ab 100644 --- a/method/__init__.py +++ b/method/__init__.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, regex, util, window @@ -216,7 +216,9 @@ class KillRegion(Method): class Copy(Method): '''Copy the contents of the current line''' def _execute(self, w, **vargs): - w.copy_line() + result = w.copy_line() + if result is None: + w.set_error("Empty kill region") class CopyRegion(Method): '''Copy the region between the mark and the cursor''' def _execute(self, w, **vargs): @@ -1017,23 +1019,3 @@ class SetModeTabWidth(Method): return app.modes[mode].tabwidth = vargs['width'] w.set_error('Default tab width set to %d' % app.modes[mode].tabwidth) - -#class HideRange(Method): -# def _execute(self, w, **vargs): -# cursor = w.logical_cursor() -# if cursor.y < w.mark.y: -# y1, y2 = cursor.y, w.mark.y -# elif w.mark.y < cursor.y: -# y1, y2 = w.mark.y, cursor.y -# else: -# w.set_error("No line range selected") -# w.hide(y1, y2) -# w.set_error("Lines %d through %d hidden" % (y1, y2)) -#class UnhideLine(Method): -# def _execute(self, w, **vargs): -# cursor = w.logical_cursor() -# if w.ishidden(cursor.y): -# w.unhide(cursor.y) -# w.set_error("Line %d is no longer hidden" % cursor.y) -# else: -# w.set_error("Line %d is not hidden" % cursor.y) diff --git a/method/buffers.py b/method/buffers.py index eed89ea..9189e26 100644 --- a/method/buffers.py +++ b/method/buffers.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, regex, util, window diff --git a/method/cvs.py b/method/cvs.py index 7aaa838..fcc6433 100644 --- a/method/cvs.py +++ b/method/cvs.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, lex, regex, util, window diff --git a/method/help.py b/method/help.py index e10e2ca..311fff2 100644 --- a/method/help.py +++ b/method/help.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, buffer.about diff --git a/method/introspect.py b/method/introspect.py index 3408da4..29c8d1d 100644 --- a/method/introspect.py +++ b/method/introspect.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, buffer.console diff --git a/method/move.py b/method/move.py index 2f1b01e..3966d99 100644 --- a/method/move.py +++ b/method/move.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, regex, util, window diff --git a/method/search.py b/method/search.py index 3b776f6..061f639 100644 --- a/method/search.py +++ b/method/search.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, regex, util, window diff --git a/method/shell.py b/method/shell.py index 09ddedb..3738e50 100644 --- a/method/shell.py +++ b/method/shell.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, regex, term, util, window diff --git a/method/svn.py b/method/svn.py index 0502cfa..68e946a 100644 --- a/method/svn.py +++ b/method/svn.py @@ -1,4 +1,4 @@ -import os, commands, re, sets, tempfile +import os, commands, re, tempfile from subprocess import Popen, PIPE, STDOUT import buffer, default, dirutil, lex, regex, util, window diff --git a/mode/__init__.py b/mode/__init__.py index abaa193..a7cac8d 100644 --- a/mode/__init__.py +++ b/mode/__init__.py @@ -1,4 +1,4 @@ -import math, os, sets, string +import math, os, string import color, method from lex import Lexer from point import Point @@ -75,19 +75,20 @@ class Handler(object): class Fundamental(Handler): '''This is the default mode''' - modename = "Fundamental" - paths = [] - basenames = [] - extensions = [] - detection = [] - savetabs = False - tabwidth = 4 - tabbercls = None - grammar = None - lexer = None - tabber = None - context = None - colors = {} + modename = "Fundamental" + paths = [] + basenames = [] + extensions = [] + detection = [] + savetabs = False + tabwidth = 4 + tabbercls = None + grammar = None + lexer = None + tabber = None + context = None + colors = {} + word_letters = None # config settings installed/modified by the mode config = {} @@ -124,7 +125,7 @@ class Fundamental(Handler): for val2 in val: app.config[key].append(val2) for (key, val) in cls.sconfig.iteritems(): - app.config.setdefault(key, sets.Set()) + app.config.setdefault(key, set()) app.config[key].add(val) for (key, d) in cls.dconfig.iteritems(): app.config.setdefault(key, {}) @@ -231,6 +232,10 @@ class Fundamental(Handler): self.add_bindings('insert-text2', ('C-c M-i',)) self.add_bindings('insert-multiline-text', ('C-c m',)) + # used for all word operations + if not self.word_letters: + self.word_letters = w.application.def_word_letters + # create all the insert actions for the basic text input for c in string.letters + string.digits + string.punctuation: self.add_binding('insert-string-%s' % c, c) @@ -259,8 +264,6 @@ class Fundamental(Handler): c, fg, bg = " ", "red", "default" if cont: c = "\\" - if w.hiddenindicator(y): - bg = "green" return [RenderString(s=c, attrs=color.build(fg, bg))] def get_lmargin(self, w, y, x, ended=False, cont=False): lm = self.lmargin @@ -342,10 +345,10 @@ class Fundamental(Handler): self.window.application.last_action = act.name except ActionError, e: #XYZ: HACK--should fix - if t not in ('C-]', 'C-g'): - self.window.set_error(str(e)) - else: + if t in ('C-]', 'C-g'): self.window.set_error('Cancelled') + else: + self.window.set_error(str(e)) except Exception, e: if DEBUG: raise diff --git a/mode/brm.py b/mode/brm.py index ae9f645..0c0563a 100644 --- a/mode/brm.py +++ b/mode/brm.py @@ -1,4 +1,4 @@ -import re, sets, string +import re, string import color, method, minibuffer, mode, searchutil from point import Point diff --git a/mode/elisp.py b/mode/elisp.py index f66a937..48ef137 100644 --- a/mode/elisp.py +++ b/mode/elisp.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule diff --git a/mode/erlang.py b/mode/erlang.py index 1ec1f22..5714846 100644 --- a/mode/erlang.py +++ b/mode/erlang.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule diff --git a/mode/haskell.py b/mode/haskell.py index 9bff8c9..b0433c1 100644 --- a/mode/haskell.py +++ b/mode/haskell.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule diff --git a/mode/lisp.py b/mode/lisp.py index c4102c8..55cce01 100644 --- a/mode/lisp.py +++ b/mode/lisp.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule diff --git a/mode/ocaml.py b/mode/ocaml.py index df96a52..881e9d2 100644 --- a/mode/ocaml.py +++ b/mode/ocaml.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, NocasePatternRule diff --git a/mode/perl.py b/mode/perl.py index 466bfb8..e8b3ce3 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -1,4 +1,4 @@ -import os, re, sets, string, sys +import os, re, string, sys import buffer, color, commands, completer, context, default, method, mode, regex, tab from point import Point from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, \ diff --git a/mode/python.py b/mode/python.py index 5a4fcc6..156199d 100644 --- a/mode/python.py +++ b/mode/python.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, context, default, mode, method, regex, tab, method.introspect from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule diff --git a/mode/replace.py b/mode/replace.py index c9434c9..1ce6817 100644 --- a/mode/replace.py +++ b/mode/replace.py @@ -1,4 +1,4 @@ -import re, sets, string +import re, string import color, method, minibuffer, mode, searchutil from point import Point diff --git a/mode/scheme.py b/mode/scheme.py index 5859d46..122dba4 100644 --- a/mode/scheme.py +++ b/mode/scheme.py @@ -1,4 +1,4 @@ -import commands, os.path, sets, string, sys, traceback +import commands, os.path, string, sys, traceback import color, completer, default, mode, method, regex, tab from point import Point from lex import Grammar, PatternRule, RegionRule, OverridePatternRule diff --git a/mode/search.py b/mode/search.py index fb68674..2d58e81 100644 --- a/mode/search.py +++ b/mode/search.py @@ -1,4 +1,4 @@ -import re, sets, string +import re, string import color, method, minibuffer, mode, searchutil from point import Point diff --git a/mode/shellmini.py b/mode/shellmini.py index 1eb1eeb..e7c0bd6 100644 --- a/mode/shellmini.py +++ b/mode/shellmini.py @@ -123,7 +123,7 @@ class OpenShell(Method): a = w.application if not a.has_buffer_name('*Shell*'): #b = buffer.pipe.PipeBuffer('/bin/bash', [], name="*Shell*", term='xterm') - b = buffer.emul.XTermBuffer('/bin/bash', [], name="*Shell*") + b = buffer.emul.XTermBuffer(a, '/bin/bash', [], name="*Shell*") a.add_buffer(b) window.Window(b, a) b = a.bufferlist.get_buffer_by_name('*Shell*') diff --git a/window.py b/window.py index 1ec3ff0..50d27cf 100644 --- a/window.py +++ b/window.py @@ -3,8 +3,6 @@ import color, highlight, regex from point import Point from render import RenderString -WORD_LETTERS = list(string.letters + string.digits) - # note about the cursor: the cursor position will insert in front of the # character it highlights. to this end, it needs to be able to highlight behind # the last character on a line. thus, the x coordinate of the (logical) cursor @@ -22,19 +20,16 @@ class Window(object): margins = ((80, 'blue'),) margins_visible = False def __init__(self, b, a, height=24, width=80, mode_name=None): - self.buffer = b - self.application = a - self.height = height - self.width = width - - self.first = Point(0, 0) - self.last = None - self.cursor = Point(0, 0) - self.mark = None - self.active_point = None - self.input_line = "" - self.hidden_ranges = {} - self.hidden_lines = {} + self.buffer = b + self.application = a + self.height = height + self.width = width + self.first = Point(0, 0) + self.last = None + self.cursor = Point(0, 0) + self.mark = None + self.active_point = None + self.input_line = "" if mode_name is not None: pass @@ -311,14 +306,14 @@ class Window(object): x = len(self.buffer.lines[y]) else: x -= 1 - while (y, x) >= start and self.xy_char(x, y) not in WORD_LETTERS: + while (y, x) >= start and self.xy_char(x, y) not in self.mode.word_letters: if x == 0: y -= 1 x = len(self.buffer.lines[y]) else: x -= 1 found_word = False - while (y, x) >= start and self.xy_char(x, y) in WORD_LETTERS: + while (y, x) >= start and self.xy_char(x, y) in self.mode.word_letters: found_word = True if x == 0: y -= 1 @@ -339,13 +334,13 @@ class Window(object): else: (x, y) = p.xy() end = self.buffer.get_buffer_end() - while (y, x) < end and self.xy_char(x, y) not in WORD_LETTERS: + while (y, x) < end and self.xy_char(x, y) not in self.mode.word_letters: if x == len(self.buffer.lines[y]): x = 0 y += 1 else: x += 1 - while (y, x) < end and self.xy_char(x, y) in WORD_LETTERS: + while (y, x) < end and self.xy_char(x, y) in self.mode.word_letters: if x == len(self.buffer.lines[y]): x = 0 y += 1 @@ -360,27 +355,27 @@ class Window(object): p = self.find_right_word() if p is not None: self.goto(p) - def get_word_bounds_at_point(self, p, wl=WORD_LETTERS): + def get_word_bounds_at_point(self, p): if len(self.buffer.lines[p.y]) == 0: return None elif self.cursor_char() not in wl: return None x1 = x2 = p.x - while x1 > 0 and self.xy_char(x1 - 1, p.y) in wl: + while x1 > 0 and self.xy_char(x1 - 1, p.y) in self.mode.word_letters: x1 -= 1 while x2 < len(self.buffer.lines[p.y]) and self.xy_char(x2, p.y) in wl: x2 += 1 return (Point(x1, p.y), Point(x2, p.y)) - def get_word_at_point(self, p, wl=WORD_LETTERS): - bounds = self.get_word_bounds_at_point(p, wl) + def get_word_at_point(self, p): + bounds = self.get_word_bounds_at_point(p) if bounds is None: return None else: return self.buffer.get_substring(bounds[0], bounds[1]) - def get_word_bounds(self, wl=WORD_LETTERS): - return self.get_word_bounds_at_point(self.logical_cursor(), wl) - def get_word(self, wl=WORD_LETTERS): - return self.get_word_at_point(self.logical_cursor(), wl) + def get_word_bounds(self): + return self.get_word_bounds_at_point(self.logical_cursor()) + def get_word(self): + return self.get_word_at_point(self.logical_cursor()) # page up/down def _pshift_up(self, p, num): @@ -496,69 +491,111 @@ class Window(object): self.set_mark_point(self.logical_cursor()) self.goto(p) - # deletion - def left_delete(self): - self.buffer.left_delete(self.logical_cursor()) - def right_delete(self): - self.buffer.right_delete(self.logical_cursor()) - def delete(self, p1, p2): - self.buffer.delete(p1, p2) - - # killing - def kill_line(self): - return self.copy_line(kill=True) - def kill_region(self): - return self.copy_region(kill=True) - def kill_left_word(self): - p1 = self.find_left_word() - p2 = self.logical_cursor() - if p1 == p2: - return - return self.kill(p1, p2) - def kill_right_word(self): - p1 = self.logical_cursor() - p2 = self.find_right_word() - if p1 == p2: - return - return self.kill(p1, p2) - def copy_line(self, kill=False): + # finding (used by deletion, killing, and copying) + def get_line(self): + (x, y) = self.logical_cursor().xy() + lines = self.buffer.lines + if y < len(lines) - 1: + return (Point(0, y), Point(0, y + 1)) + elif y > 0: + return (Point(len(lines[y - 1]), y - 1), Point(len(lines[y]), y)) + else: + return (None, None) + def get_line_left(self): + cursor = self.logical_cursor() + (x, y) = cursor.xy() + lines = self.buffer.lines + if (x > 0) and not regex.whitespace.match(lines[y][:x]): + return (Point(0, y), cursor) + elif y > 0: + return (Point(len(lines[y - 1]), y - 1), cursor) + else: + return (None, None) + def get_line_right(self): cursor = self.logical_cursor() (x, y) = cursor.xy() lines = self.buffer.lines if (x < len(lines[y]) and not regex.whitespace.match(lines[y][x:])): - limit = Point(len(lines[y]), y) + return (cursor, Point(len(lines[y]), y)) elif y < len(lines) - 1: - limit = Point(0, y + 1) + return (cursor, Point(0, y + 1)) else: - return - if kill: - return self.kill(cursor, limit) - else: - return self.copy(cursor, limit) - def copy_region(self, kill=False): + return (None, None) + def get_region(self): cursor = self.logical_cursor() + p1, p2 = None, None if cursor < self.mark: p1 = cursor p2 = self.mark elif self.mark < cursor: p1 = self.mark p2 = cursor + return (p1, p2) + def get_left_word(self): + p1 = self.find_left_word() + p2 = self.logical_cursor() + if p1 == p2: + return (None, None) else: - self.input_line = "Empty kill region" - return - if kill: - return self.kill(p1, p2) + return (p1, p2) + def get_right_word(self): + p1 = self.logical_cursor() + p2 = self.find_right_word() + if p1 == p2: + return (None, None) else: - return self.copy(p1, p2) + return (p1, p2) + + # deletion + def delete(self, p1, p2): + self.buffer.delete(p1, p2) + def delete_line(self): + (p1, p2) = self.get_line_right() + if p1 is not None: self.delete(p1, p2) + def delete_region(self): + (p1, p2) = self.get_region() + if p1 is not None: self.delete(p1, p2) + def delete_left_word(self): + (p1, p2) = self.get_left_word() + if p1 is not None: self.delete(p1, p2) + def delete_right_word(self): + (p1, p2) = self.get_right_word() + if p1 is not None: self.delete(p1, p2) + def left_delete(self): + self.buffer.left_delete(self.logical_cursor()) + def right_delete(self): + self.buffer.right_delete(self.logical_cursor()) + + # killing def kill(self, p1, p2): killed = self.buffer.get_substring(p1, p2) self.buffer.delete(p1, p2) self.application.push_kill(killed) return killed + def kill_line(self): + (p1, p2) = self.get_line_right() + if p1 is not None: self.kill(p1, p2) + def kill_region(self): + (p1, p2) = self.get_region() + if p1 is not None: self.kill(p1, p2) + def kill_left_word(self): + (p1, p2) = self.get_left_word() + if p1 is not None: self.kill(p1, p2) + def kill_right_word(self): + (p1, p2) = self.get_right_word() + if p1 is not None: self.kill(p1, p2) + + # copying def copy(self, p1, p2): copied = self.buffer.get_substring(p1, p2) self.application.push_kill(copied) return copied + def copy_line(self): + (p1, p2) = self.get_line_right() + if p1 is not None: return self.copy(p1, p2) + def copy_region(self, kill=False): + (p1, p2) = self.get_region() + if p1 is not None: return self.copy(p1, p2) # overwriting def overwrite_char_at_cursor(self, c): @@ -610,31 +647,6 @@ class Window(object): else: return self.buffer.lines[y][x] - # hiding stuff - def hide(self, y1, y2): - if y2 == 0: - return - for (py1, py2) in self.hidden_ranges.itervalues(): - if ((y1 >= py1 and y1 < py2) or - (y2 >= py1 and y2 < py2) or - (y1 <= py1 and y2 >= py2)): - return - for i in range(y1, y2): - self.hidden_lines[i] = y2 - self.hidden_ranges[y2] = (y1, y2) - def ishidden(self, y): - return self.hidden_lines.setdefault(y, False) - def hiddenindicator(self, y): - return y in self.hidden_ranges - def unhide(self, y): - py2 = self.ishidden(y) - if not py2: - return - py1 = self.hidden_ranges[py2][0] - del self.hidden_ranges[py2] - for i in range(py1, py2): - self.hidden_lines[i] = False - # undo/redo def undo(self): p = self.buffer.undo()