@rushstack/ts-command-line 5.2.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.json +40 -0
  2. package/CHANGELOG.md +15 -1
  3. package/dist/tsdoc-metadata.json +1 -1
  4. package/lib-esm/CommandLineHelper.js +19 -0
  5. package/lib-esm/CommandLineHelper.js.map +1 -0
  6. package/lib-esm/Constants.js +16 -0
  7. package/lib-esm/Constants.js.map +1 -0
  8. package/lib-esm/TypeUuidLite.js +28 -0
  9. package/lib-esm/TypeUuidLite.js.map +1 -0
  10. package/lib-esm/escapeSprintf.js +9 -0
  11. package/lib-esm/escapeSprintf.js.map +1 -0
  12. package/lib-esm/index.js +26 -0
  13. package/lib-esm/index.js.map +1 -0
  14. package/lib-esm/parameters/BaseClasses.js +163 -0
  15. package/lib-esm/parameters/BaseClasses.js.map +1 -0
  16. package/lib-esm/parameters/CommandLineChoiceListParameter.js +79 -0
  17. package/lib-esm/parameters/CommandLineChoiceListParameter.js.map +1 -0
  18. package/lib-esm/parameters/CommandLineChoiceParameter.js +90 -0
  19. package/lib-esm/parameters/CommandLineChoiceParameter.js.map +1 -0
  20. package/lib-esm/parameters/CommandLineDefinition.js +4 -0
  21. package/lib-esm/parameters/CommandLineDefinition.js.map +1 -0
  22. package/lib-esm/parameters/CommandLineFlagParameter.js +65 -0
  23. package/lib-esm/parameters/CommandLineFlagParameter.js.map +1 -0
  24. package/lib-esm/parameters/CommandLineIntegerListParameter.js +75 -0
  25. package/lib-esm/parameters/CommandLineIntegerListParameter.js.map +1 -0
  26. package/lib-esm/parameters/CommandLineIntegerParameter.js +79 -0
  27. package/lib-esm/parameters/CommandLineIntegerParameter.js.map +1 -0
  28. package/lib-esm/parameters/CommandLineRemainder.js +43 -0
  29. package/lib-esm/parameters/CommandLineRemainder.js.map +1 -0
  30. package/lib-esm/parameters/CommandLineStringListParameter.js +66 -0
  31. package/lib-esm/parameters/CommandLineStringListParameter.js.map +1 -0
  32. package/lib-esm/parameters/CommandLineStringParameter.js +78 -0
  33. package/lib-esm/parameters/CommandLineStringParameter.js.map +1 -0
  34. package/lib-esm/parameters/EnvironmentVariableParser.js +47 -0
  35. package/lib-esm/parameters/EnvironmentVariableParser.js.map +1 -0
  36. package/lib-esm/providers/AliasCommandLineAction.js +131 -0
  37. package/lib-esm/providers/AliasCommandLineAction.js.map +1 -0
  38. package/lib-esm/providers/CommandLineAction.js +76 -0
  39. package/lib-esm/providers/CommandLineAction.js.map +1 -0
  40. package/lib-esm/providers/CommandLineParameterProvider.js +671 -0
  41. package/lib-esm/providers/CommandLineParameterProvider.js.map +1 -0
  42. package/lib-esm/providers/CommandLineParser.js +262 -0
  43. package/lib-esm/providers/CommandLineParser.js.map +1 -0
  44. package/lib-esm/providers/CommandLineParserExitError.js +27 -0
  45. package/lib-esm/providers/CommandLineParserExitError.js.map +1 -0
  46. package/lib-esm/providers/DynamicCommandLineAction.js +13 -0
  47. package/lib-esm/providers/DynamicCommandLineAction.js.map +1 -0
  48. package/lib-esm/providers/DynamicCommandLineParser.js +9 -0
  49. package/lib-esm/providers/DynamicCommandLineParser.js.map +1 -0
  50. package/lib-esm/providers/ScopedCommandLineAction.js +197 -0
  51. package/lib-esm/providers/ScopedCommandLineAction.js.map +1 -0
  52. package/lib-esm/providers/TabCompletionAction.js +166 -0
  53. package/lib-esm/providers/TabCompletionAction.js.map +1 -0
  54. package/package.json +31 -7
  55. /package/{lib → lib-commonjs}/CommandLineHelper.js +0 -0
  56. /package/{lib → lib-commonjs}/CommandLineHelper.js.map +0 -0
  57. /package/{lib → lib-commonjs}/Constants.js +0 -0
  58. /package/{lib → lib-commonjs}/Constants.js.map +0 -0
  59. /package/{lib → lib-commonjs}/TypeUuidLite.js +0 -0
  60. /package/{lib → lib-commonjs}/TypeUuidLite.js.map +0 -0
  61. /package/{lib → lib-commonjs}/escapeSprintf.js +0 -0
  62. /package/{lib → lib-commonjs}/escapeSprintf.js.map +0 -0
  63. /package/{lib → lib-commonjs}/index.js +0 -0
  64. /package/{lib → lib-commonjs}/index.js.map +0 -0
  65. /package/{lib → lib-commonjs}/parameters/BaseClasses.js +0 -0
  66. /package/{lib → lib-commonjs}/parameters/BaseClasses.js.map +0 -0
  67. /package/{lib → lib-commonjs}/parameters/CommandLineChoiceListParameter.js +0 -0
  68. /package/{lib → lib-commonjs}/parameters/CommandLineChoiceListParameter.js.map +0 -0
  69. /package/{lib → lib-commonjs}/parameters/CommandLineChoiceParameter.js +0 -0
  70. /package/{lib → lib-commonjs}/parameters/CommandLineChoiceParameter.js.map +0 -0
  71. /package/{lib → lib-commonjs}/parameters/CommandLineDefinition.js +0 -0
  72. /package/{lib → lib-commonjs}/parameters/CommandLineDefinition.js.map +0 -0
  73. /package/{lib → lib-commonjs}/parameters/CommandLineFlagParameter.js +0 -0
  74. /package/{lib → lib-commonjs}/parameters/CommandLineFlagParameter.js.map +0 -0
  75. /package/{lib → lib-commonjs}/parameters/CommandLineIntegerListParameter.js +0 -0
  76. /package/{lib → lib-commonjs}/parameters/CommandLineIntegerListParameter.js.map +0 -0
  77. /package/{lib → lib-commonjs}/parameters/CommandLineIntegerParameter.js +0 -0
  78. /package/{lib → lib-commonjs}/parameters/CommandLineIntegerParameter.js.map +0 -0
  79. /package/{lib → lib-commonjs}/parameters/CommandLineRemainder.js +0 -0
  80. /package/{lib → lib-commonjs}/parameters/CommandLineRemainder.js.map +0 -0
  81. /package/{lib → lib-commonjs}/parameters/CommandLineStringListParameter.js +0 -0
  82. /package/{lib → lib-commonjs}/parameters/CommandLineStringListParameter.js.map +0 -0
  83. /package/{lib → lib-commonjs}/parameters/CommandLineStringParameter.js +0 -0
  84. /package/{lib → lib-commonjs}/parameters/CommandLineStringParameter.js.map +0 -0
  85. /package/{lib → lib-commonjs}/parameters/EnvironmentVariableParser.js +0 -0
  86. /package/{lib → lib-commonjs}/parameters/EnvironmentVariableParser.js.map +0 -0
  87. /package/{lib → lib-commonjs}/providers/AliasCommandLineAction.js +0 -0
  88. /package/{lib → lib-commonjs}/providers/AliasCommandLineAction.js.map +0 -0
  89. /package/{lib → lib-commonjs}/providers/CommandLineAction.js +0 -0
  90. /package/{lib → lib-commonjs}/providers/CommandLineAction.js.map +0 -0
  91. /package/{lib → lib-commonjs}/providers/CommandLineParameterProvider.js +0 -0
  92. /package/{lib → lib-commonjs}/providers/CommandLineParameterProvider.js.map +0 -0
  93. /package/{lib → lib-commonjs}/providers/CommandLineParser.js +0 -0
  94. /package/{lib → lib-commonjs}/providers/CommandLineParser.js.map +0 -0
  95. /package/{lib → lib-commonjs}/providers/CommandLineParserExitError.js +0 -0
  96. /package/{lib → lib-commonjs}/providers/CommandLineParserExitError.js.map +0 -0
  97. /package/{lib → lib-commonjs}/providers/DynamicCommandLineAction.js +0 -0
  98. /package/{lib → lib-commonjs}/providers/DynamicCommandLineAction.js.map +0 -0
  99. /package/{lib → lib-commonjs}/providers/DynamicCommandLineParser.js +0 -0
  100. /package/{lib → lib-commonjs}/providers/DynamicCommandLineParser.js.map +0 -0
  101. /package/{lib → lib-commonjs}/providers/ScopedCommandLineAction.js +0 -0
  102. /package/{lib → lib-commonjs}/providers/ScopedCommandLineAction.js.map +0 -0
  103. /package/{lib → lib-commonjs}/providers/TabCompletionAction.js +0 -0
  104. /package/{lib → lib-commonjs}/providers/TabCompletionAction.js.map +0 -0
  105. /package/{lib → lib-dts}/CommandLineHelper.d.ts +0 -0
  106. /package/{lib → lib-dts}/CommandLineHelper.d.ts.map +0 -0
  107. /package/{lib → lib-dts}/Constants.d.ts +0 -0
  108. /package/{lib → lib-dts}/Constants.d.ts.map +0 -0
  109. /package/{lib → lib-dts}/TypeUuidLite.d.ts +0 -0
  110. /package/{lib → lib-dts}/TypeUuidLite.d.ts.map +0 -0
  111. /package/{lib → lib-dts}/escapeSprintf.d.ts +0 -0
  112. /package/{lib → lib-dts}/escapeSprintf.d.ts.map +0 -0
  113. /package/{lib → lib-dts}/index.d.ts +0 -0
  114. /package/{lib → lib-dts}/index.d.ts.map +0 -0
  115. /package/{lib → lib-dts}/parameters/BaseClasses.d.ts +0 -0
  116. /package/{lib → lib-dts}/parameters/BaseClasses.d.ts.map +0 -0
  117. /package/{lib → lib-dts}/parameters/CommandLineChoiceListParameter.d.ts +0 -0
  118. /package/{lib → lib-dts}/parameters/CommandLineChoiceListParameter.d.ts.map +0 -0
  119. /package/{lib → lib-dts}/parameters/CommandLineChoiceParameter.d.ts +0 -0
  120. /package/{lib → lib-dts}/parameters/CommandLineChoiceParameter.d.ts.map +0 -0
  121. /package/{lib → lib-dts}/parameters/CommandLineDefinition.d.ts +0 -0
  122. /package/{lib → lib-dts}/parameters/CommandLineDefinition.d.ts.map +0 -0
  123. /package/{lib → lib-dts}/parameters/CommandLineFlagParameter.d.ts +0 -0
  124. /package/{lib → lib-dts}/parameters/CommandLineFlagParameter.d.ts.map +0 -0
  125. /package/{lib → lib-dts}/parameters/CommandLineIntegerListParameter.d.ts +0 -0
  126. /package/{lib → lib-dts}/parameters/CommandLineIntegerListParameter.d.ts.map +0 -0
  127. /package/{lib → lib-dts}/parameters/CommandLineIntegerParameter.d.ts +0 -0
  128. /package/{lib → lib-dts}/parameters/CommandLineIntegerParameter.d.ts.map +0 -0
  129. /package/{lib → lib-dts}/parameters/CommandLineRemainder.d.ts +0 -0
  130. /package/{lib → lib-dts}/parameters/CommandLineRemainder.d.ts.map +0 -0
  131. /package/{lib → lib-dts}/parameters/CommandLineStringListParameter.d.ts +0 -0
  132. /package/{lib → lib-dts}/parameters/CommandLineStringListParameter.d.ts.map +0 -0
  133. /package/{lib → lib-dts}/parameters/CommandLineStringParameter.d.ts +0 -0
  134. /package/{lib → lib-dts}/parameters/CommandLineStringParameter.d.ts.map +0 -0
  135. /package/{lib → lib-dts}/parameters/EnvironmentVariableParser.d.ts +0 -0
  136. /package/{lib → lib-dts}/parameters/EnvironmentVariableParser.d.ts.map +0 -0
  137. /package/{lib → lib-dts}/providers/AliasCommandLineAction.d.ts +0 -0
  138. /package/{lib → lib-dts}/providers/AliasCommandLineAction.d.ts.map +0 -0
  139. /package/{lib → lib-dts}/providers/CommandLineAction.d.ts +0 -0
  140. /package/{lib → lib-dts}/providers/CommandLineAction.d.ts.map +0 -0
  141. /package/{lib → lib-dts}/providers/CommandLineParameterProvider.d.ts +0 -0
  142. /package/{lib → lib-dts}/providers/CommandLineParameterProvider.d.ts.map +0 -0
  143. /package/{lib → lib-dts}/providers/CommandLineParser.d.ts +0 -0
  144. /package/{lib → lib-dts}/providers/CommandLineParser.d.ts.map +0 -0
  145. /package/{lib → lib-dts}/providers/CommandLineParserExitError.d.ts +0 -0
  146. /package/{lib → lib-dts}/providers/CommandLineParserExitError.d.ts.map +0 -0
  147. /package/{lib → lib-dts}/providers/DynamicCommandLineAction.d.ts +0 -0
  148. /package/{lib → lib-dts}/providers/DynamicCommandLineAction.d.ts.map +0 -0
  149. /package/{lib → lib-dts}/providers/DynamicCommandLineParser.d.ts +0 -0
  150. /package/{lib → lib-dts}/providers/DynamicCommandLineParser.d.ts.map +0 -0
  151. /package/{lib → lib-dts}/providers/ScopedCommandLineAction.d.ts +0 -0
  152. /package/{lib → lib-dts}/providers/ScopedCommandLineAction.d.ts.map +0 -0
  153. /package/{lib → lib-dts}/providers/TabCompletionAction.d.ts +0 -0
  154. /package/{lib → lib-dts}/providers/TabCompletionAction.d.ts.map +0 -0
@@ -0,0 +1,671 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import * as argparse from 'argparse';
4
+ import { CommandLineParameterKind } from '../parameters/BaseClasses';
5
+ import { CommandLineChoiceParameter } from '../parameters/CommandLineChoiceParameter';
6
+ import { CommandLineChoiceListParameter } from '../parameters/CommandLineChoiceListParameter';
7
+ import { CommandLineIntegerParameter } from '../parameters/CommandLineIntegerParameter';
8
+ import { CommandLineIntegerListParameter } from '../parameters/CommandLineIntegerListParameter';
9
+ import { CommandLineFlagParameter } from '../parameters/CommandLineFlagParameter';
10
+ import { CommandLineStringParameter } from '../parameters/CommandLineStringParameter';
11
+ import { CommandLineStringListParameter } from '../parameters/CommandLineStringListParameter';
12
+ import { CommandLineRemainder } from '../parameters/CommandLineRemainder';
13
+ import { SCOPING_PARAMETER_GROUP } from '../Constants';
14
+ import { CommandLineParserExitError } from './CommandLineParserExitError';
15
+ import { escapeSprintf } from '../escapeSprintf';
16
+ const SCOPE_GROUP_NAME = 'scope';
17
+ const LONG_NAME_GROUP_NAME = 'longName';
18
+ const POSSIBLY_SCOPED_LONG_NAME_REGEXP = /^--((?<scope>[a-z0-9]+(-[a-z0-9]+)*):)?(?<longName>[a-z0-9]+((-[a-z0-9]+)+)?)$/;
19
+ /**
20
+ * This is the common base class for CommandLineAction and CommandLineParser
21
+ * that provides functionality for defining command-line parameters.
22
+ *
23
+ * @public
24
+ */
25
+ export class CommandLineParameterProvider {
26
+ /** @internal */
27
+ // Third party code should not inherit subclasses or call this constructor
28
+ constructor() {
29
+ this._parameters = [];
30
+ this._parametersByLongName = new Map();
31
+ this._parametersByShortName = new Map();
32
+ this._parameterGroupsByName = new Map();
33
+ this._ambiguousParameterParserKeysByName = new Map();
34
+ this._registeredParameterParserKeysByName = new Map();
35
+ this._parametersHaveBeenRegistered = false;
36
+ this._parametersHaveBeenProcessed = false;
37
+ }
38
+ /**
39
+ * Returns a collection of the parameters that were defined for this object.
40
+ */
41
+ get parameters() {
42
+ return this._parameters;
43
+ }
44
+ /**
45
+ * Informs the caller if the argparse data has been processed into parameters.
46
+ */
47
+ get parametersProcessed() {
48
+ return this._parametersHaveBeenProcessed;
49
+ }
50
+ /**
51
+ * If {@link CommandLineParameterProvider.defineCommandLineRemainder} was called,
52
+ * this object captures any remaining command line arguments after the recognized portion.
53
+ */
54
+ get remainder() {
55
+ return this._remainder;
56
+ }
57
+ defineChoiceParameter(definition) {
58
+ const parameter = new CommandLineChoiceParameter(definition);
59
+ this._defineParameter(parameter);
60
+ return parameter;
61
+ }
62
+ /**
63
+ * Returns the CommandLineChoiceParameter with the specified long name.
64
+ * @remarks
65
+ * This method throws an exception if the parameter is not defined.
66
+ */
67
+ getChoiceParameter(parameterLongName, parameterScope) {
68
+ return this._getParameter(parameterLongName, CommandLineParameterKind.Choice, parameterScope);
69
+ }
70
+ /**
71
+ * Defines a command-line parameter whose value must be a string from a fixed set of
72
+ * allowable choices (similar to an enum). The parameter can be specified multiple times to
73
+ * build a list.
74
+ *
75
+ * @remarks
76
+ * Example of a choice list parameter:
77
+ * ```
78
+ * example-tool --allow-color red --allow-color green
79
+ * ```
80
+ */
81
+ defineChoiceListParameter(definition) {
82
+ const parameter = new CommandLineChoiceListParameter(definition);
83
+ this._defineParameter(parameter);
84
+ return parameter;
85
+ }
86
+ /**
87
+ * Returns the CommandLineChoiceListParameter with the specified long name.
88
+ * @remarks
89
+ * This method throws an exception if the parameter is not defined.
90
+ */
91
+ getChoiceListParameter(parameterLongName, parameterScope) {
92
+ return this._getParameter(parameterLongName, CommandLineParameterKind.ChoiceList, parameterScope);
93
+ }
94
+ /**
95
+ * Defines a command-line switch whose boolean value is true if the switch is provided,
96
+ * and false otherwise.
97
+ *
98
+ * @remarks
99
+ * Example usage of a flag parameter:
100
+ * ```
101
+ * example-tool --debug
102
+ * ```
103
+ */
104
+ defineFlagParameter(definition) {
105
+ const parameter = new CommandLineFlagParameter(definition);
106
+ this._defineParameter(parameter);
107
+ return parameter;
108
+ }
109
+ /**
110
+ * Returns the CommandLineFlagParameter with the specified long name.
111
+ * @remarks
112
+ * This method throws an exception if the parameter is not defined.
113
+ */
114
+ getFlagParameter(parameterLongName, parameterScope) {
115
+ return this._getParameter(parameterLongName, CommandLineParameterKind.Flag, parameterScope);
116
+ }
117
+ defineIntegerParameter(definition) {
118
+ const parameter = new CommandLineIntegerParameter(definition);
119
+ this._defineParameter(parameter);
120
+ return parameter;
121
+ }
122
+ /**
123
+ * Returns the CommandLineIntegerParameter with the specified long name.
124
+ * @remarks
125
+ * This method throws an exception if the parameter is not defined.
126
+ */
127
+ getIntegerParameter(parameterLongName, parameterScope) {
128
+ return this._getParameter(parameterLongName, CommandLineParameterKind.Integer, parameterScope);
129
+ }
130
+ /**
131
+ * Defines a command-line parameter whose argument is an integer. The parameter can be specified
132
+ * multiple times to build a list.
133
+ *
134
+ * @remarks
135
+ * Example usage of an integer list parameter:
136
+ * ```
137
+ * example-tool --avoid 4 --avoid 13
138
+ * ```
139
+ */
140
+ defineIntegerListParameter(definition) {
141
+ const parameter = new CommandLineIntegerListParameter(definition);
142
+ this._defineParameter(parameter);
143
+ return parameter;
144
+ }
145
+ /**
146
+ * Returns the CommandLineIntegerParameter with the specified long name.
147
+ * @remarks
148
+ * This method throws an exception if the parameter is not defined.
149
+ */
150
+ getIntegerListParameter(parameterLongName, parameterScope) {
151
+ return this._getParameter(parameterLongName, CommandLineParameterKind.IntegerList, parameterScope);
152
+ }
153
+ defineStringParameter(definition) {
154
+ const parameter = new CommandLineStringParameter(definition);
155
+ this._defineParameter(parameter);
156
+ return parameter;
157
+ }
158
+ /**
159
+ * Returns the CommandLineStringParameter with the specified long name.
160
+ * @remarks
161
+ * This method throws an exception if the parameter is not defined.
162
+ */
163
+ getStringParameter(parameterLongName, parameterScope) {
164
+ return this._getParameter(parameterLongName, CommandLineParameterKind.String, parameterScope);
165
+ }
166
+ /**
167
+ * Defines a command-line parameter whose argument is a single text string. The parameter can be
168
+ * specified multiple times to build a list.
169
+ *
170
+ * @remarks
171
+ * Example usage of a string list parameter:
172
+ * ```
173
+ * example-tool --add file1.txt --add file2.txt --add file3.txt
174
+ * ```
175
+ */
176
+ defineStringListParameter(definition) {
177
+ const parameter = new CommandLineStringListParameter(definition);
178
+ this._defineParameter(parameter);
179
+ return parameter;
180
+ }
181
+ /**
182
+ * Defines a rule that captures any remaining command line arguments after the recognized portion.
183
+ *
184
+ * @remarks
185
+ * This feature is useful for commands that pass their arguments along to an external tool, relying on
186
+ * that tool to perform validation. (It could also be used to parse parameters without any validation
187
+ * or documentation, but that is not recommended.)
188
+ *
189
+ * Example of capturing the remainder after an optional flag parameter.
190
+ * ```
191
+ * example-tool --my-flag this is the remainder
192
+ * ```
193
+ *
194
+ * In the "--help" documentation, the remainder rule will be represented as "...".
195
+ */
196
+ defineCommandLineRemainder(definition) {
197
+ if (this._remainder) {
198
+ throw new Error('defineRemainingArguments() has already been called for this provider');
199
+ }
200
+ this._remainder = new CommandLineRemainder(definition);
201
+ return this._remainder;
202
+ }
203
+ /**
204
+ * Returns the CommandLineStringListParameter with the specified long name.
205
+ * @remarks
206
+ * This method throws an exception if the parameter is not defined.
207
+ */
208
+ getStringListParameter(parameterLongName, parameterScope) {
209
+ return this._getParameter(parameterLongName, CommandLineParameterKind.StringList, parameterScope);
210
+ }
211
+ /**
212
+ * Generates the command-line help text.
213
+ */
214
+ renderHelpText() {
215
+ const initialState = {
216
+ parentParameterNames: new Set()
217
+ };
218
+ this._registerDefinedParameters(initialState);
219
+ return this._getArgumentParser().formatHelp();
220
+ }
221
+ /**
222
+ * Generates the command-line usage text.
223
+ */
224
+ renderUsageText() {
225
+ const initialState = {
226
+ parentParameterNames: new Set()
227
+ };
228
+ this._registerDefinedParameters(initialState);
229
+ return this._getArgumentParser().formatUsage();
230
+ }
231
+ /**
232
+ * Returns a object which maps the long name of each parameter in this.parameters
233
+ * to the stringified form of its value. This is useful for logging telemetry, but
234
+ * it is not the proper way of accessing parameters or their values.
235
+ */
236
+ getParameterStringMap() {
237
+ const parameterMap = {};
238
+ for (const parameter of this.parameters) {
239
+ const parameterName = parameter.scopedLongName || parameter.longName;
240
+ switch (parameter.kind) {
241
+ case CommandLineParameterKind.Flag:
242
+ case CommandLineParameterKind.Choice:
243
+ case CommandLineParameterKind.String:
244
+ case CommandLineParameterKind.Integer:
245
+ parameterMap[parameterName] = JSON.stringify(parameter.value);
246
+ break;
247
+ case CommandLineParameterKind.StringList:
248
+ case CommandLineParameterKind.IntegerList:
249
+ case CommandLineParameterKind.ChoiceList:
250
+ const arrayValue = parameter.values;
251
+ parameterMap[parameterName] = arrayValue ? arrayValue.join(',') : '';
252
+ break;
253
+ }
254
+ }
255
+ return parameterMap;
256
+ }
257
+ /**
258
+ * Returns an object with the parsed scope (if present) and the long name of the parameter.
259
+ */
260
+ parseScopedLongName(scopedLongName) {
261
+ const result = POSSIBLY_SCOPED_LONG_NAME_REGEXP.exec(scopedLongName);
262
+ if (!result || !result.groups) {
263
+ throw new Error(`The parameter long name "${scopedLongName}" is not valid.`);
264
+ }
265
+ return {
266
+ longName: `--${result.groups[LONG_NAME_GROUP_NAME]}`,
267
+ scope: result.groups[SCOPE_GROUP_NAME]
268
+ };
269
+ }
270
+ /** @internal */
271
+ _registerDefinedParameters(state) {
272
+ if (this._parametersHaveBeenRegistered) {
273
+ // We prevent new parameters from being defined after the first call to _registerDefinedParameters,
274
+ // so we can already ensure that all parameters were registered.
275
+ return;
276
+ }
277
+ // First, loop through all parameters with short names. If there are any duplicates, disable the short names
278
+ // since we can't prefix scopes to short names in order to deduplicate them. The duplicate short names will
279
+ // be reported as errors if the user attempts to use them.
280
+ const parametersWithDuplicateShortNames = new Set();
281
+ for (const [shortName, shortNameParameters] of this._parametersByShortName.entries()) {
282
+ if (shortNameParameters.length > 1) {
283
+ for (const parameter of shortNameParameters) {
284
+ this._defineAmbiguousParameter(shortName);
285
+ parametersWithDuplicateShortNames.add(parameter);
286
+ }
287
+ }
288
+ }
289
+ // Then, loop through all parameters and register them. If there are any duplicates, ensure that they have
290
+ // provided a scope and register them with the scope. The duplicate long names will be reported as an error
291
+ // if the user attempts to use them.
292
+ for (const longNameParameters of this._parametersByLongName.values()) {
293
+ const useScopedLongName = longNameParameters.length > 1;
294
+ for (const parameter of longNameParameters) {
295
+ if (useScopedLongName) {
296
+ if (!parameter.parameterScope) {
297
+ throw new Error(`The parameter "${parameter.longName}" is defined multiple times with the same long name. ` +
298
+ 'Parameters with the same long name must define a scope.');
299
+ }
300
+ this._defineAmbiguousParameter(parameter.longName);
301
+ }
302
+ const ignoreShortName = parametersWithDuplicateShortNames.has(parameter);
303
+ this._registerParameter(parameter, useScopedLongName, ignoreShortName);
304
+ }
305
+ }
306
+ // Register the existing parameters as ambiguous parameters. These are generally provided by the
307
+ // parent action.
308
+ const { parentParameterNames } = state;
309
+ for (const parentParameterName of parentParameterNames) {
310
+ this._defineAmbiguousParameter(parentParameterName);
311
+ }
312
+ // We also need to loop through the defined ambiguous parameters and register them. These will be reported
313
+ // as errors if the user attempts to use them.
314
+ for (const [ambiguousParameterName, parserKey] of this._ambiguousParameterParserKeysByName) {
315
+ // Only register the ambiguous parameter if it hasn't already been registered. We will still handle these
316
+ // already-registered parameters as ambiguous, but by avoiding registering again, we will defer errors
317
+ // until the user actually attempts to use the parameter.
318
+ if (!this._registeredParameterParserKeysByName.has(ambiguousParameterName)) {
319
+ this._registerAmbiguousParameter(ambiguousParameterName, parserKey);
320
+ }
321
+ }
322
+ // Need to add the remainder parameter last
323
+ if (this._remainder) {
324
+ const argparseOptions = {
325
+ help: this._remainder.description,
326
+ nargs: argparse.Const.REMAINDER,
327
+ metavar: '"..."'
328
+ };
329
+ this._getArgumentParser().addArgument(argparse.Const.REMAINDER, argparseOptions);
330
+ }
331
+ this._parametersHaveBeenRegistered = true;
332
+ }
333
+ /**
334
+ * This is called internally by {@link CommandLineParser.executeAsync}
335
+ * @internal
336
+ */
337
+ _preParse() {
338
+ var _a;
339
+ for (const parameter of this._parameters) {
340
+ (_a = parameter._preParse) === null || _a === void 0 ? void 0 : _a.call(parameter);
341
+ }
342
+ }
343
+ /**
344
+ * This is called internally by {@link CommandLineParser.executeAsync} before `printUsage` is called
345
+ * @internal
346
+ */
347
+ _postParse() {
348
+ var _a;
349
+ for (const parameter of this._parameters) {
350
+ (_a = parameter._postParse) === null || _a === void 0 ? void 0 : _a.call(parameter);
351
+ }
352
+ }
353
+ /**
354
+ * This is called internally by {@link CommandLineParser.executeAsync}
355
+ * @internal
356
+ */
357
+ _processParsedData(parserOptions, data) {
358
+ var _a;
359
+ if (!this._parametersHaveBeenRegistered) {
360
+ throw new Error('Parameters have not been registered');
361
+ }
362
+ if (this._parametersHaveBeenProcessed) {
363
+ throw new Error('Command Line Parser Data was already processed');
364
+ }
365
+ // Search for any ambiguous parameters and throw an error if any are found
366
+ for (const [parameterName, parserKey] of this._ambiguousParameterParserKeysByName) {
367
+ if (data[parserKey]) {
368
+ // When the parser key matches the actually registered parameter, we know that this is an ambiguous
369
+ // parameter sourced from the parent action or tool
370
+ if (this._registeredParameterParserKeysByName.get(parameterName) === parserKey) {
371
+ this._throwParserExitError(parserOptions, data, 1, `Ambiguous option: "${parameterName}".`);
372
+ }
373
+ // Determine if the ambiguous parameter is a short name or a long name, since the process of finding
374
+ // the non-ambiguous name is different for each.
375
+ const duplicateShortNameParameters = this._parametersByShortName.get(parameterName);
376
+ if (duplicateShortNameParameters) {
377
+ // We also need to make sure we get the non-ambiguous long name for the parameter, since it is
378
+ // possible for that the long name is ambiguous as well.
379
+ const nonAmbiguousLongNames = [];
380
+ for (const parameter of duplicateShortNameParameters) {
381
+ const matchingLongNameParameters = this._parametersByLongName.get(parameter.longName);
382
+ if (!(matchingLongNameParameters === null || matchingLongNameParameters === void 0 ? void 0 : matchingLongNameParameters.length)) {
383
+ // This should never happen
384
+ throw new Error(`Unable to find long name parameters for ambiguous short name parameter "${parameterName}".`);
385
+ }
386
+ // If there is more than one matching long name parameter, then we know that we need to use the
387
+ // scoped long name for the parameter. The scoped long name should always be provided.
388
+ if (matchingLongNameParameters.length > 1) {
389
+ if (!parameter.scopedLongName) {
390
+ // This should never happen
391
+ throw new Error(`Unable to find scoped long name for ambiguous short name parameter "${parameterName}".`);
392
+ }
393
+ nonAmbiguousLongNames.push(parameter.scopedLongName);
394
+ }
395
+ else {
396
+ nonAmbiguousLongNames.push(parameter.longName);
397
+ }
398
+ }
399
+ // Throw an error including the non-ambiguous long names for the parameters that have the ambiguous
400
+ // short name, ex.
401
+ // Error: Ambiguous option "-p" could match "--param1", "--param2"
402
+ this._throwParserExitError(parserOptions, data, 1, `Ambiguous option: "${parameterName}" could match ${nonAmbiguousLongNames.join(', ')}.`);
403
+ }
404
+ const duplicateLongNameParameters = this._parametersByLongName.get(parameterName);
405
+ if (duplicateLongNameParameters) {
406
+ const nonAmbiguousLongNames = duplicateLongNameParameters.map((p) => {
407
+ // The scoped long name should always be provided
408
+ if (!p.scopedLongName) {
409
+ // This should never happen
410
+ throw new Error(`Unable to find scoped long name for ambiguous long name parameter "${parameterName}".`);
411
+ }
412
+ return p.scopedLongName;
413
+ });
414
+ // Throw an error including the non-ambiguous scoped long names for the parameters that have the
415
+ // ambiguous long name, ex.
416
+ // Error: Ambiguous option: "--param" could match --scope1:param, --scope2:param
417
+ this._throwParserExitError(parserOptions, data, 1, `Ambiguous option: "${parameterName}" could match ${nonAmbiguousLongNames.join(', ')}.`);
418
+ }
419
+ // This shouldn't happen, but we also shouldn't allow the user to use the ambiguous parameter
420
+ this._throwParserExitError(parserOptions, data, 1, `Ambiguous option: "${parameterName}".`);
421
+ }
422
+ }
423
+ // Fill in the values for the parameters
424
+ for (const parameter of this._parameters) {
425
+ const value = data[parameter._parserKey];
426
+ parameter._setValue(value);
427
+ (_a = parameter._validateValue) === null || _a === void 0 ? void 0 : _a.call(parameter);
428
+ }
429
+ if (this.remainder) {
430
+ this.remainder._setValue(data[argparse.Const.REMAINDER]);
431
+ }
432
+ this._parametersHaveBeenProcessed = true;
433
+ }
434
+ /** @internal */
435
+ _defineParameter(parameter) {
436
+ if (this._parametersHaveBeenRegistered) {
437
+ throw new Error('Parameters have already been registered for this provider');
438
+ }
439
+ // Generate and set the parser key at definition time
440
+ parameter._parserKey = this._generateKey();
441
+ this._parameters.push(parameter);
442
+ // Collect all parameters with the same long name. We will perform conflict resolution at registration.
443
+ let longNameParameters = this._parametersByLongName.get(parameter.longName);
444
+ if (!longNameParameters) {
445
+ longNameParameters = [];
446
+ this._parametersByLongName.set(parameter.longName, longNameParameters);
447
+ }
448
+ longNameParameters.push(parameter);
449
+ // Collect all parameters with the same short name. We will perform conflict resolution at registration.
450
+ if (parameter.shortName) {
451
+ let shortNameParameters = this._parametersByShortName.get(parameter.shortName);
452
+ if (!shortNameParameters) {
453
+ shortNameParameters = [];
454
+ this._parametersByShortName.set(parameter.shortName, shortNameParameters);
455
+ }
456
+ shortNameParameters.push(parameter);
457
+ }
458
+ }
459
+ /** @internal */
460
+ _defineAmbiguousParameter(name) {
461
+ if (this._parametersHaveBeenRegistered) {
462
+ throw new Error('Parameters have already been registered for this provider');
463
+ }
464
+ // Only generate a new parser key if the ambiguous parameter hasn't been defined yet,
465
+ // either as an existing parameter or as another ambiguous parameter
466
+ let existingParserKey = this._registeredParameterParserKeysByName.get(name) ||
467
+ this._ambiguousParameterParserKeysByName.get(name);
468
+ if (!existingParserKey) {
469
+ existingParserKey = this._generateKey();
470
+ }
471
+ this._ambiguousParameterParserKeysByName.set(name, existingParserKey);
472
+ return existingParserKey;
473
+ }
474
+ /** @internal */
475
+ _registerParameter(parameter, useScopedLongName, ignoreShortName) {
476
+ var _a, _b, _c;
477
+ const { shortName, longName, scopedLongName, description, kind, required, environmentVariable, parameterGroup, undocumentedSynonyms, _parserKey: parserKey } = parameter;
478
+ const names = [];
479
+ if (shortName && !ignoreShortName) {
480
+ names.push(shortName);
481
+ }
482
+ // Use the original long name unless otherwise requested
483
+ if (!useScopedLongName) {
484
+ names.push(longName);
485
+ }
486
+ // Add the scoped long name if it exists
487
+ if (scopedLongName) {
488
+ names.push(scopedLongName);
489
+ }
490
+ let finalDescription = description;
491
+ const supplementaryNotes = [];
492
+ parameter._getSupplementaryNotes(supplementaryNotes);
493
+ if (supplementaryNotes.length > 0) {
494
+ // If they left the period off the end of their sentence, then add one.
495
+ if (finalDescription.match(/[a-z0-9]"?\s*$/i)) {
496
+ finalDescription = finalDescription.trimEnd() + '.';
497
+ }
498
+ // Append the supplementary text
499
+ finalDescription += ' ' + supplementaryNotes.join(' ');
500
+ }
501
+ let choices;
502
+ let action;
503
+ let type;
504
+ switch (kind) {
505
+ case CommandLineParameterKind.Choice: {
506
+ choices = Array.from(parameter.alternatives);
507
+ break;
508
+ }
509
+ case CommandLineParameterKind.ChoiceList: {
510
+ choices = Array.from(parameter.alternatives);
511
+ action = 'append';
512
+ break;
513
+ }
514
+ case CommandLineParameterKind.Flag:
515
+ action = 'storeTrue';
516
+ break;
517
+ case CommandLineParameterKind.Integer:
518
+ type = 'int';
519
+ break;
520
+ case CommandLineParameterKind.IntegerList:
521
+ type = 'int';
522
+ action = 'append';
523
+ break;
524
+ case CommandLineParameterKind.String:
525
+ break;
526
+ case CommandLineParameterKind.StringList:
527
+ action = 'append';
528
+ break;
529
+ }
530
+ // NOTE: Our "environmentVariable" feature takes precedence over argparse's "defaultValue",
531
+ // so we have to reimplement that feature.
532
+ const argparseOptions = {
533
+ help: escapeSprintf(finalDescription),
534
+ dest: parserKey,
535
+ metavar: parameter.argumentName,
536
+ required,
537
+ choices,
538
+ action,
539
+ type
540
+ };
541
+ const argumentParser = this._getArgumentParser();
542
+ let argumentGroup;
543
+ if (parameterGroup) {
544
+ argumentGroup = this._parameterGroupsByName.get(parameterGroup);
545
+ if (!argumentGroup) {
546
+ let parameterGroupName;
547
+ if (typeof parameterGroup === 'string') {
548
+ parameterGroupName = parameterGroup;
549
+ }
550
+ else if (parameterGroup === SCOPING_PARAMETER_GROUP) {
551
+ parameterGroupName = 'scoping';
552
+ }
553
+ else {
554
+ throw new Error('Unexpected parameter group: ' + parameterGroup);
555
+ }
556
+ argumentGroup = argumentParser.addArgumentGroup({
557
+ title: `Optional ${parameterGroupName} arguments`
558
+ });
559
+ this._parameterGroupsByName.set(parameterGroup, argumentGroup);
560
+ }
561
+ }
562
+ else {
563
+ argumentGroup = argumentParser;
564
+ }
565
+ const argparseArgument = argumentGroup.addArgument(names, argparseOptions);
566
+ if (required && environmentVariable) {
567
+ // Add some special-cased logic to handle required parameters with environment variables
568
+ const originalPreParse = (_a = parameter._preParse) === null || _a === void 0 ? void 0 : _a.bind(parameter);
569
+ parameter._preParse = () => {
570
+ originalPreParse === null || originalPreParse === void 0 ? void 0 : originalPreParse();
571
+ // Set the value as non-required before parsing. We'll validate it explicitly
572
+ argparseArgument.required = false;
573
+ };
574
+ const originalPostParse = (_b = parameter._postParse) === null || _b === void 0 ? void 0 : _b.bind(parameter);
575
+ parameter._postParse = () => {
576
+ // Reset the required value to make the usage text correct
577
+ argparseArgument.required = true;
578
+ originalPostParse === null || originalPostParse === void 0 ? void 0 : originalPostParse();
579
+ };
580
+ function throwMissingParameterError() {
581
+ argumentParser.error(`Argument "${longName}" is required`);
582
+ }
583
+ const originalValidateValue = (_c = parameter._validateValue) === null || _c === void 0 ? void 0 : _c.bind(parameter);
584
+ // For these values, we have to perform explicit validation because they're requested
585
+ // as required, but we disabled argparse's required flag to allow the environment variable
586
+ // to potentially fill the value.
587
+ switch (kind) {
588
+ case CommandLineParameterKind.Choice:
589
+ case CommandLineParameterKind.Integer:
590
+ case CommandLineParameterKind.String:
591
+ parameter._validateValue = function () {
592
+ if (this.value === undefined || this.value === null) {
593
+ throwMissingParameterError();
594
+ }
595
+ originalValidateValue === null || originalValidateValue === void 0 ? void 0 : originalValidateValue();
596
+ };
597
+ break;
598
+ case CommandLineParameterKind.ChoiceList:
599
+ case CommandLineParameterKind.IntegerList:
600
+ case CommandLineParameterKind.StringList:
601
+ parameter._validateValue = function () {
602
+ if (this.values.length === 0) {
603
+ throwMissingParameterError();
604
+ }
605
+ originalValidateValue === null || originalValidateValue === void 0 ? void 0 : originalValidateValue();
606
+ };
607
+ break;
608
+ }
609
+ }
610
+ if (undocumentedSynonyms === null || undocumentedSynonyms === void 0 ? void 0 : undocumentedSynonyms.length) {
611
+ argumentGroup.addArgument(undocumentedSynonyms, {
612
+ ...argparseOptions,
613
+ help: argparse.Const.SUPPRESS
614
+ });
615
+ }
616
+ // Register the parameter names so that we can detect ambiguous parameters
617
+ for (const name of [...names, ...(undocumentedSynonyms || [])]) {
618
+ this._registeredParameterParserKeysByName.set(name, parserKey);
619
+ }
620
+ }
621
+ _registerAmbiguousParameter(name, parserKey) {
622
+ this._getArgumentParser().addArgument(name, {
623
+ dest: parserKey,
624
+ // We don't know if this argument takes parameters or not, so we need to accept any number of args
625
+ nargs: '*',
626
+ // Ensure that the argument is not shown in the help text, since these parameters are only included
627
+ // to inform the user that ambiguous parameters are present
628
+ help: argparse.Const.SUPPRESS
629
+ });
630
+ }
631
+ _generateKey() {
632
+ return 'key_' + (CommandLineParameterProvider._keyCounter++).toString();
633
+ }
634
+ _getParameter(parameterLongName, expectedKind, parameterScope) {
635
+ // Support the parameter long name being prefixed with the scope
636
+ const { scope, longName } = this.parseScopedLongName(parameterLongName);
637
+ parameterLongName = longName;
638
+ parameterScope = scope || parameterScope;
639
+ const parameters = this._parametersByLongName.get(parameterLongName);
640
+ if (!parameters) {
641
+ throw new Error(`The parameter "${parameterLongName}" is not defined`);
642
+ }
643
+ let parameter = parameters.find((p) => p.parameterScope === parameterScope);
644
+ if (!parameter) {
645
+ if (parameterScope !== undefined) {
646
+ throw new Error(`The parameter "${parameterLongName}" with scope "${parameterScope}" is not defined.`);
647
+ }
648
+ if (parameters.length !== 1) {
649
+ throw new Error(`The parameter "${parameterLongName}" is ambiguous. You must specify a scope.`);
650
+ }
651
+ parameter = parameters[0];
652
+ }
653
+ if (parameter.kind !== expectedKind) {
654
+ throw new Error(`The parameter "${parameterLongName}" is of type "${CommandLineParameterKind[parameter.kind]}"` +
655
+ ` whereas the caller was expecting "${CommandLineParameterKind[expectedKind]}".`);
656
+ }
657
+ return parameter;
658
+ }
659
+ _throwParserExitError(parserOptions, data, errorCode, message) {
660
+ // Write out the usage text to make it easier for the user to find the correct parameter name
661
+ const targetActionName = data.aliasAction || data.action || '';
662
+ const errorPrefix = `Error: ${parserOptions.toolFilename}` +
663
+ // Handle aliases, actions, and actionless parameter providers
664
+ `${targetActionName ? ' ' : ''}${targetActionName}: error: `;
665
+ // eslint-disable-next-line no-console
666
+ console.log(this.renderUsageText());
667
+ throw new CommandLineParserExitError(errorCode, `${errorPrefix}${message.trimStart().trimEnd()}\n`);
668
+ }
669
+ }
670
+ CommandLineParameterProvider._keyCounter = 0;
671
+ //# sourceMappingURL=CommandLineParameterProvider.js.map