time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

argument.js (3158B)


      1 const { InvalidArgumentError } = require('./error.js');
      2 
      3 class Argument {
      4   /**
      5    * Initialize a new command argument with the given name and description.
      6    * The default is that the argument is required, and you can explicitly
      7    * indicate this with <> around the name. Put [] around the name for an optional argument.
      8    *
      9    * @param {string} name
     10    * @param {string} [description]
     11    */
     12 
     13   constructor(name, description) {
     14     this.description = description || '';
     15     this.variadic = false;
     16     this.parseArg = undefined;
     17     this.defaultValue = undefined;
     18     this.defaultValueDescription = undefined;
     19     this.argChoices = undefined;
     20 
     21     switch (name[0]) {
     22       case '<': // e.g. <required>
     23         this.required = true;
     24         this._name = name.slice(1, -1);
     25         break;
     26       case '[': // e.g. [optional]
     27         this.required = false;
     28         this._name = name.slice(1, -1);
     29         break;
     30       default:
     31         this.required = true;
     32         this._name = name;
     33         break;
     34     }
     35 
     36     if (this._name.length > 3 && this._name.slice(-3) === '...') {
     37       this.variadic = true;
     38       this._name = this._name.slice(0, -3);
     39     }
     40   }
     41 
     42   /**
     43    * Return argument name.
     44    *
     45    * @return {string}
     46    */
     47 
     48   name() {
     49     return this._name;
     50   }
     51 
     52   /**
     53    * @api private
     54    */
     55 
     56   _concatValue(value, previous) {
     57     if (previous === this.defaultValue || !Array.isArray(previous)) {
     58       return [value];
     59     }
     60 
     61     return previous.concat(value);
     62   }
     63 
     64   /**
     65    * Set the default value, and optionally supply the description to be displayed in the help.
     66    *
     67    * @param {*} value
     68    * @param {string} [description]
     69    * @return {Argument}
     70    */
     71 
     72   default(value, description) {
     73     this.defaultValue = value;
     74     this.defaultValueDescription = description;
     75     return this;
     76   }
     77 
     78   /**
     79    * Set the custom handler for processing CLI command arguments into argument values.
     80    *
     81    * @param {Function} [fn]
     82    * @return {Argument}
     83    */
     84 
     85   argParser(fn) {
     86     this.parseArg = fn;
     87     return this;
     88   }
     89 
     90   /**
     91    * Only allow argument value to be one of choices.
     92    *
     93    * @param {string[]} values
     94    * @return {Argument}
     95    */
     96 
     97   choices(values) {
     98     this.argChoices = values.slice();
     99     this.parseArg = (arg, previous) => {
    100       if (!this.argChoices.includes(arg)) {
    101         throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(', ')}.`);
    102       }
    103       if (this.variadic) {
    104         return this._concatValue(arg, previous);
    105       }
    106       return arg;
    107     };
    108     return this;
    109   }
    110 
    111   /**
    112    * Make argument required.
    113    */
    114   argRequired() {
    115     this.required = true;
    116     return this;
    117   }
    118 
    119   /**
    120    * Make argument optional.
    121    */
    122   argOptional() {
    123     this.required = false;
    124     return this;
    125   }
    126 }
    127 
    128 /**
    129  * Takes an argument and returns its human readable equivalent for help usage.
    130  *
    131  * @param {Argument} arg
    132  * @return {string}
    133  * @api private
    134  */
    135 
    136 function humanReadableArgName(arg) {
    137   const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');
    138 
    139   return arg.required
    140     ? '<' + nameOutput + '>'
    141     : '[' + nameOutput + ']';
    142 }
    143 
    144 exports.Argument = Argument;
    145 exports.humanReadableArgName = humanReadableArgName;