@jondotsoy/flags
Version:
A Javascript arguments processor
182 lines • 15.4 kB
JavaScript
// Remove ANSI escape codes to calculate visible length
const stripAnsi = (text) => {
return text.replace(/\x1b\[[0-9;]*m/g, "");
};
const wrapText = (text, maxWidth) => {
if (maxWidth === Infinity) {
return [text];
}
const words = text.split(/\s+/);
const lines = [];
let currentLine = "";
for (const word of words) {
if (!currentLine) {
currentLine = word;
}
else {
const testLine = `${currentLine} ${word}`;
// Use visible length (without ANSI codes) for width calculation
const visibleLength = stripAnsi(testLine).length;
if (visibleLength <= maxWidth) {
currentLine = testLine;
}
else {
lines.push(currentLine);
currentLine = word;
}
}
}
if (currentLine) {
lines.push(currentLine);
}
return lines;
};
export const helpMessage = (flagsParser, schema, options) => {
const terminalWidth = options?.terminalWidth ?? process.stdout.columns ?? 80;
const noColor = options?.noColor ?? false;
const lines = [];
// Usage line
lines.push(`Usage: ${flagsParser.metadata.program}`);
lines.push("");
// Description
if (flagsParser.metadata.description) {
const wrappedLines = wrapText(flagsParser.metadata.description, terminalWidth);
lines.push(...wrappedLines);
lines.push("");
}
// Collect flags and commands
const flags = [];
const commands = [];
for (const [key, builder] of Object.entries(schema)) {
const spec = builder.spec;
const description = spec.hasMetadata("description")
? spec.getMetadata("description")
: undefined;
// Check if it's a command by checking the builder type
const builderName = builder.constructor.name;
const isCommand = builderName.includes("Command");
if (isCommand) {
// For commands, we need to extract the command name from the refiners
// Commands use argumentMatchRefine which checks for exact string match
const refiners = spec.getRefiners();
let commandName = key;
// Try to extract command name from the refiner
if (refiners.length > 0) {
// The argumentMatchRefine stores the match string in its closure
// We'll use the key as fallback
commandName = key;
}
commands.push({
name: commandName,
description,
});
}
else {
// It's a flag
const matches = spec.hasMetadata("matches")
? spec.getMetadata("matches")
: [];
if (matches.length > 0) {
const initial = spec.getInitial();
let type = "boolean";
let hasDefault = false;
// Determine type based on initial value
if (initial === null) {
type = "string"; // Could be number or string, default to string
}
else if (typeof initial === "number") {
type = "number";
hasDefault = true;
}
else if (typeof initial === "string") {
type = "string";
hasDefault = true;
}
else if (typeof initial === "boolean") {
type = "boolean";
}
else if (Array.isArray(initial)) {
type = "array";
}
flags.push({
names: matches,
type,
description,
hasDefault,
});
}
}
}
// Print Options section
if (flags.length > 0) {
lines.push("Options:");
for (const flag of flags) {
// Sort names: short flags first (single dash), then long flags (double dash)
const sortedNames = [...flag.names].sort((a, b) => {
const aIsShort = a.startsWith("-") && !a.startsWith("--");
const bIsShort = b.startsWith("-") && !b.startsWith("--");
if (aIsShort && !bIsShort)
return -1;
if (!aIsShort && bIsShort)
return 1;
return 0;
});
// Check if there's a short flag
const hasShortFlag = sortedNames.some((name) => name.startsWith("-") && !name.startsWith("--"));
const namesStr = sortedNames.join(", ");
// For boolean flags, add a period instead of type
// For flags with defaults, show the type
// For flags without defaults (null initial), don't show type
let flagPart;
if (flag.type === "boolean") {
flagPart = `${namesStr}.`;
}
else if (flag.hasDefault) {
flagPart = `${namesStr} <${flag.type}>`;
}
else {
flagPart = namesStr;
}
const descStr = flag.description || "";
// If there's no short flag, add extra padding to align with flags that have short flags
// Short flags are typically "-X, " which is 4 characters
const indent = hasShortFlag ? " " : " ";
const totalFlagLength = indent.length + flagPart.length;
const padding = " ".repeat(Math.max(1, 27 - totalFlagLength));
// Wrap description if it's too long
if (descStr) {
const descIndent = indent.length + flagPart.length + padding.length;
const availableWidth = terminalWidth - descIndent;
const descLines = wrapText(descStr, availableWidth);
if (descLines.length > 0) {
// First line goes on the same line as the flag
lines.push(`${indent}${flagPart}${padding}${descLines[0]}`);
// Subsequent lines are indented to align with the first line of description
const descIndentStr = " ".repeat(descIndent);
for (let i = 1; i < descLines.length; i++) {
lines.push(`${descIndentStr}${descLines[i]}`);
}
}
else {
lines.push(`${indent}${flagPart}${padding}`);
}
}
else {
lines.push(`${indent}${flagPart}${padding}`);
}
}
lines.push("");
}
// Print Commands section
if (commands.length > 0) {
lines.push("Commands:");
for (const cmd of commands) {
const nameStr = cmd.name;
const descStr = cmd.description || "";
const padding = " ".repeat(Math.max(1, 25 - nameStr.length));
lines.push(` ${nameStr}${padding}${descStr}`);
}
}
return lines.join("\n") + "\n";
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC1tZXNzYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL2hlbHAtbWVzc2FnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFRQSx1REFBdUQ7QUFDdkQsTUFBTSxTQUFTLEdBQUcsQ0FBQyxJQUFZLEVBQVUsRUFBRTtJQUN6QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0MsQ0FBQyxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFZLEVBQUUsUUFBZ0IsRUFBWSxFQUFFO0lBQzVELElBQUksUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQixDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoQyxNQUFNLEtBQUssR0FBYSxFQUFFLENBQUM7SUFDM0IsSUFBSSxXQUFXLEdBQUcsRUFBRSxDQUFDO0lBRXJCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLFdBQVcsR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLFFBQVEsR0FBRyxHQUFHLFdBQVcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMxQyxnRUFBZ0U7WUFDaEUsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQztZQUVqRCxJQUFJLGFBQWEsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDOUIsV0FBVyxHQUFHLFFBQVEsQ0FBQztZQUN6QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDeEIsV0FBVyxHQUFHLElBQUksQ0FBQztZQUNyQixDQUFD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