123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- const { InvalidArgumentError } = require('./error.js');
- class Argument {
- /**
- * Initialize a new command argument with the given name and description.
- * The default is that the argument is required, and you can explicitly
- * indicate this with <> around the name. Put [] around the name for an optional argument.
- *
- * @param {string} name
- * @param {string} [description]
- */
- constructor(name, description) {
- this.description = description || '';
- this.variadic = false;
- this.parseArg = undefined;
- this.defaultValue = undefined;
- this.defaultValueDescription = undefined;
- this.argChoices = undefined;
- switch (name[0]) {
- case '<': // e.g. <required>
- this.required = true;
- this._name = name.slice(1, -1);
- break;
- case '[': // e.g. [optional]
- this.required = false;
- this._name = name.slice(1, -1);
- break;
- default:
- this.required = true;
- this._name = name;
- break;
- }
- if (this._name.length > 3 && this._name.slice(-3) === '...') {
- this.variadic = true;
- this._name = this._name.slice(0, -3);
- }
- }
- /**
- * Return argument name.
- *
- * @return {string}
- */
- name() {
- return this._name;
- }
- /**
- * @package
- */
- _concatValue(value, previous) {
- if (previous === this.defaultValue || !Array.isArray(previous)) {
- return [value];
- }
- return previous.concat(value);
- }
- /**
- * Set the default value, and optionally supply the description to be displayed in the help.
- *
- * @param {*} value
- * @param {string} [description]
- * @return {Argument}
- */
- default(value, description) {
- this.defaultValue = value;
- this.defaultValueDescription = description;
- return this;
- }
- /**
- * Set the custom handler for processing CLI command arguments into argument values.
- *
- * @param {Function} [fn]
- * @return {Argument}
- */
- argParser(fn) {
- this.parseArg = fn;
- return this;
- }
- /**
- * Only allow argument value to be one of choices.
- *
- * @param {string[]} values
- * @return {Argument}
- */
- choices(values) {
- this.argChoices = values.slice();
- this.parseArg = (arg, previous) => {
- if (!this.argChoices.includes(arg)) {
- throw new InvalidArgumentError(
- `Allowed choices are ${this.argChoices.join(', ')}.`,
- );
- }
- if (this.variadic) {
- return this._concatValue(arg, previous);
- }
- return arg;
- };
- return this;
- }
- /**
- * Make argument required.
- *
- * @returns {Argument}
- */
- argRequired() {
- this.required = true;
- return this;
- }
- /**
- * Make argument optional.
- *
- * @returns {Argument}
- */
- argOptional() {
- this.required = false;
- return this;
- }
- }
- /**
- * Takes an argument and returns its human readable equivalent for help usage.
- *
- * @param {Argument} arg
- * @return {string}
- * @private
- */
- function humanReadableArgName(arg) {
- const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');
- return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';
- }
- exports.Argument = Argument;
- exports.humanReadableArgName = humanReadableArgName;
|