@optique/core 0.8.9 → 0.8.11

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.
@@ -4,6 +4,57 @@ const require_suggestion = require('./suggestion.cjs');
4
4
 
5
5
  //#region src/constructs.ts
6
6
  /**
7
+ * Collects option names and command names that are valid at the current
8
+ * parse position by walking the usage tree. Only "leading" candidates
9
+ * (those reachable before a required positional argument) are collected.
10
+ */
11
+ function collectLeadingCandidates(terms, optionNames, commandNames) {
12
+ if (!terms || !Array.isArray(terms)) return true;
13
+ for (const term of terms) {
14
+ if (term.type === "option") {
15
+ for (const name of term.names) optionNames.add(name);
16
+ return false;
17
+ }
18
+ if (term.type === "command") {
19
+ commandNames.add(term.name);
20
+ return false;
21
+ }
22
+ if (term.type === "argument") return false;
23
+ if (term.type === "optional") {
24
+ collectLeadingCandidates(term.terms, optionNames, commandNames);
25
+ continue;
26
+ }
27
+ if (term.type === "multiple") {
28
+ collectLeadingCandidates(term.terms, optionNames, commandNames);
29
+ if (term.min === 0) continue;
30
+ return false;
31
+ }
32
+ if (term.type === "exclusive") {
33
+ let allAlternativesSkippable = true;
34
+ for (const exclusiveUsage of term.terms) {
35
+ const alternativeSkippable = collectLeadingCandidates(exclusiveUsage, optionNames, commandNames);
36
+ allAlternativesSkippable = allAlternativesSkippable && alternativeSkippable;
37
+ }
38
+ if (allAlternativesSkippable) continue;
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ }
44
+ function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput, parsers, customFormatter) {
45
+ const options = /* @__PURE__ */ new Set();
46
+ const commands = /* @__PURE__ */ new Set();
47
+ for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
48
+ const candidates = new Set([...options, ...commands]);
49
+ const suggestions = require_suggestion.findSimilar(invalidInput, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
50
+ const suggestionMsg = customFormatter ? customFormatter(suggestions) : require_suggestion.createSuggestionMessage(suggestions);
51
+ return suggestionMsg.length > 0 ? [
52
+ ...baseError,
53
+ require_message.text("\n\n"),
54
+ ...suggestionMsg
55
+ ] : baseError;
56
+ }
57
+ /**
7
58
  * Checks if the given token is an option name that requires a value
8
59
  * (i.e., has a metavar) within the given usage terms.
9
60
  * @param usage The usage terms to search through.
@@ -168,16 +219,6 @@ function getNoMatchError(options, noMatchContext) {
168
219
  return customNoMatch ? typeof customNoMatch === "function" ? customNoMatch(noMatchContext) : customNoMatch : generateNoMatchError(noMatchContext);
169
220
  }
170
221
  /**
171
- * Creates default error for parse() method when buffer is not empty.
172
- * Shared by or() and longestMatch().
173
- * @internal
174
- */
175
- function createUnexpectedInputError(token, usage, options) {
176
- const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
177
- if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
178
- return require_suggestion.createErrorWithSuggestions(defaultMsg, token, usage, "both", options?.errors?.suggestions);
179
- }
180
- /**
181
222
  * @since 0.5.0
182
223
  */
183
224
  function or(...args) {
@@ -204,7 +245,12 @@ function or(...args) {
204
245
  parse(context) {
205
246
  let error = {
206
247
  consumed: 0,
207
- error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : createUnexpectedInputError(context.buffer[0], context.usage, options)
248
+ error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
249
+ const token = context.buffer[0];
250
+ const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
251
+ if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
252
+ return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
253
+ })()
208
254
  };
209
255
  const orderedParsers = parsers.map((p, i) => [p, i]);
210
256
  orderedParsers.sort(([_, a], [__, b]) => context.state?.[0] === a ? -1 : context.state?.[0] === b ? 1 : a - b);
@@ -238,7 +284,9 @@ function or(...args) {
238
284
  },
239
285
  suggest: createExclusiveSuggest(parsers),
240
286
  getDocFragments(state, _defaultValue) {
287
+ let brief;
241
288
  let description;
289
+ let footer;
242
290
  let fragments;
243
291
  if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }, void 0).fragments);
244
292
  else {
@@ -248,7 +296,9 @@ function or(...args) {
248
296
  state: parserResult.next.state
249
297
  } : { kind: "unavailable" };
250
298
  const docFragments = parsers[index].getDocFragments(innerState, void 0);
299
+ brief = docFragments.brief;
251
300
  description = docFragments.description;
301
+ footer = docFragments.footer;
252
302
  fragments = docFragments.fragments;
253
303
  }
254
304
  const entries = fragments.filter((f) => f.type === "entry");
@@ -259,7 +309,9 @@ function or(...args) {
259
309
  else sections.push(fragment);
260
310
  }
261
311
  return {
312
+ brief,
262
313
  description,
314
+ footer,
263
315
  fragments: [...sections.map((s) => ({
264
316
  ...s,
265
317
  type: "section"
@@ -299,7 +351,12 @@ function longestMatch(...args) {
299
351
  let bestMatch = null;
300
352
  let error = {
301
353
  consumed: 0,
302
- error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : createUnexpectedInputError(context.buffer[0], context.usage, options)
354
+ error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
355
+ const token = context.buffer[0];
356
+ const defaultMsg = require_message.message`Unexpected option or subcommand: ${require_message.optionName(token)}.`;
357
+ if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
358
+ return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
359
+ })()
303
360
  };
304
361
  for (let i = 0; i < parsers.length; i++) {
305
362
  const parser = parsers[i];
@@ -333,6 +390,7 @@ function longestMatch(...args) {
333
390
  },
334
391
  suggest: createExclusiveSuggest(parsers),
335
392
  getDocFragments(state, _defaultValue) {
393
+ let brief;
336
394
  let description;
337
395
  let footer;
338
396
  let fragments;
@@ -344,12 +402,14 @@ function longestMatch(...args) {
344
402
  kind: "available",
345
403
  state: result.next.state
346
404
  });
405
+ brief = docResult.brief;
347
406
  description = docResult.description;
348
407
  footer = docResult.footer;
349
408
  fragments = docResult.fragments;
350
409
  } else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
351
410
  }
352
411
  return {
412
+ brief,
353
413
  description,
354
414
  fragments,
355
415
  footer
@@ -1,9 +1,60 @@
1
- import { message, optionName, values } from "./message.js";
1
+ import { message, optionName, text, values } from "./message.js";
2
2
  import { extractArgumentMetavars, extractCommandNames, extractOptionNames } from "./usage.js";
3
- import { createErrorWithSuggestions, deduplicateSuggestions } from "./suggestion.js";
3
+ import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar } from "./suggestion.js";
4
4
 
5
5
  //#region src/constructs.ts
6
6
  /**
7
+ * Collects option names and command names that are valid at the current
8
+ * parse position by walking the usage tree. Only "leading" candidates
9
+ * (those reachable before a required positional argument) are collected.
10
+ */
11
+ function collectLeadingCandidates(terms, optionNames, commandNames) {
12
+ if (!terms || !Array.isArray(terms)) return true;
13
+ for (const term of terms) {
14
+ if (term.type === "option") {
15
+ for (const name of term.names) optionNames.add(name);
16
+ return false;
17
+ }
18
+ if (term.type === "command") {
19
+ commandNames.add(term.name);
20
+ return false;
21
+ }
22
+ if (term.type === "argument") return false;
23
+ if (term.type === "optional") {
24
+ collectLeadingCandidates(term.terms, optionNames, commandNames);
25
+ continue;
26
+ }
27
+ if (term.type === "multiple") {
28
+ collectLeadingCandidates(term.terms, optionNames, commandNames);
29
+ if (term.min === 0) continue;
30
+ return false;
31
+ }
32
+ if (term.type === "exclusive") {
33
+ let allAlternativesSkippable = true;
34
+ for (const exclusiveUsage of term.terms) {
35
+ const alternativeSkippable = collectLeadingCandidates(exclusiveUsage, optionNames, commandNames);
36
+ allAlternativesSkippable = allAlternativesSkippable && alternativeSkippable;
37
+ }
38
+ if (allAlternativesSkippable) continue;
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ }
44
+ function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput, parsers, customFormatter) {
45
+ const options = /* @__PURE__ */ new Set();
46
+ const commands = /* @__PURE__ */ new Set();
47
+ for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
48
+ const candidates = new Set([...options, ...commands]);
49
+ const suggestions = findSimilar(invalidInput, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
50
+ const suggestionMsg = customFormatter ? customFormatter(suggestions) : createSuggestionMessage(suggestions);
51
+ return suggestionMsg.length > 0 ? [
52
+ ...baseError,
53
+ text("\n\n"),
54
+ ...suggestionMsg
55
+ ] : baseError;
56
+ }
57
+ /**
7
58
  * Checks if the given token is an option name that requires a value
8
59
  * (i.e., has a metavar) within the given usage terms.
9
60
  * @param usage The usage terms to search through.
@@ -168,16 +219,6 @@ function getNoMatchError(options, noMatchContext) {
168
219
  return customNoMatch ? typeof customNoMatch === "function" ? customNoMatch(noMatchContext) : customNoMatch : generateNoMatchError(noMatchContext);
169
220
  }
170
221
  /**
171
- * Creates default error for parse() method when buffer is not empty.
172
- * Shared by or() and longestMatch().
173
- * @internal
174
- */
175
- function createUnexpectedInputError(token, usage, options) {
176
- const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
177
- if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
178
- return createErrorWithSuggestions(defaultMsg, token, usage, "both", options?.errors?.suggestions);
179
- }
180
- /**
181
222
  * @since 0.5.0
182
223
  */
183
224
  function or(...args) {
@@ -204,7 +245,12 @@ function or(...args) {
204
245
  parse(context) {
205
246
  let error = {
206
247
  consumed: 0,
207
- error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : createUnexpectedInputError(context.buffer[0], context.usage, options)
248
+ error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
249
+ const token = context.buffer[0];
250
+ const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
251
+ if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
252
+ return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
253
+ })()
208
254
  };
209
255
  const orderedParsers = parsers.map((p, i) => [p, i]);
210
256
  orderedParsers.sort(([_, a], [__, b]) => context.state?.[0] === a ? -1 : context.state?.[0] === b ? 1 : a - b);
@@ -238,7 +284,9 @@ function or(...args) {
238
284
  },
239
285
  suggest: createExclusiveSuggest(parsers),
240
286
  getDocFragments(state, _defaultValue) {
287
+ let brief;
241
288
  let description;
289
+ let footer;
242
290
  let fragments;
243
291
  if (state.kind === "unavailable" || state.state == null) fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }, void 0).fragments);
244
292
  else {
@@ -248,7 +296,9 @@ function or(...args) {
248
296
  state: parserResult.next.state
249
297
  } : { kind: "unavailable" };
250
298
  const docFragments = parsers[index].getDocFragments(innerState, void 0);
299
+ brief = docFragments.brief;
251
300
  description = docFragments.description;
301
+ footer = docFragments.footer;
252
302
  fragments = docFragments.fragments;
253
303
  }
254
304
  const entries = fragments.filter((f) => f.type === "entry");
@@ -259,7 +309,9 @@ function or(...args) {
259
309
  else sections.push(fragment);
260
310
  }
261
311
  return {
312
+ brief,
262
313
  description,
314
+ footer,
263
315
  fragments: [...sections.map((s) => ({
264
316
  ...s,
265
317
  type: "section"
@@ -299,7 +351,12 @@ function longestMatch(...args) {
299
351
  let bestMatch = null;
300
352
  let error = {
301
353
  consumed: 0,
302
- error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : createUnexpectedInputError(context.buffer[0], context.usage, options)
354
+ error: context.buffer.length < 1 ? getNoMatchError(options, noMatchContext) : (() => {
355
+ const token = context.buffer[0];
356
+ const defaultMsg = message`Unexpected option or subcommand: ${optionName(token)}.`;
357
+ if (options?.errors?.unexpectedInput != null) return typeof options.errors.unexpectedInput === "function" ? options.errors.unexpectedInput(token) : options.errors.unexpectedInput;
358
+ return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
359
+ })()
303
360
  };
304
361
  for (let i = 0; i < parsers.length; i++) {
305
362
  const parser = parsers[i];
@@ -333,6 +390,7 @@ function longestMatch(...args) {
333
390
  },
334
391
  suggest: createExclusiveSuggest(parsers),
335
392
  getDocFragments(state, _defaultValue) {
393
+ let brief;
336
394
  let description;
337
395
  let footer;
338
396
  let fragments;
@@ -344,12 +402,14 @@ function longestMatch(...args) {
344
402
  kind: "available",
345
403
  state: result.next.state
346
404
  });
405
+ brief = docResult.brief;
347
406
  description = docResult.description;
348
407
  footer = docResult.footer;
349
408
  fragments = docResult.fragments;
350
409
  } else fragments = parsers.flatMap((p) => p.getDocFragments({ kind: "unavailable" }).fragments);
351
410
  }
352
411
  return {
412
+ brief,
353
413
  description,
354
414
  fragments,
355
415
  footer
package/dist/doc.d.cts CHANGED
@@ -60,6 +60,12 @@ type DocFragment = {
60
60
  * a final document page.
61
61
  */
62
62
  interface DocFragments {
63
+ /**
64
+ * An optional brief that provides a short summary for the collection
65
+ * of fragments.
66
+ * @since 0.7.12
67
+ */
68
+ readonly brief?: Message;
63
69
  /**
64
70
  * An optional description that applies to the entire collection of fragments.
65
71
  */
package/dist/doc.d.ts CHANGED
@@ -60,6 +60,12 @@ type DocFragment = {
60
60
  * a final document page.
61
61
  */
62
62
  interface DocFragments {
63
+ /**
64
+ * An optional brief that provides a short summary for the collection
65
+ * of fragments.
66
+ * @since 0.7.12
67
+ */
68
+ readonly brief?: Message;
63
69
  /**
64
70
  * An optional description that applies to the entire collection of fragments.
65
71
  */
package/dist/facade.cjs CHANGED
@@ -470,9 +470,9 @@ function run(parser, programName, args, options = {}) {
470
470
  } else {
471
471
  const singularMatchExact = completionName === "singular" || completionName === "both" ? arg === "--completion" : false;
472
472
  const pluralMatchExact = completionName === "plural" || completionName === "both" ? arg === "--completions" : false;
473
- if ((singularMatchExact || pluralMatchExact) && i + 1 < args.length) {
474
- const shell = args[i + 1];
475
- const completionArgs = args.slice(i + 2);
473
+ if (singularMatchExact || pluralMatchExact) {
474
+ const shell = i + 1 < args.length ? args[i + 1] : "";
475
+ const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
476
476
  return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName);
477
477
  }
478
478
  }
@@ -561,11 +561,13 @@ function run(parser, programName, args, options = {}) {
561
561
  const doc = require_parser.getDocPage(helpGeneratorParser, classified.commands);
562
562
  if (doc != null) {
563
563
  const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
564
+ const isSubcommandHelp = classified.commands.length > 0;
565
+ const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
564
566
  const augmentedDoc = {
565
567
  ...doc,
566
- brief: !isMetaCommandHelp ? brief ?? doc.brief : doc.brief,
567
- description: !isMetaCommandHelp ? description ?? doc.description : doc.description,
568
- footer: !isMetaCommandHelp ? footer ?? doc.footer : doc.footer
568
+ brief: shouldOverride ? brief ?? doc.brief : doc.brief ?? brief,
569
+ description: shouldOverride ? description ?? doc.description : doc.description ?? description,
570
+ footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
569
571
  };
570
572
  stdout(require_doc.formatDocPage(programName, augmentedDoc, {
571
573
  colors,
package/dist/facade.js CHANGED
@@ -470,9 +470,9 @@ function run(parser, programName, args, options = {}) {
470
470
  } else {
471
471
  const singularMatchExact = completionName === "singular" || completionName === "both" ? arg === "--completion" : false;
472
472
  const pluralMatchExact = completionName === "plural" || completionName === "both" ? arg === "--completions" : false;
473
- if ((singularMatchExact || pluralMatchExact) && i + 1 < args.length) {
474
- const shell = args[i + 1];
475
- const completionArgs = args.slice(i + 2);
473
+ if (singularMatchExact || pluralMatchExact) {
474
+ const shell = i + 1 < args.length ? args[i + 1] : "";
475
+ const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
476
476
  return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionMode, completionName);
477
477
  }
478
478
  }
@@ -561,11 +561,13 @@ function run(parser, programName, args, options = {}) {
561
561
  const doc = getDocPage(helpGeneratorParser, classified.commands);
562
562
  if (doc != null) {
563
563
  const isMetaCommandHelp = (completionName === "singular" || completionName === "both" ? requestedCommand === "completion" : false) || (completionName === "plural" || completionName === "both" ? requestedCommand === "completions" : false) || requestedCommand === "help" || requestedCommand === "version";
564
+ const isSubcommandHelp = classified.commands.length > 0;
565
+ const shouldOverride = !isMetaCommandHelp && !isSubcommandHelp;
564
566
  const augmentedDoc = {
565
567
  ...doc,
566
- brief: !isMetaCommandHelp ? brief ?? doc.brief : doc.brief,
567
- description: !isMetaCommandHelp ? description ?? doc.description : doc.description,
568
- footer: !isMetaCommandHelp ? footer ?? doc.footer : doc.footer
568
+ brief: shouldOverride ? brief ?? doc.brief : doc.brief ?? brief,
569
+ description: shouldOverride ? description ?? doc.description : doc.description ?? description,
570
+ footer: shouldOverride ? footer ?? doc.footer : doc.footer ?? footer
569
571
  };
570
572
  stdout(formatDocPage(programName, augmentedDoc, {
571
573
  colors,
package/dist/parser.cjs CHANGED
@@ -159,7 +159,7 @@ function getDocPage(parser, args = []) {
159
159
  if (!result.success) break;
160
160
  context = result.next;
161
161
  } while (context.buffer.length > 0);
162
- const { description, fragments, footer } = parser.getDocFragments({
162
+ const { brief, description, fragments, footer } = parser.getDocFragments({
163
163
  kind: "available",
164
164
  state: context.state
165
165
  }, void 0);
@@ -185,6 +185,7 @@ function getDocPage(parser, args = []) {
185
185
  return {
186
186
  usage,
187
187
  sections,
188
+ ...brief != null && { brief },
188
189
  ...description != null && { description },
189
190
  ...footer != null && { footer }
190
191
  };
package/dist/parser.js CHANGED
@@ -159,7 +159,7 @@ function getDocPage(parser, args = []) {
159
159
  if (!result.success) break;
160
160
  context = result.next;
161
161
  } while (context.buffer.length > 0);
162
- const { description, fragments, footer } = parser.getDocFragments({
162
+ const { brief, description, fragments, footer } = parser.getDocFragments({
163
163
  kind: "available",
164
164
  state: context.state
165
165
  }, void 0);
@@ -185,6 +185,7 @@ function getDocPage(parser, args = []) {
185
185
  return {
186
186
  usage,
187
187
  sections,
188
+ ...brief != null && { brief },
188
189
  ...description != null && { description },
189
190
  ...footer != null && { footer }
190
191
  };
@@ -725,6 +725,7 @@ function command(name, parser, options = {}) {
725
725
  const innerFragments = parser.getDocFragments(innerState, defaultValue);
726
726
  return {
727
727
  ...innerFragments,
728
+ brief: innerFragments.brief ?? options.brief,
728
729
  description: innerFragments.description ?? options.description,
729
730
  footer: innerFragments.footer ?? options.footer
730
731
  };
@@ -725,6 +725,7 @@ function command(name, parser, options = {}) {
725
725
  const innerFragments = parser.getDocFragments(innerState, defaultValue);
726
726
  return {
727
727
  ...innerFragments,
728
+ brief: innerFragments.brief ?? options.brief,
728
729
  description: innerFragments.description ?? options.description,
729
730
  footer: innerFragments.footer ?? options.footer
730
731
  };
@@ -232,5 +232,6 @@ function deduplicateSuggestions(suggestions) {
232
232
  //#endregion
233
233
  exports.DEFAULT_FIND_SIMILAR_OPTIONS = DEFAULT_FIND_SIMILAR_OPTIONS;
234
234
  exports.createErrorWithSuggestions = createErrorWithSuggestions;
235
+ exports.createSuggestionMessage = createSuggestionMessage;
235
236
  exports.deduplicateSuggestions = deduplicateSuggestions;
236
237
  exports.findSimilar = findSimilar;
@@ -230,4 +230,4 @@ function deduplicateSuggestions(suggestions) {
230
230
  }
231
231
 
232
232
  //#endregion
233
- export { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, deduplicateSuggestions, findSimilar };
233
+ export { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "0.8.9",
3
+ "version": "0.8.11",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",