first commit
This commit is contained in:
33
node_modules/@oclif/core/lib/help/command.d.ts
generated
vendored
Normal file
33
node_modules/@oclif/core/lib/help/command.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Command } from '../command';
|
||||
import * as Interfaces from '../interfaces';
|
||||
import { HelpFormatter, HelpSectionRenderer } from './formatter';
|
||||
export declare class CommandHelp extends HelpFormatter {
|
||||
command: Command.Loadable;
|
||||
config: Interfaces.Config;
|
||||
opts: Interfaces.HelpOptions;
|
||||
constructor(command: Command.Loadable, config: Interfaces.Config, opts: Interfaces.HelpOptions);
|
||||
protected aliases(aliases: string[] | undefined): string | undefined;
|
||||
protected arg(arg: Command.Arg.Any): string;
|
||||
protected args(args: Command.Arg.Any[]): [string, string | undefined][] | undefined;
|
||||
protected defaultUsage(): string;
|
||||
protected description(): string | undefined;
|
||||
protected examples(examples: Command.Example[] | string | undefined): string | undefined;
|
||||
protected flagHelpLabel(flag: Command.Flag.Any, showOptions?: boolean): string;
|
||||
protected flags(flags: Array<Command.Flag.Any>): [string, string | undefined][] | undefined;
|
||||
protected flagsDescriptions(flags: Array<Command.Flag.Any>): string | undefined;
|
||||
generate(): string;
|
||||
protected groupFlags(flags: Array<Command.Flag.Any>): {
|
||||
flagGroups: {
|
||||
[name: string]: Array<Command.Flag.Any>;
|
||||
};
|
||||
mainFlags: Array<Command.Flag.Any>;
|
||||
};
|
||||
protected sections(): Array<{
|
||||
generate: HelpSectionRenderer;
|
||||
header: string;
|
||||
}>;
|
||||
protected usage(): string;
|
||||
private formatIfCommand;
|
||||
private isCommand;
|
||||
}
|
||||
export default CommandHelp;
|
||||
338
node_modules/@oclif/core/lib/help/command.js
generated
vendored
Normal file
338
node_modules/@oclif/core/lib/help/command.js
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CommandHelp = void 0;
|
||||
const ansis_1 = __importDefault(require("ansis"));
|
||||
const ensure_arg_object_1 = require("../util/ensure-arg-object");
|
||||
const ids_1 = require("../util/ids");
|
||||
const util_1 = require("../util/util");
|
||||
const theme_1 = require("../ux/theme");
|
||||
const docopts_1 = require("./docopts");
|
||||
const formatter_1 = require("./formatter");
|
||||
// Don't use os.EOL because we need to ensure that a string
|
||||
// written on any platform, that may use \r\n or \n, will be
|
||||
// split on any platform, not just the os specific EOL at runtime.
|
||||
const POSSIBLE_LINE_FEED = /\r\n|\n/;
|
||||
/**
|
||||
* Determines the sort order of flags. Will default to alphabetical if not set or set to an invalid value.
|
||||
*/
|
||||
function determineSortOrder(flagSortOrder) {
|
||||
if (flagSortOrder === 'alphabetical')
|
||||
return 'alphabetical';
|
||||
if (flagSortOrder === 'none')
|
||||
return 'none';
|
||||
return 'alphabetical';
|
||||
}
|
||||
class CommandHelp extends formatter_1.HelpFormatter {
|
||||
command;
|
||||
config;
|
||||
opts;
|
||||
constructor(command, config, opts) {
|
||||
super(config, opts);
|
||||
this.command = command;
|
||||
this.config = config;
|
||||
this.opts = opts;
|
||||
}
|
||||
aliases(aliases) {
|
||||
if (!aliases || aliases.length === 0)
|
||||
return;
|
||||
const body = aliases
|
||||
.map((a) => [
|
||||
(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$'),
|
||||
(0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin),
|
||||
(0, theme_1.colorize)(this.config?.theme?.alias, a),
|
||||
].join(' '))
|
||||
.join('\n');
|
||||
return body;
|
||||
}
|
||||
arg(arg) {
|
||||
const name = arg.name.toUpperCase();
|
||||
if (arg.required)
|
||||
return `${name}`;
|
||||
return `[${name}]`;
|
||||
}
|
||||
args(args) {
|
||||
if (args.filter((a) => a.description).length === 0)
|
||||
return;
|
||||
return args.map((a) => {
|
||||
// Add ellipsis to indicate that the argument takes multiple values if strict is false
|
||||
let name = this.command.strict === false ? `${a.name.toUpperCase()}...` : a.name.toUpperCase();
|
||||
name = a.required ? `${name}` : `[${name}]`;
|
||||
let description = a.description || '';
|
||||
if (a.default)
|
||||
description = `${(0, theme_1.colorize)(this.config?.theme?.flagDefaultValue, `[default: ${a.default}]`)} ${description}`;
|
||||
if (a.options)
|
||||
description = `${(0, theme_1.colorize)(this.config?.theme?.flagOptions, `(${a.options.join('|')})`)} ${description}`;
|
||||
return [
|
||||
(0, theme_1.colorize)(this.config?.theme?.flag, name),
|
||||
description ? (0, theme_1.colorize)(this.config?.theme?.sectionDescription, description) : undefined,
|
||||
];
|
||||
});
|
||||
}
|
||||
defaultUsage() {
|
||||
// Docopts by default
|
||||
if (this.opts.docopts === undefined || this.opts.docopts) {
|
||||
return docopts_1.DocOpts.generate(this.command);
|
||||
}
|
||||
return (0, util_1.compact)([
|
||||
this.command.id,
|
||||
Object.values(this.command.args ?? {})
|
||||
?.filter((a) => !a.hidden)
|
||||
.map((a) => this.arg(a))
|
||||
.join(' '),
|
||||
]).join(' ');
|
||||
}
|
||||
description() {
|
||||
const cmd = this.command;
|
||||
let description;
|
||||
if (this.opts.hideCommandSummaryInDescription) {
|
||||
description = [(cmd.description || '').split(POSSIBLE_LINE_FEED).at(-1) ?? ''];
|
||||
}
|
||||
else if (cmd.description) {
|
||||
const summary = cmd.summary ? `${cmd.summary}\n` : null;
|
||||
description = summary
|
||||
? [...summary.split(POSSIBLE_LINE_FEED), ...(cmd.description || '').split(POSSIBLE_LINE_FEED)]
|
||||
: (cmd.description || '').split(POSSIBLE_LINE_FEED);
|
||||
}
|
||||
if (description) {
|
||||
return this.wrap(description.join('\n'));
|
||||
}
|
||||
}
|
||||
examples(examples) {
|
||||
if (!examples || examples.length === 0)
|
||||
return;
|
||||
const body = (0, util_1.castArray)(examples)
|
||||
.map((a) => {
|
||||
let description;
|
||||
let commands;
|
||||
if (typeof a === 'string') {
|
||||
const lines = a.split(POSSIBLE_LINE_FEED).filter(Boolean);
|
||||
// If the example is <description>\n<command> then format correctly
|
||||
if (lines.length >= 2 && !this.isCommand(lines[0]) && lines.slice(1).every((i) => this.isCommand(i))) {
|
||||
description = lines[0];
|
||||
commands = lines.slice(1);
|
||||
}
|
||||
else {
|
||||
return lines.map((line) => this.formatIfCommand(line)).join('\n');
|
||||
}
|
||||
}
|
||||
else {
|
||||
description = a.description;
|
||||
commands = [a.command];
|
||||
}
|
||||
const multilineSeparator = this.config.platform === 'win32' ? (this.config.shell.includes('powershell') ? '`' : '^') : '\\';
|
||||
// The command will be indented in the section, which is also indented
|
||||
const finalIndentedSpacing = this.indentSpacing * 2;
|
||||
const multilineCommands = commands
|
||||
.map((c) =>
|
||||
// First indent keeping room for escaped newlines
|
||||
this.indent(this.wrap(this.formatIfCommand(c), finalIndentedSpacing + 4))
|
||||
// Then add the escaped newline
|
||||
.split(POSSIBLE_LINE_FEED)
|
||||
.join(` ${multilineSeparator}\n `))
|
||||
.join('\n');
|
||||
return `${this.wrap(description, finalIndentedSpacing)}\n\n${multilineCommands}`;
|
||||
})
|
||||
.join('\n\n');
|
||||
return body;
|
||||
}
|
||||
flagHelpLabel(flag, showOptions = false) {
|
||||
let label = flag.helpLabel;
|
||||
if (!label) {
|
||||
const labels = [];
|
||||
labels.push(flag.char ? `-${flag.char[0]}` : ' ');
|
||||
if (flag.name) {
|
||||
if (flag.type === 'boolean' && flag.allowNo) {
|
||||
labels.push(`--[no-]${flag.name.trim()}`);
|
||||
}
|
||||
else {
|
||||
labels.push(`--${flag.name.trim()}`);
|
||||
}
|
||||
}
|
||||
label = labels.join(flag.char ? (0, theme_1.colorize)(this.config?.theme?.flagSeparator, ', ') : ' ');
|
||||
}
|
||||
if (flag.type === 'option') {
|
||||
let value = docopts_1.DocOpts.formatUsageType(flag, this.opts.showFlagNameInTitle ?? false, this.opts.showFlagOptionsInTitle ?? showOptions);
|
||||
if (!value.includes('|'))
|
||||
value = (0, theme_1.colorize)('underline', value);
|
||||
label += `=${value}`;
|
||||
}
|
||||
return (0, theme_1.colorize)(this.config.theme?.flag, label);
|
||||
}
|
||||
flags(flags) {
|
||||
if (flags.length === 0)
|
||||
return;
|
||||
const noChar = flags.reduce((previous, current) => previous && current.char === undefined, true);
|
||||
// eslint-disable-next-line complexity
|
||||
return flags.map((flag) => {
|
||||
let left = this.flagHelpLabel(flag);
|
||||
if (noChar)
|
||||
left = left.replace(' ', '');
|
||||
let right = flag.summary || flag.description || '';
|
||||
const canBeCached = !(this.opts.respectNoCacheDefault === true && flag.noCacheDefault === true);
|
||||
if (flag.type === 'option' && flag.default && canBeCached) {
|
||||
right = `${(0, theme_1.colorize)(this.config?.theme?.flagDefaultValue, `[default: ${flag.default}]`)} ${right}`;
|
||||
}
|
||||
if (flag.required)
|
||||
right = `${(0, theme_1.colorize)(this.config?.theme?.flagRequired, '(required)')} ${right}`;
|
||||
if (flag.type === 'option' && flag.options && !flag.helpValue && !this.opts.showFlagOptionsInTitle) {
|
||||
right += (0, theme_1.colorize)(this.config?.theme?.flagOptions, `\n<options: ${flag.options.join('|')}>`);
|
||||
}
|
||||
return [left, (0, theme_1.colorize)(this.config?.theme?.sectionDescription, right.trim())];
|
||||
});
|
||||
}
|
||||
flagsDescriptions(flags) {
|
||||
const flagsWithExtendedDescriptions = flags.filter((flag) => flag.summary && flag.description);
|
||||
if (flagsWithExtendedDescriptions.length === 0)
|
||||
return;
|
||||
const body = flagsWithExtendedDescriptions
|
||||
.map((flag) => {
|
||||
// Guaranteed to be set because of the filter above, but make ts happy
|
||||
const summary = flag.summary || '';
|
||||
let flagHelp = this.flagHelpLabel(flag, true);
|
||||
if (!flag.char)
|
||||
flagHelp = flagHelp.replace(' ', '');
|
||||
flagHelp +=
|
||||
flagHelp.length + summary.length + 2 < this.opts.maxWidth
|
||||
? ' ' + summary
|
||||
: '\n\n' + this.indent(this.wrap(summary, this.indentSpacing * 2));
|
||||
return `${flagHelp}\n\n${this.indent(this.wrap(flag.description || '', this.indentSpacing * 2))}`;
|
||||
})
|
||||
.join('\n\n');
|
||||
return body;
|
||||
}
|
||||
generate() {
|
||||
const cmd = this.command;
|
||||
const unsortedFlags = Object.entries(cmd.flags || {})
|
||||
.filter(([, v]) => !v.hidden)
|
||||
.map(([k, v]) => {
|
||||
v.name = k;
|
||||
return v;
|
||||
});
|
||||
const flags = determineSortOrder(this.opts.flagSortOrder) === 'alphabetical'
|
||||
? (0, util_1.sortBy)(unsortedFlags, (f) => [!f.char, f.char, f.name])
|
||||
: unsortedFlags;
|
||||
const args = Object.values((0, ensure_arg_object_1.ensureArgObject)(cmd.args)).filter((a) => !a.hidden);
|
||||
const output = (0, util_1.compact)(this.sections().map(({ generate, header }) => {
|
||||
const body = generate({ args, cmd, flags }, header);
|
||||
// Generate can return a list of sections
|
||||
if (Array.isArray(body)) {
|
||||
return body
|
||||
.map((helpSection) => helpSection && helpSection.body && this.section(helpSection.header, helpSection.body))
|
||||
.join('\n\n');
|
||||
}
|
||||
return body && this.section(header, body);
|
||||
})).join('\n\n');
|
||||
return output;
|
||||
}
|
||||
groupFlags(flags) {
|
||||
const mainFlags = [];
|
||||
const flagGroups = {};
|
||||
for (const flag of flags) {
|
||||
const group = flag.helpGroup;
|
||||
if (group) {
|
||||
if (!flagGroups[group])
|
||||
flagGroups[group] = [];
|
||||
flagGroups[group].push(flag);
|
||||
}
|
||||
else {
|
||||
mainFlags.push(flag);
|
||||
}
|
||||
}
|
||||
return { flagGroups, mainFlags };
|
||||
}
|
||||
sections() {
|
||||
const sections = [
|
||||
{
|
||||
generate: () => this.usage(),
|
||||
header: this.opts.usageHeader || 'USAGE',
|
||||
},
|
||||
{
|
||||
generate: ({ args }, header) => [{ body: this.args(args), header }],
|
||||
header: 'ARGUMENTS',
|
||||
},
|
||||
{
|
||||
generate: ({ flags }, header) => {
|
||||
const { flagGroups, mainFlags } = this.groupFlags(flags);
|
||||
const flagSections = [];
|
||||
const mainFlagBody = this.flags(mainFlags);
|
||||
if (mainFlagBody)
|
||||
flagSections.push({ body: mainFlagBody, header });
|
||||
for (const [name, flags] of Object.entries(flagGroups)) {
|
||||
const body = this.flags(flags);
|
||||
if (body)
|
||||
flagSections.push({ body, header: `${name.toUpperCase()} ${header}` });
|
||||
}
|
||||
return (0, util_1.compact)(flagSections);
|
||||
},
|
||||
header: 'FLAGS',
|
||||
},
|
||||
{
|
||||
generate: () => this.description(),
|
||||
header: 'DESCRIPTION',
|
||||
},
|
||||
{
|
||||
generate: ({ cmd }) => this.aliases(cmd.aliases),
|
||||
header: 'ALIASES',
|
||||
},
|
||||
{
|
||||
generate: ({ cmd }) => {
|
||||
const examples = cmd.examples || cmd.example;
|
||||
return this.examples(examples);
|
||||
},
|
||||
header: 'EXAMPLES',
|
||||
},
|
||||
{
|
||||
generate: ({ flags }) => this.flagsDescriptions(flags),
|
||||
header: 'FLAG DESCRIPTIONS',
|
||||
},
|
||||
];
|
||||
const allowedSections = this.opts.sections?.map((s) => s.toLowerCase());
|
||||
return sections.filter(({ header }) => !allowedSections || allowedSections.includes(header.toLowerCase()));
|
||||
}
|
||||
usage() {
|
||||
const { id, usage } = this.command;
|
||||
const standardId = (0, ids_1.toStandardizedId)(id, this.config);
|
||||
const configuredId = (0, ids_1.toConfiguredId)(id, this.config);
|
||||
const body = (usage ? (0, util_1.castArray)(usage) : [this.defaultUsage()])
|
||||
.map((u) => {
|
||||
const allowedSpacing = this.opts.maxWidth - this.indentSpacing;
|
||||
const dollarSign = (0, theme_1.colorize)(this.config?.theme?.dollarSign, '$');
|
||||
const bin = (0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin);
|
||||
const command = (0, theme_1.colorize)(this.config?.theme?.command, '<%= command.id %>');
|
||||
const commandDescription = (0, theme_1.colorize)(this.config?.theme?.sectionDescription, u
|
||||
.replace('<%= command.id %>', '')
|
||||
.replace(new RegExp(`^${standardId}`), '')
|
||||
.replace(new RegExp(`^${configuredId}`), '')
|
||||
.trim());
|
||||
const line = `${dollarSign} ${bin} ${command} ${commandDescription}`.trim();
|
||||
if (line.length > allowedSpacing) {
|
||||
const splitIndex = line.slice(0, Math.max(0, allowedSpacing)).lastIndexOf(' ');
|
||||
return (line.slice(0, Math.max(0, splitIndex)) +
|
||||
'\n' +
|
||||
this.indent(this.wrap(line.slice(Math.max(0, splitIndex)), this.indentSpacing * 2)));
|
||||
}
|
||||
return this.wrap(line);
|
||||
})
|
||||
.join('\n');
|
||||
return body;
|
||||
}
|
||||
formatIfCommand(example) {
|
||||
example = this.render(example);
|
||||
const dollarSign = (0, theme_1.colorize)(this.config?.theme?.dollarSign, '$');
|
||||
if (example.startsWith(this.config.bin))
|
||||
return `${dollarSign} ${example}`;
|
||||
if (example.startsWith(`$ ${this.config.bin}`))
|
||||
return `${dollarSign}${example.replace(`$`, '')}`;
|
||||
return example;
|
||||
}
|
||||
isCommand(example) {
|
||||
return ansis_1.default
|
||||
.strip(this.formatIfCommand(example))
|
||||
.startsWith(`${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${this.config.bin}`);
|
||||
}
|
||||
}
|
||||
exports.CommandHelp = CommandHelp;
|
||||
exports.default = CommandHelp;
|
||||
69
node_modules/@oclif/core/lib/help/docopts.d.ts
generated
vendored
Normal file
69
node_modules/@oclif/core/lib/help/docopts.d.ts
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Command } from '../command';
|
||||
/**
|
||||
* DocOpts - See http://docopt.org/.
|
||||
*
|
||||
* flag.exclusive: groups elements when one of the mutually exclusive cases is a required flag: (--apple | --orange)
|
||||
* flag.exclusive: groups elements when none of the mutually exclusive cases is required (optional flags): [--apple | --orange]
|
||||
* flag.dependsOn: specifies that if one element is present, then another one is required: (--apple --orange)
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* required: true,
|
||||
* exclusive: ['suitenames']
|
||||
* ...
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* type: 'array'
|
||||
* required: true
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> (-n <string> | -s <array>)
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* ...
|
||||
* excludes: ['suitenames']
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> [-n <string> | -s <string>]
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* ...
|
||||
* dependsOn: ['suitenames']
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* type: 'flag'
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> (-n <string> -s)
|
||||
*
|
||||
* TODO:
|
||||
* - Support nesting, eg:
|
||||
* Usage: my_program (--either-this <and-that> | <or-this>)
|
||||
* Usage: my_program [(<one-argument> <another-argument>)]
|
||||
*
|
||||
*/
|
||||
export declare class DocOpts {
|
||||
private cmd;
|
||||
private flagList;
|
||||
private flagMap;
|
||||
constructor(cmd: Command.Loadable);
|
||||
static formatUsageType(flag: Command.Flag.Any, showFlagName: boolean, showOptions: boolean): string;
|
||||
static generate(cmd: Command.Loadable): string;
|
||||
toString(): string;
|
||||
private combineElementsToFlag;
|
||||
private generateElements;
|
||||
private groupFlagElements;
|
||||
}
|
||||
197
node_modules/@oclif/core/lib/help/docopts.js
generated
vendored
Normal file
197
node_modules/@oclif/core/lib/help/docopts.js
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DocOpts = void 0;
|
||||
const ensure_arg_object_1 = require("../util/ensure-arg-object");
|
||||
/**
|
||||
* DocOpts - See http://docopt.org/.
|
||||
*
|
||||
* flag.exclusive: groups elements when one of the mutually exclusive cases is a required flag: (--apple | --orange)
|
||||
* flag.exclusive: groups elements when none of the mutually exclusive cases is required (optional flags): [--apple | --orange]
|
||||
* flag.dependsOn: specifies that if one element is present, then another one is required: (--apple --orange)
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* required: true,
|
||||
* exclusive: ['suitenames']
|
||||
* ...
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* type: 'array'
|
||||
* required: true
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> (-n <string> | -s <array>)
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* ...
|
||||
* excludes: ['suitenames']
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> [-n <string> | -s <string>]
|
||||
*
|
||||
* @example
|
||||
* {
|
||||
* name: 'classnames',
|
||||
* ...
|
||||
* dependsOn: ['suitenames']
|
||||
* },{
|
||||
* name: 'suitenames',
|
||||
* type: 'flag'
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Results in:
|
||||
* Usage: <%= command.id %> (-n <string> -s)
|
||||
*
|
||||
* TODO:
|
||||
* - Support nesting, eg:
|
||||
* Usage: my_program (--either-this <and-that> | <or-this>)
|
||||
* Usage: my_program [(<one-argument> <another-argument>)]
|
||||
*
|
||||
*/
|
||||
class DocOpts {
|
||||
cmd;
|
||||
flagList;
|
||||
flagMap;
|
||||
constructor(cmd) {
|
||||
this.cmd = cmd;
|
||||
// Create a new map with references to the flags that we can manipulate.
|
||||
this.flagMap = {};
|
||||
this.flagList = Object.entries(cmd.flags || {})
|
||||
.filter(([_, flag]) => !flag.hidden)
|
||||
.map(([name, flag]) => {
|
||||
this.flagMap[name] = flag;
|
||||
return flag;
|
||||
});
|
||||
}
|
||||
static formatUsageType(flag, showFlagName, showOptions) {
|
||||
if (flag.type !== 'option')
|
||||
return '';
|
||||
let helpValues;
|
||||
if (flag.helpValue) {
|
||||
// if there is a given helpValue, use it
|
||||
helpValues = typeof flag.helpValue === 'string' ? [flag.helpValue] : flag.helpValue;
|
||||
}
|
||||
else if (flag.options) {
|
||||
// if there are options, show them if wanted
|
||||
helpValues = [showOptions ? flag.options.join('|') : '<option>'];
|
||||
}
|
||||
else if (showFlagName) {
|
||||
helpValues = [flag.name];
|
||||
}
|
||||
else {
|
||||
// default to <value>
|
||||
helpValues = ['<value>'];
|
||||
}
|
||||
return helpValues.map((v) => `${v}${flag.multiple ? '...' : ''}`).join(' ');
|
||||
}
|
||||
static generate(cmd) {
|
||||
return new DocOpts(cmd).toString();
|
||||
}
|
||||
toString() {
|
||||
const opts = ['<%= command.id %>'];
|
||||
if (this.cmd.args) {
|
||||
// If strict is false, add ellipsis to indicate that the argument takes multiple values
|
||||
const suffix = this.cmd.strict === false ? '...' : '';
|
||||
const a = Object.values((0, ensure_arg_object_1.ensureArgObject)(this.cmd.args))
|
||||
.filter((arg) => !arg.hidden)
|
||||
.map((arg) => arg.required ? `${arg.name.toUpperCase()}${suffix}` : `[${arg.name.toUpperCase()}${suffix}]`) || [];
|
||||
opts.push(...a);
|
||||
}
|
||||
try {
|
||||
opts.push(...Object.values(this.groupFlagElements()));
|
||||
}
|
||||
catch {
|
||||
// If there is an error, just return no usage so we don't fail command help.
|
||||
opts.push(...this.flagList.map((flag) => {
|
||||
const name = flag.char ? `-${flag.char}` : `--${flag.name}`;
|
||||
if (flag.type === 'boolean')
|
||||
return name;
|
||||
return `${name}=${DocOpts.formatUsageType(flag, false, true)}`;
|
||||
}));
|
||||
}
|
||||
return opts.join(' ');
|
||||
}
|
||||
combineElementsToFlag(elementMap, flagName, flagNames, unionString) {
|
||||
if (!this.flagMap[flagName]) {
|
||||
return;
|
||||
}
|
||||
let isRequired = this.flagMap[flagName]?.required;
|
||||
if (typeof isRequired !== 'boolean' || !isRequired) {
|
||||
isRequired = flagNames.reduce((required, toCombine) => required || this.flagMap[toCombine]?.required || false, false);
|
||||
}
|
||||
for (const toCombine of flagNames) {
|
||||
elementMap[flagName] = `${elementMap[flagName] || ''}${unionString}${elementMap[toCombine] || ''}`;
|
||||
// We handled this flag, don't handle it again
|
||||
delete elementMap[toCombine];
|
||||
delete this.flagMap[toCombine];
|
||||
}
|
||||
elementMap[flagName] = isRequired ? `(${elementMap[flagName] || ''})` : `[${elementMap[flagName] || ''}]`;
|
||||
// We handled this flag, don't handle it again
|
||||
delete this.flagMap[flagName];
|
||||
}
|
||||
generateElements(elementMap = {}, flagGroups = []) {
|
||||
const elementStrs = [];
|
||||
for (const flag of flagGroups) {
|
||||
let type = '';
|
||||
// not all flags have short names
|
||||
const flagName = flag.char ? `-${flag.char}` : `--${flag.name}`;
|
||||
if (flag.type === 'option') {
|
||||
type = ` ${DocOpts.formatUsageType(flag, false, true)}`;
|
||||
}
|
||||
const element = `${flagName}${type}`;
|
||||
elementMap[flag.name] = element;
|
||||
elementStrs.push(element);
|
||||
}
|
||||
return elementStrs;
|
||||
}
|
||||
groupFlagElements() {
|
||||
const elementMap = {};
|
||||
// Generate all doc opt elements for combining
|
||||
// Show required flags first
|
||||
this.generateElements(elementMap, this.flagList.filter((flag) => flag.required));
|
||||
// Then show optional flags
|
||||
this.generateElements(elementMap, this.flagList.filter((flag) => !flag.required));
|
||||
for (const flag of this.flagList) {
|
||||
if (Array.isArray(flag.dependsOn)) {
|
||||
this.combineElementsToFlag(elementMap, flag.name, flag.dependsOn, ' ');
|
||||
}
|
||||
let exclusive;
|
||||
if (Array.isArray(flag.exclusive)) {
|
||||
exclusive = new Set(flag.exclusive);
|
||||
}
|
||||
if (Array.isArray(flag.combinable)) {
|
||||
const combinableFlags = new Set(flag.combinable);
|
||||
exclusive ??= new Set();
|
||||
for (const item of this.flagList) {
|
||||
// each flag not in the "combinable" list, is equivalent to an "exclusive" flag
|
||||
if (flag !== item && !combinableFlags.has(item.name)) {
|
||||
exclusive.add(item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exclusive !== undefined && exclusive.size > 0) {
|
||||
this.combineElementsToFlag(elementMap, flag.name, [...exclusive], ' | ');
|
||||
}
|
||||
}
|
||||
// Since combineElementsToFlag deletes the references in this.flags when it combines
|
||||
// them, this will go through the remaining list of uncombined elements.
|
||||
for (const remainingFlagName of Object.keys(this.flagMap)) {
|
||||
const remainingFlag = this.flagMap[remainingFlagName] || {};
|
||||
if (!remainingFlag.required) {
|
||||
elementMap[remainingFlag.name] = `[${elementMap[remainingFlag.name] || ''}]`;
|
||||
}
|
||||
}
|
||||
return elementMap;
|
||||
}
|
||||
}
|
||||
exports.DocOpts = DocOpts;
|
||||
96
node_modules/@oclif/core/lib/help/formatter.d.ts
generated
vendored
Normal file
96
node_modules/@oclif/core/lib/help/formatter.d.ts
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
import { Command } from '../command';
|
||||
import * as Interfaces from '../interfaces';
|
||||
export type HelpSectionKeyValueTable = {
|
||||
description: string;
|
||||
name: string;
|
||||
}[];
|
||||
export type HelpSection = {
|
||||
body: [string, string | undefined][] | HelpSectionKeyValueTable | string | undefined;
|
||||
header: string;
|
||||
} | undefined;
|
||||
export type HelpSectionRenderer = (data: {
|
||||
args: Command.Arg.Any[];
|
||||
cmd: Command.Loadable;
|
||||
flags: Command.Flag.Any[];
|
||||
}, header: string) => HelpSection | HelpSection[] | string | undefined;
|
||||
export declare class HelpFormatter {
|
||||
protected config: Interfaces.Config;
|
||||
indentSpacing: number;
|
||||
protected opts: Interfaces.HelpOptions;
|
||||
/**
|
||||
* Takes a string and replaces `<%= prop =>` with the value of prop, where prop is anything on
|
||||
* `config=Interfaces.Config` or `opts=Interface.HelpOptions`.
|
||||
*
|
||||
* ```javascript
|
||||
* `<%= config.bin =>` // will resolve to the bin defined in `pjson.oclif`.
|
||||
* ```
|
||||
*/
|
||||
render: (input: string) => string;
|
||||
constructor(config: Interfaces.Config, opts?: Partial<Interfaces.HelpOptions>);
|
||||
/**
|
||||
* Indent by `this.indentSpacing`. The text should be wrap based on terminal width before indented.
|
||||
*
|
||||
* In order to call indent multiple times on the same set or text, the caller must wrap based on
|
||||
* the number of times the text has been indented. For example.
|
||||
*
|
||||
* ```javascript
|
||||
* const body = `main line\n${indent(wrap('indented example line', 4))}`
|
||||
* const header = 'SECTION'
|
||||
* console.log(`${header}\n${indent(wrap(body))}`
|
||||
* ```
|
||||
* will output
|
||||
* ```
|
||||
* SECTION
|
||||
* main line
|
||||
* indented example line
|
||||
* ```
|
||||
*
|
||||
* If the terminal width was 24 and the `4` was not provided in the first wrap, it would like like the following.
|
||||
* ```
|
||||
* SECTION
|
||||
* main line
|
||||
* indented example
|
||||
* line
|
||||
* ```
|
||||
* @param body the text to indent
|
||||
* @param spacing the final number of spaces this text will be indented
|
||||
* @returns the formatted indented text
|
||||
*/
|
||||
indent(body: string, spacing?: number): string;
|
||||
renderList(input: (string | undefined)[][], opts: {
|
||||
indentation: number;
|
||||
multiline?: boolean | undefined;
|
||||
spacer?: string | undefined;
|
||||
stripAnsi?: boolean | undefined;
|
||||
}): string;
|
||||
section(header: string, body: [string, string | undefined][] | HelpSection | HelpSectionKeyValueTable | string): string;
|
||||
/**
|
||||
* Wrap text according to `opts.maxWidth` which is typically set to the terminal width. All text
|
||||
* will be rendered before bring wrapped, otherwise it could mess up the lengths.
|
||||
*
|
||||
* A terminal will automatically wrap text, so this method is primarily used for indented
|
||||
* text. For indented text, specify the indentation so it is taken into account during wrapping.
|
||||
*
|
||||
* Here is an example of wrapping with indentation.
|
||||
* ```
|
||||
* <------ terminal window width ------>
|
||||
* <---------- no indentation --------->
|
||||
* This is my text that will be wrapped
|
||||
* once it passes maxWidth.
|
||||
*
|
||||
* <- indent -><------ text space ----->
|
||||
* This is my text that will
|
||||
* be wrapped once it passes
|
||||
* maxWidth.
|
||||
*
|
||||
* <-- indent not taken into account ->
|
||||
* This is my text that will
|
||||
* be wrapped
|
||||
* once it passes maxWidth.
|
||||
* ```
|
||||
* @param body the text to wrap
|
||||
* @param spacing the indentation size to subtract from the terminal width
|
||||
* @returns the formatted wrapped text
|
||||
*/
|
||||
wrap(body: string, spacing?: number): string;
|
||||
}
|
||||
194
node_modules/@oclif/core/lib/help/formatter.js
generated
vendored
Normal file
194
node_modules/@oclif/core/lib/help/formatter.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HelpFormatter = void 0;
|
||||
const ansis_1 = __importDefault(require("ansis"));
|
||||
const indent_string_1 = __importDefault(require("indent-string"));
|
||||
const string_width_1 = __importDefault(require("string-width"));
|
||||
const widest_line_1 = __importDefault(require("widest-line"));
|
||||
const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
|
||||
const screen_1 = require("../screen");
|
||||
const theme_1 = require("../ux/theme");
|
||||
const util_1 = require("./util");
|
||||
class HelpFormatter {
|
||||
config;
|
||||
indentSpacing = 2;
|
||||
opts;
|
||||
/**
|
||||
* Takes a string and replaces `<%= prop =>` with the value of prop, where prop is anything on
|
||||
* `config=Interfaces.Config` or `opts=Interface.HelpOptions`.
|
||||
*
|
||||
* ```javascript
|
||||
* `<%= config.bin =>` // will resolve to the bin defined in `pjson.oclif`.
|
||||
* ```
|
||||
*/
|
||||
render;
|
||||
constructor(config, opts = {}) {
|
||||
this.config = config;
|
||||
this.opts = { maxWidth: screen_1.stdtermwidth, ...opts };
|
||||
this.render = (0, util_1.template)(this);
|
||||
}
|
||||
/**
|
||||
* Indent by `this.indentSpacing`. The text should be wrap based on terminal width before indented.
|
||||
*
|
||||
* In order to call indent multiple times on the same set or text, the caller must wrap based on
|
||||
* the number of times the text has been indented. For example.
|
||||
*
|
||||
* ```javascript
|
||||
* const body = `main line\n${indent(wrap('indented example line', 4))}`
|
||||
* const header = 'SECTION'
|
||||
* console.log(`${header}\n${indent(wrap(body))}`
|
||||
* ```
|
||||
* will output
|
||||
* ```
|
||||
* SECTION
|
||||
* main line
|
||||
* indented example line
|
||||
* ```
|
||||
*
|
||||
* If the terminal width was 24 and the `4` was not provided in the first wrap, it would like like the following.
|
||||
* ```
|
||||
* SECTION
|
||||
* main line
|
||||
* indented example
|
||||
* line
|
||||
* ```
|
||||
* @param body the text to indent
|
||||
* @param spacing the final number of spaces this text will be indented
|
||||
* @returns the formatted indented text
|
||||
*/
|
||||
indent(body, spacing = this.indentSpacing) {
|
||||
return (0, indent_string_1.default)(body, spacing);
|
||||
}
|
||||
renderList(input, opts) {
|
||||
if (input.length === 0) {
|
||||
return '';
|
||||
}
|
||||
const renderMultiline = () => {
|
||||
let output = '';
|
||||
for (let [left, right] of input) {
|
||||
if (!left && !right)
|
||||
continue;
|
||||
if (left) {
|
||||
if (opts.stripAnsi)
|
||||
left = ansis_1.default.strip(left);
|
||||
output += this.wrap(left.trim(), opts.indentation);
|
||||
}
|
||||
if (right) {
|
||||
if (opts.stripAnsi)
|
||||
right = ansis_1.default.strip(right);
|
||||
output += '\n';
|
||||
output += this.indent(this.wrap(right.trim(), opts.indentation + 2), 4);
|
||||
}
|
||||
output += '\n\n';
|
||||
}
|
||||
return output.trim();
|
||||
};
|
||||
if (opts.multiline)
|
||||
return renderMultiline();
|
||||
const maxLength = (0, widest_line_1.default)(input.map((i) => i[0]).join('\n'));
|
||||
let output = '';
|
||||
let spacer = opts.spacer || '\n';
|
||||
let cur = '';
|
||||
for (const [left, r] of input) {
|
||||
let right = r;
|
||||
if (cur) {
|
||||
output += spacer;
|
||||
output += cur;
|
||||
}
|
||||
cur = left || '';
|
||||
if (opts.stripAnsi)
|
||||
cur = ansis_1.default.strip(cur);
|
||||
if (!right) {
|
||||
cur = cur.trim();
|
||||
continue;
|
||||
}
|
||||
if (opts.stripAnsi)
|
||||
right = ansis_1.default.strip(right);
|
||||
right = this.wrap(right.trim(), opts.indentation + maxLength + 2);
|
||||
const [first, ...lines] = right.split('\n').map((s) => s.trim());
|
||||
cur += ' '.repeat(maxLength - (0, string_width_1.default)(cur) + 2);
|
||||
cur += first;
|
||||
if (lines.length === 0) {
|
||||
continue;
|
||||
}
|
||||
// if we start putting too many lines down, render in multiline format
|
||||
if (lines.length > 4)
|
||||
return renderMultiline();
|
||||
// if spacer is not defined, separate all rows with a newline
|
||||
if (!opts.spacer)
|
||||
spacer = '\n';
|
||||
cur += '\n';
|
||||
cur += this.indent(lines.join('\n'), maxLength + 2);
|
||||
}
|
||||
if (cur) {
|
||||
output += spacer;
|
||||
output += cur;
|
||||
}
|
||||
return output.trim();
|
||||
}
|
||||
section(header, body) {
|
||||
// Always render template strings with the provided render function before wrapping and indenting
|
||||
let newBody;
|
||||
if (typeof body === 'string') {
|
||||
newBody = this.render(body);
|
||||
}
|
||||
else if (Array.isArray(body)) {
|
||||
newBody = body.map((entry) => {
|
||||
if ('name' in entry) {
|
||||
const tableEntry = entry;
|
||||
return [this.render(tableEntry.name), this.render(tableEntry.description)];
|
||||
}
|
||||
const [left, right] = entry;
|
||||
return [this.render(left), right && this.render(right)];
|
||||
});
|
||||
}
|
||||
else if ('header' in body) {
|
||||
return this.section(body.header, body.body);
|
||||
}
|
||||
else {
|
||||
newBody = body
|
||||
.map((entry) => [entry.name, entry.description])
|
||||
.map(([left, right]) => [this.render(left), right && this.render(right)]);
|
||||
}
|
||||
const output = [
|
||||
(0, theme_1.colorize)(this.config?.theme?.sectionHeader, (0, theme_1.colorize)('bold', header)),
|
||||
(0, theme_1.colorize)(this.config?.theme?.sectionDescription, this.indent(Array.isArray(newBody) ? this.renderList(newBody, { indentation: 2, stripAnsi: this.opts.stripAnsi }) : newBody)),
|
||||
].join('\n');
|
||||
return this.opts.stripAnsi ? ansis_1.default.strip(output) : output;
|
||||
}
|
||||
/**
|
||||
* Wrap text according to `opts.maxWidth` which is typically set to the terminal width. All text
|
||||
* will be rendered before bring wrapped, otherwise it could mess up the lengths.
|
||||
*
|
||||
* A terminal will automatically wrap text, so this method is primarily used for indented
|
||||
* text. For indented text, specify the indentation so it is taken into account during wrapping.
|
||||
*
|
||||
* Here is an example of wrapping with indentation.
|
||||
* ```
|
||||
* <------ terminal window width ------>
|
||||
* <---------- no indentation --------->
|
||||
* This is my text that will be wrapped
|
||||
* once it passes maxWidth.
|
||||
*
|
||||
* <- indent -><------ text space ----->
|
||||
* This is my text that will
|
||||
* be wrapped once it passes
|
||||
* maxWidth.
|
||||
*
|
||||
* <-- indent not taken into account ->
|
||||
* This is my text that will
|
||||
* be wrapped
|
||||
* once it passes maxWidth.
|
||||
* ```
|
||||
* @param body the text to wrap
|
||||
* @param spacing the indentation size to subtract from the terminal width
|
||||
* @returns the formatted wrapped text
|
||||
*/
|
||||
wrap(body, spacing = this.indentSpacing) {
|
||||
return (0, wrap_ansi_1.default)(this.render(body), this.opts.maxWidth - spacing, { hard: true });
|
||||
}
|
||||
}
|
||||
exports.HelpFormatter = HelpFormatter;
|
||||
46
node_modules/@oclif/core/lib/help/index.d.ts
generated
vendored
Normal file
46
node_modules/@oclif/core/lib/help/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Command } from '../command';
|
||||
import * as Interfaces from '../interfaces';
|
||||
import { CommandHelp } from './command';
|
||||
import { HelpFormatter } from './formatter';
|
||||
export { CommandHelp } from './command';
|
||||
export { HelpFormatter, type HelpSection, type HelpSectionKeyValueTable, type HelpSectionRenderer } from './formatter';
|
||||
export { getHelpFlagAdditions, normalizeArgv, standardizeIDFromArgv } from './util';
|
||||
export declare abstract class HelpBase extends HelpFormatter {
|
||||
constructor(config: Interfaces.Config, opts?: Partial<Interfaces.HelpOptions>);
|
||||
/**
|
||||
* Show help for an individual command
|
||||
* @param command
|
||||
* @param topics
|
||||
*/
|
||||
abstract showCommandHelp(command: Command.Loadable, topics: Interfaces.Topic[]): Promise<void>;
|
||||
/**
|
||||
* Show help, used in multi-command CLIs
|
||||
* @param args passed into your command, useful for determining which type of help to display
|
||||
*/
|
||||
abstract showHelp(argv: string[]): Promise<void>;
|
||||
}
|
||||
export declare class Help extends HelpBase {
|
||||
protected CommandHelpClass: typeof CommandHelp;
|
||||
constructor(config: Interfaces.Config, opts?: Partial<Interfaces.HelpOptions>);
|
||||
private get _topics();
|
||||
protected get sortedCommands(): Command.Loadable[];
|
||||
protected get sortedTopics(): Interfaces.Topic[];
|
||||
protected command(command: Command.Loadable): string;
|
||||
protected description(c: Command.Loadable): string;
|
||||
protected formatCommand(command: Command.Loadable): string;
|
||||
protected formatCommands(commands: Array<Command.Loadable>): string;
|
||||
protected formatRoot(): string;
|
||||
protected formatTopic(topic: Interfaces.Topic): string;
|
||||
protected formatTopics(topics: Interfaces.Topic[]): string;
|
||||
protected getCommandHelpClass(command: Command.Loadable): CommandHelp;
|
||||
protected log(...args: string[]): void;
|
||||
showCommandHelp(command: Command.Loadable): Promise<void>;
|
||||
showHelp(argv: string[]): Promise<void>;
|
||||
protected showRootHelp(): Promise<void>;
|
||||
protected showTopicHelp(topic: Interfaces.Topic): Promise<void>;
|
||||
protected summary(c: Command.Loadable): string | undefined;
|
||||
}
|
||||
interface HelpBaseDerived {
|
||||
new (config: Interfaces.Config, opts?: Partial<Interfaces.HelpOptions>): HelpBase;
|
||||
}
|
||||
export declare function loadHelpClass(config: Interfaces.Config): Promise<HelpBaseDerived>;
|
||||
345
node_modules/@oclif/core/lib/help/index.js
generated
vendored
Normal file
345
node_modules/@oclif/core/lib/help/index.js
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Help = exports.HelpBase = exports.standardizeIDFromArgv = exports.normalizeArgv = exports.getHelpFlagAdditions = exports.HelpFormatter = exports.CommandHelp = void 0;
|
||||
exports.loadHelpClass = loadHelpClass;
|
||||
const ansis_1 = __importDefault(require("ansis"));
|
||||
const ts_path_1 = require("../config/ts-path");
|
||||
const error_1 = require("../errors/error");
|
||||
const module_loader_1 = require("../module-loader");
|
||||
const symbols_1 = require("../symbols");
|
||||
const cache_default_value_1 = require("../util/cache-default-value");
|
||||
const ids_1 = require("../util/ids");
|
||||
const util_1 = require("../util/util");
|
||||
const ux_1 = require("../ux");
|
||||
const theme_1 = require("../ux/theme");
|
||||
const command_1 = require("./command");
|
||||
const formatter_1 = require("./formatter");
|
||||
const root_1 = __importDefault(require("./root"));
|
||||
const util_2 = require("./util");
|
||||
var command_2 = require("./command");
|
||||
Object.defineProperty(exports, "CommandHelp", { enumerable: true, get: function () { return command_2.CommandHelp; } });
|
||||
var formatter_2 = require("./formatter");
|
||||
Object.defineProperty(exports, "HelpFormatter", { enumerable: true, get: function () { return formatter_2.HelpFormatter; } });
|
||||
var util_3 = require("./util");
|
||||
Object.defineProperty(exports, "getHelpFlagAdditions", { enumerable: true, get: function () { return util_3.getHelpFlagAdditions; } });
|
||||
Object.defineProperty(exports, "normalizeArgv", { enumerable: true, get: function () { return util_3.normalizeArgv; } });
|
||||
Object.defineProperty(exports, "standardizeIDFromArgv", { enumerable: true, get: function () { return util_3.standardizeIDFromArgv; } });
|
||||
function getHelpSubject(args, config) {
|
||||
// for each help flag that starts with '--' create a new flag with same name sans '--'
|
||||
const mergedHelpFlags = (0, util_2.getHelpFlagAdditions)(config);
|
||||
for (const arg of args) {
|
||||
if (arg === '--')
|
||||
return;
|
||||
if (mergedHelpFlags.includes(arg) || arg === 'help')
|
||||
continue;
|
||||
if (arg.startsWith('-'))
|
||||
return;
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
class HelpBase extends formatter_1.HelpFormatter {
|
||||
constructor(config, opts = {}) {
|
||||
super(config, opts);
|
||||
if (!config.topicSeparator)
|
||||
config.topicSeparator = ':'; // back-support @oclif/config
|
||||
}
|
||||
}
|
||||
exports.HelpBase = HelpBase;
|
||||
class Help extends HelpBase {
|
||||
CommandHelpClass = command_1.CommandHelp;
|
||||
constructor(config, opts = {}) {
|
||||
super(config, opts);
|
||||
}
|
||||
/*
|
||||
* _topics is to work around Interfaces.topics mistakenly including commands that do
|
||||
* not have children, as well as topics. A topic has children, either commands or other topics. When
|
||||
* this is fixed upstream config.topics should return *only* topics with children,
|
||||
* and this can be removed.
|
||||
*/
|
||||
get _topics() {
|
||||
return this.config.topics.filter((topic) => {
|
||||
// it is assumed a topic has a child if it has children
|
||||
const hasChild = this.config.topics.some((subTopic) => subTopic.name.includes(`${topic.name}:`));
|
||||
return hasChild;
|
||||
});
|
||||
}
|
||||
get sortedCommands() {
|
||||
let { commands } = this.config;
|
||||
commands = commands.filter((c) => this.opts.all || !c.hidden);
|
||||
commands = (0, util_1.sortBy)(commands, (c) => c.id);
|
||||
commands = (0, util_1.uniqBy)(commands, (c) => c.id);
|
||||
return commands;
|
||||
}
|
||||
get sortedTopics() {
|
||||
let topics = this._topics;
|
||||
topics = topics.filter((t) => this.opts.all || !t.hidden);
|
||||
topics = (0, util_1.sortBy)(topics, (t) => t.name);
|
||||
topics = (0, util_1.uniqBy)(topics, (t) => t.name);
|
||||
return topics;
|
||||
}
|
||||
command(command) {
|
||||
return this.formatCommand(command);
|
||||
}
|
||||
description(c) {
|
||||
const description = this.render(c.description || '');
|
||||
if (c.summary) {
|
||||
return description;
|
||||
}
|
||||
return description.split('\n').slice(1).join('\n');
|
||||
}
|
||||
formatCommand(command) {
|
||||
if (this.config.topicSeparator !== ':') {
|
||||
command.id = command.id.replaceAll(':', this.config.topicSeparator);
|
||||
command.aliases = command.aliases && command.aliases.map((a) => a.replaceAll(':', this.config.topicSeparator));
|
||||
}
|
||||
const help = this.getCommandHelpClass(command);
|
||||
return help.generate();
|
||||
}
|
||||
formatCommands(commands) {
|
||||
if (commands.length === 0)
|
||||
return '';
|
||||
const body = this.renderList(commands
|
||||
.filter((c) => (this.opts.hideAliasesFromRoot ? !c.aliases?.includes(c.id) : true))
|
||||
.map((c) => {
|
||||
if (this.config.topicSeparator !== ':')
|
||||
c.id = c.id.replaceAll(':', this.config.topicSeparator);
|
||||
const summary = this.summary(c);
|
||||
return [
|
||||
(0, theme_1.colorize)(this.config?.theme?.command, c.id),
|
||||
summary && (0, theme_1.colorize)(this.config?.theme?.sectionDescription, ansis_1.default.strip(summary)),
|
||||
];
|
||||
}), {
|
||||
indentation: 2,
|
||||
spacer: '\n',
|
||||
stripAnsi: this.opts.stripAnsi,
|
||||
});
|
||||
return this.section('COMMANDS', body);
|
||||
}
|
||||
formatRoot() {
|
||||
const help = new root_1.default(this.config, this.opts);
|
||||
return help.root();
|
||||
}
|
||||
formatTopic(topic) {
|
||||
let description = this.render(topic.description || '');
|
||||
const summary = description.split('\n')[0];
|
||||
description = description.split('\n').slice(1).join('\n');
|
||||
let topicID = `${topic.name}:COMMAND`;
|
||||
if (this.config.topicSeparator !== ':')
|
||||
topicID = topicID.replaceAll(':', this.config.topicSeparator);
|
||||
let output = (0, util_1.compact)([
|
||||
(0, theme_1.colorize)(this.config?.theme?.commandSummary, summary),
|
||||
this.section(this.opts.usageHeader || 'USAGE', `${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${(0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin)} ${topicID}`),
|
||||
description &&
|
||||
this.section('DESCRIPTION', this.wrap((0, theme_1.colorize)(this.config?.theme?.sectionDescription, description))),
|
||||
]).join('\n\n');
|
||||
if (this.opts.stripAnsi)
|
||||
output = ansis_1.default.strip(output);
|
||||
return output + '\n';
|
||||
}
|
||||
formatTopics(topics) {
|
||||
if (topics.length === 0)
|
||||
return '';
|
||||
const body = this.renderList(topics.map((c) => {
|
||||
if (this.config.topicSeparator !== ':')
|
||||
c.name = c.name.replaceAll(':', this.config.topicSeparator);
|
||||
return [
|
||||
(0, theme_1.colorize)(this.config?.theme?.topic, c.name),
|
||||
c.description && this.render((0, theme_1.colorize)(this.config?.theme?.sectionDescription, c.description.split('\n')[0])),
|
||||
];
|
||||
}), {
|
||||
indentation: 2,
|
||||
spacer: '\n',
|
||||
stripAnsi: this.opts.stripAnsi,
|
||||
});
|
||||
return this.section('TOPICS', body);
|
||||
}
|
||||
getCommandHelpClass(command) {
|
||||
return new this.CommandHelpClass(command, this.config, this.opts);
|
||||
}
|
||||
log(...args) {
|
||||
return this.opts.sendToStderr ? ux_1.ux.stderr(args) : ux_1.ux.stdout(args);
|
||||
}
|
||||
async showCommandHelp(command) {
|
||||
const name = command.id;
|
||||
const depth = name.split(':').length;
|
||||
const subTopics = this.sortedTopics.filter((t) => t.name.startsWith(name + ':') && t.name.split(':').length === depth + 1);
|
||||
const subCommands = this.sortedCommands.filter((c) => c.id.startsWith(name + ':') && c.id.split(':').length === depth + 1);
|
||||
const plugin = this.config.plugins.get(command.pluginName);
|
||||
const state = this.config.pjson?.oclif?.state || plugin?.pjson?.oclif?.state || command.state;
|
||||
if (state) {
|
||||
this.log(state === 'deprecated'
|
||||
? `${(0, util_2.formatCommandDeprecationWarning)((0, ids_1.toConfiguredId)(name, this.config), command.deprecationOptions)}\n`
|
||||
: `This command is in ${state}.\n`);
|
||||
}
|
||||
if (command.deprecateAliases && command.aliases.includes(name)) {
|
||||
const actualCmd = this.config.commands.find((c) => c.aliases.includes(name));
|
||||
const actualCmdName = actualCmd ? (0, ids_1.toConfiguredId)(actualCmd.id, this.config) : '';
|
||||
const opts = { ...command.deprecationOptions, ...(actualCmd ? { to: actualCmdName } : {}) };
|
||||
this.log(`${(0, util_2.formatCommandDeprecationWarning)((0, ids_1.toConfiguredId)(name, this.config), opts)}\n`);
|
||||
}
|
||||
const summary = this.summary(command);
|
||||
if (summary) {
|
||||
this.log(summary + '\n');
|
||||
}
|
||||
this.log(this.formatCommand(command));
|
||||
this.log('');
|
||||
if (subTopics.length > 0) {
|
||||
this.log(this.formatTopics(subTopics));
|
||||
this.log('');
|
||||
}
|
||||
if (subCommands.length > 0) {
|
||||
const aliases = [];
|
||||
const uniqueSubCommands = subCommands.filter((p) => {
|
||||
aliases.push(...p.aliases);
|
||||
return !aliases.includes(p.id);
|
||||
});
|
||||
this.log(this.formatCommands(uniqueSubCommands));
|
||||
this.log('');
|
||||
}
|
||||
}
|
||||
async showHelp(argv) {
|
||||
const originalArgv = argv.slice(1);
|
||||
argv = argv.filter((arg) => !(0, util_2.getHelpFlagAdditions)(this.config).includes(arg));
|
||||
if (this.config.topicSeparator !== ':')
|
||||
argv = (0, util_2.standardizeIDFromArgv)(argv, this.config);
|
||||
const subject = getHelpSubject(argv, this.config);
|
||||
if (!subject) {
|
||||
if (this.config.isSingleCommandCLI) {
|
||||
const rootCmd = this.config.findCommand(symbols_1.SINGLE_COMMAND_CLI_SYMBOL);
|
||||
if (rootCmd) {
|
||||
// set the command id to an empty string to prevent the
|
||||
// SINGLE_COMMAND_CLI_SYMBOL from being displayed in the help output
|
||||
rootCmd.id = '';
|
||||
await this.showCommandHelp(rootCmd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await this.showRootHelp();
|
||||
return;
|
||||
}
|
||||
const command = this.config.findCommand(subject);
|
||||
if (command) {
|
||||
if (command.id === symbols_1.SINGLE_COMMAND_CLI_SYMBOL) {
|
||||
// If the command is the root command of a single command CLI,
|
||||
// then set the command id to an empty string to prevent the
|
||||
// the SINGLE_COMMAND_CLI_SYMBOL from being displayed in the help output.
|
||||
command.id = '';
|
||||
}
|
||||
if (command.hasDynamicHelp && command.pluginType !== 'jit') {
|
||||
const loaded = await command.load();
|
||||
for (const [name, flag] of Object.entries(loaded.flags ?? {})) {
|
||||
// As of v3 each flag that needs to be re-evaluated has the `hasDynamicHelp` property.
|
||||
// However, we cannot assume that the absence of this property means that the flag
|
||||
// doesn't need to be re-evaluated since any command from a v2 or older plugin will
|
||||
// not have the `hasDynamicHelp` property on it.
|
||||
// In the future we could improve performance by skipping any flag that doesn't
|
||||
// have `hasDynamicHelp === true`
|
||||
if (flag.type === 'boolean')
|
||||
continue;
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
command.flags[name].default = await (0, cache_default_value_1.cacheDefaultValue)(flag, false);
|
||||
}
|
||||
await this.showCommandHelp(command);
|
||||
}
|
||||
else {
|
||||
await this.showCommandHelp(command);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const topic = this.config.findTopic(subject);
|
||||
if (topic) {
|
||||
await this.showTopicHelp(topic);
|
||||
return;
|
||||
}
|
||||
if (this.config.flexibleTaxonomy) {
|
||||
const matches = this.config.findMatches(subject, originalArgv);
|
||||
if (matches.length > 0) {
|
||||
const result = await this.config.runHook('command_incomplete', {
|
||||
argv: originalArgv.filter((o) => !subject.split(':').includes(o)),
|
||||
id: subject,
|
||||
matches,
|
||||
});
|
||||
if (result.successes.length > 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
(0, error_1.error)(`Command ${subject} not found.`);
|
||||
}
|
||||
async showRootHelp() {
|
||||
let rootTopics = this.sortedTopics;
|
||||
let rootCommands = this.sortedCommands;
|
||||
const state = this.config.pjson?.oclif?.state;
|
||||
if (state) {
|
||||
this.log(state === 'deprecated' ? `${this.config.bin} is deprecated` : `${this.config.bin} is in ${state}.\n`);
|
||||
}
|
||||
this.log(this.formatRoot());
|
||||
this.log('');
|
||||
if (!this.opts.all) {
|
||||
rootTopics = rootTopics.filter((t) => !t.name.includes(':'));
|
||||
rootCommands = rootCommands.filter((c) => !c.id.includes(':'));
|
||||
}
|
||||
if (rootTopics.length > 0) {
|
||||
this.log(this.formatTopics(rootTopics));
|
||||
this.log('');
|
||||
}
|
||||
if (rootCommands.length > 0) {
|
||||
rootCommands = rootCommands.filter((c) => c.id);
|
||||
this.log(this.formatCommands(rootCommands));
|
||||
this.log('');
|
||||
}
|
||||
}
|
||||
async showTopicHelp(topic) {
|
||||
const { name } = topic;
|
||||
const depth = name.split(':').length;
|
||||
const subTopics = this.sortedTopics.filter((t) => t.name.startsWith(name + ':') && t.name.split(':').length === depth + 1);
|
||||
const commands = this.sortedCommands.filter((c) => c.id.startsWith(name + ':') && c.id.split(':').length === depth + 1);
|
||||
const state = this.config.pjson?.oclif?.state;
|
||||
if (state)
|
||||
this.log(`This topic is in ${state}.\n`);
|
||||
this.log(this.formatTopic(topic));
|
||||
if (subTopics.length > 0) {
|
||||
this.log(this.formatTopics(subTopics));
|
||||
this.log('');
|
||||
}
|
||||
if (commands.length > 0) {
|
||||
this.log(this.formatCommands(commands));
|
||||
this.log('');
|
||||
}
|
||||
}
|
||||
summary(c) {
|
||||
if (this.opts.sections && !this.opts.sections.map((s) => s.toLowerCase()).includes('summary'))
|
||||
return;
|
||||
if (c.summary)
|
||||
return (0, theme_1.colorize)(this.config?.theme?.commandSummary, this.render(c.summary.split('\n')[0]));
|
||||
return c.description && (0, theme_1.colorize)(this.config?.theme?.commandSummary, this.render(c.description).split('\n')[0]);
|
||||
}
|
||||
}
|
||||
exports.Help = Help;
|
||||
function extractClass(exported) {
|
||||
return exported && exported.default ? exported.default : exported;
|
||||
}
|
||||
function determineLocation(helpClass) {
|
||||
if (typeof helpClass === 'string')
|
||||
return { identifier: 'default', target: helpClass };
|
||||
if (!helpClass.identifier)
|
||||
return { ...helpClass, identifier: 'default' };
|
||||
return helpClass;
|
||||
}
|
||||
async function loadHelpClass(config) {
|
||||
if (config.pjson.oclif?.helpClass) {
|
||||
const { identifier, target } = determineLocation(config.pjson.oclif?.helpClass);
|
||||
try {
|
||||
const path = (await (0, ts_path_1.tsPath)(config.root, target)) ?? target;
|
||||
const module = await (0, module_loader_1.load)(config, path);
|
||||
const helpClass = module[identifier] ?? (identifier === 'default' ? extractClass(module) : undefined);
|
||||
return extractClass(helpClass);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`Unable to load configured help class "${target}", failed with message:\n${error.message}`);
|
||||
}
|
||||
}
|
||||
return Help;
|
||||
}
|
||||
11
node_modules/@oclif/core/lib/help/root.d.ts
generated
vendored
Normal file
11
node_modules/@oclif/core/lib/help/root.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import * as Interfaces from '../interfaces';
|
||||
import { HelpFormatter } from './formatter';
|
||||
export default class RootHelp extends HelpFormatter {
|
||||
config: Interfaces.Config;
|
||||
opts: Interfaces.HelpOptions;
|
||||
constructor(config: Interfaces.Config, opts: Interfaces.HelpOptions);
|
||||
protected description(): string | undefined;
|
||||
root(): string;
|
||||
protected usage(): string;
|
||||
protected version(): string;
|
||||
}
|
||||
47
node_modules/@oclif/core/lib/help/root.js
generated
vendored
Normal file
47
node_modules/@oclif/core/lib/help/root.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const ansis_1 = __importDefault(require("ansis"));
|
||||
const util_1 = require("../util/util");
|
||||
const theme_1 = require("../ux/theme");
|
||||
const formatter_1 = require("./formatter");
|
||||
class RootHelp extends formatter_1.HelpFormatter {
|
||||
config;
|
||||
opts;
|
||||
constructor(config, opts) {
|
||||
super(config, opts);
|
||||
this.config = config;
|
||||
this.opts = opts;
|
||||
}
|
||||
description() {
|
||||
let description = this.config.pjson.oclif.description || this.config.pjson.description || '';
|
||||
description = this.render(description);
|
||||
description = description.split('\n').slice(1).join('\n');
|
||||
if (!description)
|
||||
return;
|
||||
return this.section('DESCRIPTION', this.wrap((0, theme_1.colorize)(this.config?.theme?.sectionDescription, description)));
|
||||
}
|
||||
root() {
|
||||
let description = this.config.pjson.oclif.description || this.config.pjson.description || '';
|
||||
description = this.render(description);
|
||||
description = description.split('\n')[0];
|
||||
let output = (0, util_1.compact)([
|
||||
(0, theme_1.colorize)(this.config?.theme?.commandSummary, description),
|
||||
this.version(),
|
||||
this.usage(),
|
||||
this.description(),
|
||||
]).join('\n\n');
|
||||
if (this.opts.stripAnsi)
|
||||
output = ansis_1.default.strip(output);
|
||||
return output;
|
||||
}
|
||||
usage() {
|
||||
return this.section(this.opts.usageHeader || 'USAGE', this.wrap(`${(0, theme_1.colorize)(this.config?.theme?.dollarSign, '$')} ${(0, theme_1.colorize)(this.config?.theme?.bin, this.config.bin)} ${(0, theme_1.colorize)(this.config?.theme?.sectionDescription, '[COMMAND]')}`));
|
||||
}
|
||||
version() {
|
||||
return this.section('VERSION', this.wrap((0, theme_1.colorize)(this.config?.theme?.version, this.config.userAgent)));
|
||||
}
|
||||
}
|
||||
exports.default = RootHelp;
|
||||
7
node_modules/@oclif/core/lib/help/util.d.ts
generated
vendored
Normal file
7
node_modules/@oclif/core/lib/help/util.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Deprecation, Config as IConfig } from '../interfaces';
|
||||
export declare function template(context: any): (t: string) => string;
|
||||
export declare function standardizeIDFromArgv(argv: string[], config: IConfig): string[];
|
||||
export declare function getHelpFlagAdditions(config: IConfig): string[];
|
||||
export declare function formatFlagDeprecationWarning(flag: string, opts: Deprecation | true): string;
|
||||
export declare function formatCommandDeprecationWarning(command: string, opts?: Deprecation): string;
|
||||
export declare function normalizeArgv(config: IConfig, argv?: string[]): string[];
|
||||
129
node_modules/@oclif/core/lib/help/util.js
generated
vendored
Normal file
129
node_modules/@oclif/core/lib/help/util.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
"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;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.template = template;
|
||||
exports.standardizeIDFromArgv = standardizeIDFromArgv;
|
||||
exports.getHelpFlagAdditions = getHelpFlagAdditions;
|
||||
exports.formatFlagDeprecationWarning = formatFlagDeprecationWarning;
|
||||
exports.formatCommandDeprecationWarning = formatCommandDeprecationWarning;
|
||||
exports.normalizeArgv = normalizeArgv;
|
||||
const ejs = __importStar(require("ejs"));
|
||||
const util_1 = require("../config/util");
|
||||
const ids_1 = require("../util/ids");
|
||||
function template(context) {
|
||||
function render(t) {
|
||||
return ejs.render(t, context);
|
||||
}
|
||||
return render;
|
||||
}
|
||||
const isFlag = (s) => s.startsWith('-');
|
||||
const isArgWithValue = (s) => s.includes('=');
|
||||
function collateSpacedCmdIDFromArgs(argv, config) {
|
||||
if (argv.length === 1)
|
||||
return argv;
|
||||
const findId = (argv) => {
|
||||
const ids = (0, util_1.collectUsableIds)(config.commandIDs);
|
||||
const final = [];
|
||||
const idPresent = (id) => ids.has(id);
|
||||
const finalizeId = (s) => (s ? [...final, s] : final).filter(Boolean).join(':');
|
||||
const hasArgs = () => {
|
||||
const id = finalizeId();
|
||||
if (!id)
|
||||
return false;
|
||||
const cmd = config.findCommand(id);
|
||||
return Boolean(cmd && (cmd.strict === false || Object.keys(cmd.args ?? {}).length > 0));
|
||||
};
|
||||
for (const arg of argv) {
|
||||
if (idPresent(finalizeId(arg)))
|
||||
final.push(arg);
|
||||
// If the parent topic has a command that expects positional arguments, then we cannot
|
||||
// assume that any subsequent string could be part of the command name
|
||||
else if (isArgWithValue(arg) || isFlag(arg) || hasArgs())
|
||||
break;
|
||||
else
|
||||
final.push(arg);
|
||||
}
|
||||
return finalizeId();
|
||||
};
|
||||
const id = findId(argv);
|
||||
if (id) {
|
||||
const argvSlice = argv.slice(id.split(':').length);
|
||||
return [id, ...argvSlice];
|
||||
}
|
||||
return argv; // ID is argv[0]
|
||||
}
|
||||
function standardizeIDFromArgv(argv, config) {
|
||||
if (argv.length === 0)
|
||||
return argv;
|
||||
if (config.topicSeparator === ' ')
|
||||
argv = collateSpacedCmdIDFromArgs(argv, config);
|
||||
else if (config.topicSeparator !== ':')
|
||||
argv[0] = (0, ids_1.toStandardizedId)(argv[0], config);
|
||||
return argv;
|
||||
}
|
||||
function getHelpFlagAdditions(config) {
|
||||
const helpFlags = ['--help'];
|
||||
const additionalHelpFlags = config.pjson.oclif.additionalHelpFlags ?? [];
|
||||
return [...new Set([...additionalHelpFlags, ...helpFlags]).values()];
|
||||
}
|
||||
function formatFlagDeprecationWarning(flag, opts) {
|
||||
let message = `The "${flag}" flag has been deprecated`;
|
||||
if (opts === true)
|
||||
return `${message}.`;
|
||||
if (opts.message)
|
||||
return opts.message;
|
||||
if (opts.version) {
|
||||
message += ` and will be removed in version ${opts.version}`;
|
||||
}
|
||||
message += opts.to ? `. Use "${opts.to}" instead.` : '.';
|
||||
return message;
|
||||
}
|
||||
function formatCommandDeprecationWarning(command, opts) {
|
||||
let message = `The "${command}" command has been deprecated`;
|
||||
if (!opts)
|
||||
return `${message}.`;
|
||||
if (opts.message)
|
||||
return opts.message;
|
||||
if (opts.version) {
|
||||
message += ` and will be removed in version ${opts.version}`;
|
||||
}
|
||||
message += opts.to ? `. Use "${opts.to}" instead.` : '.';
|
||||
return message;
|
||||
}
|
||||
function normalizeArgv(config, argv = process.argv.slice(2)) {
|
||||
if (config.topicSeparator !== ':' && !argv[0]?.includes(':'))
|
||||
argv = standardizeIDFromArgv(argv, config);
|
||||
return argv;
|
||||
}
|
||||
Reference in New Issue
Block a user