def flush(self): self.finish_wrapping() term.home_cursor() buf = self.textBuf for i in range(len(buf)): for j in range(len(buf[i])): c = buf[i][j] write_char(c.char, c.fg_color, c.bg_color, c.text_style) if i < len(buf) - 1: write_char('\n', c.fg_color, c.bg_color, c.text_style) else: term.fill_to_eol_with_bg_color() term.flush()
def first_draw(self): env = self.env for i in range(env.hdr.screen_height_units - 1): write_char('\n', env.fg_color, env.bg_color, env.text_style) term.fill_to_eol_with_bg_color() term.home_cursor()
def get_line_of_input(self, prompt='', prefilled=''): env = self.env for c in prompt: self.write_unwrapped( [ScreenChar(c, env.fg_color, env.bg_color, env.text_style)]) self.flush() self.update_seen_lines() row, col = env.cursor[env.current_window] term.home_cursor() term.cursor_down(row) term.cursor_right(col) term.set_color(env.fg_color, env.bg_color) if line_empty(self.textBuf[row][col:]): term.fill_to_eol_with_bg_color() term.show_cursor() col = max( 0, col - len(prefilled) ) # TODO: prefilled is a seldom-used old and crusty feature, but make unicode safe env.cursor[env.current_window] = row, col class CursorLine(object): def __init__(self, cursor_start, chars): self.cursor = cursor_start self.chars = chars def backspace(self): if self.cursor == 0: return self.left() self.delete_char() def delete_char(self): del self.chars[self.cursor:self.cursor + 1] self.refresh_rest_of_line(is_delete=True) def refresh_rest_of_line(self, is_delete=False): rest = self.chars[self.cursor:] term.puts(''.join(rest)) to_back_up = len(rest) if is_delete: term.puts(' ') to_back_up += 1 if to_back_up: term.cursor_left(to_back_up) def left(self): if self.cursor > 0: self.cursor -= 1 term.cursor_left() def right(self): if self.cursor < len(self.chars): self.cursor += 1 term.cursor_right() def home(self): while self.cursor > 0: self.left() def end(self): while self.cursor != len(self.chars): self.right() def kill_left(self): while self.chars[:self.cursor]: self.backspace() def kill_right(self): while self.chars[self.cursor:]: self.delete_char() def insert(self, c): self.chars.insert(self.cursor, c) term.puts(c) self.cursor += 1 self.refresh_rest_of_line() cursor_start = len(prefilled) cursor_line = CursorLine(cursor_start, [c for c in prefilled]) max_input_len = 120 # 120 char limit seen on gargoyle c = term.getch_or_esc_seq() while c != '\n' and c != '\r': if c == '\b' or c == '\x7f': cursor_line.backspace() # normal edit keys and a bit of readline flavor # left arrow or C-b elif c == '\x1b[D' or c == '\x02': cursor_line.left() # right arrow or C-f elif c == '\x1b[C' or c == '\x06': cursor_line.right() # home or C-a elif c == '\x1b[H' or c == '\x01': cursor_line.home() # end or C-e elif c == '\x1b[F' or c == '\x05': cursor_line.end() # delete or C-d elif c == '\x1b[3~' or c == '\x04': cursor_line.delete_char() # C-u, kill left of cursor elif c == '\x15': cursor_line.kill_left() # C-u, kill right of cursor elif c == '\x0b': cursor_line.kill_right() else: if is_valid_inline_char(c) and len( cursor_line.chars) < max_input_len: if c == '\t': if len(cursor_line.chars) + 4 <= max_input_len: for i in range(4): cursor_line.insert(' ') else: cursor_line.insert(c) c = term.getch_or_esc_seq() term.hide_cursor() term.flush() for c in cursor_line.chars: self.write_unwrapped( [ScreenChar(c, env.fg_color, env.bg_color, env.text_style)]) self.new_line_via_spaces(env.fg_color, env.bg_color, env.text_style) term.home_cursor() return ''.join(cursor_line.chars)
def overwrite_line_with(self, new_line): term.clear_line() for c in new_line: write_char(c.char, c.fg_color, c.bg_color, c.text_style) term.fill_to_eol_with_bg_color()