diff --git a/Pyboard Editor.doc b/Pyboard Editor.doc index bfbf4f2..9e5f5c5 100644 Binary files a/Pyboard Editor.doc and b/Pyboard Editor.doc differ diff --git a/Pyboard Editor.pdf b/Pyboard Editor.pdf index a6ab71d..29496ad 100644 Binary files a/Pyboard Editor.pdf and b/Pyboard Editor.pdf differ diff --git a/README.md b/README.md index 93d7338..0db4f74 100644 --- a/README.md +++ b/README.md @@ -110,3 +110,9 @@ c) expandtabs() and packtabs() with a second argument for tabsize (not for pye, - Removed UART mode on WiPy. Not stable yet. UART mode can be achieved by redirecting REPL. - A variant of pye.py, called pye2.py, keeps the cursor column even if the cursor is moved beyond the text in a line, instead of moving to the end of text if a line is shorter than the actual cursor column. Another variant, pye3, tries to go back to the cursor column which once was set by a horizontal move. That's more how gedit works. Not sure which I like better. +**1.10** Further refinement of Mark +- When the mark is set, the whole area affected is now highlighted instead of just the line with the mark. +- Paste, Delete and Backspace now also take notice of the line Mark. You can Mark a line range and delete it (or cut it). Implicit deleting marked lines when pressing the Enter or character key was considered but rejected (easy - just 3 lines of code). +- Except for Delete, Backspace, Cut and Paste, Mark has to be toggled off when not needed any more. +- Right click (Button 2) or Ctrl-Click on the mouse sets/unsets the Mark, left Click extends it, when set. + diff --git a/pe.py b/pe.py index 0bdeb1b..5dc4008 100644 --- a/pe.py +++ b/pe.py @@ -56,10 +56,7 @@ def __init__(self, tab_size, undo_limit): self.case = "n" self.autoindent = "y" self.yank_buffer = [] - self.mark = -1 - self.check_mark = -1 - self.mark_tab = False - self.msg_find = "Find: " + self.mark = None self.replc_pattern = "" self.write_tabs = "n" if sys.platform == "pyboard": @@ -89,10 +86,7 @@ def goto(self, row, col): def clear_to_eol(self): self.wr(b"\x1b[0K") def cursor(self, onoff): - if onoff: - self.wr(b"\x1b[?25h") - else: - self.wr(b"\x1b[?25l") + self.wr(b"\x1b[?25h" if onoff else b"\x1b[?25l") def hilite(self, mode): if mode == 1: self.wr(b"\x1b[1m") @@ -101,15 +95,9 @@ def hilite(self, mode): else: self.wr(b"\x1b[0m") def mouse_reporting(self, onoff): - if onoff: - self.wr('\x1b[?9h') - else: - self.wr('\x1b[?9l') + self.wr('\x1b[?9h' if onoff else '\x1b[?9l') def scroll_region(self, stop): - if stop: - self.wr('\x1b[1;{}r'.format(stop)) - else: - self.wr('\x1b[r') + self.wr('\x1b[1;{}r'.format(stop) if stop else '\x1b[r') def scroll_up(self, scrolling): self.scrbuf[scrolling:] = self.scrbuf[:-scrolling] self.scrbuf[:scrolling] = [''] * scrolling @@ -130,7 +118,7 @@ def set_screen_parms(self): char = self.rd() (self.height, self.width) = [int(i, 10) for i in pos[2:].split(b';')] self.height -= 1 - self.scrbuf = ["\x01"] * self.height + self.scrbuf = [(False,"\x00")] * self.height self.scroll_region(self.height) def get_input(self): while True: @@ -146,12 +134,12 @@ def get_input(self): if c != 0x1b: return c else: - mf = ord((self.rd())) + self.mouse_fct = ord((self.rd())) self.mouse_x = ord(self.rd()) - 33 self.mouse_y = ord(self.rd()) - 33 - if mf == 0x61: + if self.mouse_fct == 0x61: return 0x1d - elif mf == 0x60: + elif self.mouse_fct == 0x60: return 0x1c else: return 0x1b @@ -171,23 +159,24 @@ def display_window(self): i = self.top_line for c in range(self.height): if i == self.total_lines: - if self.scrbuf[c] != '': + if self.scrbuf[c][1] != '': self.goto(c, 0) self.clear_to_eol() - self.scrbuf[c] = '' + self.scrbuf[c] = (False,'') else: - l = self.content[i][self.margin:self.margin + self.width] - if l != self.scrbuf[c] or i == self.check_mark: + l = (self.mark != None and ( + (self.mark <= i <= self.cur_line) or (self.cur_line <= i <= self.mark)), + self.content[i][self.margin:self.margin + self.width]) + if l != self.scrbuf[c]: self.goto(c, 0) - if i == self.mark: + if l[0]: self.hilite(2) - self.wr(l) - if l == "": self.wr(' ') + self.wr(l[1]) + if l[1] == '': self.wr(' ') self.hilite(0) else: - self.wr(l) - if i == self.check_mark: self.check_mark = -1 - if len(l) < self.width: + self.wr(l[1]) + if len(l[1]) < self.width: self.clear_to_eol() self.scrbuf[c] = l i += 1 @@ -201,18 +190,11 @@ def display_window(self): self.goto(self.row, self.col - self.margin) self.cursor(True) def spaces(self, line, pos = None): - if pos == None: - return len(line) - len(line.lstrip(" ")) - else: - return len(line[:pos]) - len(line[:pos].rstrip(" ")) + return (len(line) - len(line.lstrip(" ")) if pos == None else + len(line[:pos]) - len(line[:pos].rstrip(" "))) def line_range(self): - if self.mark < 0: - return (self.cur_line, self.cur_line + 1) - else: - if self.mark < self.cur_line: - return (self.mark, self.cur_line + 1) - else: - return (self.cur_line, self.mark + 1) + return ((self.mark, self.cur_line + 1) if self.mark < self.cur_line else + (self.cur_line, self.mark + 1)) def line_edit(self, prompt, default): self.goto(self.height, 0) self.hilite(1) @@ -294,7 +276,7 @@ def handle_cursor_keys(self, key): elif key == 0x19: self.cur_line += self.height elif key == 0x06: - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: self.find_in_file(pat, self.col, self.total_lines) self.row = self.height >> 1 @@ -314,6 +296,8 @@ def handle_cursor_keys(self, key): if self.mouse_y < self.height: self.col = self.mouse_x + self.margin self.cur_line = self.mouse_y + self.top_line + if self.mouse_fct in (0x22, 0x30): + self.mark = self.cur_line if self.mark == None else None elif key == 0x1c: if self.top_line > 0: self.top_line = max(self.top_line - 3, 0) @@ -352,9 +336,20 @@ def undo_add(self, lnum, text, key, span = 1): del self.undo[0] self.undo_zero -= 1 self.undo.append((lnum, span, text, key, self.col)) + def delete_lines(self, yank): + lrange = self.line_range() + if yank: self.yank_buffer = self.content[lrange[0]:lrange[1]] + self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) + del self.content[lrange[0]:lrange[1]] + if self.content == []: + self.content = [""] + self.total_lines = len(self.content) + self.cur_line = lrange[0] + self.mark = None def handle_edit_key(self, key): l = self.content[self.cur_line] if key == 0x0a: + self.mark = None self.undo_add(self.cur_line, [l], 0, 2) self.content[self.cur_line] = l[:self.col] ni = 0 @@ -368,7 +363,9 @@ def handle_edit_key(self, key): self.total_lines += 1 self.col = ni elif key == 0x08: - if self.col > 0: + if self.mark != None: + self.delete_lines(False) + elif self.col > 0: self.undo_add(self.cur_line, [l], 0x08) self.content[self.cur_line] = l[:self.col - 1] + l[self.col:] self.col -= 1 @@ -379,7 +376,9 @@ def handle_edit_key(self, key): self.cur_line -= 1 self.total_lines -= 1 elif key == 0x7f: - if self.col < len(l): + if self.mark != None: + self.delete_lines(False) + elif self.col < len(l): self.undo_add(self.cur_line, [l], 0x7f) self.content[self.cur_line] = l[:self.col] + l[self.col + 1:] elif (self.cur_line + 1) < self.total_lines: @@ -387,8 +386,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l + self.content.pop(self.cur_line + 1) self.total_lines -= 1 elif key == 0x09: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -400,8 +398,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l[:self.col] + ' ' * ni + l[self.col:] self.col += ni elif key == 0x15: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -416,13 +413,13 @@ def handle_edit_key(self, key): self.col -= ni elif key == 0x12: count = 0 - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: rpat = self.line_edit("Replace with: ", self.replc_pattern) if rpat != None: self.replc_pattern = rpat q = '' - if self.mark >= 0: + if self.mark != None: lrange = self.line_range() self.cur_line = lrange[0] else: @@ -456,36 +453,26 @@ def handle_edit_key(self, key): self.content[self.cur_line:self.cur_line] = content self.total_lines = len(self.content) elif key == 0x0c: - if self.mark < 0: - self.mark = self.check_mark = self.cur_line - self.mark_tab = False - else: - self.mark = -1 + self.mark = self.cur_line if self.mark == None else None elif key == 0x18: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) - del self.content[lrange[0]:lrange[1]] - if self.content == []: - self.content = [""] - self.total_lines = len(self.content) - self.cur_line = lrange[0] - self.mark = -1 + if self.mark != None: + self.delete_lines(True) elif key == 0x04: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.mark = -1 + if self.mark != None: + lrange = self.line_range() + self.yank_buffer = self.content[lrange[0]:lrange[1]] elif key == 0x16: if self.yank_buffer: + if self.mark != None: + self.delete_lines(False) self.undo_add(self.cur_line, None, 0, -len(self.yank_buffer)) self.content[self.cur_line:self.cur_line] = self.yank_buffer self.total_lines += len(self.yank_buffer) elif key == 0x13: if False: pass - elif self.mark >= 0: + elif self.mark != None: fname = self.line_edit("Save Mark: ", "") lrange = self.line_range() - self.mark = -1 else: fname = self.fname if fname == None: @@ -521,11 +508,12 @@ def handle_edit_key(self, key): self.total_lines = len(self.content) self.changed = ' ' if len(self.undo) == self.undo_zero else '*' elif key >= 0x20: + self.mark = None self.undo_add(self.cur_line, [l], 0x20 if key == 0x20 else 0x41) self.content[self.cur_line] = l[:self.col] + chr(key) + l[self.col:] self.col += 1 def edit_loop(self): - if len(self.content) == 0: + if self.content == []: self.content = [""] self.total_lines = len(self.content) self.set_screen_parms() @@ -534,8 +522,6 @@ def edit_loop(self): self.display_window() key = self.get_input() self.message = '' - if self.mark_tab and key != 0x09 and key != 0x15: - self.mark = -1 if key == 0x11: if self.changed != ' ': res = self.line_edit("Content changed! Quit without saving (y/N)? ", "N") diff --git a/pemin.py b/pemin.py index 3c50ea2..ca4a693 100644 --- a/pemin.py +++ b/pemin.py @@ -33,10 +33,7 @@ def __init__(self, tab_size, undo_limit): self.case = "n" self.autoindent = "y" self.yank_buffer = [] - self.mark = -1 - self.check_mark = -1 - self.mark_tab = False - self.msg_find = "Find: " + self.mark = None if sys.platform == "pyboard": def wr(self,s): ns = 0 @@ -64,10 +61,7 @@ def goto(self, row, col): def clear_to_eol(self): self.wr(b"\x1b[0K") def cursor(self, onoff): - if onoff: - self.wr(b"\x1b[?25h") - else: - self.wr(b"\x1b[?25l") + self.wr(b"\x1b[?25h" if onoff else b"\x1b[?25l") def hilite(self, mode): if mode == 1: self.wr(b"\x1b[1m") @@ -76,10 +70,7 @@ def hilite(self, mode): else: self.wr(b"\x1b[0m") def scroll_region(self, stop): - if stop: - self.wr('\x1b[1;{}r'.format(stop)) - else: - self.wr('\x1b[r') + self.wr('\x1b[1;{}r'.format(stop) if stop else '\x1b[r') def scroll_up(self, scrolling): self.scrbuf[scrolling:] = self.scrbuf[:-scrolling] self.scrbuf[:scrolling] = [''] * scrolling @@ -100,7 +91,7 @@ def set_screen_parms(self): char = self.rd() (self.height, self.width) = [int(i, 10) for i in pos[2:].split(b';')] self.height -= 1 - self.scrbuf = ["\x01"] * self.height + self.scrbuf = [(False,"\x00")] * self.height self.scroll_region(self.height) def get_input(self): while True: @@ -131,23 +122,24 @@ def display_window(self): i = self.top_line for c in range(self.height): if i == self.total_lines: - if self.scrbuf[c] != '': + if self.scrbuf[c][1] != '': self.goto(c, 0) self.clear_to_eol() - self.scrbuf[c] = '' + self.scrbuf[c] = (False,'') else: - l = self.content[i][self.margin:self.margin + self.width] - if l != self.scrbuf[c] or i == self.check_mark: + l = (self.mark != None and ( + (self.mark <= i <= self.cur_line) or (self.cur_line <= i <= self.mark)), + self.content[i][self.margin:self.margin + self.width]) + if l != self.scrbuf[c]: self.goto(c, 0) - if i == self.mark: + if l[0]: self.hilite(2) - self.wr(l) - if l == "": self.wr(' ') + self.wr(l[1]) + if l[1] == '': self.wr(' ') self.hilite(0) else: - self.wr(l) - if i == self.check_mark: self.check_mark = -1 - if len(l) < self.width: + self.wr(l[1]) + if len(l[1]) < self.width: self.clear_to_eol() self.scrbuf[c] = l i += 1 @@ -161,18 +153,11 @@ def display_window(self): self.goto(self.row, self.col - self.margin) self.cursor(True) def spaces(self, line, pos = None): - if pos == None: - return len(line) - len(line.lstrip(" ")) - else: - return len(line[:pos]) - len(line[:pos].rstrip(" ")) + return (len(line) - len(line.lstrip(" ")) if pos == None else + len(line[:pos]) - len(line[:pos].rstrip(" "))) def line_range(self): - if self.mark < 0: - return (self.cur_line, self.cur_line + 1) - else: - if self.mark < self.cur_line: - return (self.mark, self.cur_line + 1) - else: - return (self.cur_line, self.mark + 1) + return ((self.mark, self.cur_line + 1) if self.mark < self.cur_line else + (self.cur_line, self.mark + 1)) def line_edit(self, prompt, default): self.goto(self.height, 0) self.hilite(1) @@ -242,7 +227,7 @@ def handle_cursor_keys(self, key): elif key == 0x19: self.cur_line += self.height elif key == 0x06: - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: self.find_in_file(pat, self.col, self.total_lines) self.row = self.height >> 1 @@ -269,28 +254,40 @@ def undo_add(self, lnum, text, key, span = 1): del self.undo[0] self.undo_zero -= 1 self.undo.append((lnum, span, text, key, self.col)) + def delete_lines(self, yank): + lrange = self.line_range() + if yank: self.yank_buffer = self.content[lrange[0]:lrange[1]] + self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) + del self.content[lrange[0]:lrange[1]] + if self.content == []: + self.content = [""] + self.total_lines = len(self.content) + self.cur_line = lrange[0] + self.mark = None def handle_edit_key(self, key): l = self.content[self.cur_line] if key == 0x0a: + self.mark = None self.undo_add(self.cur_line, [l], 0, 2) self.content[self.cur_line] = l[:self.col] ni = 0 if self.autoindent == "y": ni = min(self.spaces(l), self.col) - r = l.partition("\x23")[0].rstrip() - if r and r[-1] == ':' and self.col >= len(r): - ni += self.tab_size self.cur_line += 1 self.content[self.cur_line:self.cur_line] = [' ' * ni + l[self.col:]] self.total_lines += 1 self.col = ni elif key == 0x08: - if self.col > 0: + if self.mark != None: + self.delete_lines(False) + elif self.col > 0: self.undo_add(self.cur_line, [l], 0x08) self.content[self.cur_line] = l[:self.col - 1] + l[self.col:] self.col -= 1 elif key == 0x7f: - if self.col < len(l): + if self.mark != None: + self.delete_lines(False) + elif self.col < len(l): self.undo_add(self.cur_line, [l], 0x7f) self.content[self.cur_line] = l[:self.col] + l[self.col + 1:] elif (self.cur_line + 1) < self.total_lines: @@ -298,8 +295,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l + self.content.pop(self.cur_line + 1) self.total_lines -= 1 elif key == 0x09: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -311,8 +307,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l[:self.col] + ' ' * ni + l[self.col:] self.col += ni elif key == 0x15: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -326,27 +321,18 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l[:self.col - ni] + l[self.col:] self.col -= ni elif key == 0x0c: - if self.mark < 0: - self.mark = self.check_mark = self.cur_line - self.mark_tab = False - else: - self.mark = -1 + self.mark = self.cur_line if self.mark == None else None elif key == 0x18: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) - del self.content[lrange[0]:lrange[1]] - if self.content == []: - self.content = [""] - self.total_lines = len(self.content) - self.cur_line = lrange[0] - self.mark = -1 + if self.mark != None: + self.delete_lines(True) elif key == 0x04: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.mark = -1 + if self.mark != None: + lrange = self.line_range() + self.yank_buffer = self.content[lrange[0]:lrange[1]] elif key == 0x16: if self.yank_buffer: + if self.mark != None: + self.delete_lines(False) self.undo_add(self.cur_line, None, 0, -len(self.yank_buffer)) self.content[self.cur_line:self.cur_line] = self.yank_buffer self.total_lines += len(self.yank_buffer) @@ -384,11 +370,12 @@ def handle_edit_key(self, key): self.total_lines = len(self.content) self.changed = ' ' if len(self.undo) == self.undo_zero else '*' elif key >= 0x20: + self.mark = None self.undo_add(self.cur_line, [l], 0x20 if key == 0x20 else 0x41) self.content[self.cur_line] = l[:self.col] + chr(key) + l[self.col:] self.col += 1 def edit_loop(self): - if len(self.content) == 0: + if self.content == []: self.content = [""] self.total_lines = len(self.content) self.set_screen_parms() @@ -396,8 +383,6 @@ def edit_loop(self): self.display_window() key = self.get_input() self.message = '' - if self.mark_tab and key != 0x09 and key != 0x15: - self.mark = -1 if key == 0x11: if self.changed != ' ': res = self.line_edit("Content changed! Quit without saving (y/N)? ", "N") diff --git a/pye.py b/pye.py index 2b74a54..14c7465 100644 --- a/pye.py +++ b/pye.py @@ -158,10 +158,7 @@ def __init__(self, tab_size, undo_limit): self.case = "n" self.autoindent = "y" self.yank_buffer = [] - self.mark = -1 - self.check_mark = -1 - self.mark_tab = False - self.msg_find = "Find: " + self.mark = None #ifndef BASIC self.replc_pattern = "" self.write_tabs = "n" @@ -233,11 +230,10 @@ def wr(self, s): def rd(self): while True: - try: - ch = sys.stdin.read(1) - if ch != "\x00": - return ch.encode() - except: pass + try: + return sys.stdin.read(1).encode() + except: + pass def init_tty(self, device, baud): pass @@ -252,10 +248,7 @@ def clear_to_eol(self): self.wr(b"\x1b[0K") def cursor(self, onoff): - if onoff: - self.wr(b"\x1b[?25h") - else: - self.wr(b"\x1b[?25l") + self.wr(b"\x1b[?25h" if onoff else b"\x1b[?25l") def hilite(self, mode): if mode == 1: @@ -267,16 +260,10 @@ def hilite(self, mode): #ifndef BASIC def mouse_reporting(self, onoff): - if onoff: - self.wr('\x1b[?9h') ## enable mouse reporting - else: - self.wr('\x1b[?9l') ## disable mouse reporting + self.wr('\x1b[?9h' if onoff else '\x1b[?9l') ## enable/disable mouse reporting #endif def scroll_region(self, stop): - if stop: - self.wr('\x1b[1;{}r'.format(stop)) ## enable partial scrolling - else: - self.wr('\x1b[r') ## full scrolling + self.wr('\x1b[1;{}r'.format(stop) if stop else '\x1b[r') ## set scrolling range def scroll_up(self, scrolling): self.scrbuf[scrolling:] = self.scrbuf[:-scrolling] @@ -300,7 +287,7 @@ def set_screen_parms(self): char = self.rd() (self.height, self.width) = [int(i, 10) for i in pos[2:].split(b';')] self.height -= 1 - self.scrbuf = ["\x01"] * self.height ## force delete + self.scrbuf = [(False,"\x00")] * self.height ## force delete self.scroll_region(self.height) def get_input(self): ## read from interface/keyboard one byte each and match against function keys @@ -318,12 +305,12 @@ def get_input(self): ## read from interface/keyboard one byte each and match ag return c #ifndef BASIC else: ## special for mice - mf = ord((self.rd())) ## read 3 more chars + self.mouse_fct = ord((self.rd())) ## read 3 more chars self.mouse_x = ord(self.rd()) - 33 self.mouse_y = ord(self.rd()) - 33 - if mf == 0x61: + if self.mouse_fct == 0x61: return KEY_SCRLDN - elif mf == 0x60: + elif self.mouse_fct == 0x60: return KEY_SCRLUP else: return KEY_MOUSE ## do nothing but set the cursor @@ -350,23 +337,24 @@ def display_window(self): ## Update window and status line i = self.top_line for c in range(self.height): if i == self.total_lines: ## at empty bottom screen part - if self.scrbuf[c] != '': + if self.scrbuf[c][1] != '': self.goto(c, 0) self.clear_to_eol() - self.scrbuf[c] = '' + self.scrbuf[c] = (False,'') else: - l = self.content[i][self.margin:self.margin + self.width] - if l != self.scrbuf[c] or i == self.check_mark: ## line changed, print it + l = (self.mark != None and ( + (self.mark <= i <= self.cur_line) or (self.cur_line <= i <= self.mark)), + self.content[i][self.margin:self.margin + self.width]) + if l != self.scrbuf[c]: ## line changed, print it self.goto(c, 0) - if i == self.mark: + if l[0]: self.hilite(2) - self.wr(l) - if l == "": self.wr(' ') ## add a spaces + self.wr(l[1]) + if l[1] == '': self.wr(' ') ## add a space to show a marked empty line self.hilite(0) else: - self.wr(l) - if i == self.check_mark: self.check_mark = -1 - if len(l) < self.width: + self.wr(l[1]) + if len(l[1]) < self.width: self.clear_to_eol() self.scrbuf[c] = l i += 1 @@ -382,19 +370,15 @@ def display_window(self): ## Update window and status line self.cursor(True) def spaces(self, line, pos = None): ## count spaces - if pos == None: ## at line start - return len(line) - len(line.lstrip(" ")) - else: ## left to pos - return len(line[:pos]) - len(line[:pos].rstrip(" ")) + return (len(line) - len(line.lstrip(" ")) if pos == None else ## at line start + len(line[:pos]) - len(line[:pos].rstrip(" "))) def line_range(self): - if self.mark < 0: - return (self.cur_line, self.cur_line + 1) - else: - if self.mark < self.cur_line: - return (self.mark, self.cur_line + 1) - else: - return (self.cur_line, self.mark + 1) +## if self.mark == None: +## return (self.cur_line, self.cur_line + 1) +## else: + return ((self.mark, self.cur_line + 1) if self.mark < self.cur_line else + (self.cur_line, self.mark + 1)) def line_edit(self, prompt, default): ## simple one: only 4 fcts self.goto(self.height, 0) @@ -486,7 +470,7 @@ def handle_cursor_keys(self, key): ## keys which move, sanity checks later elif key == KEY_PGDN: self.cur_line += self.height elif key == KEY_FIND: - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: self.find_in_file(pat, self.col, self.total_lines) self.row = self.height >> 1 @@ -507,6 +491,8 @@ def handle_cursor_keys(self, key): ## keys which move, sanity checks later if self.mouse_y < self.height: self.col = self.mouse_x + self.margin self.cur_line = self.mouse_y + self.top_line + if self.mouse_fct in (0x22, 0x30): ## Right/Ctrl button on Mouse + self.mark = self.cur_line if self.mark == None else None elif key == KEY_SCRLUP: ## if self.top_line > 0: self.top_line = max(self.top_line - 3, 0) @@ -548,23 +534,39 @@ def undo_add(self, lnum, text, key, span = 1): self.undo_zero -= 1 self.undo.append((lnum, span, text, key, self.col)) + def delete_lines(self, yank): + lrange = self.line_range() + if yank: self.yank_buffer = self.content[lrange[0]:lrange[1]] + self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) ## undo inserts + del self.content[lrange[0]:lrange[1]] + if self.content == []: ## if all was wiped + self.content = [""] + self.total_lines = len(self.content) + self.cur_line = lrange[0] + self.mark = None ## unset line mark + def handle_edit_key(self, key): ## keys which change content l = self.content[self.cur_line] if key == KEY_ENTER: + self.mark = None self.undo_add(self.cur_line, [l], 0, 2) self.content[self.cur_line] = l[:self.col] ni = 0 if self.autoindent == "y": ## Autoindent ni = min(self.spaces(l), self.col) ## query indentation +#ifndef BASIC r = l.partition("\x23")[0].rstrip() ## \x23 == # if r and r[-1] == ':' and self.col >= len(r): ## look for : as the last non-space before comment ni += self.tab_size +#endif self.cur_line += 1 self.content[self.cur_line:self.cur_line] = [' ' * ni + l[self.col:]] self.total_lines += 1 self.col = ni elif key == KEY_BACKSPACE: - if self.col > 0: + if self.mark != None: + self.delete_lines(False) + elif self.col > 0: self.undo_add(self.cur_line, [l], KEY_BACKSPACE) self.content[self.cur_line] = l[:self.col - 1] + l[self.col:] self.col -= 1 @@ -577,7 +579,9 @@ def handle_edit_key(self, key): ## keys which change content self.total_lines -= 1 #endif elif key == KEY_DELETE: - if self.col < len(l): + if self.mark != None: + self.delete_lines(False) + elif self.col < len(l): self.undo_add(self.cur_line, [l], KEY_DELETE) self.content[self.cur_line] = l[:self.col] + l[self.col + 1:] elif (self.cur_line + 1) < self.total_lines: ## test for last line @@ -585,8 +589,7 @@ def handle_edit_key(self, key): ## keys which change content self.content[self.cur_line] = l + self.content.pop(self.cur_line + 1) self.total_lines -= 1 elif key == KEY_TAB: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], KEY_INDENT, lrange[1] - lrange[0]) ## undo replaces for i in range(lrange[0],lrange[1]): @@ -598,8 +601,7 @@ def handle_edit_key(self, key): ## keys which change content self.content[self.cur_line] = l[:self.col] + ' ' * ni + l[self.col:] self.col += ni elif key == KEY_BACKTAB: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], KEY_INDENT, lrange[1] - lrange[0]) ## undo replaces for i in range(lrange[0],lrange[1]): @@ -615,13 +617,13 @@ def handle_edit_key(self, key): ## keys which change content #ifndef BASIC elif key == KEY_REPLC: count = 0 - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: rpat = self.line_edit("Replace with: ", self.replc_pattern) if rpat != None: self.replc_pattern = rpat q = '' - if self.mark >= 0: ## Replace in Marked area + if self.mark != None: ## Replace in Marked area lrange = self.line_range() self.cur_line = lrange[0] else: @@ -656,37 +658,27 @@ def handle_edit_key(self, key): ## keys which change content self.total_lines = len(self.content) #endif elif key == KEY_MARK: - if self.mark < 0: - self.mark = self.check_mark = self.cur_line - self.mark_tab = False - else: - self.mark = -1 + self.mark = self.cur_line if self.mark == None else None elif key == KEY_YANK: # delete line or line(s) into buffer - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) ## undo inserts - del self.content[lrange[0]:lrange[1]] - if self.content == []: ## if all was wiped - self.content = [""] - self.total_lines = len(self.content) - self.cur_line = lrange[0] - self.mark = -1 ## unset line mark + if self.mark != None: + self.delete_lines(True) elif key == KEY_DUP: # copy line(s) into buffer - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.mark = -1 ## unset line mark + if self.mark != None: + lrange = self.line_range() + self.yank_buffer = self.content[lrange[0]:lrange[1]] elif key == KEY_ZAP: ## insert buffer if self.yank_buffer: + if self.mark != None: + self.delete_lines(False) self.undo_add(self.cur_line, None, 0, -len(self.yank_buffer)) self.content[self.cur_line:self.cur_line] = self.yank_buffer # insert lines self.total_lines += len(self.yank_buffer) elif key == KEY_WRITE: if False: pass #ifndef BASIC - elif self.mark >= 0: + elif self.mark != None: fname = self.line_edit("Save Mark: ", "") lrange = self.line_range() - self.mark = -1 #endif else: fname = self.fname @@ -725,13 +717,15 @@ def handle_edit_key(self, key): ## keys which change content self.total_lines = len(self.content) ## brute force self.changed = ' ' if len(self.undo) == self.undo_zero else '*' elif key >= 0x20: ## character to be added + self.mark = None self.undo_add(self.cur_line, [l], 0x20 if key == 0x20 else 0x41) self.content[self.cur_line] = l[:self.col] + chr(key) + l[self.col:] self.col += 1 + def edit_loop(self): ## main editing loop - if len(self.content) == 0: ## check for empty content + if self.content == []: ## check for empty content self.content = [""] self.total_lines = len(self.content) self.set_screen_parms() @@ -743,8 +737,6 @@ def edit_loop(self): ## main editing loop self.display_window() ## Update & display window key = self.get_input() ## Get Char of Fct-key code self.message = '' ## clear message - if self.mark_tab and key != KEY_TAB and key != KEY_BACKTAB: - self.mark = -1 if key == KEY_QUIT: if self.changed != ' ': diff --git a/pye2.py b/pye2.py index eaca744..81b141e 100644 --- a/pye2.py +++ b/pye2.py @@ -158,10 +158,7 @@ def __init__(self, tab_size, undo_limit): self.case = "n" self.autoindent = "y" self.yank_buffer = [] - self.mark = -1 - self.check_mark = -1 - self.mark_tab = False - self.msg_find = "Find: " + self.mark = None #ifndef BASIC self.replc_pattern = "" self.write_tabs = "n" @@ -233,11 +230,10 @@ def wr(self, s): def rd(self): while True: - try: - ch = sys.stdin.read(1) - if ch != "\x00": - return ch.encode() - except: pass + try: + return sys.stdin.read(1).encode() + except: + pass def init_tty(self, device, baud): pass @@ -252,10 +248,7 @@ def clear_to_eol(self): self.wr(b"\x1b[0K") def cursor(self, onoff): - if onoff: - self.wr(b"\x1b[?25h") - else: - self.wr(b"\x1b[?25l") + self.wr(b"\x1b[?25h" if onoff else b"\x1b[?25l") def hilite(self, mode): if mode == 1: @@ -267,16 +260,10 @@ def hilite(self, mode): #ifndef BASIC def mouse_reporting(self, onoff): - if onoff: - self.wr('\x1b[?9h') ## enable mouse reporting - else: - self.wr('\x1b[?9l') ## disable mouse reporting + self.wr('\x1b[?9h' if onoff else '\x1b[?9l') ## enable/disable mouse reporting #endif def scroll_region(self, stop): - if stop: - self.wr('\x1b[1;{}r'.format(stop)) ## enable partial scrolling - else: - self.wr('\x1b[r') ## full scrolling + self.wr('\x1b[1;{}r'.format(stop) if stop else '\x1b[r') ## set scrolling range def scroll_up(self, scrolling): self.scrbuf[scrolling:] = self.scrbuf[:-scrolling] @@ -300,7 +287,7 @@ def set_screen_parms(self): char = self.rd() (self.height, self.width) = [int(i, 10) for i in pos[2:].split(b';')] self.height -= 1 - self.scrbuf = ["\x01"] * self.height ## force delete + self.scrbuf = [(False,"\x00")] * self.height ## force delete self.scroll_region(self.height) def get_input(self): ## read from interface/keyboard one byte each and match against function keys @@ -318,12 +305,12 @@ def get_input(self): ## read from interface/keyboard one byte each and match ag return c #ifndef BASIC else: ## special for mice - mf = ord((self.rd())) ## read 3 more chars + self.mouse_fct = ord((self.rd())) ## read 3 more chars self.mouse_x = ord(self.rd()) - 33 self.mouse_y = ord(self.rd()) - 33 - if mf == 0x61: + if self.mouse_fct == 0x61: return KEY_SCRLDN - elif mf == 0x60: + elif self.mouse_fct == 0x60: return KEY_SCRLUP else: return KEY_MOUSE ## do nothing but set the cursor @@ -349,23 +336,24 @@ def display_window(self): ## Update window and status line i = self.top_line for c in range(self.height): if i == self.total_lines: ## at empty bottom screen part - if self.scrbuf[c] != '': + if self.scrbuf[c][1] != '': self.goto(c, 0) self.clear_to_eol() - self.scrbuf[c] = '' + self.scrbuf[c] = (False,'') else: - l = self.content[i][self.margin:self.margin + self.width] - if l != self.scrbuf[c] or i == self.check_mark: ## line changed, print it + l = (self.mark != None and ( + (self.mark <= i <= self.cur_line) or (self.cur_line <= i <= self.mark)), + self.content[i][self.margin:self.margin + self.width]) + if l != self.scrbuf[c]: ## line changed, print it self.goto(c, 0) - if i == self.mark: + if l[0]: self.hilite(2) - self.wr(l) - if l == "": self.wr(' ') ## add a spaces + self.wr(l[1]) + if l[1] == '': self.wr(' ') ## add a space to show a marked empty line self.hilite(0) else: - self.wr(l) - if i == self.check_mark: self.check_mark = -1 - if len(l) < self.width: + self.wr(l[1]) + if len(l[1]) < self.width: self.clear_to_eol() self.scrbuf[c] = l i += 1 @@ -381,19 +369,15 @@ def display_window(self): ## Update window and status line self.cursor(True) def spaces(self, line, pos = None): ## count spaces - if pos == None: ## at line start - return len(line) - len(line.lstrip(" ")) - else: ## left to pos - return len(line[:pos]) - len(line[:pos].rstrip(" ")) + return (len(line) - len(line.lstrip(" ")) if pos == None else ## at line start + len(line[:pos]) - len(line[:pos].rstrip(" "))) def line_range(self): - if self.mark < 0: - return (self.cur_line, self.cur_line + 1) - else: - if self.mark < self.cur_line: - return (self.mark, self.cur_line + 1) - else: - return (self.cur_line, self.mark + 1) +## if self.mark == None: +## return (self.cur_line, self.cur_line + 1) +## else: + return ((self.mark, self.cur_line + 1) if self.mark < self.cur_line else + (self.cur_line, self.mark + 1)) def line_edit(self, prompt, default): ## simple one: only 4 fcts self.goto(self.height, 0) @@ -469,7 +453,7 @@ def handle_cursor_keys(self, key): ## keys which move, sanity checks later #endif if self.col > 0: self.col -= 1 elif key == KEY_RIGHT: - self.col += 1 + self.col += 1 elif key == KEY_HOME: self.col = self.spaces(self.content[self.cur_line]) if self.col == 0 else 0 elif key == KEY_END: @@ -479,7 +463,7 @@ def handle_cursor_keys(self, key): ## keys which move, sanity checks later elif key == KEY_PGDN: self.cur_line += self.height elif key == KEY_FIND: - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: self.find_in_file(pat, self.col, self.total_lines) self.row = self.height >> 1 @@ -500,6 +484,8 @@ def handle_cursor_keys(self, key): ## keys which move, sanity checks later if self.mouse_y < self.height: self.col = self.mouse_x + self.margin self.cur_line = self.mouse_y + self.top_line + if self.mouse_fct in (0x22, 0x30): ## Right/Ctrl button on Mouse + self.mark = self.cur_line if self.mark == None else None elif key == KEY_SCRLUP: ## if self.top_line > 0: self.top_line = max(self.top_line - 3, 0) @@ -541,6 +527,17 @@ def undo_add(self, lnum, text, key, span = 1): self.undo_zero -= 1 self.undo.append((lnum, span, text, key, self.col)) + def delete_lines(self, yank): + lrange = self.line_range() + if yank: self.yank_buffer = self.content[lrange[0]:lrange[1]] + self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) ## undo inserts + del self.content[lrange[0]:lrange[1]] + if self.content == []: ## if all was wiped + self.content = [""] + self.total_lines = len(self.content) + self.cur_line = lrange[0] + self.mark = None ## unset line mark + def handle_edit_key(self, key): ## keys which change content l = self.content[self.cur_line] jut = self.col - len(l) ## <0: before text end, =0 at text end, >0 beyond text end @@ -550,21 +547,36 @@ def handle_edit_key(self, key): ## keys which change content ni = 0 if self.autoindent == "y": ## Autoindent ni = min(self.spaces(l), self.col) ## query indentation +#ifndef BASIC r = l.partition("\x23")[0].rstrip() ## \x23 == # if r and r[-1] == ':' and self.col >= len(r): ## look for : as the last non-space before comment ni += self.tab_size +#endif self.cur_line += 1 self.content[self.cur_line:self.cur_line] = [' ' * ni + l[self.col:]] if jut < 0 else [""] self.total_lines += 1 self.col = ni + self.mark = None ## unset line mark elif key == KEY_BACKSPACE: - if self.col > 0: + if self.mark != None: + self.delete_lines(False) + elif self.col > 0: if jut <= 0: ## if on solid ground self.undo_add(self.cur_line, [l], KEY_BACKSPACE) self.content[self.cur_line] = l[:self.col - 1] + l[self.col:] self.col -= 1 +#ifndef BASIC + elif self.cur_line > 0: # at the start of a line, but not the first + self.undo_add(self.cur_line - 1, [self.content[self.cur_line - 1], l], 0) + self.col = len(self.content[self.cur_line - 1]) + self.content[self.cur_line - 1] += self.content.pop(self.cur_line) + self.cur_line -= 1 + self.total_lines -= 1 +#endif elif key == KEY_DELETE: - if jut < 0: + if self.mark != None: + self.delete_lines(False) + elif jut < 0: self.undo_add(self.cur_line, [l], KEY_DELETE) self.content[self.cur_line] = l[:self.col] + l[self.col + 1:] elif (self.cur_line + 1) < self.total_lines: ## test for last line @@ -574,8 +586,7 @@ def handle_edit_key(self, key): ## keys which change content self.content[self.cur_line] = l + self.content.pop(self.cur_line + 1) self.total_lines -= 1 elif key == KEY_TAB: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], KEY_INDENT, lrange[1] - lrange[0]) ## undo replaces for i in range(lrange[0],lrange[1]): @@ -588,8 +599,7 @@ def handle_edit_key(self, key): ## keys which change content self.content[self.cur_line] = l[:self.col] + ' ' * ni + l[self.col:] self.col += ni elif key == KEY_BACKTAB: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], KEY_INDENT, lrange[1] - lrange[0]) ## undo replaces for i in range(lrange[0],lrange[1]): @@ -609,13 +619,13 @@ def handle_edit_key(self, key): ## keys which change content #ifndef BASIC elif key == KEY_REPLC: count = 0 - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: rpat = self.line_edit("Replace with: ", self.replc_pattern) if rpat != None: self.replc_pattern = rpat q = '' - if self.mark >= 0: ## Replace in Marked area + if self.mark != None: ## Replace in Marked area lrange = self.line_range() self.cur_line = lrange[0] else: @@ -650,37 +660,27 @@ def handle_edit_key(self, key): ## keys which change content self.total_lines = len(self.content) #endif elif key == KEY_MARK: - if self.mark < 0: - self.mark = self.check_mark = self.cur_line - self.mark_tab = False - else: - self.mark = -1 + self.mark = self.cur_line if self.mark == None else None elif key == KEY_YANK: # delete line or line(s) into buffer - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) ## undo inserts - del self.content[lrange[0]:lrange[1]] - if self.content == []: ## if all was wiped - self.content = [""] - self.total_lines = len(self.content) - self.cur_line = lrange[0] - self.mark = -1 ## unset line mark + if self.mark != None: + self.delete_lines(True) elif key == KEY_DUP: # copy line(s) into buffer - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.mark = -1 ## unset line mark + if self.mark != None: + lrange = self.line_range() + self.yank_buffer = self.content[lrange[0]:lrange[1]] elif key == KEY_ZAP: ## insert buffer if self.yank_buffer: + if self.mark != None: + self.delete_lines(False) self.undo_add(self.cur_line, None, 0, -len(self.yank_buffer)) self.content[self.cur_line:self.cur_line] = self.yank_buffer # insert lines self.total_lines += len(self.yank_buffer) elif key == KEY_WRITE: if False: pass #ifndef BASIC - elif self.mark >= 0: + elif self.mark != None: fname = self.line_edit("Save Mark: ", "") lrange = self.line_range() - self.mark = -1 #endif else: fname = self.fname @@ -724,10 +724,11 @@ def handle_edit_key(self, key): ## keys which change content l += ' ' * jut self.content[self.cur_line] = l[:self.col] + chr(key) + l[self.col:] self.col += 1 + self.mark = None ## unset line mark def edit_loop(self): ## main editing loop - if len(self.content) == 0: ## check for empty content + if self.content == []: ## check for empty content self.content = [""] self.total_lines = len(self.content) self.set_screen_parms() @@ -739,8 +740,6 @@ def edit_loop(self): ## main editing loop self.display_window() ## Update & display window key = self.get_input() ## Get Char of Fct-key code self.message = '' ## clear message - if self.mark_tab and key != KEY_TAB and key != KEY_BACKTAB: - self.mark = -1 if key == KEY_QUIT: if self.changed != ' ': diff --git a/wipye.py b/wipye.py index 882e1ef..ea1b4f8 100644 --- a/wipye.py +++ b/wipye.py @@ -33,20 +33,16 @@ def __init__(self, tab_size, undo_limit): self.case = "n" self.autoindent = "y" self.yank_buffer = [] - self.mark = -1 - self.check_mark = -1 - self.mark_tab = False - self.msg_find = "Find: " + self.mark = None if sys.platform == "WiPy": def wr(self, s): sys.stdout.write(s) def rd(self): while True: try: - ch = sys.stdin.read(1) - if ch != "\x00": - return ch.encode() - except: pass + return sys.stdin.read(1).encode() + except: + pass def init_tty(self, device, baud): pass def deinit_tty(self): @@ -56,10 +52,7 @@ def goto(self, row, col): def clear_to_eol(self): self.wr(b"\x1b[0K") def cursor(self, onoff): - if onoff: - self.wr(b"\x1b[?25h") - else: - self.wr(b"\x1b[?25l") + self.wr(b"\x1b[?25h" if onoff else b"\x1b[?25l") def hilite(self, mode): if mode == 1: self.wr(b"\x1b[1m") @@ -68,10 +61,7 @@ def hilite(self, mode): else: self.wr(b"\x1b[0m") def scroll_region(self, stop): - if stop: - self.wr('\x1b[1;{}r'.format(stop)) - else: - self.wr('\x1b[r') + self.wr('\x1b[1;{}r'.format(stop) if stop else '\x1b[r') def scroll_up(self, scrolling): self.scrbuf[scrolling:] = self.scrbuf[:-scrolling] self.scrbuf[:scrolling] = [''] * scrolling @@ -92,7 +82,7 @@ def set_screen_parms(self): char = self.rd() (self.height, self.width) = [int(i, 10) for i in pos[2:].split(b';')] self.height -= 1 - self.scrbuf = ["\x01"] * self.height + self.scrbuf = [(False,"\x00")] * self.height self.scroll_region(self.height) def get_input(self): while True: @@ -123,23 +113,24 @@ def display_window(self): i = self.top_line for c in range(self.height): if i == self.total_lines: - if self.scrbuf[c] != '': + if self.scrbuf[c][1] != '': self.goto(c, 0) self.clear_to_eol() - self.scrbuf[c] = '' + self.scrbuf[c] = (False,'') else: - l = self.content[i][self.margin:self.margin + self.width] - if l != self.scrbuf[c] or i == self.check_mark: + l = (self.mark != None and ( + (self.mark <= i <= self.cur_line) or (self.cur_line <= i <= self.mark)), + self.content[i][self.margin:self.margin + self.width]) + if l != self.scrbuf[c]: self.goto(c, 0) - if i == self.mark: + if l[0]: self.hilite(2) - self.wr(l) - if l == "": self.wr(' ') + self.wr(l[1]) + if l[1] == '': self.wr(' ') self.hilite(0) else: - self.wr(l) - if i == self.check_mark: self.check_mark = -1 - if len(l) < self.width: + self.wr(l[1]) + if len(l[1]) < self.width: self.clear_to_eol() self.scrbuf[c] = l i += 1 @@ -153,18 +144,11 @@ def display_window(self): self.goto(self.row, self.col - self.margin) self.cursor(True) def spaces(self, line, pos = None): - if pos == None: - return len(line) - len(line.lstrip(" ")) - else: - return len(line[:pos]) - len(line[:pos].rstrip(" ")) + return (len(line) - len(line.lstrip(" ")) if pos == None else + len(line[:pos]) - len(line[:pos].rstrip(" "))) def line_range(self): - if self.mark < 0: - return (self.cur_line, self.cur_line + 1) - else: - if self.mark < self.cur_line: - return (self.mark, self.cur_line + 1) - else: - return (self.cur_line, self.mark + 1) + return ((self.mark, self.cur_line + 1) if self.mark < self.cur_line else + (self.cur_line, self.mark + 1)) def line_edit(self, prompt, default): self.goto(self.height, 0) self.hilite(1) @@ -234,7 +218,7 @@ def handle_cursor_keys(self, key): elif key == 0x19: self.cur_line += self.height elif key == 0x06: - pat = self.line_edit(self.msg_find, self.find_pattern) + pat = self.line_edit("Find: ", self.find_pattern) if pat: self.find_in_file(pat, self.col, self.total_lines) self.row = self.height >> 1 @@ -261,28 +245,40 @@ def undo_add(self, lnum, text, key, span = 1): del self.undo[0] self.undo_zero -= 1 self.undo.append((lnum, span, text, key, self.col)) + def delete_lines(self, yank): + lrange = self.line_range() + if yank: self.yank_buffer = self.content[lrange[0]:lrange[1]] + self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) + del self.content[lrange[0]:lrange[1]] + if self.content == []: + self.content = [""] + self.total_lines = len(self.content) + self.cur_line = lrange[0] + self.mark = None def handle_edit_key(self, key): l = self.content[self.cur_line] if key == 0x0a: + self.mark = None self.undo_add(self.cur_line, [l], 0, 2) self.content[self.cur_line] = l[:self.col] ni = 0 if self.autoindent == "y": ni = min(self.spaces(l), self.col) - r = l.partition("\x23")[0].rstrip() - if r and r[-1] == ':' and self.col >= len(r): - ni += self.tab_size self.cur_line += 1 self.content[self.cur_line:self.cur_line] = [' ' * ni + l[self.col:]] self.total_lines += 1 self.col = ni elif key == 0x08: - if self.col > 0: + if self.mark != None: + self.delete_lines(False) + elif self.col > 0: self.undo_add(self.cur_line, [l], 0x08) self.content[self.cur_line] = l[:self.col - 1] + l[self.col:] self.col -= 1 elif key == 0x7f: - if self.col < len(l): + if self.mark != None: + self.delete_lines(False) + elif self.col < len(l): self.undo_add(self.cur_line, [l], 0x7f) self.content[self.cur_line] = l[:self.col] + l[self.col + 1:] elif (self.cur_line + 1) < self.total_lines: @@ -290,8 +286,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l + self.content.pop(self.cur_line + 1) self.total_lines -= 1 elif key == 0x09: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -303,8 +298,7 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l[:self.col] + ' ' * ni + l[self.col:] self.col += ni elif key == 0x15: - if self.mark >= 0: - self.mark_tab = True + if self.mark != None: lrange = self.line_range() self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0xffff, lrange[1] - lrange[0]) for i in range(lrange[0],lrange[1]): @@ -318,27 +312,18 @@ def handle_edit_key(self, key): self.content[self.cur_line] = l[:self.col - ni] + l[self.col:] self.col -= ni elif key == 0x0c: - if self.mark < 0: - self.mark = self.check_mark = self.cur_line - self.mark_tab = False - else: - self.mark = -1 + self.mark = self.cur_line if self.mark == None else None elif key == 0x18: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.undo_add(lrange[0], self.content[lrange[0]:lrange[1]], 0, 0) - del self.content[lrange[0]:lrange[1]] - if self.content == []: - self.content = [""] - self.total_lines = len(self.content) - self.cur_line = lrange[0] - self.mark = -1 + if self.mark != None: + self.delete_lines(True) elif key == 0x04: - lrange = self.line_range() - self.yank_buffer = self.content[lrange[0]:lrange[1]] - self.mark = -1 + if self.mark != None: + lrange = self.line_range() + self.yank_buffer = self.content[lrange[0]:lrange[1]] elif key == 0x16: if self.yank_buffer: + if self.mark != None: + self.delete_lines(False) self.undo_add(self.cur_line, None, 0, -len(self.yank_buffer)) self.content[self.cur_line:self.cur_line] = self.yank_buffer self.total_lines += len(self.yank_buffer) @@ -376,11 +361,12 @@ def handle_edit_key(self, key): self.total_lines = len(self.content) self.changed = ' ' if len(self.undo) == self.undo_zero else '*' elif key >= 0x20: + self.mark = None self.undo_add(self.cur_line, [l], 0x20 if key == 0x20 else 0x41) self.content[self.cur_line] = l[:self.col] + chr(key) + l[self.col:] self.col += 1 def edit_loop(self): - if len(self.content) == 0: + if self.content == []: self.content = [""] self.total_lines = len(self.content) self.set_screen_parms() @@ -388,8 +374,6 @@ def edit_loop(self): self.display_window() key = self.get_input() self.message = '' - if self.mark_tab and key != 0x09 and key != 0x15: - self.mark = -1 if key == 0x11: if self.changed != ' ': res = self.line_edit("Content changed! Quit without saving (y/N)? ", "N")