From f0dfa4375121987b140afae3cbb32a676de658b3 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Sat, 30 Mar 2019 02:34:45 -0500 Subject: [PATCH] Switched to using terminaltables package; catches both value and index error for selection --- main.py | 16 +++----- print2d.py | 102 ++++++++++++++++++++++++++++------------------- requirements.txt | 3 +- 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/main.py b/main.py index 2aeb893..e5e41fe 100755 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ import urllib import os.path as osp import sys CHICAGO_TZ = tz.gettz("America/Chicago") +DATETIME_FORMAT = "%A, %B %e, %Y %H:%M:%S" # https://stackoverflow.com/a/5967539 @@ -64,6 +65,7 @@ def pprint_delta(delta): def gen_list(objs, data, *displays, key=None, sort=0, num_pic=True): + from print2d import create_table, render_table k = displays[sort] display_data = {obj[k]: obj[data] for obj in objs} srt_keys = sorted(display_data.keys(), key=key) @@ -77,15 +79,8 @@ def gen_list(objs, data, *displays, key=None, sort=0, num_pic=True): if num_pic: display = [[i] + data for i, data in enumerate(display)] - opts = { - 'spacer': ' ', - 'seperator': ' ', - 'interactive': True, - 'bottom': '=', - 'l_end': '<', - 'r_end': '>', - } - print2d(display, **opts) + table = create_table(display, DATETIME_FORMAT) + render_table(table) if num_pic: which = None while not which: @@ -95,7 +90,7 @@ def gen_list(objs, data, *displays, key=None, sort=0, num_pic=True): quit() try: which = srt_keys[int(which)] - except ValueError: + except (ValueError, IndexError): which = None return display_data[which] else: @@ -145,7 +140,6 @@ def main(args): if not args.arg.isdecimal(): # save on import time slightly - from print2d import print2d from search import Search, StopSearch # routes if not args.route: diff --git a/print2d.py b/print2d.py index 100b993..ce702dd 100644 --- a/print2d.py +++ b/print2d.py @@ -1,5 +1,38 @@ import datetime -from pydoc import pager +import os +import sys +import pydoc +from pydoc import pager, pipepager, tempfilepager, plainpager, plain +from textwrap import fill +from terminaltables import AsciiTable +from terminaltables.terminal_io import terminal_size + + +def getpager(): + """Decide what method to use for paging through text.""" + if not hasattr(sys.stdin, "isatty"): + return plainpager + if not hasattr(sys.stdout, "isatty"): + return plainpager + if not sys.stdin.isatty() or not sys.stdout.isatty(): + return plainpager + use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER') + if use_pager: + if sys.platform == 'win32': # pipes completely broken in Windows + return lambda text: tempfilepager(plain(text), use_pager) + elif os.environ.get('TERM') in ('dumb', 'emacs'): + return lambda text: pipepager(plain(text), use_pager) + else: + return lambda text: pipepager(text, use_pager) + if os.environ.get('TERM') in ('dumb', 'emacs'): + return plainpager + if sys.platform == 'win32': + return lambda text: tempfilepager(plain(text), 'more <') + if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: + return lambda text: pipepager(text, 'less -X') + + +pydoc.getpager = getpager def str_coerce(s, **kwargs): @@ -9,48 +42,33 @@ def str_coerce(s, **kwargs): return str(s) -def print2d(list_param, - datetime_format="%A, %B %e, %Y %H:%M:%S", - seperator=' | ', - spacer=' ', - bottom='=', - l_end='|', r_end='|', - interactive=False - ): - list_param = [[str_coerce(s, datetime_format=datetime_format) - for s in row] for row in list_param] - - max_col = [] +def create_table(list_param, datetime_format): + rows = [] for row in list_param: - for i, col in enumerate(row): - try: - max_col[i] = max(max_col[i], len(col)) - except IndexError: - max_col.append(len(col)) - - fmt_row = '{content}' - if l_end: - fmt_row = '{} {}'.format(l_end, fmt_row) - if r_end: - fmt_row = '{} {}'.format(fmt_row, r_end) - - done = [] - for row in list_param: - content = seperator.join(col.ljust(max_col[i], spacer if i < len( - row)-1 or r_end else ' ') for i, col in enumerate(row)) - done.append(fmt_row.format(content=content)) + rows.append([]) + for item in row: + rows[-1].append(str_coerce(item, datetime_format=datetime_format)) + return AsciiTable(rows) - if bottom: - bottom = bottom*len(done[0]) - row_sep = ('\n'+bottom+'\n') - else: - row_sep = '\n' - final = row_sep.join(done) - if bottom: - final = '\n'.join((bottom, final, bottom)) + +def render_table(table: AsciiTable, interactive=True): + '''Do all wrapping to make the table fit in screen''' + table.inner_row_border = True + data = table.table_data + terminal_width = terminal_size()[0] + n_cols = len(data[0]) + even_distribution = terminal_width // n_cols + for row_num, row in enumerate(data): + for col_num, col_data in enumerate(row): + if len(col_data) > even_distribution: + if col_num != n_cols - 1: + data[row_num][col_num] = fill(col_data, even_distribution) + else: + data[row_num][col_num] = '' + data[row_num][col_num] = fill( + col_data, table.column_max_width(col_num)) if interactive: - if not bottom: - final += '\n' - pager(final) + pager(table.table) else: - return final + print(table.table) + diff --git a/requirements.txt b/requirements.txt index db25db4..0c78596 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ edlib -python-dateutil \ No newline at end of file +python-dateutil +terminaltables