def max_box_width(num_boxes, name_width=0, padding=0): screen_width = zyutils.get_terminal_width() total_boxes_width = screen_width - name_width - (2 * padding) print("Screen is {} wide, fitting {} boxes".format(screen_width, num_boxes)) return total_boxes_width // num_boxes
def zygrid(*iterables, **kwargs): """ Takes lists, returns them formatted as a printable table. *iterables: Multiple same-length lists or tuples. These can be either rows or columns depending on whether the 'row' arg in kwargs is True or False. *kwargs: Formatting args, passed in as a dictionary. Options include: True/False options: 'rows': whether *iterables are to be formatted as rows or columns. 'color': whether each box is formatted with itself, or with an optional passed in color function. Options with arguments: 'wrap': whether or not rows are wrapped after a certain length. Options: int: wrap after that many columns 'max': wrap after as many columns will fit on terminal screen 'column_names': optional column names 'column_names_trim_func': function used to trim column names longer than box_width 'row_names': optional row names 'box_width': otherwise box_width will be set as a function of the widest item 'side_padding': buffer of blank spaces to the right and left of the formatted table 'table_justification': 'right': table formatted to right margin 'center': table centered 'left' or None: formatted to left margin """ # set up the crucial variables rows = kwargs.get('rows', True) row_name_width, row_name_iterator = row_names_generator( kwargs.get('row_names', None)) # next, massage & measure the iterables if rows is False: iterables = rotate_iterables(iterables) rows = True # are we wrapping the rows: wrap_flag = kwargs.get('wrap', False) screen_width = zyutils.get_terminal_width() minimum_box_width = min_box_width(iterables, buffer=kwargs.get('box_buffer', 1), color=kwargs.get('color', False)) if wrap_flag is not False: iterables = wrap_iterables(iterables, screen_width, minimum_box_width, row_name_width, rows, wrap_flag, kwargs.get('color', False)) num_rows = len(iterables) num_boxes = len(iterables[0]) # deal with color vs. no color if kwargs.get('color', None) is not None: format_func = lambda x: "{}{:^{wid}}{}".format(*x, wid=box_width) else: format_func = lambda x: "{:^{wid}}".format(str(x), wid=box_width) # set up the row contents row_content_iterator = row_content_generator(iterables, format_func, rows) # get the width of the boxes if kwargs.get('box_width', None) == 'max': box_width = max_box_width(num_boxes=num_boxes, name_width=row_name_width, padding=kwargs.get('side_padding', 0)) elif kwargs.get('box_width', None) is not None: box_width = kwargs['box_width'] else: box_width = minimum_box_width # box_width = min_box_width(iterables, # buffer=kwargs.get('box_buffer', 1), # color=kwargs.get('color', False)) box_width = max(box_width, minimum_box_width) width_residual = screen_width - (num_boxes * box_width) - row_name_width # justification for table if kwargs.get('table_justification', None) == 'right': right_pad = ' ' * width_residual elif kwargs.get('table_justification', None) == 'center': right_pad = ' ' * (width_residual // 2) else: if kwargs.get('side_padding', 0) > 0: right_pad = ' ' * kwargs['side_padding'] else: right_pad = '' # prepare the column names if kwargs.get('column_names', None) is not None: # column_names = kwargs['column_names'] column_names = ' ' * row_name_width if kwargs.get('column_names_trim_func', None) is None: for nam in kwargs['column_names']: column_names += '{:^{wid}}'.format( nam if len(nam) < box_width else nam[:box_width - 4] + '...', wid=box_width) else: for nam in kwargs['column_names']: column_names += '{:^{wid}}'.format( nam if len(nam) < box_width else kwargs['column_names_trim_func'](nam)[:box_width], wid=box_width) column_names = right_pad + column_names else: column_names = None # make the strings! res = [] for i in range(num_rows): r_nam = next(row_name_iterator) temp = next(row_content_iterator) res.append(right_pad + r_nam + temp) if column_names is not None: res.insert(0, column_names) return res
def zygrid(*iterables, **kwargs): """ Takes lists, returns them formatted as a printable table. *iterables: Multiple same-length lists or tuples. These can be either rows or columns depending on whether the 'row' arg in kwargs is True or False. *kwargs: Formatting args, passed in as a dictionary. Options include: True/False options: 'rows': whether *iterables are to be formatted as rows or columns. 'color': whether each box is formatted with itself, or with an optional passed in color function. Options with arguments: 'wrap': whether or not rows are wrapped after a certain length. Options: int: wrap after that many columns 'max': wrap after as many columns will fit on terminal screen 'column_names': optional column names 'column_names_trim_func': function used to trim column names longer than box_width 'row_names': optional row names 'box_width': otherwise box_width will be set as a function of the widest item 'side_padding': buffer of blank spaces to the right and left of the formatted table 'table_justification': 'right': table formatted to right margin 'center': table centered 'left' or None: formatted to left margin """ # set up the crucial variables rows = kwargs.get('rows', True) row_name_width, row_name_iterator = row_names_generator( kwargs.get('row_names', None)) # next, massage & measure the iterables if rows is False: iterables = rotate_iterables(iterables) rows = True # are we wrapping the rows: wrap_flag = kwargs.get('wrap', False) screen_width = zyutils.get_terminal_width() minimum_box_width = min_box_width(iterables, buffer=kwargs.get('box_buffer', 1), color=kwargs.get('color', False)) if wrap_flag is not False: iterables = wrap_iterables(iterables, screen_width, minimum_box_width, row_name_width, rows, wrap_flag, kwargs.get('color', False)) num_rows = len(iterables) num_boxes = len(iterables[0]) # deal with color vs. no color if kwargs.get('color', None) is not None: format_func = lambda x: "{}{:^{wid}}{}".format(*x, wid=box_width) else: format_func = lambda x: "{:^{wid}}".format(str(x), wid=box_width) # set up the row contents row_content_iterator = row_content_generator(iterables, format_func, rows) # get the width of the boxes if kwargs.get('box_width', None) == 'max': box_width = max_box_width(num_boxes=num_boxes, name_width=row_name_width, padding=kwargs.get('side_padding', 0)) elif kwargs.get('box_width', None) is not None: box_width = kwargs['box_width'] else: box_width = minimum_box_width # box_width = min_box_width(iterables, # buffer=kwargs.get('box_buffer', 1), # color=kwargs.get('color', False)) box_width = max(box_width, minimum_box_width) width_residual = screen_width - (num_boxes * box_width) - row_name_width # justification for table if kwargs.get('table_justification', None) == 'right': right_pad = ' ' * width_residual elif kwargs.get('table_justification', None) == 'center': right_pad = ' ' * (width_residual // 2) else: if kwargs.get('side_padding', 0) > 0: right_pad = ' ' * kwargs['side_padding'] else: right_pad = '' # prepare the column names if kwargs.get('column_names', None) is not None: # column_names = kwargs['column_names'] column_names = ' ' * row_name_width if kwargs.get('column_names_trim_func', None) is None: for nam in kwargs['column_names']: column_names += '{:^{wid}}'.format(nam if len(nam) < box_width else nam[:box_width - 4] + '...', wid=box_width) else: for nam in kwargs['column_names']: column_names += '{:^{wid}}'.format( nam if len(nam) < box_width else kwargs['column_names_trim_func'](nam)[:box_width], wid=box_width) column_names = right_pad + column_names else: column_names = None # make the strings! res = [] for i in range(num_rows): r_nam = next(row_name_iterator) temp = next(row_content_iterator) res.append(right_pad + r_nam + temp) if column_names is not None: res.insert(0, column_names) return res