def ctrl_d(self): if self.line == '': self.quit = True util.putstr('^D') # no newline, caller handles it. self.stop() else: self.delete_char()
def interrupt(self): 'Handle ^C, exit from Python sesson' # raw mode terminal doesn't respond to ^C, must handle here util.putstr('^C') terminal.set_line_mode() # on new line... print() # ... otherwise traceback is a mess raise KeyboardInterrupt
def backward_delete_last_char(self): if self.point > 0: ch = self.line[-1] self.line = self.line[:-1] self.point -= 1 # util.putstr('^H') # omit, it is more helpful to echo util.putstr('\\%s' % ch) # echo \c where c is deleted char
def put_render(line, column, text, *attributes): """ At line, column, print text with attributes but without newline, then clear attributes. """ put_cursor(line, column) putstr(sgr % attrs(*attributes) + text + sgr % attrs(clear))
def redraw(self): 'redraw line' # Maybe ^L on vt should refresh whole window or even whole frame? display.move_to_column(self.start_col) self.point = len(self.line) util.putstr(self.line) display.kill_line() # remove any leftover text past self.line
def ctrl_z(self): if self.line == '': self.quit = True print('^Z') util.putstr('\rStopped') # still in raw mode, print didn't RET self.stop() else: util.putstr(keyboard.bel) # sound indicates no handler
def restart(self): 'Prepare to collect a line' self.quit = False self.line = '' # empty line at beginning of cycle self.point = 0 # index into self.line at beginning of cycle self.start_col = len(self.prompt())+1 # 1-based indexing, not 0-based util.putstr(self.prompt() + self.line) # line might be empty self.move_to_point() # might not be end of line terminal.set_char_mode()
def discard(self): # name like gnu readline unix-line-discard 'Delete line from start-of-line to point' killed_segment = self.line[:self.point] if killed_segment: # Do not overwrite yank buffer with empty segment self.yank_buffer = killed_segment self.line = self.line[self.point:] self.move_beginning() # accounts for prompt, assigns point util.putstr(self.line) display.kill_line() # remove any leftover text past self.line self.move_beginning() # replace cursor again
def main(): c = line = '' set_char_mode() # enter single character more putstr('> ') while not c == '\r': c = getchar() putstr(c) line += c set_line_mode() # return to normal mode print() print(line)
def main(): 'Demonstrate Key class' key = Key() util.putstr('> ') terminal.set_char_mode() line = '' k = '' # anything but cr while k != keyboard.cr: k = key() line += k util.putstr(k) terminal.set_line_mode() print() print([ c for c in line ]) # show any esc or other unprintables
def handle_key(self, keycode): 'Call this handle_key as handler when keycode is already available' # keycode might be single character or a sequence of characters. # Printable keys require special-case handling, # because their method takes an additional argument: the key itself. if keycode in printing_chars: method = self.keymap()[printable] method(keycode) elif keycode in self.keymap(): method = self.keymap()[keycode] method() elif keycode: util.putstr(keyboard.bel) # sound indicates no handler else: pass # incomplete or unrecognized keycode, do nothing
def main(): import terminal # only needed for this test def edit(): 'event loop for testing inputline' while True: # reads single chars, arrow keys won't work key = terminal.getchar() if key in printing_chars or key in command.keymap: command.handler(key) else: break print('Enter and edit a fresh line:') util.putstr(command.prompt) terminal.set_char_mode() # inputline event loop edit() # based on Console restore method terminal.set_line_mode() print() # advance to next line command.redraw() # echo so we can see what we edited print() # Caller can reassign prompt, line to edit, and point print('Now edit a previously entered line:') command.reinit(prompt='>> ', line='Here is some text to edit.', point=0) util.putstr(command.prompt) # command.redraw() # no good - resets point util.putstr(command.line) # preserves point command.move_to_point() # restore cursor to point terminal.set_char_mode() edit() terminal.set_line_mode() print() print(command.line)
def render(text, *attributes): """ Print text with one or more attributes, each given by separate int arg, then clear attributes, but do not print newline. """ putstr(sgr % attrs(*attributes) + text + sgr % attrs(clear))
def insert_char(key): 'Insert character in front of cursor' putstr((ich % 1) + key) # open space to insert char
def insert_string(string): putstr((ich % len(string)) + string)
def forward_char(): putstr(cuf) # move just one char
def redraw_with_prefix(self, prefix): 'redraw entire line with prefix and prompt on printing terminal' util.putstr(prefix + self.prompt()) self.redraw()
def kill_whole_line(): 'Erase entire line' putstr(el_all)
def put_cursor(line, column): # not in emacs or gnu readline putstr(cup % (line, column))
def erase(): # erase_display in gnu readline putstr(ed)
def move_to_column(column): putstr(cha % column)
def backward_char(): putstr(cub)
def next_line(): 'replacement for print() in terminal char mode, explicitly sends \n\r' putstr('\n\r')
def set_scroll(ltop, lbottom): 'Set scrolling region to lines ltop through lbottom (line numbers)' putstr(decstbm % (ltop, lbottom))
def redraw(self): 'Refresh line' display.move_to_column(self.start_col) self.point = len(self.line) util.putstr(self.line) display.kill_line() # remove any leftover text past self.line
def set_scroll_all(): 'Set scrolling region to entire display' putstr(decstbmn)
def status(self): '^T handler, can override this method with custom handlers in subclasses' util.putstr(' '.join(sys.argv)) # just echo the command line for now
def delete_char(): 'Delete character under the cursor' putstr(dch % 1)
def kill_line(): 'Erase from cursor to end of line' putstr(el_end)
def backward_delete_char(): 'Delete character before cursor' putstr(cub + dch % 1)