我们从Python开源项目中,提取了以下36个代码示例,用于说明如何使用curses.A_REVERSE。
def __init__(self, username): os.environ.setdefault('ESCDELAY', '25') # shorten esc delay self.username = username # set up IRC self.channel = "##HTP" # set up curses self.scr = curses.initscr() self.disconnect = False curses.start_color() self.scr_height, self.scr_width = self.scr.getmaxyx() self.chatbar = curses.newwin(5, self.scr_height - 1, 5, 10) self.msg_text = '' self.logfile = '../data/irc.txt' self.log_text = [] # curses color config curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_GREEN) # start the client try: curses.wrapper(self.start_loop()) except Exception as e: self.scr.addstr(2, 0, str(e), curses.A_REVERSE) # client game loop
def start_editor(self): try: # draw the top bar top_bar = 'Editing ' + self.file.name + ' [press Ctrl+G to save and close]' i = len(top_bar) while i < self.scr_width: top_bar += ' ' i += 1 self.scr.addstr(0, 0, top_bar, curses.A_REVERSE) self.scr.refresh() # let the user edit th efile box = Textbox(self.text_win) box.edit() # get the file contents self.file_text = box.gather() finally: # return to the game curses.endwin() gc.clear() self.file.content = self.file_text
def refresh_line(self, line, *, no_refresh=False): if self.invalidate: self.refresh() return if len(self.logic.get_order()) == 0: return max_y, max_x = self.stdscr.getmaxyx() row = line - self.top if row < 0 or row >= max_y: return bit = self.logic.get_order()[line] if hasattr(self.logic, "get_line"): title = self.logic.get_line(bit, max_x - _INDICATOR_OFFSET * 2) else: title = bit[:max_x - _INDICATOR_OFFSET * 2] if line == self.active: self.stdscr.addstr(row, 0, "> ", curses.A_REVERSE) self.stdscr.addstr(row, _INDICATOR_OFFSET, title, curses.A_REVERSE) self.stdscr.chgat(row, 0, curses.A_REVERSE) else: self.stdscr.addstr(row, _INDICATOR_OFFSET, title) self.stdscr.chgat(row, 0, curses.A_NORMAL) if not no_refresh: self.stdscr.refresh()
def refresh(self): global _INDICATOR_OFFSET self.invalidate = False self.stdscr.clear() max_y, max_x = self.stdscr.getmaxyx() max_y -= 2 self.refresh_status(no_refresh=True) if len(self.logic.get_order()) == 0: self.stdscr.addstr(0, 0, "> ", curses.A_REVERSE) self.stdscr.chgat(0, 0, curses.A_REVERSE) self.stdscr.addstr(0, _INDICATOR_OFFSET, "<no data>", curses.A_REVERSE) return for y in range(0, max_y): if y + self.top >= len(self.logic.get_order()): break self.refresh_line(y + self.top, no_refresh=True) self.stdscr.refresh()
def tick(self, scr, steps): height, width = scr.getmaxyx() if self.advances(steps): # if window was resized and char is out of bounds, reset self.out_of_bounds_reset(width, height) # make previous char curses.A_NORMAL if USE_COLORS: scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_NORMAL)) else: scr.addstr(self.y, self.x, self.char, curses.A_NORMAL) # choose new char and draw it A_REVERSE if not out of bounds self.char = random.choice(FallingChar.matrixchr).encode(encoding) self.y += 1 if not self.out_of_bounds_reset(width, height): if USE_COLORS: scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_HIGHLIGHT)) else: scr.addstr(self.y, self.x, self.char, curses.A_REVERSE)
def draw_frame(self, scr, x1, y1, x2, y2, attrs, clear_char=None): if USE_COLORS: if attrs == curses.A_REVERSE: attrs = curses.color_pair(COLOR_WINDOW) h, w = scr.getmaxyx() for y in (y1, y2): for x in range(x1, x2+1): if x < 0 or x > w-1 or y < 0 or y > h-2: continue if clear_char is None: scr.chgat(y, x, 1, attrs) else: scr.addstr(y, x, clear_char, attrs) for x in (x1, x2): for y in range(y1, y2+1): if x < 0 or x > w-1 or y < 0 or y > h-2: continue if clear_char is None: scr.chgat(y, x, 1, attrs) else: scr.addstr(y, x, clear_char, attrs) # we don't need a good PRNG, just something that looks a bit random.
def __init__(self): self._colors = { 'white': curses.color_pair(self.PAIRS['white']), 'black': curses.color_pair(self.PAIRS['white']) | curses.A_REVERSE, 'red': curses.color_pair(self.PAIRS['red']), 'blue': curses.color_pair(self.PAIRS['blue']), 'green': curses.color_pair(self.PAIRS['green']), 'green_reverse': (curses.color_pair(self.PAIRS['green']) | curses.A_REVERSE), 'cyan': curses.color_pair(self.PAIRS['cyan']), 'cyan_reverse': (curses.color_pair(self.PAIRS['cyan']) | curses.A_REVERSE), 'yellow': curses.color_pair(self.PAIRS['yellow']), 'yellow_reverse': (curses.color_pair(self.PAIRS['yellow']) | curses.A_REVERSE), 'magenta': curses.color_pair(self.PAIRS['magenta']), 'magenta_reverse': (curses.color_pair(self.PAIRS['magenta']) | curses.A_REVERSE), } curses.start_color() curses.use_default_colors() for definition, (color, background) in self.DEFINITION.items(): curses.init_pair(definition, color, background)
def draw_footer(stdscr, game): """Displays the controls in the last line.""" if game.is_lost() or game.is_solved(): controls = [("Press any key to continue", "")] else: controls = [ ("Navigate:", "\u2190 \u2192 \u2191 \u2193"), ("Reveal:", "Space \u2423"), ("Toggle Mark:", "Enter \u23CE"), ("Menu:", "Escape"), ] offset = 0 for name, control in controls: stdscr.addstr(curses.LINES-1, offset, name, curses.A_REVERSE) offset += len(name) stdscr.addstr(curses.LINES-1, offset, " " + control + " ") offset += len(control) + 2 return Rect(0, curses.LINES-1, curses.COLS-1, 1)
def tick(self, scr, steps, padding_rows, padding_cols, output_rows, output_cols): height, width = scr.getmaxyx() in_picture_frame = self.y >= padding_rows and self.y <= padding_rows + output_rows and self.x >= padding_cols and self.x <= padding_cols + output_cols if self.advances(steps): # if window was resized and char is out of bounds, reset self.out_of_bounds_reset(width, height) # make previous char curses.A_NORMAL if not in_picture_frame: if USE_COLORS: scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_NORMAL)) else: scr.addstr(self.y, self.x, self.char, curses.A_NORMAL) # choose new char and draw it A_REVERSE if not out of bounds self.char = random.choice(FallingChar.matrixchr).encode(encoding) self.y += 1 in_picture_frame = self.y >= padding_rows and self.y <= padding_rows + output_rows and self.x >= padding_cols and self.x <= padding_cols + output_cols if not self.out_of_bounds_reset(width, height) and not in_picture_frame: if USE_COLORS: scr.addstr(self.y, self.x, self.char, curses.color_pair(COLOR_CHAR_HIGHLIGHT)) else: scr.addstr(self.y, self.x, self.char, curses.A_REVERSE)
def get(colorType, delta=0): global cache__ if type(colorType) == type(0): colorIndex = colorType else: colorIndex = app.prefs.color[colorType] colorIndex = min(colors - 1, colorIndex + delta) #colorIndex = colorIndex % colors r = cache__.get(colorIndex) if r is not None: return r color = curses.color_pair(colorIndex) if colorType in ('error', 'misspelling'): color |= curses.A_BOLD | curses.A_REVERSE cache__[colorIndex] = color return color
def print_line(line, highlight=False): """A thin wrapper around curses's addstr().""" global lineno try: if highlight: line += " " * (win.getmaxyx()[1] - len(line)) win.addstr(lineno, 0, line, curses.A_REVERSE) else: win.addstr(lineno, 0, line, 0) except curses.error: lineno = 0 win.refresh() raise else: lineno += 1 # --- curses stuff
def print_line(line, highlight=False): """A thin wrapper around curses's addstr().""" global lineno try: if highlight: line += " " * (win.getmaxyx()[1] - len(line)) win.addstr(lineno, 0, line, curses.A_REVERSE) else: win.addstr(lineno, 0, line, 0) except curses.error: lineno = 0 win.refresh() raise else: lineno += 1 # --- /curses stuff
def curses_input(self, stdscr, row, col, prompt_string, ascii_mode=False): """ Get an input string with curses. Row and col are the start position ot the prompt_string. """ curses.echo() stdscr.addstr(row, col, str(prompt_string), curses.A_REVERSE) stdscr.addstr(row + 1, col, " " * (curses.COLS - 1)) stdscr.refresh() input_val = "" while len(input_val) <= 0: if ascii_mode: input_val = chr(stdscr.getch()) break else: input_val = stdscr.getstr(row + 1, col, 20) return input_val
def move(self, x = None): if x is not None: if x < self.x1 or x >= self.x2: return self.stdscr.chgat(self.y, self.cursor, 1, curses.A_NORMAL) self.cursor = x self.stdscr.chgat(self.y, self.cursor, 1, curses.A_REVERSE)
def display(self): self.panel.top() self.panel.show() self.window.clear() while True: self.window.refresh() curses.doupdate() for index, item in enumerate(self.items): if index == self.position: mode = curses.A_REVERSE else: mode = curses.A_NORMAL msg = '%d. %s' % (index, item[0]) self.window.addstr(1+index, 1, msg, mode) key = self.window.getch() if key in [curses.KEY_ENTER, ord('\n')]: # Handle exit from menu if self.position == len(self.items)-1 or str(self.items[self.position][1]) == "exit": break else: if self.rootmenu.set_selection(self.items[self.position][1]): break elif key == curses.KEY_UP: self.navigate(-1) elif key == curses.KEY_DOWN: self.navigate(1) self.window.clear() self.panel.hide() panel.update_panels() curses.doupdate()
def displayDay(scr, day, cursor, topString, bottomString): string = day.isoformat() max_y, max_x = scr.getmaxyx() y = int(max_y/2) x = int(max_x/2) - 5 scr.addstr(y - 2, x - int(len(topString)/2) + 5, topString) scr.addstr(y, x, string[0:cursor]) scr.addstr(y, x + cursor, string[cursor:cursor+1], curses.A_REVERSE) scr.addstr(y, x + cursor + 1, string[cursor+1:]) scr.addstr(y + 2, x - int(len(bottomString)/2) + 5, bottomString) scr.refresh()
def displayTime(scr, time, cursor, topString, bottomString): string = time.isoformat() max_y, max_x = scr.getmaxyx() y = int(max_y/2) x = int(max_x/2) - 4 scr.addstr(y - 2, x - int(len(topString)/2) + 4, topString) scr.addstr(y, x, string[0:cursor]) scr.addstr(y, x + cursor, string[cursor:cursor+1], curses.A_REVERSE) scr.addstr(y, x + cursor + 1, string[cursor+1:]) scr.addstr(y + 2, x - int(len(bottomString)/2) + 4, bottomString) scr.refresh()
def displayDateTime(scr, day, time, cursor, topString, bottomString): string = day.isoformat() + " " + time.isoformat() max_y, max_x = scr.getmaxyx() y = int(max_y/2) x = int(max_x/2) - 9 scr.addstr(y - 2, x - int(len(topString)/2) + 9, topString) scr.addstr(y, x, string[0:cursor]) scr.addstr(y, x + cursor, string[cursor:cursor+1], curses.A_REVERSE) scr.addstr(y, x + cursor + 1, string[cursor+1:]) scr.addstr(y + 2, x - int(len(bottomString)/2) + 9, bottomString) scr.refresh()
def tick(self, scr, steps): if self.step > WINDOW_SIZE: #stop window animation after some steps self.draw_frame(scr, self.x - self.step, self.y - self.step, self.x + self.step, self.y + self.step, curses.A_NORMAL) return False # clear all characters covered by the window frame for i in range(WINDOW_ANIMATION_SPEED): anistep = self.step + i self.draw_frame(scr, self.x - anistep, self.y - anistep, self.x + anistep, self.y + anistep, curses.A_NORMAL, ' ') #cancel last animation self.draw_frame(scr, self.x - self.step, self.y - self.step, self.x + self.step, self.y + self.step, curses.A_NORMAL) #next step self.step += WINDOW_ANIMATION_SPEED #draw outer frame self.draw_frame(scr, self.x - self.step, self.y - self.step, self.x + self.step, self.y + self.step, curses.A_REVERSE) return True
def _render_title(self): """ rendering of title bar on first line (space to display modal info, and even keybinding hints) """ title = "{title bar placeholder}" title_bar = title + (" " * (curses.COLS - len(title))) self.screen.addstr(0,0, title_bar, curses.A_REVERSE)
def _cw_menu_display(cls): x = 0 # Because cls with MENU will add 1 to y in _fix_xy, we need true origin y = -1 # Makes the menu standout menu_attrs = curses.A_REVERSE | curses.A_BOLD saved_pos = cls.getxy() for menu in Menu.ALL: # double check we're not going to write out of bounds if x + len(menu.title) + 2 >= cls.WIDTH: raise CursedSizeError('Menu %s exceeds width of window: x=%d' % (menu.title, x)) y = -1 cls.addstr(menu.title + ' ', x, y, attr=menu_attrs) mxlen = max([len(str(i)) for i in menu.items]) if menu is cls._OPENED_MENU: for item in menu.items: y += 1 itemstr = str(item) wspace = (mxlen - len(itemstr)) * ' ' itemstr = itemstr + wspace if item is menu.selected: attr = curses.A_UNDERLINE else: attr = curses.A_REVERSE cls.addstr(itemstr, x, y, attr=attr) # For the empty space filler x += len(menu.title) + 2 # color the rest of the top of the window extra = 2 if cls.BORDERED else 0 cls.addstr(' ' * (cls.WIDTH - x - extra), x, -1, attr=menu_attrs) cls.move(*saved_pos)
def curses_input(self, stdscr, r, c, prompt_string): curses.echo() stdscr.addstr(r, c, str(prompt_string), curses.A_REVERSE) stdscr.addstr(r + 1, c, " " * (curses.COLS - 1)) stdscr.refresh() input_val = "" while len(input_val) <= 0: input_val = stdscr.getstr(r + 1, c, 20) return input_val
def cpprint(self, print_string, finish=False, reverse=False): if self.use_curses: try: attr = curses.A_NORMAL if reverse: attr = curses.A_REVERSE if self.start: self.scrn.erase() self.start = False hw = self.scrn.getmaxyx() pos = self.scrn.getyx() if pos[0] < hw[0] and pos[1] == 0: print_string = print_string[:hw[1] - 1] self.scrn.addstr(print_string, attr) if pos[0] + 1 < hw[0]: self.scrn.move(pos[0] + 1, 0) if finish: self.scrn.refresh() self.start = True except curses.CursesError as e: # show curses errors at top of screen for easier debugging self.scrn.move(0, 0) self.scrn.addstr("{} {} {} {}\n".format(type(e), e, pos, hw), attr) self.scrn.addstr(print_string + "\n", attr) else: print print_string
def show_env_to_terminal(terminal, env): terminal.update_main_screen(env.screen) for i, p in enumerate(env.pointers): terminal.update_main_window_attr(env.screen, i, p, curses.A_REVERSE) terminal.refresh_main_window()
def draw_header(stdscr, game): """Draws some info about in the first line.""" if game.is_solved(): text = "Congratulations, You Won!" elif game.is_lost(): text = "You Lost!" else: remaining = game.mines.count(True) - game.flags.count(minesweeper.Flags.Marked) text = "Remaining Mines: {0}".format(remaining) stdscr.addstr(0, 0, text, curses.A_REVERSE) return Rect(0, 0, curses.COLS-1, 1)
def video_options(self, item, position): if position == self.pos: return curses.color_pair(1) options = 0 options |= curses.A_DIM if item['seen'] else 0 options |= curses.color_pair(3) if item.get('fav') else 0 if item['title'] in self.data: info = self.data[item['title']] options |= curses.A_UNDERLINE if info.get('watch') else 0 if any(item['title'] == i['title'] for i in self.selected): options |= curses.A_REVERSE return options
def draw_items(self): for y, i in enumerate(self.items[self.off:self.off+self.height-4]): if y == self.pos: options = curses.A_REVERSE else: options = 0 if all(x['seen'] for x in self.data[i]['videos']): options |= curses.A_DIM title = ' {} '.format(i).ljust(self.width) self.screen.addstr(y+3, 0, title, options) return None
def disp_bottom_line(bottom_line): stdscr.addstr(jack.term.size_y - 1, 0, (bottom_line + " " * (jack.term.size_x - len(bottom_line)))[:jack.term.size_x - 1], A_REVERSE) if pad_start_y < pad_end_y: status_pad.refresh( pad_y, pad_x, pad_start_y, pad_start_x, pad_end_y, pad_end_x) stdscr.refresh()
def dae_stat_upd(num, string, reverse=-1): track = jack.ripstuff.all_tracks[num - 1] if reverse >= 0: split_point = int(6.5 + reverse / 100.0 * 32) front = jack.ripstuff.printable_names[ num] + ": " + jack.status.dae_status[num][:6] middle = jack.status.dae_status[num][6:split_point] end = jack.status.dae_status[num][ split_point:] + " " + jack.status.enc_status[num] try: status_pad.addstr(map_track_num[num], 0, front) status_pad.addstr( map_track_num[num], len(front), middle, A_REVERSE) status_pad.addstr(map_track_num[num], len(front + middle), end) except error: pass else: try: status_pad.addstr(map_track_num[num], 0, (jack.ripstuff.printable_names[ num] + ": " + jack.status.dae_status[num] + " " + jack.status.enc_status[num])) except error: pass dummy = """ if ripper == "cdparanoia" and track in dae_tracks or (track in enc_queue and track not in mp3s_done): status_pad.addstr(map_track_num[num], 0, jack.ripstuff.printable_names[num] + ": " + jack.status.dae_status[num][:7]) pos = find(jack.status.dae_status[num], ">") if pos < 7: pos = 37 status_pad.addstr(jack.status.dae_status[num][7:pos], A_REVERSE) status_pad.addstr(jack.status.dae_status[num][pos:]) else: status_pad.addstr(map_track_num[num], 0, jack.ripstuff.printable_names[num] + ": " + jack.status.dae_status[num] + " " + jack.status.enc_status[num]) """ status_pad.clrtoeol()
def select_mode(self, index): if self.has_focus: if self.first_item_index == 0 and index == self.position: mode = curses.A_REVERSE elif (self.position - self.first_item_index) == index: mode = curses.A_REVERSE elif (self.position + 1 == self.last_item_index) and (index == len(self.employees) - 1): mode = curses.A_REVERSE else: mode = curses.A_NORMAL else: mode = curses.A_NORMAL return mode
def display(self): self.window.clear() while True: self.window.refresh() curses.doupdate() for index, item in enumerate(self.items): if index == self.position: mode = curses.A_REVERSE else: mode = curses.A_NORMAL msg = '- %s\n (Features: %s, Design: %s)' % (item, item.features, item.design_need) self.window.addstr(1+index*2, 2, msg, mode) key = self.window.getch() if key in [curses.KEY_ENTER, ord('\n')]: if self.position == len(self.items)-1: return None else: return self.position if key == curses.KEY_UP: self.navigate(-1) elif key == curses.KEY_DOWN: self.navigate(1)
def start_loop(self): while not self.disconnect: self.msg_text = '' # draw top bar self.scr.addstr(0, 0, '// Hack the Planet IRC Chat // (type /exit to quit)', curses.A_REVERSE) self.draw_line(1) # draw channel self.scr.addstr(self.scr_height - 1, 0, self.channel, curses.color_pair(1)) # draw username self.scr.addstr(self.scr_height - 1, len(self.channel) + 1, '[' + self.username + ']:') self.draw_line(self.scr_height - 2) # draw latest chat messages self.get_log_text() i = self.scr_height - 3 log_line = len(self.log_text) - 1 while i > 1: self.scr.addstr(i, 0, self.log_text[log_line]) log_line -= 1 i -= 1 # get user input input_y = self.scr_height - 1 input_x = len(self.channel) + len(self.username) + 5 self.msg_text = self.scr.getstr(input_y, input_x) # check if input is blank if self.msg_text == '': pass # check if the input is a command elif self.msg_text[0] == '/': command = self.msg_text[1:].lower() if command== 'exit': self.disconnect = True else: # send message to channel try: file = open(self.logfile, 'a+') text = 'S[' + self.get_timestamp() + ']<' + self.username + '> ' + self.msg_text + '\n' file.write(text) file.close() except Exception as e: print("Error: " + str(e)) # draw any changes self.scr.clear() self.scr.refresh() # reset to standard terminal and exit curses.endwin() # draws a horizontal line at a given y-coordinate
def _draw_input(self, stdscr, header, message): """ Draw an input window with the provided message. Parameters: stdscr (WindowObject): the screen; handled by curses.wrapper header (str): header message displayed above the text entry box message (str): the message to the user displayed between the header and the text entry Returns: (Textbox): the Textbox's edit() returns a string representing the user's input """ stdscr.clear() # Setup the title stdscr.addstr("ec2rl module configurator", curses.A_REVERSE) stdscr.chgat(-1, curses.A_REVERSE) curses.curs_set(0) num_columns = 30 num_lines = 1 uly = 3 ulx = 3 main_window = curses.newwin(curses.LINES - 1, curses.COLS, 1, 0) screen = main_window.subwin(curses.LINES - 7, curses.COLS - 4, 4, 2) # Setup background colors main_window.bkgd(" ", curses.color_pair(1)) screen.bkgd(" ", curses.color_pair(2)) # Draw borders around the screen subwindow screen.box() input_screen = main_window.subwin(num_lines, num_columns, uly + 5, ulx + 3) ec2rlcore.menu_textpad_mod.rectangle(screen, uly, ulx, uly + 1 + num_lines, ulx + 1 + num_columns) screen.addstr(1, 2, header, curses.A_UNDERLINE) # Truncate the string, if needed display_str = message[:curses.COLS - 10] screen.addstr(2, 5, display_str) # Draw the pieces of the overall screen (order matters) stdscr.refresh() main_window.noutrefresh() screen.noutrefresh() input_screen.noutrefresh() stdscr.noutrefresh() curses.doupdate() return ec2rlcore.menu_textpad_mod.Textbox(input_screen, bkgd_color=curses.color_pair(2)).edit()
def render(self): tb = self.host.textBuffer color = app.color.get('status_line') if self.host.showTips: tipRows = app.help.docs['tips'] if len(tipRows) + 1 < self.rows: for i in range(self.rows): self.addStr(i, 0, ' ' * self.cols, color) for i,k in enumerate(tipRows): self.addStr(i + 1, 4, k, color) self.addStr(1, 40, "(Press F1 to show/hide tips)", color | curses.A_REVERSE) statusLine = '' if tb.message: statusLine = tb.message[0] color = tb.message[1] tb.setMessage() if 0: if tb.isDirty(): statusLine += ' * ' else: statusLine += ' . ' # Percentages. rowPercentage = 0 colPercentage = 0 lineCount = len(tb.lines) if lineCount: rowPercentage = self.host.cursorRow * 100 / lineCount if self.host.cursorRow >= lineCount - 1: rowPercentage = 100 charCount = len(tb.lines[self.host.cursorRow]) if (self.host.cursorCol < charCount): colPercentage = self.host.cursorCol * 100 / charCount else: colPercentage = 100 # Format. rightSide = '' if len(statusLine): rightSide += ' |' if app.prefs.startup.get('showLogWindow'): rightSide += ' %s | %s |' % (tb.cursorGrammarName(), tb.selectionModeName()) rightSide += ' %4d,%2d | %3d%%,%3d%%' % ( self.host.cursorRow+1, self.host.cursorCol + 1, rowPercentage, colPercentage) statusLine += \ ' ' * (self.cols - len(statusLine) - len(rightSide)) + rightSide self.addStr(self.rows - 1, 0, statusLine[:self.cols], color)
def set_list(self, node): self.win.erase() highlighted = node.highlighted if not node.item_list: no_data_str = "no VPN data" self.win.addstr(self.height//2,(self.width-len(no_data_str))//2, no_data_str) self.win.refresh() return list_len = len(node.item_list) half_win_height = self.height//2 if highlighted < half_win_height or list_len < self.height: left = 0 right = min(list_len, self.height) elif highlighted + half_win_height < list_len: left = highlighted - half_win_height right = highlighted + half_win_height else: left = list_len - self.height right = min(highlighted + half_win_height, list_len) for index in range(left, right): try: item = node.item_list[index] except IndexError: self.win.addstr("Index out of range!") break text_atr = curses.A_REVERSE if index == highlighted else curses.A_NORMAL left_str = str(item[0]) if isinstance(item[1], int): right_str = str(item[1]) else: right_str = "{:.2f}".format(item[1]) left_str = left_str if len(left_str)+len(right_str) < self.width else left_str[:self.width-len(right_str)-3]+'~' left_str = left_str.ljust(self.width-len(right_str)-1) item_str = "{}{}".format(left_str, right_str) self.win.addstr(index-left, 0, item_str, text_atr) self.win.refresh()