# FIXME: Make this whole package less fragile TYPES = ["tbl", "chrt", "csv", "json"] def wall(len, fill="\u2501"): return fill * len # FIXME: normalize/analyze table data before building for optimization def table(data): lens = dict() for row in data: for col in row: col_len = len(col) val_len = len(str(row[col])) max_len = 0 if col in lens: max_len = lens[col] lens[col] = max(col_len, val_len, max_len) col_hdrs = [{"column": col_hdr, "length": lens[col_hdr]} for col_hdr in lens] out = f"\u250F{wall(col_hdrs[0]['length'] + 2)}" for col_hdr in col_hdrs[1:]: out += f"\u2533{wall(col_hdr['length'] + 2)}" out += "\u2513\n" for col_hdr in col_hdrs: out += f"\u2503 {col_hdr['column'].ljust(col_hdr['length'])} " out += f"\u2503\n\u2523{wall(col_hdrs[0]['length'] + 2)}" for col_hdr in col_hdrs[1:]: out += f"\u254B{wall(col_hdr['length'] + 2)}" out += "\u252B\n" for row in data[:-1]: for col_hdr in col_hdrs: out += "\u2503 " if col_hdr["column"] in row: out += str(row[col_hdr["column"]]).ljust(col_hdr["length"]) else: out += " " * col_hdr["length"] out += " " out += f"\u2503\n\u2523{wall(col_hdrs[0]['length'] + 2)}" for col_hdr in col_hdrs[1:]: out += f"\u254B{wall(col_hdr['length'] + 2)}" out += "\u252B\n" for col_hdr in col_hdrs: out += "\u2503 " if col_hdr["column"] in data[-1]: out += str(data[-1][col_hdr["column"]]).ljust(col_hdr["length"]) else: out += " " * col_hdr["length"] out += " " out += "\u2503\n" out += f"\u2517{wall(col_hdrs[0]['length'] + 2)}" for col_hdr in col_hdrs[1:]: out += f"\u253B{wall(col_hdr['length'] + 2)}" out += "\u251B" return out def chrt(data): return data def csv(data): return data def json(data): return data def render(out, data): # FIXME: option to pipe into pager, cut off at max column, squeeze, or do # nothing (depends on TTY/PAGER) if out == "tbl": return table(data) elif out == "chrt": return chart(data) elif out == "csv": return csv(data) elif out == "json": return json(data) # FIXME: error unrecognized out format