UNPKG

leetcode-fetcher-cli

Version:

A CLi Application for local fetching of leetcode problems

261 lines (260 loc) 10.5 kB
"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;