@fig/complete-commander
Version:
Export commander command as a Fig spec
158 lines (155 loc) • 6.05 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCompletionSpecCommand = exports.generateCompletionSpec = void 0;
const prettier_1 = __importDefault(require("prettier"));
const DEFAULT_FIG_SUBCOMMAND_NAME = "generate-fig-spec";
function convertDefaultValue(v) {
if (typeof v === "string")
return v;
if (Array.isArray(v))
return v.join(",");
if (typeof v === "object")
return undefined;
return String(v);
}
function getTemplate(spec) {
return __awaiter(this, void 0, void 0, function* () {
return prettier_1.default.format(`
// Autogenerated by @fig/complete-commander
const completionSpec: Fig.Spec = ${JSON.stringify(spec)}
export default completionSpec;
`, { parser: "typescript" });
});
}
function generateArg(_arg) {
const { _name: name, description, required, variadic, defaultValue } = _arg;
const arg = { name };
if (description)
arg.description = description;
if (!required)
arg.isOptional = true;
if (variadic)
arg.isVariadic = true;
if (defaultValue)
arg.default = convertDefaultValue(defaultValue);
return arg;
}
function generateOption(_option) {
const { short, long, flags, description, mandatory, required, optional, variadic, argChoices, defaultValue, } = _option;
const name = new Set();
if (short)
name.add(short);
if (long)
name.add(long);
const option = { name: Array.from(name) };
if (description)
option.description = description;
if (mandatory)
option.isRequired = true;
// Option argument e.g. "-f, --flag <string>"
// If required and optional are both false it does not have an argument
if (required || optional) {
// eslint-disable-next-line no-useless-escape
const matches = flags.match(/.*[\[<](.*)[\]>]/); // !!! This is all but an useless escape. It is required to make the regex working
const arg = {
name: matches ? matches[1].replace(/\./g, "") : "",
};
if (optional)
arg.isOptional = true;
if (variadic)
arg.isVariadic = true;
if (argChoices)
arg.suggestions = argChoices;
if (defaultValue)
arg.default = convertDefaultValue(defaultValue);
option.args = arg;
}
return option;
}
function helpSubcommand({ _helpCommandName, // 'help'
_helpCommandDescription, _helpCommandnameAndArgs, // 'help [cmd]'
}) {
const [, arg] = _helpCommandnameAndArgs.split(" ");
return Object.assign({ name: _helpCommandName, description: _helpCommandDescription, priority: 49 }, (arg && {
args: {
name: arg.slice(1, -1),
isOptional: true,
template: "help",
},
}));
}
function helpOption({ _helpDescription, _helpShortFlag, _helpLongFlag, }) {
return {
name: [_helpShortFlag, _helpLongFlag],
description: _helpDescription,
priority: 49,
};
}
function generateCommand(_command, figSpecCommandName) {
const { _name, _description, _aliases, commands, _args, options, _addImplicitHelpCommandL, _hasHelpOption, _hidden, } = _command;
if (_name === figSpecCommandName)
return undefined;
const name = _aliases.length > 0 ? Array.from(new Set([_name, ..._aliases])) : _name;
const command = { name };
if (_description)
command.description = _description;
if (_hidden)
command.hidden = true;
// Subcommands
if (commands.length) {
command.subcommands = [];
for (const cmd of commands) {
const subcommand = generateCommand(cmd, figSpecCommandName);
if (subcommand)
command.subcommands.push(subcommand);
}
if (_addImplicitHelpCommandL !== false) {
command.subcommands.push(helpSubcommand(_command));
}
}
// Options
command.options = [];
if (options.length) {
command.options = options.map(generateOption);
}
if (_hasHelpOption) {
command.options.push(helpOption(_command));
}
// Args
if (_args.length) {
command.args = _args.map(generateArg);
}
return command;
}
function generateCompletionSpec(command, options) {
return __awaiter(this, void 0, void 0, function* () {
const figSpecCommandName = (options === null || options === void 0 ? void 0 : options.figSpecCommandName) || DEFAULT_FIG_SUBCOMMAND_NAME;
// The first subcommand will never have the name of the `figSpecCommandName`
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const spec = getTemplate(generateCommand(command, figSpecCommandName));
return spec;
});
}
exports.generateCompletionSpec = generateCompletionSpec;
function addCompletionSpecCommand(command) {
command
.command(DEFAULT_FIG_SUBCOMMAND_NAME)
.description("Print the Fig completion spec")
.action(() => __awaiter(this, void 0, void 0, function* () {
const spec = yield generateCompletionSpec(command);
console.log(spec);
}));
}
exports.addCompletionSpecCommand = addCompletionSpecCommand;