hereby
Version:
A simple task runner
81 lines (80 loc) • 3.86 kB
JavaScript
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 names = visibleTasks.map((task) => task === defaultTask ? `${style.green(task.options.name)} (default)` : style.blue(task.options.name));
const descriptions = visibleTasks.map((task) => {
var _a, _b;
let parts = task.options.description ? [task.options.description] : undefined;
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) {
const depNames = deps.map((task) => style.blue(task.options.name));
(parts !== null && parts !== void 0 ? parts : (parts = [])).push(`Depends on: ${depNames.join(", ")}`);
}
return (_b = parts === null || parts === void 0 ? void 0 : parts.join("\n")) !== null && _b !== void 0 ? _b : "";
});
// 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, ...names.map(visibleLength));
// 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 = names.map((name, i) => formatAsColumns(" ", name, nameWidth, descriptions[i], descriptionWidth));
return `
${style.bold(style.underline("Available tasks"))}
${formatted.join("")}`;
}
function isTaskVisible(task) {
return !task.options.hiddenFromTaskList;
}
function formatAsColumns(indent, leftText, leftWidth, rightText, rightWidth) {
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 = leftLines[i] || "";
const rightPart = rightLines[i] || "";
const paddedLeft = leftPart + " ".repeat(Math.max(0, leftWidth - visibleLength(leftPart)));
result += `${indent}${paddedLeft} ${rightPart}\n`;
}
return result;
}
// eslint-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 = [];
maxWidth = Math.max(1, maxWidth);
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.trim()) {
result.push(current.trim());
current = "";
}
if (visibleLength(token) > maxWidth) {
// eslint-disable-next-line @typescript-eslint/no-misused-spread
const chars = [...token];
while (chars.length > 0)
result.push(chars.splice(0, maxWidth).join(""));
}
else {
current += /^\s/.test(token) && !current ? "" : token;
}
}
if (current.trim())
result.push(current.trim());
}
return result.length > 0 ? result : [""];
}
//# sourceMappingURL=formatTasks.js.map