def __init__(self): self.progress = itertools.cycle('|/-\\') self.gathering = 'Gathering output...' with pager.nopager(): with redirect.nolog(): sys.stdout.write('\r' + self.gathering) self.sio = StringIO()
def ttypager(text): """Page through text on a text terminal.""" lines = string.split(plain(text), '\n') if redirect.state != redirect.NOLOG_STATE: with redirect.logonly(): sys.stdout.write(string.join(lines, '\n') + '\n') if redirect.state == redirect.LOGONLY_STATE: return with pager.nopager(): with redirect.nolog(): height = min(bits.get_width_height(term)[1] for term in range(bits.get_term_count())) r = inc = height - 1 sys.stdout.write(string.join(lines[:inc], '\n') + '\n') while True: if lines[r:]: prompt = '-- any key to advance; PgUp to page up; q to quit --' else: prompt = '-- END; PgUp to page up; q to quit --' prompt_len = len(prompt) sys.stdout.write(prompt) c = bits.get_key() # Write the spaces one at a time to defeat word-wrap sys.stdout.write('\r') for i in range(prompt_len): sys.stdout.write(' ') sys.stdout.write('\r') if c in (ord('q'), ord('Q')): break elif c in (ord('\r'), ord('\n'), bits.KEY_DOWN, bits.MOD_CTRL | ord('n')): if lines[r:]: sys.stdout.write(lines[r] + '\n') r = r + 1 continue if c == bits.KEY_HOME: bits.clear_screen() r = 0 if c == bits.KEY_END: bits.clear_screen() r = len(lines) - inc if r < 0: r = 0 if c in (bits.KEY_UP, bits.MOD_CTRL | ord('p')): bits.clear_screen() r = r - 1 - inc if r < 0: r = 0 if c in (bits.KEY_PAGE_UP, ord('b'), ord('B')): bits.clear_screen() r = r - inc - inc if r < 0: r = 0 if lines[r:]: sys.stdout.write(string.join(lines[r:r+inc], '\n') + '\n') r = r + inc if not lines[r:]: r = len(lines)
def _readline(prompt=""): global width, height, line_x, line_y, buffer_max, history, ctrl_o_index, completer with redirect.nolog(): with pager.nopager(): sys.stdout.write(prompt) line_buffer = '' pos = 0 prev_len = 0 term_count = bits.get_term_count() width = [0] * term_count height = [0] * term_count line_x = [0] * term_count line_y = [0] * term_count for term in range(term_count): width[term], height[term] = bits.get_width_height(term) line_x[term], line_y[term] = bits.get_xy(term) buffer_max = min((width[term] - 2 - line_x[term]) + ((height[term] - 1) * (width[term] - 1)) for term in range(term_count)) history_index = len(history) history_state = dict() completer_state = 0 if ctrl_o_index is not None: if ctrl_o_index < len(history): history_index = ctrl_o_index line_buffer = history[history_index] pos = len(line_buffer) ctrl_o_index = None while True: # Update history history_state[history_index] = (line_buffer, pos) try: # clear any characters after the current line buffer trailing_len = prev_len - len(line_buffer) if trailing_len > 0: for term in range(term_count): trailing_x, trailing_y = PositionCursor(len(line_buffer), line_x[term], line_y[term], term) print_buffer(" " * trailing_len, trailing_x, trailing_y, term) prev_len = len(line_buffer) for term in range(term_count): # print the current line buffer print_buffer(line_buffer, line_x[term], line_y[term], term) # move the cursor to location of pos within the line buffer PositionCursor(pos, line_x[term], line_y[term], term) c = bits.get_key() def ctrl(k): return bits.MOD_CTRL | ord(k) if c == ord('\r') or c == ord('\n') or c == ctrl('o'): if line_buffer or (history and history[-1]): history.append(line_buffer) if c == ctrl('o'): # Ctrl-O ctrl_o_index = history_index + 1 sys.stdout.write('\n') return line_buffer + '\n' if not (c == ord('\t') or c == ctrl('i')): # reset completer state to force restart of the completer completer_state = 0 if c == bits.KEY_HOME or c == ctrl('a'): # start of line pos = 0 elif c == bits.KEY_LEFT or c == ctrl('b'): # left if pos != 0: pos -= 1 elif c == ctrl('d'): # EOF if len(line_buffer) == 0: return "" if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == bits.KEY_DELETE: if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == bits.KEY_END or c == ctrl('e'): # end of line pos = len(line_buffer) elif c == bits.KEY_RIGHT or c == ctrl('f'): # right if pos != len(line_buffer): pos += 1 elif c == ord('\b') or c == ctrl('h'): # backspace line_buffer, pos = delete_char_left(line_buffer, pos) elif c == ord('\t') or c == ctrl('i'): # tab completion if completer is not None: if completer_state != 0: for c in range(len(current_completion)): line_buffer, pos = delete_char_left(line_buffer, pos) else: cur = pos while pos != 0 and line_buffer[pos-1] != ' ': pos -= 1 saved_str = line_buffer[pos:cur] line_buffer = line_buffer[:pos] + line_buffer[cur:] current_completion = completer(saved_str, completer_state) completer_state += 1 if current_completion is not None: for c in current_completion: line_buffer, pos = insert_char(line_buffer, c, pos) else: for c in saved_str: line_buffer, pos = insert_char(line_buffer, c, pos) completer_state = 0 elif c == ctrl('k'): # delete from current to end of line line_buffer = line_buffer[:pos] elif c == ctrl('l'): # clear screen bits.clear_screen() sys.stdout.write(prompt) for term in range(term_count): line_x[term], line_y[term] = bits.get_xy(term); elif c == bits.KEY_DOWN or c == ctrl('n'): # Next line in history if history_index < len(history): history_index += 1 if history_index == len(history): line_buffer, pos = history_state.get(history_index) else: line_buffer, pos = history_state.get(history_index, (history[history_index], len(history[history_index]))) elif c == bits.KEY_UP or c == ctrl('p'): # Previous line in history if history_index > 0: history_index -= 1 line_buffer, pos = history_state.get(history_index, (history[history_index], len(history[history_index]))) elif c == ctrl('u'): # delete from current to beginning of line line_buffer = line_buffer[pos:] pos = 0 elif c == ctrl('w'): # delete previous word cur = pos while pos != 0 and line_buffer[pos-1] == ' ': pos -= 1 while pos != 0 and line_buffer[pos-1] != ' ': pos -= 1 line_buffer = line_buffer[:pos] + line_buffer[cur:] elif c == ctrl('z') or c == bits.KEY_ESC: if len(line_buffer) == 0: return "" elif c in key_hooks: key_hooks[c]() elif c < 256 and chr(c) in string.printable: # printable line_buffer, pos = insert_char(line_buffer, chr(c), pos) else: pass except IOError: pass
def ttypager(text): """Page through text on a text terminal.""" try: import efi efi_options = ["f to write file"] except ImportError as e: efi_options = [] lines = string.split(plain(text), '\n') if redirect.state != redirect.NOLOG_STATE: with redirect.logonly(): sys.stdout.write(string.join(lines, '\n') + '\n') if redirect.state == redirect.LOGONLY_STATE: return with pager.nopager(): with redirect.nolog(): height = min(bits.get_width_height(term)[1] for term in range(bits.get_term_count())) r = inc = height - 1 sys.stdout.write(string.join(lines[:inc], '\n') + '\n') while True: if lines[r:]: advance = ['any key to advance'] else: advance = ['END'] if r > inc: back = ["Up/PgUp to go back"] else: back = [] options = "; ".join(advance + back + efi_options + ["q to quit"]) prompt = '-- {} --'.format(options) prompt_len = len(prompt) sys.stdout.write(prompt) c = bits.get_key() # Write the spaces one at a time to defeat word-wrap sys.stdout.write('\r') for i in range(prompt_len): sys.stdout.write(' ') sys.stdout.write('\r') if efi_options and c in (ord('f'), ord('F')): ttydir = efi.get_boot_fs() filepath = os.path.normpath(str.strip(readline._readline("filename: "), "\n")) basepath, fname = os.path.split(filepath) for dirname in str.split(basepath, os.sep): if dirname is not "": ttydir = ttydir.mkdir(dirname) print "Saving {}...".format(filepath), ttydir.create(fname).write(string.join(lines, '\n') + '\n') print "Done" print "Hit any key to continue..." c = bits.get_key() if c in (ord('q'), ord('Q')): break elif c in (ord('\r'), ord('\n'), bits.KEY_DOWN, bits.MOD_CTRL | ord('n')): if lines[r:]: sys.stdout.write(lines[r] + '\n') r = r + 1 continue if c == bits.KEY_HOME: bits.clear_screen() r = 0 if c == bits.KEY_END: bits.clear_screen() r = len(lines) - inc if r < 0: r = 0 if c in (bits.KEY_UP, bits.MOD_CTRL | ord('p')): bits.clear_screen() r = r - 1 - inc if r < 0: r = 0 if c in (bits.KEY_PAGE_UP, ord('b'), ord('B')): bits.clear_screen() r = r - inc - inc if r < 0: r = 0 if lines[r:]: sys.stdout.write(string.join(lines[r:r+inc], '\n') + '\n') r = r + inc if not lines[r:]: r = len(lines)
def _readline(prompt=""): global width, height, line_x, line_y, buffer_max, history, kill_ring, kill_accumulate, ctrl_o_index, completer with redirect.nolog(): with pager.nopager(): sys.stdout.write(prompt) line_buffer = '' pos = 0 prev_len = 0 term_count = bits.get_term_count() width = [0] * term_count height = [0] * term_count line_x = [0] * term_count line_y = [0] * term_count for term in range(term_count): width[term], height[term] = bits.get_width_height(term) line_x[term], line_y[term] = bits.get_xy(term) buffer_max = min((width[term] - 2 - line_x[term]) + ((height[term] - 1) * (width[term] - 1)) for term in range(term_count)) history_index = len(history) history_state = dict() completer_state = 0 last_yank_start = None kill_accumulate = False if ctrl_o_index is not None: if ctrl_o_index < len(history): history_index = ctrl_o_index line_buffer = history[history_index] pos = len(line_buffer) ctrl_o_index = None while True: # Update history history_state[history_index] = (line_buffer, pos) try: # clear any characters after the current line buffer trailing_len = prev_len - len(line_buffer) if trailing_len > 0: for term in range(term_count): trailing_x, trailing_y = PositionCursor(len(line_buffer), line_x[term], line_y[term], term) print_buffer(" " * trailing_len, trailing_x, trailing_y, term) prev_len = len(line_buffer) for term in range(term_count): # print the current line buffer print_buffer(line_buffer, line_x[term], line_y[term], term) # move the cursor to location of pos within the line buffer PositionCursor(pos, line_x[term], line_y[term], term) c = bits.input.get_key() key = bits.input.key def ctrl(k): return key(k, ctrl=True) # Reset states that depend on last key if c != key('y', alt=True): last_yank_start = None if c not in (ctrl('k'), ctrl('u'), ctrl('w')): kill_accumulate = False if c == key('\r') or c == key('\n') or c == ctrl('o'): if line_buffer or (history and history[-1]): history.append(line_buffer) if c == ctrl('o'): # Ctrl-O ctrl_o_index = history_index + 1 sys.stdout.write('\n') return line_buffer + '\n' if not (c == key('\t') or c == ctrl('i')): # reset completer state to force restart of the completer completer_state = 0 if c == key(bits.input.KEY_HOME) or c == ctrl('a'): # start of line pos = 0 elif c == key(bits.input.KEY_LEFT) or c == ctrl('b'): # left if pos != 0: pos -= 1 elif c == ctrl('d'): # EOF if len(line_buffer) == 0: return "" if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == key(bits.input.KEY_DELETE): if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == key(bits.input.KEY_END) or c == ctrl('e'): # end of line pos = len(line_buffer) elif c == key(bits.input.KEY_RIGHT) or c == ctrl('f'): # right if pos != len(line_buffer): pos += 1 elif c == key('\b') or c == ctrl('h'): # backspace line_buffer, pos = delete_char_left(line_buffer, pos) elif c == key('\t') or c == ctrl('i'): # tab completion if completer is not None: if completer_state != 0: for c in range(len(current_completion)): line_buffer, pos = delete_char_left(line_buffer, pos) else: cur = pos while pos != 0 and line_buffer[pos-1] != ' ': pos -= 1 saved_str = line_buffer[pos:cur] line_buffer = line_buffer[:pos] + line_buffer[cur:] current_completion = completer(saved_str, completer_state) completer_state += 1 if current_completion is not None: for c in current_completion: line_buffer, pos = insert_char(line_buffer, c, pos) else: for c in saved_str: line_buffer, pos = insert_char(line_buffer, c, pos) completer_state = 0 elif c == ctrl('k'): # delete from current to end of line killed_text = line_buffer[pos:] line_buffer = line_buffer[:pos] add_to_kill_ring(killed_text, to_right=True) elif c == ctrl('l'): # clear screen bits.clear_screen() sys.stdout.write(prompt) for term in range(term_count): line_x[term], line_y[term] = bits.get_xy(term); elif c == key(bits.input.KEY_DOWN) or c == ctrl('n'): # Next line in history if history_index < len(history): history_index += 1 if history_index == len(history): line_buffer, pos = history_state.get(history_index, ('', 0)) else: line_buffer, pos = history_state.get(history_index, (history[history_index], len(history[history_index]))) elif c == key(bits.input.KEY_UP) or c == ctrl('p'): # Previous line in history if history_index > 0: history_index -= 1 line_buffer, pos = history_state.get(history_index, (history[history_index], len(history[history_index]))) elif c == ctrl('u'): # delete from current to beginning of line killed_text = line_buffer[:pos] line_buffer = line_buffer[pos:] pos = 0 add_to_kill_ring(killed_text, to_right=False) elif c == ctrl(bits.input.KEY_LEFT): # Move left by word while pos != 0 and not line_buffer[pos-1].isalnum(): pos -= 1 while pos != 0 and line_buffer[pos-1].isalnum(): pos -= 1 elif c == ctrl(bits.input.KEY_RIGHT): # Move right by word end = len(line_buffer) while pos != end and not line_buffer[pos].isalnum(): pos += 1 while pos != end and line_buffer[pos].isalnum(): pos += 1 elif c == ctrl('w'): # delete previous word; note that this uses a different # definition of "word" than Ctrl-Left and Ctrl-Right. cur = pos while pos != 0 and line_buffer[pos-1] == ' ': pos -= 1 while pos != 0 and line_buffer[pos-1] != ' ': pos -= 1 killed_text = line_buffer[pos:cur] line_buffer = line_buffer[:pos] + line_buffer[cur:] add_to_kill_ring(killed_text, to_right=False) elif c == ctrl('y'): # Yank if kill_ring: line_buffer, last_yank_start, pos = insert_string(line_buffer, kill_ring[-1], pos) elif c == key('y', alt=True): # If immediately after yank, rotate kill ring and yank # the new top instead. if last_yank_start is not None: line_buffer = line_buffer[:last_yank_start] + line_buffer[pos:] pos = last_yank_start kill_ring.insert(0, kill_ring.pop()) # Rotate line_buffer, last_yank_start, pos = insert_string(line_buffer, kill_ring[-1], pos) elif c == ctrl('z') or c == key(bits.input.KEY_ESC): if len(line_buffer) == 0: return "" elif c.key in key_hooks: key_hooks[c.key]() elif not(c.ctrl) and not(c.alt) and isinstance(c.key, basestring) and c.key in string.printable: # printable try: line_buffer, pos = insert_char(line_buffer, c.key.encode('ascii'), pos) except UnicodeError: pass else: pass except IOError: pass
def _readline(prompt=""): global width, height, line_x, line_y, buffer_max, history, kill_ring, kill_accumulate, ctrl_o_index, completer with redirect.nolog(): with pager.nopager(): sys.stdout.write(prompt) line_buffer = '' pos = 0 prev_len = 0 term_count = bits.get_term_count() width = [0] * term_count height = [0] * term_count line_x = [0] * term_count line_y = [0] * term_count for term in range(term_count): width[term], height[term] = bits.get_width_height(term) line_x[term], line_y[term] = bits.get_xy(term) buffer_max = min((width[term] - 2 - line_x[term]) + ((height[term] - 1) * (width[term] - 1)) for term in range(term_count)) history_index = len(history) history_state = dict() completer_state = 0 last_yank_start = None kill_accumulate = False if ctrl_o_index is not None: if ctrl_o_index < len(history): history_index = ctrl_o_index line_buffer = history[history_index] pos = len(line_buffer) ctrl_o_index = None while True: # Update history history_state[history_index] = (line_buffer, pos) try: # clear any characters after the current line buffer trailing_len = prev_len - len(line_buffer) if trailing_len > 0: for term in range(term_count): trailing_x, trailing_y = PositionCursor( len(line_buffer), line_x[term], line_y[term], term) print_buffer(" " * trailing_len, trailing_x, trailing_y, term) prev_len = len(line_buffer) for term in range(term_count): # print the current line buffer print_buffer(line_buffer, line_x[term], line_y[term], term) # move the cursor to location of pos within the line buffer PositionCursor(pos, line_x[term], line_y[term], term) c = bits.input.get_key() key = bits.input.key def ctrl(k): return key(k, ctrl=True) # Reset states that depend on last key if c != key('y', alt=True): last_yank_start = None if c not in (ctrl('k'), ctrl('u'), ctrl('w')): kill_accumulate = False if c == key('\r') or c == key('\n') or c == ctrl('o'): if line_buffer or (history and history[-1]): history.append(line_buffer) if c == ctrl('o'): # Ctrl-O ctrl_o_index = history_index + 1 sys.stdout.write('\n') return line_buffer + '\n' if not (c == key('\t') or c == ctrl('i')): # reset completer state to force restart of the completer completer_state = 0 if c == key(bits.input.KEY_HOME) or c == ctrl('a'): # start of line pos = 0 elif c == key(bits.input.KEY_LEFT) or c == ctrl('b'): # left if pos != 0: pos -= 1 elif c == ctrl('d'): # EOF if len(line_buffer) == 0: return "" if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == key(bits.input.KEY_DELETE): if pos < len(line_buffer): line_buffer, pos = delete_char(line_buffer, pos) elif c == key(bits.input.KEY_END) or c == ctrl('e'): # end of line pos = len(line_buffer) elif c == key(bits.input.KEY_RIGHT) or c == ctrl('f'): # right if pos != len(line_buffer): pos += 1 elif c == key('\b') or c == ctrl('h'): # backspace line_buffer, pos = delete_char_left(line_buffer, pos) elif c == key('\t') or c == ctrl('i'): # tab completion if completer is not None: if completer_state != 0: for c in range(len(current_completion)): line_buffer, pos = delete_char_left( line_buffer, pos) else: cur = pos while pos != 0 and line_buffer[pos - 1] != ' ': pos -= 1 saved_str = line_buffer[pos:cur] line_buffer = line_buffer[:pos] + line_buffer[ cur:] current_completion = completer( saved_str, completer_state) completer_state += 1 if current_completion is not None: for c in current_completion: line_buffer, pos = insert_char( line_buffer, c, pos) else: for c in saved_str: line_buffer, pos = insert_char( line_buffer, c, pos) completer_state = 0 elif c == ctrl('k'): # delete from current to end of line killed_text = line_buffer[pos:] line_buffer = line_buffer[:pos] add_to_kill_ring(killed_text, to_right=True) elif c == ctrl('l'): # clear screen bits.clear_screen() sys.stdout.write(prompt) for term in range(term_count): line_x[term], line_y[term] = bits.get_xy(term) elif c == key(bits.input.KEY_DOWN) or c == ctrl('n'): # Next line in history if history_index < len(history): history_index += 1 if history_index == len(history): line_buffer, pos = history_state.get( history_index, ('', 0)) else: line_buffer, pos = history_state.get( history_index, (history[history_index], len(history[history_index]))) elif c == key(bits.input.KEY_UP) or c == ctrl('p'): # Previous line in history if history_index > 0: history_index -= 1 line_buffer, pos = history_state.get( history_index, (history[history_index], len(history[history_index]))) elif c == ctrl('u'): # delete from current to beginning of line killed_text = line_buffer[:pos] line_buffer = line_buffer[pos:] pos = 0 add_to_kill_ring(killed_text, to_right=False) elif c == ctrl(bits.input.KEY_LEFT): # Move left by word while pos != 0 and not line_buffer[pos - 1].isalnum(): pos -= 1 while pos != 0 and line_buffer[pos - 1].isalnum(): pos -= 1 elif c == ctrl(bits.input.KEY_RIGHT): # Move right by word end = len(line_buffer) while pos != end and not line_buffer[pos].isalnum(): pos += 1 while pos != end and line_buffer[pos].isalnum(): pos += 1 elif c == ctrl('w'): # delete previous word; note that this uses a different # definition of "word" than Ctrl-Left and Ctrl-Right. cur = pos while pos != 0 and line_buffer[pos - 1] == ' ': pos -= 1 while pos != 0 and line_buffer[pos - 1] != ' ': pos -= 1 killed_text = line_buffer[pos:cur] line_buffer = line_buffer[:pos] + line_buffer[cur:] add_to_kill_ring(killed_text, to_right=False) elif c == ctrl('y'): # Yank if kill_ring: line_buffer, last_yank_start, pos = insert_string( line_buffer, kill_ring[-1], pos) elif c == key('y', alt=True): # If immediately after yank, rotate kill ring and yank # the new top instead. if last_yank_start is not None: line_buffer = line_buffer[: last_yank_start] + line_buffer[ pos:] pos = last_yank_start kill_ring.insert(0, kill_ring.pop()) # Rotate line_buffer, last_yank_start, pos = insert_string( line_buffer, kill_ring[-1], pos) elif c == ctrl('z') or c == key(bits.input.KEY_ESC): if len(line_buffer) == 0: return "" elif c.key in key_hooks: key_hooks[c.key]() elif not (c.ctrl) and not (c.alt) and isinstance( c.key, basestring) and c.key in string.printable: # printable try: line_buffer, pos = insert_char( line_buffer, c.key.encode('ascii'), pos) except UnicodeError: pass else: pass except IOError: pass
def getvalue(self): with pager.nopager(): with redirect.nolog(): sys.stdout.write('\r' + ' ' * (len(self.gathering) + 1) + '\r') return self.sio.getvalue()
def write(self, s): with pager.nopager(): with redirect.nolog(): sys.stdout.write('\r' + self.gathering + self.progress.next()) self.sio.write(s)
def ttypager(text): """Page through text on a text terminal.""" try: import efi import readline efi_options = ["f to write file"] except ImportError as e: efi_options = [] lines = string.split(plain(text), '\n') if redirect.state != redirect.NOLOG_STATE: with redirect.logonly(): sys.stdout.write(string.join(lines, '\n') + '\n') if redirect.state == redirect.LOGONLY_STATE: return with pager.nopager(): with redirect.nolog(): height = min(bits.get_width_height(term)[1] for term in range(bits.get_term_count())) r = inc = height - 1 sys.stdout.write(string.join(lines[:inc], '\n') + '\n') while True: if lines[r:]: advance = ['any key to advance'] else: advance = ['END'] if r > inc: back = ["Up/PgUp to go back"] else: back = [] options = "; ".join(advance + back + efi_options + ["q to quit"]) prompt = '-- {} --'.format(options) prompt_len = len(prompt) sys.stdout.write(prompt) c = bits.input.get_key() key = bits.input.key # Write the spaces one at a time to defeat word-wrap sys.stdout.write('\r') for i in range(prompt_len): sys.stdout.write(' ') sys.stdout.write('\r') if efi_options and c in (key('f'), key('F')): ttydir = efi.get_boot_fs() filepath = os.path.normpath(str.strip(readline._readline("filename: "), "\n")) basepath, fname = os.path.split(filepath) for dirname in str.split(basepath, os.sep): if dirname is not "": ttydir = ttydir.mkdir(dirname) print "Saving {}...".format(filepath), ttydir.create(fname).write(string.join(lines, '\n') + '\n') print "Done" print "Hit any key to continue..." c = bits.input.get_key() if c in (key('q'), key('Q')): break elif c in (key('\r'), key('\n'), key(bits.input.KEY_DOWN), key('n', ctrl=True)): if lines[r:]: sys.stdout.write(lines[r] + '\n') r = r + 1 continue if c == key(bits.input.KEY_HOME): bits.clear_screen() r = 0 if c == key(bits.input.KEY_END): bits.clear_screen() r = len(lines) - inc if r < 0: r = 0 if c in (key(bits.input.KEY_UP), key('p', ctrl=True)): bits.clear_screen() r = r - 1 - inc if r < 0: r = 0 if c in (key(bits.input.KEY_PAGE_UP), key('b'), key('B')): bits.clear_screen() r = r - inc - inc if r < 0: r = 0 if lines[r:]: sys.stdout.write(string.join(lines[r:r+inc], '\n') + '\n') r = r + inc if not lines[r:]: r = len(lines)