mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-25 21:34:12 +01:00
Current file header is : /*! showdown v 2.0.0-alpha1 - 25-09-2018 */ Official 2.0.0-alpha doesn't match neither on content nor date :( Considering date we would be at 1.8.7, but it is also quite different (and has vulnerabilities) In consequence switching to 2.0.0.
244 lines
10 KiB
JavaScript
244 lines
10 KiB
JavaScript
import { isCommandBuilderCallback } from './command.js';
|
|
import { assertNotStrictEqual } from './typings/common-types.js';
|
|
import * as templates from './completion-templates.js';
|
|
import { isPromise } from './utils/is-promise.js';
|
|
import { parseCommand } from './parse-command.js';
|
|
export class Completion {
|
|
constructor(yargs, usage, command, shim) {
|
|
var _a, _b, _c;
|
|
this.yargs = yargs;
|
|
this.usage = usage;
|
|
this.command = command;
|
|
this.shim = shim;
|
|
this.completionKey = 'get-yargs-completions';
|
|
this.aliases = null;
|
|
this.customCompletionFunction = null;
|
|
this.indexAfterLastReset = 0;
|
|
this.zshShell =
|
|
(_c = (((_a = this.shim.getEnv('SHELL')) === null || _a === void 0 ? void 0 : _a.includes('zsh')) ||
|
|
((_b = this.shim.getEnv('ZSH_NAME')) === null || _b === void 0 ? void 0 : _b.includes('zsh')))) !== null && _c !== void 0 ? _c : false;
|
|
}
|
|
defaultCompletion(args, argv, current, done) {
|
|
const handlers = this.command.getCommandHandlers();
|
|
for (let i = 0, ii = args.length; i < ii; ++i) {
|
|
if (handlers[args[i]] && handlers[args[i]].builder) {
|
|
const builder = handlers[args[i]].builder;
|
|
if (isCommandBuilderCallback(builder)) {
|
|
this.indexAfterLastReset = i + 1;
|
|
const y = this.yargs.getInternalMethods().reset();
|
|
builder(y, true);
|
|
return y.argv;
|
|
}
|
|
}
|
|
}
|
|
const completions = [];
|
|
this.commandCompletions(completions, args, current);
|
|
this.optionCompletions(completions, args, argv, current);
|
|
this.choicesFromOptionsCompletions(completions, args, argv, current);
|
|
this.choicesFromPositionalsCompletions(completions, args, argv, current);
|
|
done(null, completions);
|
|
}
|
|
commandCompletions(completions, args, current) {
|
|
const parentCommands = this.yargs
|
|
.getInternalMethods()
|
|
.getContext().commands;
|
|
if (!current.match(/^-/) &&
|
|
parentCommands[parentCommands.length - 1] !== current &&
|
|
!this.previousArgHasChoices(args)) {
|
|
this.usage.getCommands().forEach(usageCommand => {
|
|
const commandName = parseCommand(usageCommand[0]).cmd;
|
|
if (args.indexOf(commandName) === -1) {
|
|
if (!this.zshShell) {
|
|
completions.push(commandName);
|
|
}
|
|
else {
|
|
const desc = usageCommand[1] || '';
|
|
completions.push(commandName.replace(/:/g, '\\:') + ':' + desc);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
optionCompletions(completions, args, argv, current) {
|
|
if ((current.match(/^-/) || (current === '' && completions.length === 0)) &&
|
|
!this.previousArgHasChoices(args)) {
|
|
const options = this.yargs.getOptions();
|
|
const positionalKeys = this.yargs.getGroups()[this.usage.getPositionalGroupName()] || [];
|
|
Object.keys(options.key).forEach(key => {
|
|
const negable = !!options.configuration['boolean-negation'] &&
|
|
options.boolean.includes(key);
|
|
const isPositionalKey = positionalKeys.includes(key);
|
|
if (!isPositionalKey &&
|
|
!options.hiddenOptions.includes(key) &&
|
|
!this.argsContainKey(args, key, negable)) {
|
|
this.completeOptionKey(key, completions, current, negable && !!options.default[key]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
choicesFromOptionsCompletions(completions, args, argv, current) {
|
|
if (this.previousArgHasChoices(args)) {
|
|
const choices = this.getPreviousArgChoices(args);
|
|
if (choices && choices.length > 0) {
|
|
completions.push(...choices.map(c => c.replace(/:/g, '\\:')));
|
|
}
|
|
}
|
|
}
|
|
choicesFromPositionalsCompletions(completions, args, argv, current) {
|
|
if (current === '' &&
|
|
completions.length > 0 &&
|
|
this.previousArgHasChoices(args)) {
|
|
return;
|
|
}
|
|
const positionalKeys = this.yargs.getGroups()[this.usage.getPositionalGroupName()] || [];
|
|
const offset = Math.max(this.indexAfterLastReset, this.yargs.getInternalMethods().getContext().commands.length +
|
|
1);
|
|
const positionalKey = positionalKeys[argv._.length - offset - 1];
|
|
if (!positionalKey) {
|
|
return;
|
|
}
|
|
const choices = this.yargs.getOptions().choices[positionalKey] || [];
|
|
for (const choice of choices) {
|
|
if (choice.startsWith(current)) {
|
|
completions.push(choice.replace(/:/g, '\\:'));
|
|
}
|
|
}
|
|
}
|
|
getPreviousArgChoices(args) {
|
|
if (args.length < 1)
|
|
return;
|
|
let previousArg = args[args.length - 1];
|
|
let filter = '';
|
|
if (!previousArg.startsWith('-') && args.length > 1) {
|
|
filter = previousArg;
|
|
previousArg = args[args.length - 2];
|
|
}
|
|
if (!previousArg.startsWith('-'))
|
|
return;
|
|
const previousArgKey = previousArg.replace(/^-+/, '');
|
|
const options = this.yargs.getOptions();
|
|
const possibleAliases = [
|
|
previousArgKey,
|
|
...(this.yargs.getAliases()[previousArgKey] || []),
|
|
];
|
|
let choices;
|
|
for (const possibleAlias of possibleAliases) {
|
|
if (Object.prototype.hasOwnProperty.call(options.key, possibleAlias) &&
|
|
Array.isArray(options.choices[possibleAlias])) {
|
|
choices = options.choices[possibleAlias];
|
|
break;
|
|
}
|
|
}
|
|
if (choices) {
|
|
return choices.filter(choice => !filter || choice.startsWith(filter));
|
|
}
|
|
}
|
|
previousArgHasChoices(args) {
|
|
const choices = this.getPreviousArgChoices(args);
|
|
return choices !== undefined && choices.length > 0;
|
|
}
|
|
argsContainKey(args, key, negable) {
|
|
const argsContains = (s) => args.indexOf((/^[^0-9]$/.test(s) ? '-' : '--') + s) !== -1;
|
|
if (argsContains(key))
|
|
return true;
|
|
if (negable && argsContains(`no-${key}`))
|
|
return true;
|
|
if (this.aliases) {
|
|
for (const alias of this.aliases[key]) {
|
|
if (argsContains(alias))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
completeOptionKey(key, completions, current, negable) {
|
|
var _a, _b, _c, _d;
|
|
let keyWithDesc = key;
|
|
if (this.zshShell) {
|
|
const descs = this.usage.getDescriptions();
|
|
const aliasKey = (_b = (_a = this === null || this === void 0 ? void 0 : this.aliases) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.find(alias => {
|
|
const desc = descs[alias];
|
|
return typeof desc === 'string' && desc.length > 0;
|
|
});
|
|
const descFromAlias = aliasKey ? descs[aliasKey] : undefined;
|
|
const desc = (_d = (_c = descs[key]) !== null && _c !== void 0 ? _c : descFromAlias) !== null && _d !== void 0 ? _d : '';
|
|
keyWithDesc = `${key.replace(/:/g, '\\:')}:${desc
|
|
.replace('__yargsString__:', '')
|
|
.replace(/(\r\n|\n|\r)/gm, ' ')}`;
|
|
}
|
|
const startsByTwoDashes = (s) => /^--/.test(s);
|
|
const isShortOption = (s) => /^[^0-9]$/.test(s);
|
|
const dashes = !startsByTwoDashes(current) && isShortOption(key) ? '-' : '--';
|
|
completions.push(dashes + keyWithDesc);
|
|
if (negable) {
|
|
completions.push(dashes + 'no-' + keyWithDesc);
|
|
}
|
|
}
|
|
customCompletion(args, argv, current, done) {
|
|
assertNotStrictEqual(this.customCompletionFunction, null, this.shim);
|
|
if (isSyncCompletionFunction(this.customCompletionFunction)) {
|
|
const result = this.customCompletionFunction(current, argv);
|
|
if (isPromise(result)) {
|
|
return result
|
|
.then(list => {
|
|
this.shim.process.nextTick(() => {
|
|
done(null, list);
|
|
});
|
|
})
|
|
.catch(err => {
|
|
this.shim.process.nextTick(() => {
|
|
done(err, undefined);
|
|
});
|
|
});
|
|
}
|
|
return done(null, result);
|
|
}
|
|
else if (isFallbackCompletionFunction(this.customCompletionFunction)) {
|
|
return this.customCompletionFunction(current, argv, (onCompleted = done) => this.defaultCompletion(args, argv, current, onCompleted), completions => {
|
|
done(null, completions);
|
|
});
|
|
}
|
|
else {
|
|
return this.customCompletionFunction(current, argv, completions => {
|
|
done(null, completions);
|
|
});
|
|
}
|
|
}
|
|
getCompletion(args, done) {
|
|
const current = args.length ? args[args.length - 1] : '';
|
|
const argv = this.yargs.parse(args, true);
|
|
const completionFunction = this.customCompletionFunction
|
|
? (argv) => this.customCompletion(args, argv, current, done)
|
|
: (argv) => this.defaultCompletion(args, argv, current, done);
|
|
return isPromise(argv)
|
|
? argv.then(completionFunction)
|
|
: completionFunction(argv);
|
|
}
|
|
generateCompletionScript($0, cmd) {
|
|
let script = this.zshShell
|
|
? templates.completionZshTemplate
|
|
: templates.completionShTemplate;
|
|
const name = this.shim.path.basename($0);
|
|
if ($0.match(/\.js$/))
|
|
$0 = `./${$0}`;
|
|
script = script.replace(/{{app_name}}/g, name);
|
|
script = script.replace(/{{completion_command}}/g, cmd);
|
|
return script.replace(/{{app_path}}/g, $0);
|
|
}
|
|
registerFunction(fn) {
|
|
this.customCompletionFunction = fn;
|
|
}
|
|
setParsed(parsed) {
|
|
this.aliases = parsed.aliases;
|
|
}
|
|
}
|
|
export function completion(yargs, usage, command, shim) {
|
|
return new Completion(yargs, usage, command, shim);
|
|
}
|
|
function isSyncCompletionFunction(completionFunction) {
|
|
return completionFunction.length < 3;
|
|
}
|
|
function isFallbackCompletionFunction(completionFunction) {
|
|
return completionFunction.length > 3;
|
|
}
|