cligen/tab

Procs

proc colOptimize(lens: seq[int]; W = 80; gap = 1; mx = 999; m = 1; nr: var int): int {.
    ...raises: [ValueError], tags: [], forbids: [].}
Return number of columns to minimize the number of rows. lens should be rendered terminal widths, not string lengths & entries can be <0 (abs used). m is the column stride. The units of mx are also minor columns.
proc colPad(cw: var seq[int]; fw = 80; pm = 999; m = 1; j = -1) {.
    ...raises: [ValueError], tags: [], forbids: [].}
Pad layout of column widths cw with up to pm spaces per major col, not overflowing the full width fw. m is the stride over columns, and j is the end relative offset of the minor column receiving padding.
proc format(f: File; tw: int; wids: seq[int]; strs: seq[string]; gap = 1;
            pfx = "") {....raises: [ValueError, IOError], tags: [WriteIOEffect],
                        forbids: [].}
A simpler interface to format a table to a File, assuming m=1, 0 widest.
proc layout(lens: seq[int]; W, gap, mx, m: int; nr, nc: var int): seq[int] {.
    ...raises: [ValueError], tags: [], forbids: [].}
proc sortByWidth(lens: seq[int]; m, nr, nc: int): seq[int] {....raises: [],
    tags: [], forbids: [].}
proc sortByWidth(strs: var seq[string]; lens: var seq[int]; m, nr, nc: int) {.
    ...raises: [], tags: [], forbids: [].}
Permute strs,lens to be in-maj-col width-sorted; May sound odd, but is useful for finding promising renames/deletes to get more rows in a listing.
proc write(f: File; strs: seq[string]; lens: seq[int]; ws: seq[int];
           m, nr, nc, widest: int; pfx: string) {....raises: [IOError],
    tags: [WriteIOEffect], forbids: [].}
Write lines to file w/pads; lens[i]<0 means left align else right align.