| @@ 7-50 (lines=44) @@ | ||
| 4 | , { first, strlen } = require ('printable-characters') // handles ANSI codes and invisible characters |
|
| 5 | , limit = (s, n) => (first (s, n - 1) + '…') |
|
| 6 | ||
| 7 | const asColumns = (rows, cfg_) => { |
|
| 8 | ||
| 9 | const |
|
| 10 | ||
| 11 | zip = (arrs, f) => arrs.reduce ((a, b) => b.map ((b, i) => [...a[i] || [], b]), []).map (args => f (...args)), |
|
| 12 | ||
| 13 | /* Convert cell data to string (converting multiline text to singleline) */ |
|
| 14 | ||
| 15 | cells = rows.map (r => r.map (c => (c === undefined) ? '' : cfg_.print (c).replace (/\n/g, '\\n'))), |
|
| 16 | ||
| 17 | /* Compute column widths (per row) and max widths (per column) */ |
|
| 18 | ||
| 19 | cellWidths = cells.map (r => r.map (strlen)), |
|
| 20 | maxWidths = zip (cellWidths, Math.max), |
|
| 21 | ||
| 22 | /* Default config */ |
|
| 23 | ||
| 24 | cfg = O.assign ({ |
|
| 25 | delimiter: ' ', |
|
| 26 | minColumnWidths: maxWidths.map (x => 0), |
|
| 27 | maxTotalWidth: 0 }, cfg_), |
|
| 28 | ||
| 29 | delimiterLength = strlen (cfg.delimiter), |
|
| 30 | ||
| 31 | /* Project desired column widths, taking maxTotalWidth and minColumnWidths in account. */ |
|
| 32 | ||
| 33 | totalWidth = maxWidths.reduce ((a, b) => a + b, 0), |
|
| 34 | relativeWidths = maxWidths.map (w => w / totalWidth), |
|
| 35 | maxTotalWidth = cfg.maxTotalWidth - (delimiterLength * (maxWidths.length - 1)), |
|
| 36 | excessWidth = Math.max (0, totalWidth - maxTotalWidth), |
|
| 37 | computedWidths = zip ([cfg.minColumnWidths, maxWidths, relativeWidths], |
|
| 38 | (min, max, relative) => Math.max (min, Math.floor (max - excessWidth * relative))), |
|
| 39 | ||
| 40 | /* This is how many symbols we should pad or cut (per column). */ |
|
| 41 | ||
| 42 | restCellWidths = cellWidths.map (widths => zip ([computedWidths, widths], (a, b) => a - b)) |
|
| 43 | ||
| 44 | /* Perform final composition. */ |
|
| 45 | ||
| 46 | return zip ([cells, restCellWidths], (a, b) => |
|
| 47 | zip ([a, b], (str, w) => (w >= 0) |
|
| 48 | ? (cfg.right ? (' '.repeat (w) + str) : (str + ' '.repeat (w))) |
|
| 49 | : (limit (str, strlen (str) + w))).join (cfg.delimiter)) |
|
| 50 | } |
|
| 51 | ||
| 52 | const asTable = cfg => O.assign (arr => { |
|
| 53 | ||
| @@ 13-54 (lines=42) @@ | ||
| 10 | strlen = _require.strlen, |
|
| 11 | limit = (s, n) => first(s, n - 1) + '…'; |
|
| 12 | ||
| 13 | const asColumns = (rows, cfg_) => { |
|
| 14 | ||
| 15 | const zip = (arrs, f) => arrs.reduce((a, b) => b.map((b, i) => [].concat(_toConsumableArray(a[i] || []), [b])), []).map(args => f.apply(undefined, _toConsumableArray(args))), |
|
| 16 | ||
| 17 | ||
| 18 | /* Convert cell data to string (converting multiline text to singleline) */ |
|
| 19 | ||
| 20 | cells = rows.map(r => r.map(c => c === undefined ? '' : cfg_.print(c).replace(/\n/g, '\\n'))), |
|
| 21 | ||
| 22 | ||
| 23 | /* Compute column widths (per row) and max widths (per column) */ |
|
| 24 | ||
| 25 | cellWidths = cells.map(r => r.map(strlen)), |
|
| 26 | maxWidths = zip(cellWidths, Math.max), |
|
| 27 | ||
| 28 | ||
| 29 | /* Default config */ |
|
| 30 | ||
| 31 | cfg = O.assign({ |
|
| 32 | delimiter: ' ', |
|
| 33 | minColumnWidths: maxWidths.map(x => 0), |
|
| 34 | maxTotalWidth: 0 }, cfg_), |
|
| 35 | delimiterLength = strlen(cfg.delimiter), |
|
| 36 | ||
| 37 | ||
| 38 | /* Project desired column widths, taking maxTotalWidth and minColumnWidths in account. */ |
|
| 39 | ||
| 40 | totalWidth = maxWidths.reduce((a, b) => a + b, 0), |
|
| 41 | relativeWidths = maxWidths.map(w => w / totalWidth), |
|
| 42 | maxTotalWidth = cfg.maxTotalWidth - delimiterLength * (maxWidths.length - 1), |
|
| 43 | excessWidth = Math.max(0, totalWidth - maxTotalWidth), |
|
| 44 | computedWidths = zip([cfg.minColumnWidths, maxWidths, relativeWidths], (min, max, relative) => Math.max(min, Math.floor(max - excessWidth * relative))), |
|
| 45 | ||
| 46 | ||
| 47 | /* This is how many symbols we should pad or cut (per column). */ |
|
| 48 | ||
| 49 | restCellWidths = cellWidths.map(widths => zip([computedWidths, widths], (a, b) => a - b)); |
|
| 50 | ||
| 51 | /* Perform final composition. */ |
|
| 52 | ||
| 53 | return zip([cells, restCellWidths], (a, b) => zip([a, b], (str, w) => w >= 0 ? cfg.right ? ' '.repeat(w) + str : str + ' '.repeat(w) : limit(str, strlen(str) + w)).join(cfg.delimiter)); |
|
| 54 | }; |
|
| 55 | ||
| 56 | const asTable = cfg => O.assign(arr => { |
|
| 57 | var _ref; |
|