Last active
January 28, 2022 19:08
-
-
Save jerlendds/bf786d3f5b460f75f3b0b8faa2e6538f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| # -*- coding: utf-8 -*- | |
| # tuic - textual user interface controller | |
| # Experiments With Curses | 2021, July 17 | |
| # I'm currently working on writing a simple TUI for a web crawler | |
| # that supports scraping and analyzing anything you want to write a plugin for. | |
| # This file creates two windows and draws boxes around the created windows | |
| # The windows respond to the terminal resizing and the terminal display will be redrawn to reflect the new size | |
| # KNOWN ISSUES: When terminal size becomes too small the program crashes | |
| import curses as c | |
| VERSION_STRING = "0.1.6" | |
| def draw_win_border(win: c.newwin, height: int, width: int, | |
| title: str = 'Active scrapers', b_color: int = 4, | |
| t_color: int = 1): | |
| hort = '━' | |
| vert = '┃' | |
| tr = '┓' | |
| br = '┛' | |
| tl = '┏' | |
| bl = '┗' | |
| win.clear() | |
| win.scrollok(0) | |
| border_color_pair = b_color | |
| win.addstr(0, 2, title, c.color_pair(t_color)) | |
| try: | |
| win.addstr(height - 3, 2, "Height:", c.color_pair(t_color)) | |
| win.addstr(height - 3, 10, f"{height}", c.color_pair(5)) | |
| win.addstr(height - 4, 2, "Width:", c.color_pair(t_color)) | |
| win.addstr(height - 4, 9, f"{width}", c.color_pair(5)) | |
| except c.error: | |
| pass | |
| for pnt in range(0, width): | |
| try: | |
| if pnt == win.getmaxyx()[1] - 1: | |
| pass | |
| elif pnt not in range(0, len(title) + 3): | |
| win.addch(0, pnt, hort, c.color_pair(border_color_pair)) | |
| if pnt == 0: | |
| pass | |
| elif pnt == width: | |
| pass | |
| else: | |
| win.addch(height - 1, pnt, hort, c.color_pair(border_color_pair)) | |
| except c.error: | |
| pass | |
| for pnt in range(0, height): | |
| try: | |
| if pnt == 0: | |
| win.addch(pnt, 0, tl, c.color_pair(border_color_pair)) | |
| win.addch(pnt, win.getmaxyx()[1] - 1, tr, c.color_pair(border_color_pair)) | |
| elif pnt == height - 1: | |
| win.addch(pnt, 0, bl, c.color_pair(border_color_pair)) | |
| win.addch(pnt, win.getmaxyx()[1] - 1, br, c.color_pair(border_color_pair)) | |
| else: | |
| win.addch(pnt, 0, vert, c.color_pair(border_color_pair)) | |
| win.addch(pnt, win.getmaxyx()[1] - 1, vert, c.color_pair(border_color_pair)) | |
| except c.error: | |
| pass | |
| win.refresh() | |
| def create_win(**kwargs) -> c.newwin: | |
| """Create new curses window from dict | |
| Parameters | |
| ---------- | |
| kwargs | |
| dict containing keys: height (or nlines), width (or ncols), begin_y (or start_y), begin_x (or start_x) | |
| Returns | |
| ------- | |
| _CursesWindow object | |
| """ | |
| win_conf = {} | |
| for key, value in kwargs.items(): | |
| if key == "height" or key == "nlines": | |
| win_conf["nlines"] = value | |
| elif key == "width" or key == "ncols": | |
| win_conf["ncols"] = value | |
| elif key == "begin_y" or key == "start_y": | |
| win_conf["begin_y"] = value | |
| elif key == "begin_x" or key == "start_x": | |
| win_conf["begin_x"] = value | |
| elif key == "parent_win": | |
| win_conf['parent_win'] = value | |
| else: | |
| raise KeyError | |
| nlines = win_conf.get('nlines') | |
| ncols = win_conf.get('ncols') | |
| begin_y = win_conf.get('begin_y') | |
| begin_x = win_conf.get('begin_x') | |
| win = c.newwin(nlines, ncols, begin_y, begin_x) | |
| if win_conf.get('parent_win'): | |
| win1 = c.newwin(nlines - 2, ncols - 2, begin_y, begin_x + 1) | |
| win.refresh() | |
| win1.refresh() | |
| return [win, win1] | |
| win.refresh() | |
| return win | |
| def constrain_win_size(win: c.newwin, min_value: int = 11, constrain_type: str = 'height'): | |
| """Print an error when the terminal does not meet the requested dimensions | |
| Parameters | |
| ---------- | |
| win | |
| expects a _CursesWindow object, typically the stdscr | |
| min_value | |
| constraint value | |
| constrain_type | |
| constraint axis can be either 'height' or 'width' | |
| Returns | |
| ------- | |
| None | |
| """ | |
| try: | |
| g['height'], g['width'] = win.getmaxyx() | |
| if g.get(constrain_type) <= min_value: | |
| while True: | |
| win.addstr(0, 0, 'Error: 12 is minimum terminal height\t') | |
| win.addstr(1, 0, f'Current height: {g.get("height")}\t') | |
| if c.KEY_RESIZE: | |
| win.refresh() | |
| g['height'], g['width'] = win.getmaxyx() | |
| if g.get(constrain_type) > min_value: | |
| break | |
| except c.error: | |
| pass | |
| g = {} | |
| def main(stdscr: c.newwin): # noqa | |
| c.curs_set(0) | |
| c.init_pair(1, c.COLOR_CYAN, c.COLOR_BLACK) | |
| c.init_pair(2, c.COLOR_GREEN, c.COLOR_BLACK) | |
| c.init_pair(3, c.COLOR_BLUE, c.COLOR_BLACK) | |
| c.init_pair(4, c.COLOR_WHITE, c.COLOR_BLACK) | |
| c.init_pair(5, c.COLOR_MAGENTA, c.COLOR_BLACK) | |
| c.init_pair(6, 255, 2) | |
| c.init_pair(7, c.COLOR_BLACK, c.COLOR_WHITE) | |
| c.init_pair(9, c.COLOR_BLACK, c.COLOR_GREEN) | |
| while True: | |
| constrain_win_size(stdscr) | |
| shell_conf = { | |
| "height": g.get('height'), | |
| "width": int(g.get('width') / 3 * 2), | |
| "begin_y": 0, | |
| "begin_x": 0, | |
| "parent_win": True | |
| } | |
| sess_conf = { | |
| "height": g.get('height'), | |
| "width": int(g.get('width') / 3), | |
| "begin_y": 0, | |
| "begin_x": int(g.get('width') / 3 * 2), | |
| "parent_win": False | |
| } | |
| shell_win_set = create_win(**shell_conf) | |
| shell_win_b = shell_win_set[0] | |
| shell_win = shell_win_set[1] | |
| sess_win = create_win(**sess_conf) | |
| draw_win_border(win=shell_win_b, height=g.get('height') - 6, width=g.get('width'), | |
| title=f"running u-serp {VERSION_STRING}", t_color=2) | |
| draw_win_border(win=sess_win, height=g.get('height'), width=g.get('width')) | |
| shell_win.addstr(1, 1, "[STATUS]", c.color_pair(5)) | |
| shell_win.addstr(1, 10, "welcome to an experiment with curses", c.color_pair(2)) | |
| shell_win.addstr(3, 10, "- github/jerlendds", c.color_pair(2)) | |
| shell_win.getch() | |
| sess_win.getch() | |
| if __name__ == "__main__": | |
| c.wrapper(main) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment