source: frontend/node_modules/commander/lib/option.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 4.8 KB
Line 
1const { InvalidArgumentError } = require('./error.js');
2
3// @ts-check
4
5class Option {
6 /**
7 * Initialize a new `Option` with the given `flags` and `description`.
8 *
9 * @param {string} flags
10 * @param {string} [description]
11 */
12
13 constructor(flags, description) {
14 this.flags = flags;
15 this.description = description || '';
16
17 this.required = flags.includes('<'); // A value must be supplied when the option is specified.
18 this.optional = flags.includes('['); // A value is optional when the option is specified.
19 // variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
20 this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
21 this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
22 const optionFlags = splitOptionFlags(flags);
23 this.short = optionFlags.shortFlag;
24 this.long = optionFlags.longFlag;
25 this.negate = false;
26 if (this.long) {
27 this.negate = this.long.startsWith('--no-');
28 }
29 this.defaultValue = undefined;
30 this.defaultValueDescription = undefined;
31 this.envVar = undefined;
32 this.parseArg = undefined;
33 this.hidden = false;
34 this.argChoices = undefined;
35 }
36
37 /**
38 * Set the default value, and optionally supply the description to be displayed in the help.
39 *
40 * @param {any} value
41 * @param {string} [description]
42 * @return {Option}
43 */
44
45 default(value, description) {
46 this.defaultValue = value;
47 this.defaultValueDescription = description;
48 return this;
49 };
50
51 /**
52 * Set environment variable to check for option value.
53 * Priority order of option values is default < env < cli
54 *
55 * @param {string} name
56 * @return {Option}
57 */
58
59 env(name) {
60 this.envVar = name;
61 return this;
62 };
63
64 /**
65 * Set the custom handler for processing CLI option arguments into option values.
66 *
67 * @param {Function} [fn]
68 * @return {Option}
69 */
70
71 argParser(fn) {
72 this.parseArg = fn;
73 return this;
74 };
75
76 /**
77 * Whether the option is mandatory and must have a value after parsing.
78 *
79 * @param {boolean} [mandatory=true]
80 * @return {Option}
81 */
82
83 makeOptionMandatory(mandatory = true) {
84 this.mandatory = !!mandatory;
85 return this;
86 };
87
88 /**
89 * Hide option in help.
90 *
91 * @param {boolean} [hide=true]
92 * @return {Option}
93 */
94
95 hideHelp(hide = true) {
96 this.hidden = !!hide;
97 return this;
98 };
99
100 /**
101 * @api private
102 */
103
104 _concatValue(value, previous) {
105 if (previous === this.defaultValue || !Array.isArray(previous)) {
106 return [value];
107 }
108
109 return previous.concat(value);
110 }
111
112 /**
113 * Only allow option value to be one of choices.
114 *
115 * @param {string[]} values
116 * @return {Option}
117 */
118
119 choices(values) {
120 this.argChoices = values;
121 this.parseArg = (arg, previous) => {
122 if (!values.includes(arg)) {
123 throw new InvalidArgumentError(`Allowed choices are ${values.join(', ')}.`);
124 }
125 if (this.variadic) {
126 return this._concatValue(arg, previous);
127 }
128 return arg;
129 };
130 return this;
131 };
132
133 /**
134 * Return option name.
135 *
136 * @return {string}
137 */
138
139 name() {
140 if (this.long) {
141 return this.long.replace(/^--/, '');
142 }
143 return this.short.replace(/^-/, '');
144 };
145
146 /**
147 * Return option name, in a camelcase format that can be used
148 * as a object attribute key.
149 *
150 * @return {string}
151 * @api private
152 */
153
154 attributeName() {
155 return camelcase(this.name().replace(/^no-/, ''));
156 };
157
158 /**
159 * Check if `arg` matches the short or long flag.
160 *
161 * @param {string} arg
162 * @return {boolean}
163 * @api private
164 */
165
166 is(arg) {
167 return this.short === arg || this.long === arg;
168 };
169}
170
171/**
172 * Convert string from kebab-case to camelCase.
173 *
174 * @param {string} str
175 * @return {string}
176 * @api private
177 */
178
179function camelcase(str) {
180 return str.split('-').reduce((str, word) => {
181 return str + word[0].toUpperCase() + word.slice(1);
182 });
183}
184
185/**
186 * Split the short and long flag out of something like '-m,--mixed <value>'
187 *
188 * @api private
189 */
190
191function splitOptionFlags(flags) {
192 let shortFlag;
193 let longFlag;
194 // Use original very loose parsing to maintain backwards compatibility for now,
195 // which allowed for example unintended `-sw, --short-word` [sic].
196 const flagParts = flags.split(/[ |,]+/);
197 if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) shortFlag = flagParts.shift();
198 longFlag = flagParts.shift();
199 // Add support for lone short flag without significantly changing parsing!
200 if (!shortFlag && /^-[^-]$/.test(longFlag)) {
201 shortFlag = longFlag;
202 longFlag = undefined;
203 }
204 return { shortFlag, longFlag };
205}
206
207exports.Option = Option;
208exports.splitOptionFlags = splitOptionFlags;
Note: See TracBrowser for help on using the repository browser.