leetcode-fetcher-cli
Version:
A CLi Application for local fetching of leetcode problems
261 lines (260 loc) • 10.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = __importDefault(require("chalk"));
const generic = __importStar(require("../utils/general"));
const formatter = __importStar(require("../utils/formatter"));
const ascii = {
hb: "─", vb: "│",
dt: "┬", ut: "┴", lt: "┤", rt: "├",
adr: "┌", adl: "┐", aur: "└", aul: "┘",
cr: "┼", dhl: "═", dvl: "║", ddr: "╔",
dur: "╚", dul: "╝", ddl: "╗", dut: "╩",
ddt: "╦"
};
function getVisibleTextLength(input) {
// Regular expression to remove ANSI escape sequences
const strippedText = input.replace(/\x1b\]8;;.*?\x1b\\|\x1b\]8;;\x1b\\/g, '');
return strippedText.length;
}
class TablePrinter {
ncols = 0;
nrows = 0;
columns = [];
cprops = [];
padding = [2, 3, 2];
rows = [];
rowsizes = [];
title;
showLines = true;
header = true;
show_title = true;
constructor(title, cols, props) {
// If both columns and props are given check that the dimensions matches.
if (cols !== undefined && props !== undefined) {
if (cols.length !== props.length) {
console.error(chalk_1.default.redBright("Not enough properties or columns"));
throw new Error("Error");
}
}
// If only columns are defined or in general the columns parameter
// is not undefined than we can set the columns and a number of
// default properties.
if (cols !== undefined) {
this.columns = cols;
this.ncols = cols.length;
this.cprops = Array(this.ncols).fill({ size: 20, just: 0 });
}
// If also or only properties are defined, then we can set the
// properties. We have already check the two dimensions matches
// and we can set the values correspondly.
if (props !== undefined) {
this.cprops = this.cprops = props.map((x) => ({
size: x.size,
style: x.style || ((x) => x),
just: x.just || 0
}));
this.ncols = this.cprops.length;
// If columns are undefined or empty then set the show columsn to false
if ((!cols) || (cols.length == 0)) {
this.header = false;
}
}
this.title = title ?? "";
this.showTitle = (title !== undefined || title !== null);
}
getContentSize(content) {
return (typeof content == "string") ? getVisibleTextLength(content)
: getVisibleTextLength(content.toString());
}
getRowVerticalSize(content) {
const rows_vsize = content.map((x, idx) => {
const x_size = this.getContentSize(x);
return Math.ceil(x_size / this.cprops[idx].size);
});
return Math.max(...rows_vsize, 1);
}
checkContentLen = (clen) => {
if (clen !== this.ncols) {
console.error(chalk_1.default.redBright(`Input content has `
+ `${clen} columns instead of ${this.ncols}.`));
return false;
}
return true;
};
valueToString(x) {
return (typeof x == 'string') ? x : x.toString();
}
getContent(content, idx, header) {
const properties = this.cprops[idx];
const style = (header) ? (x) => chalk_1.default.bold(x.toUpperCase()) : properties.style;
const content_just = (header) ? 0 : properties.just;
return style(formatter.JustifyString(content, properties.size, content_just));
}
line(x) {
return (this.showLines) ? x : '';
}
contentToString(content, header) {
const c = content.map((y, idx) => this.getContent(this.valueToString(y), idx, header)).join(` ${this.line(ascii.vb)} `);
const s = (this.showLine) ? ' ' : '';
return `${this.line(ascii.vb)}${s}${c}${s}${this.line(ascii.vb)}`;
}
rowToString(row_idx, vsize) {
const rows = this.rows.slice(row_idx, row_idx + vsize);
return rows.map((x) => this.contentToString(x)).join("\n");
}
addColumn(name, prop) {
this.columns.push(name);
this.cprops.push({
size: prop.size,
style: prop.style || ((x) => x),
just: prop.just || 0
});
this.ncols++;
}
pushRow(...content) {
if (!this.checkContentLen(content.length))
return;
const vsize = this.getRowVerticalSize(content);
this.rowsizes.push(vsize);
if (vsize < 2) {
this.rows.push(content);
this.nrows += vsize;
return;
}
// If the vertical size if > 1 we need to split the row
const rows = content.map((x, idx) => {
const size = this.getContentSize(x);
const colsize = this.cprops[idx].size;
const x_str = this.valueToString(x);
// If the current content size is less than the column size
// we can just returns the content and then a number of spaces
if (size < colsize) {
return [x_str, ...Array(vsize - 1).fill(" ")];
}
// Otherwise we need to cut the content
return Array.from({ length: vsize }, (_, i) => i).map((i) => {
const start_idx = i * colsize;
if (start_idx > size)
return " ";
const stop_idx = Math.min((i + 1) * colsize, size);
return x_str.slice(start_idx, stop_idx);
});
});
this.rows = [...this.rows, ...generic.Transpose(rows)];
this.nrows += vsize;
}
getWidth() {
const sizes = this.cprops.map((x) => x.size);
return generic.ArraySum(...sizes) + 2 * this.padding[0]
+ this.padding[1] * (this.ncols - 1);
}
get showLine() {
return this.showLines;
}
set showLine(value) {
this.showLines = value;
}
get showHeader() {
return this.header;
}
set showHeader(value) {
this.header = value;
}
get showTitle() {
return this.show_title;
}
set showTitle(value) {
this.show_title = value;
}
getColumnSize(col_idx) {
const column = generic.Transpose(this.rows)[col_idx];
return Math.max(...column.map((x) => this.getContentSize(x)));
}
fitColumnSize() {
let total_size = 1 + this.padding[1] * (this.ncols - 1);
for (let i = 0; i < this.ncols; i++) {
const actual_size = this.getColumnSize(i);
this.cprops[i].size = Math.min(actual_size, this.cprops[i].size);
if (this.columns[i] !== undefined) {
this.cprops[i].size = Math.max(this.cprops[i].size, this.columns[i].length);
}
total_size += this.cprops[i].size;
}
// Check if the total size is grater then the current terminal window size
const [terminal_w, _] = process.stdout.getWindowSize();
if (total_size > terminal_w) {
console.warn(chalk_1.default.yellowBright(`[WARNING] Total table width is grater then ` +
`current terminal window size (${total_size} > ${terminal_w}).`));
}
}
toString() {
// Before transforming the table into a string we need to re-fit the columns
this.fitColumnSize();
const formatBasicLine = (start, end, sep1, sep2) => {
const middle_content = this.cprops.map((x) => Array(x.size + this.padding[0]).fill(this.line(sep1)).join(""))
.join(this.line(sep2));
return `${this.line(start)}${middle_content}${this.line(end)}`;
};
// Let's construct the first basic lines of ascii characters
const t_upper = formatBasicLine(ascii.adr, ascii.adl, ascii.hb, ascii.dt);
const t_middle = formatBasicLine(ascii.rt, ascii.lt, ascii.hb, ascii.cr);
const t_lower = formatBasicLine(ascii.aur, ascii.aul, ascii.hb, ascii.ut);
let formatted_rows = [];
let current_row_idx = 0;
for (const vsize of this.rowsizes) {
formatted_rows.push(this.rowToString(current_row_idx, vsize));
current_row_idx += vsize;
}
const middle_del = (this.showLine) ? `\n${t_middle}\n` : '\n';
const content = formatted_rows.join(middle_del);
const header = this.contentToString(this.columns, true);
let title_str = "";
if (this.title.length > 0) {
const table_size = this.getWidth();
const title = formatter.JustifyString(this.title, table_size, 0);
title_str = `${chalk_1.default.bold(title)}\n`;
}
// Formats the table
const prefix = (this.header) ? `${t_upper}\n${header}\n${t_middle}` : `${t_upper}`;
const table = `${(this.show_title) ? title_str : ''}${prefix}\n${content}\n${t_lower}`;
return table;
}
}
;
exports.default = TablePrinter;