UNPKG

hereby

Version:
87 lines (86 loc) • 4.13 kB
import * as style from "./style.js"; import { compareTaskNames } from "./utils.js"; export function formatTasks(format, tasks, defaultTask, columns) { const visibleTasks = [...tasks].filter(isTaskVisible).sort(compareTaskNames); if (format === "simple") { return visibleTasks.map((task) => task.options.name).join("\n"); } const rows = visibleTasks.map((task) => { var _a; const name = task === defaultTask ? `${style.green(task.options.name)} (default)` : style.blue(task.options.name); const parts = task.options.description ? [task.options.description] : []; const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(isTaskVisible).sort(compareTaskNames); if (deps === null || deps === void 0 ? void 0 : deps.length) { parts.push(`Depends on: ${deps.map((dep) => style.blue(dep.options.name)).join(", ")}`); } return { name, description: parts.join("\n") }; }); // There's a 2 space indent plus 3 spaces between columns, hence take away 5 // padding spaces from the available width. Keep widths positive so narrow // terminals still wrap safely. const maxTotalWidth = Math.max(1, columns - 5); const maxNameWidth = Math.max(1, ...rows.map((row) => visibleLength(row.name))); // Check the name doesn't take up more than half the space const nameWidth = Math.min(maxNameWidth, Math.max(1, maxTotalWidth >> 1)); const descriptionWidth = Math.max(1, maxTotalWidth - nameWidth); const formatted = rows.map((row) => formatAsColumns(" ", row.name, nameWidth, row.description, descriptionWidth)); return ` ${style.bold(style.underline("Available tasks"))} ${formatted.join("")}`; } function isTaskVisible(task) { return !task.options.hiddenFromTaskList; } function formatAsColumns(indent, leftText, leftWidth, rightText, rightWidth) { var _a, _b; const leftLines = wrapText(leftText, leftWidth); const rightLines = wrapText(rightText, rightWidth); const maxLines = Math.max(leftLines.length, rightLines.length); let result = ""; for (let i = 0; i < maxLines; i++) { const leftPart = (_a = leftLines[i]) !== null && _a !== void 0 ? _a : ""; const rightPart = (_b = rightLines[i]) !== null && _b !== void 0 ? _b : ""; // Only pad the left column when there's something to the right of it, // so we don't emit trailing whitespace. The clamp is needed because // wrapText chunks long tokens by code point, while visibleLength counts // UTF-16 code units; astral characters can overshoot leftWidth. const paddedLeft = leftPart + " ".repeat(Math.max(0, leftWidth - visibleLength(leftPart))); result += rightPart ? `${indent}${paddedLeft} ${rightPart}\n` : `${indent}${leftPart}\n`; } return result; } // oxlint-disable-next-line no-control-regex const ANSI_REGEX = /\u001B\[([0-9]{1,2})m/g; function visibleLength(str) { return str.replace(ANSI_REGEX, "").length; } const TOKEN_REGEX = /[^\s-]+?-\b|\S+|\s+/g; function wrapText(text, maxWidth) { var _a; const result = []; for (const line of text.split(/\r?\n/)) { let current = ""; for (const token of (_a = line.match(TOKEN_REGEX)) !== null && _a !== void 0 ? _a : []) { if (visibleLength(current) + visibleLength(token) > maxWidth && current) { result.push(current.trim()); current = ""; } if (visibleLength(token) > maxWidth) { // oxlint-disable-next-line typescript/no-misused-spread const chars = [...token]; while (chars.length > 0) result.push(chars.splice(0, maxWidth).join("")); } else { // Drop whitespace tokens that would otherwise start a line. current = current ? current + token : token.trimStart(); } } if (current) result.push(current.trim()); } return result; } //# sourceMappingURL=formatTasks.js.map