UNPKG

prettyjsontable

Version:

print json files as pretty table

179 lines (178 loc) 6.46 kB
import chalk from 'chalk'; function makeScale(min, max) { const deltamm = max - min; const sig = Math.floor(Math.log10(deltamm)); const factor = Math.pow(10, sig); const low = Math.floor(min / factor) * factor; const high = Math.ceil(max / factor) * factor; const delta = high - low; let count = Math.round(delta / factor); let count2 = count; const scale = []; if (count === 10) { count = 5; count2 = 5; } if (count === 2) { count = 4; count2 = 4; } if (count > 6) { count = count / 2 + 0.5; count2 = count2 / 2; } for (let i = 0; i <= count; ++i) { scale.push(rounds(low + i * delta / count2, sig - 1)); } return { sig, factor, min: scale[0], max: scale[scale.length - 1], scale, delta, count }; } function rounds(val, sig) { if (sig < 1) { return +val.toFixed(-sig); } const factor = Math.pow(10, sig); return Math.round(val / factor) * factor; } export class Matrix { murks; width; height; matrix; lastx; lasty; header; ylabels; xlabel; x; y; constructor(width, height, minx, miny, maxx, maxy, header) { this.murks = [' ', '▖', '▗', '▄', '▘', '▌', '▚', '▙', '▝', '▞', '▐', '▟', '▀', '▛', '▜', '█']; width = (width - 10) * 2; height *= 2; this.lastx = 0; this.lasty = 0; this.x = makeScale(minx, maxx); this.y = makeScale(miny, maxy); this.width = width; this.height = height; this.matrix = new Array(width * height).fill(0); this.header = header; this.ylabels = this.scaleToLabels(this.y, (this.height / 2 - 1)); this.xlabel = ' '; for (const v of this.x.scale) { const pos = 6 + (v - this.x.min) / (this.x.max - this.x.min) * (width / 2 - 6 - this.x.max.toString().length); const pad = pos - this.xlabel.length; this.xlabel = this.xlabel + ' '.repeat(pad) + v.toString(); } } scaleToLabels(m, len) { const labels = []; for (let i = Math.floor(this.height / 2) - 1; i >= 0; --i) { labels.push(''); } for (const v of m.scale) { const pos = (v - m.min) / (m.max - m.min) * len; labels[Math.round(pos)] = v.toString(); } return labels; } set(x, y, v) { this.matrix[Math.round(x) + (Math.round(y)) * this.width] = v; this.lastx = x; this.lasty = y; } get(x, y) { return this.matrix[Math.round(x) + (Math.round(y)) * this.width]; } line(x, y, v) { const dx = x - this.lastx; const dy = y - this.lasty; const maxd = Math.max(Math.abs(dx), Math.abs(dy)); for (let i = 0; i < Math.floor(maxd); ++i) { this.set(this.lastx + dx / maxd, this.lasty + dy / maxd, v); } this.set(x, y, v); } plot(x, y, v) { const xx = (x - this.x.min) / (this.x.max - this.x.min) * (this.width - 1); const yy = (y - this.y.min) / (this.y.max - this.y.min) * (this.height - 1); this.set(xx, yy, v); } plotLine(x, y, v) { const xx = (x - this.x.min) / (this.x.max - this.x.min) * (this.width - 1); const yy = (y - this.y.min) / (this.y.max - this.y.min) * (this.height - 1); this.line(xx, yy, v); } toRaster() { const pix = []; for (let y = Math.floor(this.height / 2) - 1; y >= 0; --y) { const vlabel = `${this.ylabels[y]}`; const p = (' '.repeat(6 - vlabel.length)) + vlabel; pix.push(p); for (let x = 0; x < Math.floor(this.width / 2); ++x) { const four = (this.get(2 * x, 2 * y) !== 0 ? 1 : 0) + (this.get(2 * x + 1, 2 * y) !== 0 ? 2 : 0) + (this.get(2 * x, 2 * y + 1) !== 0 ? 4 : 0) + (this.get(2 * x + 1, 2 * y + 1) !== 0 ? 8 : 0); const color = Math.max(this.get(2 * x, 2 * y), this.get(2 * x + 1, 2 * y), this.get(2 * x, 2 * y + 1), this.get(2 * x + 1, 2 * y + 1)); pix.push(chalk.ansi256(color)(this.murks[four])); } pix.push('\n'); } pix.push(this.xlabel); pix.push(' ' + this.header.map((s, i) => chalk.ansi256(i + 8)(s)).join(' ')); return pix.join(''); } toString() { function chunk(arr, chunkSize) { if (chunkSize <= 0) throw new Error('Invalid chunk size'); const R = []; for (let i = 0, len = arr.length; i < len; i += chunkSize) { R.push(arr.slice(i, i + chunkSize)); } return R; } return (chunk(this.matrix, this.width).map(line => line.join('')).reverse().join('\n')); } static drawGraph(table, header) { const minval = (table).map(a => a.reduce(min)).reduce(min); const maxval = (table).map(a => a.reduce(max)).reduce(max); const terminalwidth = process.stdout.columns !== undefined ? process.stdout.columns : 80; const matrix = new Matrix(terminalwidth, 19, 0, minval, table[0].length, maxval, header); table.forEach((row, i) => { row.forEach((value, j) => { if (j === 0) { matrix.plot(0, value, i + 8); } else { matrix.plotLine(j, value, i + 8); } }); }); return matrix.toRaster(); } static drawXY(table, header) { const minvalx = table.map(a => a[0]).reduce(min); const maxvalx = table.map(a => a[0]).reduce(max); const minvaly = table.map(a => a[1]).reduce(min); const maxvaly = table.map(a => a[1]).reduce(max); const terminalwidth = process.stdout.columns !== undefined ? process.stdout.columns : 80; const matrix = new Matrix(terminalwidth, 40, minvalx, minvaly, maxvalx, maxvaly, header); table.forEach((row, j) => { if (j === 0) { matrix.plot(row[0], row[1], 8); } else { matrix.plotLine(row[0], row[1], 8 + 1); } }); return matrix.toRaster(); } } export function max(a, b) { return +a > +b ? +a : +b; } export function min(a, b) { return +a < +b ? +a : +b; }