@optique/core 1.0.0-dev.427 → 1.0.0-dev.429

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.
package/dist/usage.d.cts CHANGED
@@ -12,6 +12,30 @@ import { NonEmptyString } from "./nonempty.cjs";
12
12
  * - Plus-prefixed options (`+o`)
13
13
  */
14
14
  type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
15
+ /**
16
+ * Visibility control for parser terms.
17
+ *
18
+ * - `true`: hidden from usage, documentation, and suggestions
19
+ * - `"usage"`: hidden from usage only
20
+ * - `"doc"`: hidden from documentation only
21
+ */
22
+ type HiddenVisibility = boolean | "usage" | "doc";
23
+ /**
24
+ * Returns whether the term should be hidden from usage output.
25
+ */
26
+ declare function isUsageHidden(hidden?: HiddenVisibility): boolean;
27
+ /**
28
+ * Returns whether the term should be hidden from documentation output.
29
+ */
30
+ declare function isDocHidden(hidden?: HiddenVisibility): boolean;
31
+ /**
32
+ * Returns whether the term should be hidden from suggestion/error candidates.
33
+ */
34
+ declare function isSuggestionHidden(hidden?: HiddenVisibility): boolean;
35
+ /**
36
+ * Merges two hidden visibility settings by taking the union of restrictions.
37
+ */
38
+ declare function mergeHidden(a?: HiddenVisibility, b?: HiddenVisibility): HiddenVisibility | undefined;
15
39
  /**
16
40
  * Represents a single term in a command-line usage description.
17
41
  */
@@ -31,11 +55,10 @@ type UsageTerm =
31
55
  */
32
56
  readonly metavar: NonEmptyString;
33
57
  /**
34
- * When `true`, hides the argument from help text, shell completion
35
- * suggestions, and error suggestions.
58
+ * Visibility controls for this term.
36
59
  * @since 0.9.0
37
60
  */
38
- readonly hidden?: boolean;
61
+ readonly hidden?: HiddenVisibility;
39
62
  }
40
63
  /**
41
64
  * An option term, which represents a command-line option that can
@@ -56,11 +79,10 @@ type UsageTerm =
56
79
  */
57
80
  readonly metavar?: NonEmptyString;
58
81
  /**
59
- * When `true`, hides the option from help text, shell completion
60
- * suggestions, and "Did you mean?" error suggestions.
82
+ * Visibility controls for this term.
61
83
  * @since 0.9.0
62
84
  */
63
- readonly hidden?: boolean;
85
+ readonly hidden?: HiddenVisibility;
64
86
  }
65
87
  /**
66
88
  * A command term, which represents a subcommand in the command-line
@@ -76,11 +98,10 @@ type UsageTerm =
76
98
  */
77
99
  readonly name: string;
78
100
  /**
79
- * When `true`, hides the command from help text, shell completion
80
- * suggestions, and "Did you mean?" error suggestions.
101
+ * Visibility controls for this term.
81
102
  * @since 0.9.0
82
103
  */
83
- readonly hidden?: boolean;
104
+ readonly hidden?: HiddenVisibility;
84
105
  }
85
106
  /**
86
107
  * An optional term, which represents an optional component
@@ -155,11 +176,10 @@ type UsageTerm =
155
176
  */
156
177
  readonly type: "passthrough";
157
178
  /**
158
- * When `true`, hides the pass-through from help text and shell
159
- * completion suggestions.
179
+ * Visibility controls for this term.
160
180
  * @since 0.9.0
161
181
  */
162
- readonly hidden?: boolean;
182
+ readonly hidden?: HiddenVisibility;
163
183
  };
164
184
  /**
165
185
  * Represents a command-line usage description, which is a sequence of
@@ -330,4 +350,4 @@ interface UsageTermFormatOptions extends UsageFormatOptions {
330
350
  */
331
351
  declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
332
352
  //#endregion
333
- export { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, normalizeUsage };
353
+ export { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage };
package/dist/usage.d.ts CHANGED
@@ -12,6 +12,30 @@ import { NonEmptyString } from "./nonempty.js";
12
12
  * - Plus-prefixed options (`+o`)
13
13
  */
14
14
  type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
15
+ /**
16
+ * Visibility control for parser terms.
17
+ *
18
+ * - `true`: hidden from usage, documentation, and suggestions
19
+ * - `"usage"`: hidden from usage only
20
+ * - `"doc"`: hidden from documentation only
21
+ */
22
+ type HiddenVisibility = boolean | "usage" | "doc";
23
+ /**
24
+ * Returns whether the term should be hidden from usage output.
25
+ */
26
+ declare function isUsageHidden(hidden?: HiddenVisibility): boolean;
27
+ /**
28
+ * Returns whether the term should be hidden from documentation output.
29
+ */
30
+ declare function isDocHidden(hidden?: HiddenVisibility): boolean;
31
+ /**
32
+ * Returns whether the term should be hidden from suggestion/error candidates.
33
+ */
34
+ declare function isSuggestionHidden(hidden?: HiddenVisibility): boolean;
35
+ /**
36
+ * Merges two hidden visibility settings by taking the union of restrictions.
37
+ */
38
+ declare function mergeHidden(a?: HiddenVisibility, b?: HiddenVisibility): HiddenVisibility | undefined;
15
39
  /**
16
40
  * Represents a single term in a command-line usage description.
17
41
  */
@@ -31,11 +55,10 @@ type UsageTerm =
31
55
  */
32
56
  readonly metavar: NonEmptyString;
33
57
  /**
34
- * When `true`, hides the argument from help text, shell completion
35
- * suggestions, and error suggestions.
58
+ * Visibility controls for this term.
36
59
  * @since 0.9.0
37
60
  */
38
- readonly hidden?: boolean;
61
+ readonly hidden?: HiddenVisibility;
39
62
  }
40
63
  /**
41
64
  * An option term, which represents a command-line option that can
@@ -56,11 +79,10 @@ type UsageTerm =
56
79
  */
57
80
  readonly metavar?: NonEmptyString;
58
81
  /**
59
- * When `true`, hides the option from help text, shell completion
60
- * suggestions, and "Did you mean?" error suggestions.
82
+ * Visibility controls for this term.
61
83
  * @since 0.9.0
62
84
  */
63
- readonly hidden?: boolean;
85
+ readonly hidden?: HiddenVisibility;
64
86
  }
65
87
  /**
66
88
  * A command term, which represents a subcommand in the command-line
@@ -76,11 +98,10 @@ type UsageTerm =
76
98
  */
77
99
  readonly name: string;
78
100
  /**
79
- * When `true`, hides the command from help text, shell completion
80
- * suggestions, and "Did you mean?" error suggestions.
101
+ * Visibility controls for this term.
81
102
  * @since 0.9.0
82
103
  */
83
- readonly hidden?: boolean;
104
+ readonly hidden?: HiddenVisibility;
84
105
  }
85
106
  /**
86
107
  * An optional term, which represents an optional component
@@ -155,11 +176,10 @@ type UsageTerm =
155
176
  */
156
177
  readonly type: "passthrough";
157
178
  /**
158
- * When `true`, hides the pass-through from help text and shell
159
- * completion suggestions.
179
+ * Visibility controls for this term.
160
180
  * @since 0.9.0
161
181
  */
162
- readonly hidden?: boolean;
182
+ readonly hidden?: HiddenVisibility;
163
183
  };
164
184
  /**
165
185
  * Represents a command-line usage description, which is a sequence of
@@ -330,4 +350,4 @@ interface UsageTermFormatOptions extends UsageFormatOptions {
330
350
  */
331
351
  declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
332
352
  //#endregion
333
- export { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, normalizeUsage };
353
+ export { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage };
package/dist/usage.js CHANGED
@@ -1,5 +1,33 @@
1
1
  //#region src/usage.ts
2
2
  /**
3
+ * Returns whether the term should be hidden from usage output.
4
+ */
5
+ function isUsageHidden(hidden) {
6
+ return hidden === true || hidden === "usage";
7
+ }
8
+ /**
9
+ * Returns whether the term should be hidden from documentation output.
10
+ */
11
+ function isDocHidden(hidden) {
12
+ return hidden === true || hidden === "doc";
13
+ }
14
+ /**
15
+ * Returns whether the term should be hidden from suggestion/error candidates.
16
+ */
17
+ function isSuggestionHidden(hidden) {
18
+ return hidden === true;
19
+ }
20
+ /**
21
+ * Merges two hidden visibility settings by taking the union of restrictions.
22
+ */
23
+ function mergeHidden(a, b) {
24
+ if (a == null) return b;
25
+ if (b == null) return a;
26
+ if (a === true || b === true) return true;
27
+ if (a !== b) return true;
28
+ return a;
29
+ }
30
+ /**
3
31
  * Extracts all option names from a usage description.
4
32
  *
5
33
  * This function recursively traverses a {@link Usage} tree and collects all
@@ -24,7 +52,7 @@ function extractOptionNames(usage) {
24
52
  function traverseUsage(terms) {
25
53
  if (!terms || !Array.isArray(terms)) return;
26
54
  for (const term of terms) if (term.type === "option") {
27
- if (term.hidden) continue;
55
+ if (isSuggestionHidden(term.hidden)) continue;
28
56
  for (const name of term.names) names.add(name);
29
57
  } else if (term.type === "optional" || term.type === "multiple") traverseUsage(term.terms);
30
58
  else if (term.type === "exclusive") for (const exclusiveUsage of term.terms) traverseUsage(exclusiveUsage);
@@ -57,7 +85,7 @@ function extractCommandNames(usage) {
57
85
  function traverseUsage(terms) {
58
86
  if (!terms || !Array.isArray(terms)) return;
59
87
  for (const term of terms) if (term.type === "command") {
60
- if (term.hidden) continue;
88
+ if (isSuggestionHidden(term.hidden)) continue;
61
89
  names.add(term.name);
62
90
  } else if (term.type === "optional" || term.type === "multiple") traverseUsage(term.terms);
63
91
  else if (term.type === "exclusive") for (const exclusiveUsage of term.terms) traverseUsage(exclusiveUsage);
@@ -91,7 +119,7 @@ function extractArgumentMetavars(usage) {
91
119
  function traverseUsage(terms) {
92
120
  if (!terms || !Array.isArray(terms)) return;
93
121
  for (const term of terms) if (term.type === "argument") {
94
- if (term.hidden) continue;
122
+ if (isSuggestionHidden(term.hidden)) continue;
95
123
  metavars.add(term.metavar);
96
124
  } else if (term.type === "optional" || term.type === "multiple") traverseUsage(term.terms);
97
125
  else if (term.type === "exclusive") for (const exclusiveUsage of term.terms) traverseUsage(exclusiveUsage);
@@ -116,14 +144,14 @@ function extractArgumentMetavars(usage) {
116
144
  * @returns A formatted string representation of the usage description.
117
145
  */
118
146
  function formatUsage(programName, usage, options = {}) {
119
- usage = normalizeUsage(usage);
147
+ usage = normalizeUsage(filterUsageForDisplay(usage));
120
148
  if (options.expandCommands) {
121
149
  const lastTerm = usage.at(-1);
122
150
  if (usage.length > 0 && usage.slice(0, -1).every((t) => t.type === "command") && lastTerm.type === "exclusive" && lastTerm.terms.every((t) => t.length > 0 && (t[0].type === "command" || t[0].type === "option" || t[0].type === "argument" || t[0].type === "optional" && t[0].terms.length === 1 && (t[0].terms[0].type === "command" || t[0].terms[0].type === "option" || t[0].terms[0].type === "argument")))) {
123
151
  const lines = [];
124
152
  for (let command of lastTerm.terms) {
125
153
  const firstTerm = command[0];
126
- if (firstTerm?.type === "command" && firstTerm.hidden) continue;
154
+ if (firstTerm?.type === "command" && isUsageHidden(firstTerm.hidden)) continue;
127
155
  if (usage.length > 1) command = [...usage.slice(0, -1), ...command];
128
156
  lines.push(formatUsage(programName, command, options));
129
157
  }
@@ -204,9 +232,47 @@ function normalizeUsageTerm(term) {
204
232
  };
205
233
  } else return term;
206
234
  }
235
+ function filterUsageForDisplay(usage) {
236
+ const terms = [];
237
+ for (const term of usage) {
238
+ if ((term.type === "argument" || term.type === "option" || term.type === "command" || term.type === "passthrough") && isUsageHidden(term.hidden)) continue;
239
+ if (term.type === "optional") {
240
+ const filtered = filterUsageForDisplay(term.terms);
241
+ if (filtered.length > 0) terms.push({
242
+ type: "optional",
243
+ terms: filtered
244
+ });
245
+ continue;
246
+ }
247
+ if (term.type === "multiple") {
248
+ const filtered = filterUsageForDisplay(term.terms);
249
+ if (filtered.length > 0) terms.push({
250
+ type: "multiple",
251
+ terms: filtered,
252
+ min: term.min
253
+ });
254
+ continue;
255
+ }
256
+ if (term.type === "exclusive") {
257
+ const filteredBranches = term.terms.map((branch) => {
258
+ const first = branch[0];
259
+ if (first?.type === "command" && isUsageHidden(first.hidden)) return [];
260
+ return filterUsageForDisplay(branch);
261
+ }).filter((branch) => branch.length > 0);
262
+ if (filteredBranches.length > 0) terms.push({
263
+ type: "exclusive",
264
+ terms: filteredBranches
265
+ });
266
+ continue;
267
+ }
268
+ terms.push(term);
269
+ }
270
+ return terms;
271
+ }
207
272
  function* formatUsageTerms(terms, options) {
208
273
  let i = 0;
209
274
  for (const t of terms) {
275
+ if ("hidden" in t && (t.type === "argument" || t.type === "option" || t.type === "command" || t.type === "passthrough") && isUsageHidden(t.hidden)) continue;
210
276
  if (i > 0) yield {
211
277
  text: " ",
212
278
  width: 1
@@ -225,9 +291,11 @@ function* formatUsageTerms(terms, options) {
225
291
  * @returns A formatted string representation of the usage term.
226
292
  */
227
293
  function formatUsageTerm(term, options = {}) {
294
+ const visibleTerms = filterUsageForDisplay([term]);
295
+ if (visibleTerms.length < 1) return "";
228
296
  let lineWidth = 0;
229
297
  let output = "";
230
- for (const { text, width } of formatUsageTermInternal(term, options)) {
298
+ for (const { text, width } of formatUsageTermInternal(visibleTerms[0], options)) {
231
299
  if (options.maxWidth != null && lineWidth + width > options.maxWidth) {
232
300
  output += "\n";
233
301
  lineWidth = 0;
@@ -350,4 +418,4 @@ function* formatUsageTermInternal(term, options) {
350
418
  }
351
419
 
352
420
  //#endregion
353
- export { extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, normalizeUsage };
421
+ export { extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.427+497e26fe",
3
+ "version": "1.0.0-dev.429+66edc8ed",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",