def draw_clock(term): tprint( term, term.move(0, term.width - 12), term.color(colors[APP_CLOCK]), term.on_color(colors[APP_FRAME]), term.bold, datetime.datetime.now().strftime("%H:%M:%S"), )
def main_loop(term, screen): sighook = SignalHook() selected_window = 0 windows[selected_window].selected = True windows[selected_window].draw_frame() while not sighook.exit: force = False key_code = screen.getch() while key_code != curses.ERR: force = force or (key_code != curses.ERR) if key_code in [ord("q"), ord("Q")]: return elif key_code == curses.KEY_RESIZE: draw_app(term) calculate_windows(term) elif key_code == 9: # TAB windows[selected_window].selected = False selected_window += 1 if selected_window >= len(windows): selected_window = 0 windows[selected_window].selected = True elif key_code == curses.KEY_UP: # also scroll up windows[selected_window].scroll_up() elif key_code == curses.KEY_PPAGE: # PGUP windows[selected_window].page_up() elif key_code == curses.KEY_DOWN: # also scroll down windows[selected_window].scroll_down() elif key_code == curses.KEY_NPAGE: # PGDN windows[selected_window].page_down() elif key_code == ord(" "): windows[selected_window].scroll_end() key_code = screen.getch() draw_clock(term) for window in windows: window.refresh(force) tprint(term) time.sleep(LOOP_MS / 1000)
def draw_app(term): top_before_title = int((term.width - len(APPLICATION_TITLE)) / 2) top_after_title = int(((term.width - len(APPLICATION_TITLE)) / 2) + (((term.width - len(APPLICATION_TITLE)) / 2) % 1) - 12 # clock space ) tprint( term, term.move(0, 0), term.color(colors[APP_FRAME]), term.on_color(colors[APP_BG]), BLK * top_before_title, term.color(colors[APP_TITLE]), term.on_color(colors[APP_FRAME]), term.bold, APPLICATION_TITLE, term.color(colors[APP_FRAME]), term.on_color(colors[APP_BG]), BLK * top_after_title, term.color(colors[APP_CLOCK]), term.on_color(colors[APP_FRAME]), term.bold, datetime.datetime.now().strftime("%H:%M:%S"), term.color(colors[APP_FRAME]), term.on_color(colors[APP_BG]), BLK * 4, term.move(term.height - 1, 0), # BLK * term.width, term.color(colors[APP_CLOCK]), term.on_color(colors[APP_FRAME]), "TAB: Next Window SPACE: Jump to end Q: Quit".center(term.width), ) tformat(term.color(colors[APP_FRAME]), term.on_color(colors[APP_BG])) for row in range(1, term.height - 1): print(term.move(row, 0) + BLK + term.move(row, term.width - 1) + BLK) tprint(term)
def draw_frame(self, fill=False): tprint( # draw top edge and corners self.term, self.term.move(self.y, self.x), self.term.color(self.frame) + self.term.on_color(self.colors[LOG_BG]), BLK * int((self.w - len(self.name)) / 2), self.term.color(self.colors[WIN_TITLE]) + self.term.on_color(self.frame), self.term.bold, self.name, self.term.color(self.frame) + self.term.on_color(self.colors[LOG_BG]), BLK * int((((self.w - len(self.name)) / 2) + (((self.w - len(self.name)) / 2) % 1)) - 18), self.term.color(self.colors[WIN_LINES]), self.term.on_color(self.frame), self.term.bold, f"lines: {locale.format_string('%d', self.reader.lines, True):>9}", self.term.color(self.frame) + self.term.on_color(self.colors[LOG_BG]), BLK * 2, ) tprint( # draw bottom edge and corners self.term, self.term.move(self.y + self.h - 1, self.x), self.term.color(self.frame) + self.term.on_color(self.colors[LOG_BG]), BLK_BL, BLK_B * (self.w - 2), BLK_BR, ) # draw left and right edge and fill window tformat( self.term.color(self.frame) + self.term.on_color(self.colors[LOG_BG])) if fill: for row in range(self.y + 1, self.y + self.h - 1): print( self.term.move(row, self.x) + BLK_L + (" " * (self.w - 2)) + BLK_R) else: for row in range(self.y + 1, self.y + self.h - 1): print( self.term.move(row, self.x) + BLK_L + self.term.move(row, self.x + self.w - 1) + BLK_R) # reset formatting tprint(self.term)
def logview(): term = blessings.Terminal() if not term.is_a_tty: print("logview output cannot be piped, it is for display only") elif term.number_of_colors < 16: print( "logview requires a terminal that supports a minimum of 16 colours" ) else: global config config = parse_args() print(f"\x1b]2;{TERM_TITLE}\x07", end="") colors.extend(COLORS[term.number_of_colors]) for filename in config.file: filepath = os.path.abspath(os.path.join(config.dir, filename)) if os.access(filepath, os.R_OK, effective_ids=True): windows.append(Window(filepath, config, Logger)) elif os.access(filepath, os.F_OK, effective_ids=True): print(f"File '{filepath}' is not readable") else: print(f"File '{filepath}' does not exist") if windows and not windows[-1].reader.isOpen: windows.pop(len(windows) - 1) if windows: screen = None try: screen = curses.initscr() curses.noecho() curses.cbreak() screen.keypad(True) screen.nodelay(True) screen.getch() print(term.enter_fullscreen + term.hide_cursor + term.color(colors[APP_FG]) + term.on_color(colors[APP_BG]) + term.clear) draw_app(term) calculate_windows(term, False) for window in windows: window.start(term) # window.load() # window.refresh(True) with futures.ThreadPoolExecutor() as pool: threads = { pool.submit(window.load): window for window in windows } for future in futures.as_completed(threads): threads[future].refresh(True) main_loop(term, screen) except Exception as err: raise err finally: tprint(term, term.exit_fullscreen + term.normal_cursor) curses.nocbreak() if screen: screen.keypad(False) curses.echo() curses.endwin() print(*log, sep="\n") exit(0) exit(1)