123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- const { InvalidArgumentError } = require('./error.js');
- class Option {
-
- constructor(flags, description) {
- this.flags = flags;
- this.description = description || '';
- this.required = flags.includes('<');
- this.optional = flags.includes('[');
-
- this.variadic = /\w\.\.\.[>\]]$/.test(flags);
- this.mandatory = false;
- const optionFlags = splitOptionFlags(flags);
- this.short = optionFlags.shortFlag;
- this.long = optionFlags.longFlag;
- this.negate = false;
- if (this.long) {
- this.negate = this.long.startsWith('--no-');
- }
- this.defaultValue = undefined;
- this.defaultValueDescription = undefined;
- this.presetArg = undefined;
- this.envVar = undefined;
- this.parseArg = undefined;
- this.hidden = false;
- this.argChoices = undefined;
- this.conflictsWith = [];
- this.implied = undefined;
- }
-
- default(value, description) {
- this.defaultValue = value;
- this.defaultValueDescription = description;
- return this;
- }
-
- preset(arg) {
- this.presetArg = arg;
- return this;
- }
-
- conflicts(names) {
- this.conflictsWith = this.conflictsWith.concat(names);
- return this;
- }
-
- implies(impliedOptionValues) {
- let newImplied = impliedOptionValues;
- if (typeof impliedOptionValues === 'string') {
-
- newImplied = { [impliedOptionValues]: true };
- }
- this.implied = Object.assign(this.implied || {}, newImplied);
- return this;
- }
-
- env(name) {
- this.envVar = name;
- return this;
- }
-
- argParser(fn) {
- this.parseArg = fn;
- return this;
- }
-
- makeOptionMandatory(mandatory = true) {
- this.mandatory = !!mandatory;
- return this;
- }
-
- hideHelp(hide = true) {
- this.hidden = !!hide;
- return this;
- }
-
- _concatValue(value, previous) {
- if (previous === this.defaultValue || !Array.isArray(previous)) {
- return [value];
- }
- return previous.concat(value);
- }
-
- 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;
- }
-
- name() {
- if (this.long) {
- return this.long.replace(/^--/, '');
- }
- return this.short.replace(/^-/, '');
- }
-
- attributeName() {
- return camelcase(this.name().replace(/^no-/, ''));
- }
-
- is(arg) {
- return this.short === arg || this.long === arg;
- }
-
- isBoolean() {
- return !this.required && !this.optional && !this.negate;
- }
- }
- class DualOptions {
-
- constructor(options) {
- this.positiveOptions = new Map();
- this.negativeOptions = new Map();
- this.dualOptions = new Set();
- options.forEach((option) => {
- if (option.negate) {
- this.negativeOptions.set(option.attributeName(), option);
- } else {
- this.positiveOptions.set(option.attributeName(), option);
- }
- });
- this.negativeOptions.forEach((value, key) => {
- if (this.positiveOptions.has(key)) {
- this.dualOptions.add(key);
- }
- });
- }
-
- valueFromOption(value, option) {
- const optionKey = option.attributeName();
- if (!this.dualOptions.has(optionKey)) return true;
-
- const preset = this.negativeOptions.get(optionKey).presetArg;
- const negativeValue = preset !== undefined ? preset : false;
- return option.negate === (negativeValue === value);
- }
- }
- function camelcase(str) {
- return str.split('-').reduce((str, word) => {
- return str + word[0].toUpperCase() + word.slice(1);
- });
- }
- function splitOptionFlags(flags) {
- let shortFlag;
- let longFlag;
-
-
- const flagParts = flags.split(/[ |,]+/);
- if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
- shortFlag = flagParts.shift();
- longFlag = flagParts.shift();
-
- if (!shortFlag && /^-[^-]$/.test(longFlag)) {
- shortFlag = longFlag;
- longFlag = undefined;
- }
- return { shortFlag, longFlag };
- }
- exports.Option = Option;
- exports.DualOptions = DualOptions;
|