@optique/core 1.0.0-dev.488 → 1.0.0-dev.490

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/facade.d.cts CHANGED
@@ -32,6 +32,7 @@ interface CommandSubConfig {
32
32
  * - `true`: Hidden from usage, documentation, and suggestions.
33
33
  * - `"usage"`: Hidden from usage lines only.
34
34
  * - `"doc"`: Hidden from documentation only.
35
+ * - `"help"`: Hidden from usage and documentation only.
35
36
  */
36
37
  readonly hidden?: HiddenVisibility;
37
38
  }
@@ -55,6 +56,7 @@ interface OptionSubConfig {
55
56
  * - `true`: Hidden from usage, documentation, and suggestions.
56
57
  * - `"usage"`: Hidden from usage lines only.
57
58
  * - `"doc"`: Hidden from documentation only.
59
+ * - `"help"`: Hidden from usage and documentation only.
58
60
  */
59
61
  readonly hidden?: HiddenVisibility;
60
62
  }
package/dist/facade.d.ts CHANGED
@@ -32,6 +32,7 @@ interface CommandSubConfig {
32
32
  * - `true`: Hidden from usage, documentation, and suggestions.
33
33
  * - `"usage"`: Hidden from usage lines only.
34
34
  * - `"doc"`: Hidden from documentation only.
35
+ * - `"help"`: Hidden from usage and documentation only.
35
36
  */
36
37
  readonly hidden?: HiddenVisibility;
37
38
  }
@@ -55,6 +56,7 @@ interface OptionSubConfig {
55
56
  * - `true`: Hidden from usage, documentation, and suggestions.
56
57
  * - `"usage"`: Hidden from usage lines only.
57
58
  * - `"doc"`: Hidden from documentation only.
59
+ * - `"help"`: Hidden from usage and documentation only.
58
60
  */
59
61
  readonly hidden?: HiddenVisibility;
60
62
  }
package/dist/parser.cjs CHANGED
@@ -416,14 +416,26 @@ function buildDocPage(parser, context, args) {
416
416
  }
417
417
  const sections = buildingSections;
418
418
  const usage = [...require_usage.normalizeUsage(parser.usage)];
419
+ const maybeApplyCommandUsageLine = (term, arg, isLastArg, usageIndex) => {
420
+ if (term?.type !== "command" || term.name !== arg || !isLastArg || term.usageLine == null) return;
421
+ const defaultUsageLine = usage.slice(usageIndex + 1);
422
+ const customUsageLine = typeof term.usageLine === "function" ? term.usageLine(defaultUsageLine) : term.usageLine;
423
+ const normalizedCustomUsageLine = require_usage.normalizeUsage(customUsageLine);
424
+ usage.splice(usageIndex + 1, usage.length - (usageIndex + 1), ...normalizedCustomUsageLine);
425
+ };
419
426
  let i = 0;
420
- for (const arg of args) {
427
+ for (let argIndex = 0; argIndex < args.length; argIndex++) {
428
+ const arg = args[argIndex];
421
429
  if (i >= usage.length) break;
422
- const term = usage[i];
430
+ let term = usage[i];
423
431
  if (term.type === "exclusive") {
424
432
  const found = findCommandInExclusive(term, arg);
425
- if (found) usage.splice(i, 1, ...found);
433
+ if (found) {
434
+ usage.splice(i, 1, ...found);
435
+ term = usage[i];
436
+ }
426
437
  }
438
+ maybeApplyCommandUsageLine(term, arg, argIndex === args.length - 1, i);
427
439
  i++;
428
440
  }
429
441
  return {
package/dist/parser.js CHANGED
@@ -416,14 +416,26 @@ function buildDocPage(parser, context, args) {
416
416
  }
417
417
  const sections = buildingSections;
418
418
  const usage = [...normalizeUsage(parser.usage)];
419
+ const maybeApplyCommandUsageLine = (term, arg, isLastArg, usageIndex) => {
420
+ if (term?.type !== "command" || term.name !== arg || !isLastArg || term.usageLine == null) return;
421
+ const defaultUsageLine = usage.slice(usageIndex + 1);
422
+ const customUsageLine = typeof term.usageLine === "function" ? term.usageLine(defaultUsageLine) : term.usageLine;
423
+ const normalizedCustomUsageLine = normalizeUsage(customUsageLine);
424
+ usage.splice(usageIndex + 1, usage.length - (usageIndex + 1), ...normalizedCustomUsageLine);
425
+ };
419
426
  let i = 0;
420
- for (const arg of args) {
427
+ for (let argIndex = 0; argIndex < args.length; argIndex++) {
428
+ const arg = args[argIndex];
421
429
  if (i >= usage.length) break;
422
- const term = usage[i];
430
+ let term = usage[i];
423
431
  if (term.type === "exclusive") {
424
432
  const found = findCommandInExclusive(term, arg);
425
- if (found) usage.splice(i, 1, ...found);
433
+ if (found) {
434
+ usage.splice(i, 1, ...found);
435
+ term = usage[i];
436
+ }
426
437
  }
438
+ maybeApplyCommandUsageLine(term, arg, argIndex === args.length - 1, i);
427
439
  i++;
428
440
  }
429
441
  return {
@@ -927,6 +927,7 @@ function command(name, parser, options = {}) {
927
927
  usage: [{
928
928
  type: "command",
929
929
  name,
930
+ ...options.usageLine != null && { usageLine: options.usageLine },
930
931
  ...options.hidden != null && { hidden: options.hidden }
931
932
  }, ...parser.usage],
932
933
  initialState: void 0,
@@ -1,5 +1,5 @@
1
1
  import { Message } from "./message.cjs";
2
- import { HiddenVisibility, OptionName } from "./usage.cjs";
2
+ import { HiddenVisibility, OptionName, Usage } from "./usage.cjs";
3
3
  import { ValueParser, ValueParserResult } from "./valueparser.cjs";
4
4
  import { DeferredParseState, PendingDependencySourceState } from "./dependency.cjs";
5
5
  import { Mode, Parser } from "./parser.cjs";
@@ -52,6 +52,7 @@ interface OptionOptions {
52
52
  * - `true`: hide from usage, docs, and suggestions
53
53
  * - `"usage"`: hide from usage only
54
54
  * - `"doc"`: hide from docs only
55
+ * - `"help"`: hide from usage and docs, keep suggestions
55
56
  *
56
57
  * @since 0.9.0
57
58
  */
@@ -166,6 +167,7 @@ interface FlagOptions {
166
167
  * - `true`: hide from usage, docs, and suggestions
167
168
  * - `"usage"`: hide from usage only
168
169
  * - `"doc"`: hide from docs only
170
+ * - `"help"`: hide from usage and docs, keep suggestions
169
171
  *
170
172
  * @since 0.9.0
171
173
  */
@@ -255,6 +257,7 @@ interface ArgumentOptions {
255
257
  * - `true`: hide from usage, docs, and suggestions
256
258
  * - `"usage"`: hide from usage only
257
259
  * - `"doc"`: hide from docs only
260
+ * - `"help"`: hide from usage and docs, keep suggestions
258
261
  *
259
262
  * @since 0.9.0
260
263
  */
@@ -323,12 +326,26 @@ interface CommandOptions {
323
326
  * @since 0.6.0
324
327
  */
325
328
  readonly footer?: Message;
329
+ /**
330
+ * Usage line override for this command's own help page.
331
+ *
332
+ * This option customizes the usage tail shown when rendering help for this
333
+ * command itself (e.g., `myapp config --help`). It does not change parsing
334
+ * behavior or shell completion.
335
+ *
336
+ * - `Usage`: Replaces the default usage tail.
337
+ * - `(defaultUsageLine) => Usage`: Computes the usage tail from the default.
338
+ *
339
+ * @since 1.0.0
340
+ */
341
+ readonly usageLine?: Usage | ((defaultUsageLine: Usage) => Usage);
326
342
  /**
327
343
  * Controls command visibility:
328
344
  *
329
345
  * - `true`: hide from usage, docs, and suggestions
330
346
  * - `"usage"`: hide from usage only
331
347
  * - `"doc"`: hide from docs only
348
+ * - `"help"`: hide from usage and docs, keep suggestions
332
349
  *
333
350
  * @since 0.9.0
334
351
  */
@@ -416,6 +433,7 @@ interface PassThroughOptions {
416
433
  * - `true`: hide from usage, docs, and suggestions
417
434
  * - `"usage"`: hide from usage only
418
435
  * - `"doc"`: hide from docs only
436
+ * - `"help"`: hide from usage and docs, keep suggestions
419
437
  *
420
438
  * @since 0.9.0
421
439
  */
@@ -1,5 +1,5 @@
1
1
  import { Message } from "./message.js";
2
- import { HiddenVisibility, OptionName } from "./usage.js";
2
+ import { HiddenVisibility, OptionName, Usage } from "./usage.js";
3
3
  import { ValueParser, ValueParserResult } from "./valueparser.js";
4
4
  import { DeferredParseState, PendingDependencySourceState } from "./dependency.js";
5
5
  import { Mode, Parser } from "./parser.js";
@@ -52,6 +52,7 @@ interface OptionOptions {
52
52
  * - `true`: hide from usage, docs, and suggestions
53
53
  * - `"usage"`: hide from usage only
54
54
  * - `"doc"`: hide from docs only
55
+ * - `"help"`: hide from usage and docs, keep suggestions
55
56
  *
56
57
  * @since 0.9.0
57
58
  */
@@ -166,6 +167,7 @@ interface FlagOptions {
166
167
  * - `true`: hide from usage, docs, and suggestions
167
168
  * - `"usage"`: hide from usage only
168
169
  * - `"doc"`: hide from docs only
170
+ * - `"help"`: hide from usage and docs, keep suggestions
169
171
  *
170
172
  * @since 0.9.0
171
173
  */
@@ -255,6 +257,7 @@ interface ArgumentOptions {
255
257
  * - `true`: hide from usage, docs, and suggestions
256
258
  * - `"usage"`: hide from usage only
257
259
  * - `"doc"`: hide from docs only
260
+ * - `"help"`: hide from usage and docs, keep suggestions
258
261
  *
259
262
  * @since 0.9.0
260
263
  */
@@ -323,12 +326,26 @@ interface CommandOptions {
323
326
  * @since 0.6.0
324
327
  */
325
328
  readonly footer?: Message;
329
+ /**
330
+ * Usage line override for this command's own help page.
331
+ *
332
+ * This option customizes the usage tail shown when rendering help for this
333
+ * command itself (e.g., `myapp config --help`). It does not change parsing
334
+ * behavior or shell completion.
335
+ *
336
+ * - `Usage`: Replaces the default usage tail.
337
+ * - `(defaultUsageLine) => Usage`: Computes the usage tail from the default.
338
+ *
339
+ * @since 1.0.0
340
+ */
341
+ readonly usageLine?: Usage | ((defaultUsageLine: Usage) => Usage);
326
342
  /**
327
343
  * Controls command visibility:
328
344
  *
329
345
  * - `true`: hide from usage, docs, and suggestions
330
346
  * - `"usage"`: hide from usage only
331
347
  * - `"doc"`: hide from docs only
348
+ * - `"help"`: hide from usage and docs, keep suggestions
332
349
  *
333
350
  * @since 0.9.0
334
351
  */
@@ -416,6 +433,7 @@ interface PassThroughOptions {
416
433
  * - `true`: hide from usage, docs, and suggestions
417
434
  * - `"usage"`: hide from usage only
418
435
  * - `"doc"`: hide from docs only
436
+ * - `"help"`: hide from usage and docs, keep suggestions
419
437
  *
420
438
  * @since 0.9.0
421
439
  */
@@ -927,6 +927,7 @@ function command(name, parser, options = {}) {
927
927
  usage: [{
928
928
  type: "command",
929
929
  name,
930
+ ...options.usageLine != null && { usageLine: options.usageLine },
930
931
  ...options.hidden != null && { hidden: options.hidden }
931
932
  }, ...parser.usage],
932
933
  initialState: void 0,
package/dist/usage.cjs CHANGED
@@ -4,13 +4,13 @@
4
4
  * Returns whether the term should be hidden from usage output.
5
5
  */
6
6
  function isUsageHidden(hidden) {
7
- return hidden === true || hidden === "usage";
7
+ return hidden === true || hidden === "usage" || hidden === "help";
8
8
  }
9
9
  /**
10
10
  * Returns whether the term should be hidden from documentation output.
11
11
  */
12
12
  function isDocHidden(hidden) {
13
- return hidden === true || hidden === "doc";
13
+ return hidden === true || hidden === "doc" || hidden === "help";
14
14
  }
15
15
  /**
16
16
  * Returns whether the term should be hidden from suggestion/error candidates.
@@ -25,7 +25,11 @@ function mergeHidden(a, b) {
25
25
  if (a == null) return b;
26
26
  if (b == null) return a;
27
27
  if (a === true || b === true) return true;
28
- if (a !== b) return true;
28
+ if (a === false) return b;
29
+ if (b === false) return a;
30
+ if (a === b) return a;
31
+ if (a === "help" || b === "help") return "help";
32
+ if ((a === "usage" || a === "doc") && (b === "usage" || b === "doc")) return "help";
29
33
  return a;
30
34
  }
31
35
  /**
@@ -415,6 +419,12 @@ function* formatUsageTermInternal(term, options) {
415
419
  text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
416
420
  width: 5
417
421
  };
422
+ } else if (term.type === "ellipsis") {
423
+ const text = "...";
424
+ yield {
425
+ text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
426
+ width: 3
427
+ };
418
428
  } else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
419
429
  }
420
430
 
package/dist/usage.d.cts CHANGED
@@ -18,8 +18,9 @@ type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
18
18
  * - `true`: hidden from usage, documentation, and suggestions
19
19
  * - `"usage"`: hidden from usage only
20
20
  * - `"doc"`: hidden from documentation only
21
+ * - `"help"`: hidden from usage and documentation, but shown in suggestions
21
22
  */
22
- type HiddenVisibility = boolean | "usage" | "doc";
23
+ type HiddenVisibility = boolean | "usage" | "doc" | "help";
23
24
  /**
24
25
  * Returns whether the term should be hidden from usage output.
25
26
  */
@@ -97,6 +98,12 @@ type UsageTerm =
97
98
  * in the command-line usage.
98
99
  */
99
100
  readonly name: string;
101
+ /**
102
+ * Optional usage line override for this command's own help page.
103
+ * This affects help/documentation rendering only.
104
+ * @since 1.0.0
105
+ */
106
+ readonly usageLine?: Usage | ((defaultUsageLine: Usage) => Usage);
100
107
  /**
101
108
  * Visibility controls for this term.
102
109
  * @since 0.9.0
@@ -180,6 +187,17 @@ type UsageTerm =
180
187
  * @since 0.9.0
181
188
  */
182
189
  readonly hidden?: HiddenVisibility;
190
+ }
191
+ /**
192
+ * An ellipsis term, which represents a summary placeholder in usage output.
193
+ * Unlike {@link passthrough}, this term has no parsing semantics and is used
194
+ * only for display.
195
+ * @since 1.0.0
196
+ */ | {
197
+ /**
198
+ * The type of the term, which is always `"ellipsis"` for this term.
199
+ */
200
+ readonly type: "ellipsis";
183
201
  };
184
202
  /**
185
203
  * Represents a command-line usage description, which is a sequence of
package/dist/usage.d.ts CHANGED
@@ -18,8 +18,9 @@ type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
18
18
  * - `true`: hidden from usage, documentation, and suggestions
19
19
  * - `"usage"`: hidden from usage only
20
20
  * - `"doc"`: hidden from documentation only
21
+ * - `"help"`: hidden from usage and documentation, but shown in suggestions
21
22
  */
22
- type HiddenVisibility = boolean | "usage" | "doc";
23
+ type HiddenVisibility = boolean | "usage" | "doc" | "help";
23
24
  /**
24
25
  * Returns whether the term should be hidden from usage output.
25
26
  */
@@ -97,6 +98,12 @@ type UsageTerm =
97
98
  * in the command-line usage.
98
99
  */
99
100
  readonly name: string;
101
+ /**
102
+ * Optional usage line override for this command's own help page.
103
+ * This affects help/documentation rendering only.
104
+ * @since 1.0.0
105
+ */
106
+ readonly usageLine?: Usage | ((defaultUsageLine: Usage) => Usage);
100
107
  /**
101
108
  * Visibility controls for this term.
102
109
  * @since 0.9.0
@@ -180,6 +187,17 @@ type UsageTerm =
180
187
  * @since 0.9.0
181
188
  */
182
189
  readonly hidden?: HiddenVisibility;
190
+ }
191
+ /**
192
+ * An ellipsis term, which represents a summary placeholder in usage output.
193
+ * Unlike {@link passthrough}, this term has no parsing semantics and is used
194
+ * only for display.
195
+ * @since 1.0.0
196
+ */ | {
197
+ /**
198
+ * The type of the term, which is always `"ellipsis"` for this term.
199
+ */
200
+ readonly type: "ellipsis";
183
201
  };
184
202
  /**
185
203
  * Represents a command-line usage description, which is a sequence of
package/dist/usage.js CHANGED
@@ -3,13 +3,13 @@
3
3
  * Returns whether the term should be hidden from usage output.
4
4
  */
5
5
  function isUsageHidden(hidden) {
6
- return hidden === true || hidden === "usage";
6
+ return hidden === true || hidden === "usage" || hidden === "help";
7
7
  }
8
8
  /**
9
9
  * Returns whether the term should be hidden from documentation output.
10
10
  */
11
11
  function isDocHidden(hidden) {
12
- return hidden === true || hidden === "doc";
12
+ return hidden === true || hidden === "doc" || hidden === "help";
13
13
  }
14
14
  /**
15
15
  * Returns whether the term should be hidden from suggestion/error candidates.
@@ -24,7 +24,11 @@ function mergeHidden(a, b) {
24
24
  if (a == null) return b;
25
25
  if (b == null) return a;
26
26
  if (a === true || b === true) return true;
27
- if (a !== b) return true;
27
+ if (a === false) return b;
28
+ if (b === false) return a;
29
+ if (a === b) return a;
30
+ if (a === "help" || b === "help") return "help";
31
+ if ((a === "usage" || a === "doc") && (b === "usage" || b === "doc")) return "help";
28
32
  return a;
29
33
  }
30
34
  /**
@@ -414,6 +418,12 @@ function* formatUsageTermInternal(term, options) {
414
418
  text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
415
419
  width: 5
416
420
  };
421
+ } else if (term.type === "ellipsis") {
422
+ const text = "...";
423
+ yield {
424
+ text: options?.colors ? `\x1b[2m${text}\x1b[0m` : text,
425
+ width: 3
426
+ };
417
427
  } else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
418
428
  }
419
429
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.488+690cf201",
3
+ "version": "1.0.0-dev.490+fe0b9010",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",