politty 0.9.2 → 0.10.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.
@@ -228,6 +228,8 @@ interface Logger {
228
228
  log(message: string): void;
229
229
  /** Log error message to stderr */
230
230
  error(message: string): void;
231
+ /** Log warning message to stderr */
232
+ warn?(message: string): void;
231
233
  }
232
234
  /**
233
235
  * Supported schema types for args
@@ -939,4 +941,4 @@ declare function arg<T extends z.ZodType>(schema: T): T;
939
941
  declare function arg<T extends z.ZodType, M extends ArgMeta<z.output<T>>>(schema: T, meta: ValidateArgMeta<M, z.output<T>>): T;
940
942
  //#endregion
941
943
  export { toKebabCase as $, LogStream as A, SetupContext as B, Example as C, IsEmpty as D, GlobalSetupContext as E, RunCommandOptions as F, isLazyCommand as G, SubCommandsRecord as H, RunResult as I, ResolvedFieldMeta as J, lazy as K, RunResultFailure as L, MainOptions as M, NonRunnableCommand as N, LogEntry as O, PromptResolver as P, toCamelCase as Q, RunResultSuccess as R, CommandBase as S, GlobalCleanupContext as T, UnknownSubcommandHandler as U, SubCommandValue as V, LazyCommand as W, extractFields as X, UnknownKeysMode as Y, getUnknownKeysMode as Z, AnyCommand as _, EffectContext as a, CollectedLogs as b, arg as c, ResolvedExpandCandidate as d, CompletionDirectiveMask as f, DynamicCompletionResult as g, DynamicCompletionResolver as h, CustomCompletion as i, Logger as j, LogLevel as k, ExpandCandidate as l, DynamicCompletionContext as m, CompletionMeta as n, PromptMeta as o, DynamicCompletionCandidate as p, ExtractedFields as q, CompletionType as r, PromptType as s, ArgMeta as t, ExpandCompletion as u, ArgsSchema as v, GlobalArgs as w, Command as x, CleanupContext as y, RunnableCommand as z };
942
- //# sourceMappingURL=arg-registry-DDJpsUea.d.ts.map
944
+ //# sourceMappingURL=arg-registry-BN3I-XON.d.ts.map
package/dist/augment.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as ArgMeta } from "./arg-registry-DDJpsUea.js";
1
+ import { t as ArgMeta } from "./arg-registry-BN3I-XON.js";
2
2
 
3
3
  //#region src/augment.d.ts
4
4
  declare module "zod" {
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as runMain } from "./runner-BmWR9TLM.js";
2
+ import { n as runMain } from "./runner-BCMB67GV.js";
3
3
  import { t as arg } from "./arg-registry-BeLLAW5-.js";
4
4
  import { n as defineCommand } from "./command-B4yA4LXX.js";
5
5
  import { p as generateBundledCompletionWorker } from "./completion-DwTFOtQk.js";
@@ -1,3 +1,3 @@
1
- import { f as CompletionDirectiveMask, g as DynamicCompletionResult, h as DynamicCompletionResolver, m as DynamicCompletionContext, p as DynamicCompletionCandidate } from "../arg-registry-DDJpsUea.js";
2
- import { A as BundledWorkerOptions, C as CandidateResult, D as CompletionContext, E as generateCandidates, F as CompletionMode, I as CompletionOptions, L as CompletionResult, M as CompletableSubcommand, N as CompletionData, O as CompletionType, P as CompletionGenerator, R as ShellType, S as hasCompleteCommand, T as CompletionDirective, _ as extractCompletionData, a as detectShell, b as formatForShell, c as withCompletionCommand, d as GenerateBundledCompletionWorkerOptions, f as GenerateBundledCompletionWorkerResult, g as validateBundledWorkerFile, h as generateBundledCompletionWorker, i as createRefreshCompletionCommand, j as CompletableOption, k as parseCompletionContext, l as ValueCompletionField, m as defaultBundledWorkerOutputPath, n as createCompletionCommand, o as generateCompletion, p as bundledWorkerShellExtension, r as createCompletionWorkerPathCommand, s as getSupportedShells, t as WithCompletionOptions, u as resolveValueCompletion, v as extractPositionals, w as CompletionCandidate, x as createDynamicCompleteCommand, y as ShellFormatOptions } from "../index-DKGn3lIl.js";
1
+ import { f as CompletionDirectiveMask, g as DynamicCompletionResult, h as DynamicCompletionResolver, m as DynamicCompletionContext, p as DynamicCompletionCandidate } from "../arg-registry-BN3I-XON.js";
2
+ import { A as BundledWorkerOptions, C as CandidateResult, D as CompletionContext, E as generateCandidates, F as CompletionMode, I as CompletionOptions, L as CompletionResult, M as CompletableSubcommand, N as CompletionData, O as CompletionType, P as CompletionGenerator, R as ShellType, S as hasCompleteCommand, T as CompletionDirective, _ as extractCompletionData, a as detectShell, b as formatForShell, c as withCompletionCommand, d as GenerateBundledCompletionWorkerOptions, f as GenerateBundledCompletionWorkerResult, g as validateBundledWorkerFile, h as generateBundledCompletionWorker, i as createRefreshCompletionCommand, j as CompletableOption, k as parseCompletionContext, l as ValueCompletionField, m as defaultBundledWorkerOutputPath, n as createCompletionCommand, o as generateCompletion, p as bundledWorkerShellExtension, r as createCompletionWorkerPathCommand, s as getSupportedShells, t as WithCompletionOptions, u as resolveValueCompletion, v as extractPositionals, w as CompletionCandidate, x as createDynamicCompleteCommand, y as ShellFormatOptions } from "../index-CtRrTVTL.js";
3
3
  export { type BundledWorkerOptions, type CandidateResult, type CompletableOption, type CompletableSubcommand, type CompletionCandidate, type CompletionContext, type CompletionData, CompletionDirective, type CompletionDirectiveMask, type CompletionGenerator, type CompletionMode, type CompletionOptions, type CompletionResult, type CompletionType, type DynamicCompletionCandidate, type DynamicCompletionContext, type DynamicCompletionResolver, type DynamicCompletionResult, type GenerateBundledCompletionWorkerOptions, type GenerateBundledCompletionWorkerResult, type ShellFormatOptions, type ShellType, type ValueCompletionField, WithCompletionOptions, bundledWorkerShellExtension, createCompletionCommand, createCompletionWorkerPathCommand, createDynamicCompleteCommand, createRefreshCompletionCommand, defaultBundledWorkerOutputPath, detectShell, extractCompletionData, extractPositionals, formatForShell, generateBundledCompletionWorker, generateCandidates, generateCompletion, getSupportedShells, hasCompleteCommand, parseCompletionContext, resolveValueCompletion, validateBundledWorkerFile, withCompletionCommand };
@@ -1,4 +1,4 @@
1
- import { C as Example, J as ResolvedFieldMeta, V as SubCommandValue, _ as AnyCommand, q as ExtractedFields, v as ArgsSchema } from "../arg-registry-DDJpsUea.js";
1
+ import { C as Example, J as ResolvedFieldMeta, V as SubCommandValue, _ as AnyCommand, q as ExtractedFields, v as ArgsSchema } from "../arg-registry-BN3I-XON.js";
2
2
  import { z } from "zod";
3
3
  import * as fs from "node:fs";
4
4
 
@@ -11,6 +11,12 @@ import * as fs from "node:fs";
11
11
  */
12
12
  declare function resolveLazyCommand(cmd: SubCommandValue): Promise<AnyCommand>;
13
13
  //#endregion
14
+ //#region src/docs/option-rows.d.ts
15
+ /**
16
+ * Column identifiers for the options markdown table, in their canonical order.
17
+ */
18
+ type ColumnId = "option" | "alias" | "description" | "required" | "default" | "env";
19
+ //#endregion
14
20
  //#region src/docs/render-args.d.ts
15
21
  /**
16
22
  * Args shape type (Record of string keys to Zod schemas)
@@ -21,7 +27,7 @@ type ArgsShape = Record<string, z.ZodType>;
21
27
  * Options for rendering args table
22
28
  */
23
29
  type ArgsTableOptions = {
24
- /** Columns to include in the table (default: all columns) */columns?: ("option" | "alias" | "description" | "required" | "default" | "env")[];
30
+ /** Columns to include in the table (default: all columns) */columns?: ColumnId[];
25
31
  };
26
32
  /**
27
33
  * Render args definition as a markdown options table
@@ -6,6 +6,204 @@ import * as path$1 from "node:path";
6
6
  import path from "node:path";
7
7
  import { isDeepStrictEqual } from "node:util";
8
8
 
9
+ //#region src/docs/option-rows.ts
10
+ /** Canonical column order used when no explicit column subset is requested. */
11
+ const DEFAULT_COLUMNS = [
12
+ "option",
13
+ "alias",
14
+ "description",
15
+ "required",
16
+ "default"
17
+ ];
18
+ /**
19
+ * Marker appended to a custom negation row/line so readers can see which
20
+ * positive flag it negates (e.g. `--monochrome` → ``(↔ `--color`)``).
21
+ */
22
+ function negationRelationMarker(opt) {
23
+ return `(↔ \`--${opt.cliName}\`)`;
24
+ }
25
+ /**
26
+ * Resolve placeholder for an option (uses kebab-case cliName).
27
+ */
28
+ function resolvePlaceholder(opt) {
29
+ return opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
30
+ }
31
+ /**
32
+ * Normalize a single {@link ResolvedFieldMeta} into an {@link OptionRow}.
33
+ */
34
+ function toOptionRow(opt) {
35
+ const longFlag = opt.type === "boolean" ? `--${opt.cliName}` : `--${opt.cliName} <${resolvePlaceholder(opt)}>`;
36
+ const aliases = [];
37
+ if (opt.alias) for (const a of opt.alias) aliases.push(a.length === 1 ? `-${a}` : `--${a}`);
38
+ const hasNegationDisplay = opt.type === "boolean" && !!opt.negationDisplay;
39
+ const inlineNegation = hasNegationDisplay && !opt.negationDescription ? `--${opt.negationDisplay}` : void 0;
40
+ const negationRow = hasNegationDisplay && opt.negationDescription ? {
41
+ flag: `--${opt.negationDisplay}`,
42
+ description: opt.negationDescription,
43
+ relationMarker: negationRelationMarker(opt),
44
+ required: opt.required
45
+ } : void 0;
46
+ return {
47
+ longFlag,
48
+ aliases,
49
+ inlineNegation,
50
+ description: opt.description,
51
+ required: opt.required,
52
+ hasDefault: opt.defaultValue !== void 0,
53
+ defaultValue: opt.defaultValue,
54
+ env: opt.env,
55
+ negationRow
56
+ };
57
+ }
58
+ /**
59
+ * Build the normalized intermediate representation for a list of options.
60
+ * This is the single source of truth for per-option display decisions; the
61
+ * emitters below ({@link emitMarkdownTable}, {@link emitMarkdownList}) are pure
62
+ * formatting.
63
+ */
64
+ function toOptionRows(options) {
65
+ return options.map(toOptionRow);
66
+ }
67
+ /**
68
+ * Escape markdown special characters in table cells.
69
+ */
70
+ function escapeTableCell$2(str) {
71
+ return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
72
+ }
73
+ function backtick(value) {
74
+ return `\`${value}\``;
75
+ }
76
+ /**
77
+ * Format default value for table display.
78
+ */
79
+ function formatDefaultValue(row) {
80
+ if (!row.hasDefault) return "-";
81
+ return `\`${JSON.stringify(row.defaultValue)}\``;
82
+ }
83
+ /**
84
+ * Format env variable names for a markdown table cell.
85
+ */
86
+ function formatEnvNames(env) {
87
+ if (!env) return "-";
88
+ if (Array.isArray(env)) return env.map((e) => `\`${e}\``).join(", ");
89
+ return `\`${env}\``;
90
+ }
91
+ /**
92
+ * Format env variable info for a markdown list item (e.g. `[env: PORT, SERVER_PORT]`).
93
+ */
94
+ function formatEnvInfo(env) {
95
+ if (!env) return "";
96
+ return ` [env: ${(Array.isArray(env) ? env : [env]).join(", ")}]`;
97
+ }
98
+ /** Header label + separator dashes for each column, matching legacy widths. */
99
+ const COLUMN_META = {
100
+ option: {
101
+ header: "Option",
102
+ separator: "--------"
103
+ },
104
+ alias: {
105
+ header: "Alias",
106
+ separator: "-------"
107
+ },
108
+ description: {
109
+ header: "Description",
110
+ separator: "-------------"
111
+ },
112
+ required: {
113
+ header: "Required",
114
+ separator: "----------"
115
+ },
116
+ default: {
117
+ header: "Default",
118
+ separator: "---------"
119
+ },
120
+ env: {
121
+ header: "Env",
122
+ separator: "-----"
123
+ }
124
+ };
125
+ /**
126
+ * Render the table cell for a base option row in the given column.
127
+ */
128
+ function tableCell(row, col) {
129
+ switch (col) {
130
+ case "option": {
131
+ const name = backtick(row.longFlag);
132
+ return row.inlineNegation ? `${name} / ${backtick(row.inlineNegation)}` : name;
133
+ }
134
+ case "alias": return row.aliases.length > 0 ? row.aliases.map(backtick).join(", ") : "-";
135
+ case "description": return escapeTableCell$2(row.description ?? "");
136
+ case "required": return row.required ? "Yes" : "No";
137
+ case "default": return formatDefaultValue(row);
138
+ case "env": return formatEnvNames(row.env);
139
+ }
140
+ }
141
+ /**
142
+ * Render the table cell for a negation row in the given column.
143
+ */
144
+ function negationTableCell(neg, col) {
145
+ switch (col) {
146
+ case "option": return backtick(neg.flag);
147
+ case "description": return `${escapeTableCell$2(neg.description)} ${neg.relationMarker}`;
148
+ case "required": return neg.required ? "Yes" : "No";
149
+ case "alias":
150
+ case "default":
151
+ case "env": return "-";
152
+ }
153
+ }
154
+ /**
155
+ * Emit option rows as a markdown table.
156
+ *
157
+ * When `columns` is omitted, the canonical column set is used and the `Env`
158
+ * column is appended automatically iff any row has env configured. When
159
+ * `columns` is provided, exactly those columns are emitted, in that order.
160
+ *
161
+ * The separator row always uses the canonical fixed-width dashes from
162
+ * {@link COLUMN_META}, so every table — default or column-filtered — shares a
163
+ * single, consistent format.
164
+ */
165
+ function emitMarkdownTable(rows, columns) {
166
+ if (rows.length === 0) return "";
167
+ const cols = columns ?? (rows.some((r) => r.env) ? [...DEFAULT_COLUMNS, "env"] : DEFAULT_COLUMNS);
168
+ const lines = [];
169
+ lines.push(`| ${cols.map((c) => COLUMN_META[c].header).join(" | ")} |`);
170
+ lines.push(`|${cols.map((c) => COLUMN_META[c].separator).join("|")}|`);
171
+ for (const row of rows) {
172
+ lines.push(`| ${cols.map((c) => tableCell(row, c)).join(" | ")} |`);
173
+ if (row.negationRow) lines.push(`| ${cols.map((c) => negationTableCell(row.negationRow, c)).join(" | ")} |`);
174
+ }
175
+ return lines.join("\n");
176
+ }
177
+ /**
178
+ * Emit option rows as a markdown list.
179
+ *
180
+ * Aliases are joined with `, ` (short flags first, then the long flag, then
181
+ * long aliases); the inline negation is appended with ` / ` so it stays
182
+ * visually distinct from aliases.
183
+ */
184
+ function emitMarkdownList(rows) {
185
+ if (rows.length === 0) return "";
186
+ const lines = [];
187
+ for (const row of rows) {
188
+ const shortAliases = row.aliases.filter((a) => !a.startsWith("--"));
189
+ const longAliases = row.aliases.filter((a) => a.startsWith("--"));
190
+ let flags = [
191
+ ...shortAliases,
192
+ row.longFlag,
193
+ ...longAliases
194
+ ].map(backtick).join(", ");
195
+ if (row.inlineNegation) flags += ` / ${backtick(row.inlineNegation)}`;
196
+ const desc = row.description ? ` - ${row.description}` : "";
197
+ const required = row.required ? " (required)" : "";
198
+ const defaultVal = row.hasDefault ? ` (default: ${JSON.stringify(row.defaultValue)})` : "";
199
+ const envInfo = formatEnvInfo(row.env);
200
+ lines.push(`- ${flags}${desc}${required}${defaultVal}${envInfo}`);
201
+ if (row.negationRow) lines.push(`- ${backtick(row.negationRow.flag)} - ${row.negationRow.description} ${row.negationRow.relationMarker}`);
202
+ }
203
+ return lines.join("\n");
204
+ }
205
+
206
+ //#endregion
9
207
  //#region src/docs/types.ts
10
208
  /**
11
209
  * Environment variable name for update mode
@@ -108,24 +306,10 @@ function indexEndMarker(scope) {
108
306
  /**
109
307
  * Escape markdown special characters in table cells
110
308
  */
111
- function escapeTableCell$2(str) {
309
+ function escapeTableCell$1(str) {
112
310
  return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
113
311
  }
114
312
  /**
115
- * Marker appended to a custom negation row/line so readers can see which
116
- * positive flag it negates (e.g. `--monochrome` → `(↔ \`--color\`)`).
117
- */
118
- function negationRelationMarker(opt) {
119
- return `(↔ \`--${opt.cliName}\`)`;
120
- }
121
- /**
122
- * Format default value for display
123
- */
124
- function formatDefaultValue$1(value) {
125
- if (value === void 0) return "-";
126
- return `\`${JSON.stringify(value)}\``;
127
- }
128
- /**
129
313
  * Render usage line
130
314
  */
131
315
  function renderUsage(info) {
@@ -146,7 +330,7 @@ function renderArgumentsTable(info) {
146
330
  lines.push("| Argument | Description | Required |");
147
331
  lines.push("|----------|-------------|----------|");
148
332
  for (const arg of info.positionalArgs) {
149
- const desc = escapeTableCell$2(arg.description ?? "");
333
+ const desc = escapeTableCell$1(arg.description ?? "");
150
334
  const required = arg.required ? "Yes" : "No";
151
335
  lines.push(`| \`${arg.name}\` | ${desc} | ${required} |`);
152
336
  }
@@ -166,70 +350,6 @@ function renderArgumentsList(info) {
166
350
  return lines.join("\n");
167
351
  }
168
352
  /**
169
- * Format environment variable info for display
170
- */
171
- function formatEnvInfo(env) {
172
- if (!env) return "";
173
- return ` [env: ${(Array.isArray(env) ? env : [env]).join(", ")}]`;
174
- }
175
- /**
176
- * Resolve placeholder for an option (uses kebab-case cliName)
177
- */
178
- function resolvePlaceholder(opt) {
179
- return opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
180
- }
181
- /**
182
- * Format option name for table display (e.g., `--dry-run` or `--port <PORT>`)
183
- *
184
- * Boolean fields with a custom inline `negation` (no separate description) are
185
- * shown as `\`--cache\` / \`--disable-cache\``.
186
- */
187
- function formatOptionName(opt) {
188
- const placeholder = resolvePlaceholder(opt);
189
- if (opt.type === "boolean") {
190
- const positive = `\`--${opt.cliName}\``;
191
- if (opt.negationDisplay && !opt.negationDescription) return `${positive} / \`--${opt.negationDisplay}\``;
192
- return positive;
193
- }
194
- return `\`--${opt.cliName} <${placeholder}>\``;
195
- }
196
- /**
197
- * Format option flags for list display (uses kebab-case cliName).
198
- * Aliases are joined with `, `; the inline negation (when no separate
199
- * `negationDescription` is set) is appended with ` / ` so it stays
200
- * visually distinct from aliases, matching help and table output.
201
- */
202
- function formatOptionFlags(opt) {
203
- const placeholder = resolvePlaceholder(opt);
204
- const longFlag = opt.type === "boolean" ? `--${opt.cliName}` : `--${opt.cliName} <${placeholder}>`;
205
- const parts = [];
206
- if (opt.alias) {
207
- for (const a of opt.alias) if (a.length === 1) parts.push(`\`-${a}\``);
208
- }
209
- parts.push(`\`${longFlag}\``);
210
- if (opt.alias) {
211
- for (const a of opt.alias) if (a.length > 1) parts.push(`\`--${a}\``);
212
- }
213
- const aliasJoined = parts.join(", ");
214
- if (opt.type === "boolean" && opt.negationDisplay && !opt.negationDescription) return `${aliasJoined} / \`--${opt.negationDisplay}\``;
215
- return aliasJoined;
216
- }
217
- /**
218
- * Format aliases for a markdown table cell
219
- */
220
- function formatAliasCell(alias) {
221
- if (!alias || alias.length === 0) return "-";
222
- return alias.map((a) => `\`${a.length === 1 ? `-${a}` : `--${a}`}\``).join(", ");
223
- }
224
- /**
225
- * Format env variable names for table display
226
- */
227
- function formatEnvNames(env) {
228
- if (!env) return "-";
229
- if (Array.isArray(env)) return env.map((e) => `\`${e}\``).join(", ");
230
- return `\`${env}\``;
231
- }
232
- /**
233
353
  * Render options as markdown table
234
354
  *
235
355
  * Features:
@@ -244,34 +364,7 @@ function formatEnvNames(env) {
244
364
  * | `--port <PORT>` | - | Server port | Yes | - | `PORT`, `SERVER_PORT` |
245
365
  */
246
366
  function renderOptionsTable(info) {
247
- if (info.options.length === 0) return "";
248
- const hasEnv = info.options.some((opt) => opt.env);
249
- const lines = [];
250
- if (hasEnv) {
251
- lines.push("| Option | Alias | Description | Required | Default | Env |");
252
- lines.push("|--------|-------|-------------|----------|---------|-----|");
253
- } else {
254
- lines.push("| Option | Alias | Description | Required | Default |");
255
- lines.push("|--------|-------|-------------|----------|---------|");
256
- }
257
- for (const opt of info.options) {
258
- const optionName = formatOptionName(opt);
259
- const alias = formatAliasCell(opt.alias);
260
- const desc = escapeTableCell$2(opt.description ?? "");
261
- const required = opt.required ? "Yes" : "No";
262
- const defaultVal = formatDefaultValue$1(opt.defaultValue);
263
- if (hasEnv) {
264
- const envNames = formatEnvNames(opt.env);
265
- lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`);
266
- } else lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);
267
- if (opt.type === "boolean" && opt.negationDisplay && opt.negationDescription) {
268
- const negName = `\`--${opt.negationDisplay}\``;
269
- const negDesc = `${escapeTableCell$2(opt.negationDescription)} ${negationRelationMarker(opt)}`;
270
- if (hasEnv) lines.push(`| ${negName} | - | ${negDesc} | ${required} | - | - |`);
271
- else lines.push(`| ${negName} | - | ${negDesc} | ${required} | - |`);
272
- }
273
- }
274
- return lines.join("\n");
367
+ return emitMarkdownTable(toOptionRows(info.options));
275
368
  }
276
369
  /**
277
370
  * Render options as markdown list
@@ -285,18 +378,7 @@ function renderOptionsTable(info) {
285
378
  * - `--port <PORT>` - Server port (required) [env: PORT, SERVER_PORT]
286
379
  */
287
380
  function renderOptionsList(info) {
288
- if (info.options.length === 0) return "";
289
- const lines = [];
290
- for (const opt of info.options) {
291
- const flags = formatOptionFlags(opt);
292
- const desc = opt.description ? ` - ${opt.description}` : "";
293
- const required = opt.required ? " (required)" : "";
294
- const defaultVal = opt.defaultValue !== void 0 ? ` (default: ${JSON.stringify(opt.defaultValue)})` : "";
295
- const envInfo = formatEnvInfo(opt.env);
296
- lines.push(`- ${flags}${desc}${required}${defaultVal}${envInfo}`);
297
- if (opt.type === "boolean" && opt.negationDisplay && opt.negationDescription) lines.push(`- \`--${opt.negationDisplay}\` - ${opt.negationDescription} ${negationRelationMarker(opt)}`);
298
- }
299
- return lines.join("\n");
381
+ return emitMarkdownList(toOptionRows(info.options));
300
382
  }
301
383
  /**
302
384
  * Generate anchor from command path
@@ -323,34 +405,7 @@ function renderSubcommandsTable(info, generateAnchors = true) {
323
405
  * Render options from array as table
324
406
  */
325
407
  function renderOptionsTableFromArray(options) {
326
- if (options.length === 0) return "";
327
- const hasEnv = options.some((opt) => opt.env);
328
- const lines = [];
329
- if (hasEnv) {
330
- lines.push("| Option | Alias | Description | Required | Default | Env |");
331
- lines.push("|--------|-------|-------------|----------|---------|-----|");
332
- } else {
333
- lines.push("| Option | Alias | Description | Required | Default |");
334
- lines.push("|--------|-------|-------------|----------|---------|");
335
- }
336
- for (const opt of options) {
337
- const optionName = formatOptionName(opt);
338
- const alias = formatAliasCell(opt.alias);
339
- const desc = escapeTableCell$2(opt.description ?? "");
340
- const required = opt.required ? "Yes" : "No";
341
- const defaultVal = formatDefaultValue$1(opt.defaultValue);
342
- if (hasEnv) {
343
- const envNames = formatEnvNames(opt.env);
344
- lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`);
345
- } else lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);
346
- if (opt.type === "boolean" && opt.negationDisplay && opt.negationDescription) {
347
- const negName = `\`--${opt.negationDisplay}\``;
348
- const negDesc = `${escapeTableCell$2(opt.negationDescription)} ${negationRelationMarker(opt)}`;
349
- if (hasEnv) lines.push(`| ${negName} | - | ${negDesc} | ${required} | - | - |`);
350
- else lines.push(`| ${negName} | - | ${negDesc} | ${required} | - |`);
351
- }
352
- }
353
- return lines.join("\n");
408
+ return emitMarkdownTable(toOptionRows(options));
354
409
  }
355
410
  /**
356
411
  * Render union/xor options as markdown with variant grouping
@@ -421,18 +476,7 @@ function renderDiscriminatedUnionOptionsMarkdown(extracted, style = "table") {
421
476
  * Render options from array as list
422
477
  */
423
478
  function renderOptionsListFromArray(options) {
424
- if (options.length === 0) return "";
425
- const lines = [];
426
- for (const opt of options) {
427
- const flags = formatOptionFlags(opt);
428
- const desc = opt.description ? ` - ${opt.description}` : "";
429
- const required = opt.required ? " (required)" : "";
430
- const defaultVal = opt.defaultValue !== void 0 ? ` (default: ${JSON.stringify(opt.defaultValue)})` : "";
431
- const envInfo = formatEnvInfo(opt.env);
432
- lines.push(`- ${flags}${desc}${required}${defaultVal}${envInfo}`);
433
- if (opt.type === "boolean" && opt.negationDisplay && opt.negationDescription) lines.push(`- \`--${opt.negationDisplay}\` - ${opt.negationDescription} ${negationRelationMarker(opt)}`);
434
- }
435
- return lines.join("\n");
479
+ return emitMarkdownList(toOptionRows(options));
436
480
  }
437
481
  /**
438
482
  * Render arguments from array as table
@@ -443,7 +487,7 @@ function renderArgumentsTableFromArray(args) {
443
487
  lines.push("| Argument | Description | Required |");
444
488
  lines.push("|----------|-------------|----------|");
445
489
  for (const arg of args) {
446
- const desc = escapeTableCell$2(arg.description ?? "");
490
+ const desc = escapeTableCell$1(arg.description ?? "");
447
491
  const required = arg.required ? "Yes" : "No";
448
492
  lines.push(`| \`${arg.name}\` | ${desc} | ${required} |`);
449
493
  }
@@ -480,9 +524,9 @@ function renderSubcommandsTableFromArray(subcommands, info, generateAnchors = tr
480
524
  const fileMap = info.fileMap;
481
525
  for (const sub of subcommands) {
482
526
  const fullName = sub.fullPath.join(" ");
483
- const desc = escapeTableCell$2(sub.description ?? "");
527
+ const desc = escapeTableCell$1(sub.description ?? "");
484
528
  const subCommandPath = sub.fullPath.join(" ");
485
- const aliasCell = hasAliases ? sub.aliases && sub.aliases.length > 0 ? sub.aliases.map((a) => `\`${escapeTableCell$2(a)}\``).join(", ") : "-" : "";
529
+ const aliasCell = hasAliases ? sub.aliases && sub.aliases.length > 0 ? sub.aliases.map((a) => `\`${escapeTableCell$1(a)}\``).join(", ") : "-" : "";
486
530
  let cmdCell;
487
531
  if (generateAnchors) {
488
532
  const anchor = generateAnchor$1(sub.fullPath);
@@ -875,7 +919,7 @@ async function executeSingleExample(example, rootCommand, commandPath) {
875
919
  collector.start();
876
920
  let success = true;
877
921
  try {
878
- const { runCommand } = await import("../runner-BmWR9TLM.js").then((n) => n.r);
922
+ const { runCommand } = await import("../runner-BCMB67GV.js").then((n) => n.r);
879
923
  const result = await runCommand(rootCommand, argv);
880
924
  success = result.success;
881
925
  if (!result.success && result.error) console.error(result.error.message);
@@ -967,111 +1011,7 @@ function extractArgsFields(args) {
967
1011
  function renderArgsTable(args, options) {
968
1012
  const optionFields = extractArgsFields(args).filter((f) => !f.positional);
969
1013
  if (optionFields.length === 0) return "";
970
- if (options?.columns) return renderFilteredTable(optionFields, options.columns);
971
- return renderOptionsTableFromArray(optionFields);
972
- }
973
- /**
974
- * Escape markdown special characters in table cells
975
- */
976
- function escapeTableCell$1(str) {
977
- return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
978
- }
979
- /**
980
- * Format default value for display
981
- */
982
- function formatDefaultValue(value) {
983
- if (value === void 0) return "-";
984
- return `\`${JSON.stringify(value)}\``;
985
- }
986
- /**
987
- * Render table with filtered columns
988
- */
989
- function renderFilteredTable(options, columns) {
990
- const lines = [];
991
- const headerCells = [];
992
- const separatorCells = [];
993
- for (const col of columns) switch (col) {
994
- case "option":
995
- headerCells.push("Option");
996
- separatorCells.push("------");
997
- break;
998
- case "alias":
999
- headerCells.push("Alias");
1000
- separatorCells.push("-----");
1001
- break;
1002
- case "description":
1003
- headerCells.push("Description");
1004
- separatorCells.push("-----------");
1005
- break;
1006
- case "required":
1007
- headerCells.push("Required");
1008
- separatorCells.push("--------");
1009
- break;
1010
- case "default":
1011
- headerCells.push("Default");
1012
- separatorCells.push("-------");
1013
- break;
1014
- case "env":
1015
- headerCells.push("Env");
1016
- separatorCells.push("---");
1017
- break;
1018
- }
1019
- lines.push(`| ${headerCells.join(" | ")} |`);
1020
- lines.push(`| ${separatorCells.join(" | ")} |`);
1021
- for (const opt of options) {
1022
- const cells = [];
1023
- for (const col of columns) switch (col) {
1024
- case "option": {
1025
- const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
1026
- let optionName;
1027
- if (opt.type === "boolean") {
1028
- optionName = `\`--${opt.cliName}\``;
1029
- if (opt.negationDisplay && !opt.negationDescription) optionName += ` / \`--${opt.negationDisplay}\``;
1030
- } else optionName = `\`--${opt.cliName} <${placeholder}>\``;
1031
- cells.push(optionName);
1032
- break;
1033
- }
1034
- case "alias":
1035
- cells.push(opt.alias && opt.alias.length > 0 ? opt.alias.map((a) => `\`${a.length === 1 ? `-${a}` : `--${a}`}\``).join(", ") : "-");
1036
- break;
1037
- case "description":
1038
- cells.push(escapeTableCell$1(opt.description ?? ""));
1039
- break;
1040
- case "required":
1041
- cells.push(opt.required ? "Yes" : "No");
1042
- break;
1043
- case "default":
1044
- cells.push(formatDefaultValue(opt.defaultValue));
1045
- break;
1046
- case "env": {
1047
- const envNames = opt.env ? Array.isArray(opt.env) ? opt.env.map((e) => `\`${e}\``).join(", ") : `\`${opt.env}\`` : "-";
1048
- cells.push(envNames);
1049
- break;
1050
- }
1051
- }
1052
- lines.push(`| ${cells.join(" | ")} |`);
1053
- if (opt.type === "boolean" && opt.negationDisplay && opt.negationDescription) {
1054
- const negCells = [];
1055
- for (const col of columns) switch (col) {
1056
- case "option":
1057
- negCells.push(`\`--${opt.negationDisplay}\``);
1058
- break;
1059
- case "description":
1060
- negCells.push(`${escapeTableCell$1(opt.negationDescription)} ${negationRelationMarker(opt)}`);
1061
- break;
1062
- case "required":
1063
- negCells.push(opt.required ? "Yes" : "No");
1064
- break;
1065
- case "alias":
1066
- case "default":
1067
- case "env":
1068
- negCells.push("-");
1069
- break;
1070
- }
1071
- lines.push(`| ${negCells.join(" | ")} |`);
1072
- }
1073
- }
1074
- return lines.join("\n");
1014
+ return emitMarkdownTable(toOptionRows(optionFields), options?.columns);
1075
1015
  }
1076
1016
 
1077
1017
  //#endregion
@@ -1,4 +1,4 @@
1
- import { J as ResolvedFieldMeta, _ as AnyCommand, d as ResolvedExpandCandidate, h as DynamicCompletionResolver, u as ExpandCompletion, v as ArgsSchema, x as Command } from "./arg-registry-DDJpsUea.js";
1
+ import { J as ResolvedFieldMeta, _ as AnyCommand, d as ResolvedExpandCandidate, h as DynamicCompletionResolver, u as ExpandCompletion, v as ArgsSchema, x as Command } from "./arg-registry-BN3I-XON.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/completion/types.d.ts
@@ -660,4 +660,4 @@ interface WithCompletionOptions {
660
660
  declare function withCompletionCommand<T extends AnyCommand>(command: T, options?: string | WithCompletionOptions): T;
661
661
  //#endregion
662
662
  export { BundledWorkerOptions as A, CandidateResult as C, CompletionContext as D, generateCandidates as E, CompletionMode as F, CompletionOptions as I, CompletionResult as L, CompletableSubcommand as M, CompletionData as N, CompletionType as O, CompletionGenerator as P, ShellType as R, hasCompleteCommand as S, CompletionDirective as T, extractCompletionData as _, detectShell as a, formatForShell as b, withCompletionCommand as c, GenerateBundledCompletionWorkerOptions as d, GenerateBundledCompletionWorkerResult as f, validateBundledWorkerFile as g, generateBundledCompletionWorker as h, createRefreshCompletionCommand as i, CompletableOption as j, parseCompletionContext as k, ValueCompletionField as l, defaultBundledWorkerOutputPath as m, createCompletionCommand as n, generateCompletion as o, bundledWorkerShellExtension as p, createCompletionWorkerPathCommand as r, getSupportedShells as s, WithCompletionOptions as t, resolveValueCompletion as u, extractPositionals as v, CompletionCandidate as w, createDynamicCompleteCommand as x, ShellFormatOptions as y };
663
- //# sourceMappingURL=index-DKGn3lIl.d.ts.map
663
+ //# sourceMappingURL=index-CtRrTVTL.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as toKebabCase, A as LogStream, B as SetupContext, C as Example, D as IsEmpty, E as GlobalSetupContext, F as RunCommandOptions, G as isLazyCommand, H as SubCommandsRecord, I as RunResult, J as ResolvedFieldMeta, K as lazy, L as RunResultFailure, M as MainOptions, N as NonRunnableCommand, O as LogEntry, P as PromptResolver, Q as toCamelCase, R as RunResultSuccess, S as CommandBase, T as GlobalCleanupContext, U as UnknownSubcommandHandler, V as SubCommandValue, W as LazyCommand, X as extractFields, Y as UnknownKeysMode, Z as getUnknownKeysMode, _ as AnyCommand, a as EffectContext, b as CollectedLogs, c as arg, d as ResolvedExpandCandidate, f as CompletionDirectiveMask, g as DynamicCompletionResult, h as DynamicCompletionResolver, i as CustomCompletion, j as Logger, k as LogLevel, l as ExpandCandidate, m as DynamicCompletionContext, n as CompletionMeta, o as PromptMeta, p as DynamicCompletionCandidate, q as ExtractedFields, r as CompletionType, s as PromptType, t as ArgMeta, u as ExpandCompletion, v as ArgsSchema, w as GlobalArgs, x as Command, y as CleanupContext, z as RunnableCommand } from "./arg-registry-DDJpsUea.js";
2
- import { I as CompletionOptions, L as CompletionResult, c as withCompletionCommand, d as GenerateBundledCompletionWorkerOptions, f as GenerateBundledCompletionWorkerResult, h as generateBundledCompletionWorker, o as generateCompletion, t as WithCompletionOptions } from "./index-DKGn3lIl.js";
1
+ import { $ as toKebabCase, A as LogStream, B as SetupContext, C as Example, D as IsEmpty, E as GlobalSetupContext, F as RunCommandOptions, G as isLazyCommand, H as SubCommandsRecord, I as RunResult, J as ResolvedFieldMeta, K as lazy, L as RunResultFailure, M as MainOptions, N as NonRunnableCommand, O as LogEntry, P as PromptResolver, Q as toCamelCase, R as RunResultSuccess, S as CommandBase, T as GlobalCleanupContext, U as UnknownSubcommandHandler, V as SubCommandValue, W as LazyCommand, X as extractFields, Y as UnknownKeysMode, Z as getUnknownKeysMode, _ as AnyCommand, a as EffectContext, b as CollectedLogs, c as arg, d as ResolvedExpandCandidate, f as CompletionDirectiveMask, g as DynamicCompletionResult, h as DynamicCompletionResolver, i as CustomCompletion, j as Logger, k as LogLevel, l as ExpandCandidate, m as DynamicCompletionContext, n as CompletionMeta, o as PromptMeta, p as DynamicCompletionCandidate, q as ExtractedFields, r as CompletionType, s as PromptType, t as ArgMeta, u as ExpandCompletion, v as ArgsSchema, w as GlobalArgs, x as Command, y as CleanupContext, z as RunnableCommand } from "./arg-registry-BN3I-XON.js";
2
+ import { I as CompletionOptions, L as CompletionResult, c as withCompletionCommand, d as GenerateBundledCompletionWorkerOptions, f as GenerateBundledCompletionWorkerResult, h as generateBundledCompletionWorker, o as generateCompletion, t as WithCompletionOptions } from "./index-CtRrTVTL.js";
3
3
  import { z } from "zod";
4
4
 
5
5
  //#region src/core/case-types.d.ts
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as renderMarkdown, S as renderInline, _ as DuplicateFieldError, a as parseArgv, b as ReservedAliasError, c as validateCommand, d as validateDuplicateFields, f as validateDuplicateNegations, g as DuplicateAliasError, h as CaseVariantCollisionError, i as formatValidationErrors, l as validateCrossSchemaCollisions, m as validateReservedAliases, n as runMain, o as formatCommandValidationErrors, p as validatePositionalConfig, s as validateCaseVariantCollisions, t as runCommand, u as validateDuplicateAliases, v as DuplicateNegationError, w as createDualCaseProxy, x as generateHelp, y as PositionalConfigError } from "./runner-BmWR9TLM.js";
1
+ import { C as renderMarkdown, S as renderInline, _ as DuplicateFieldError, a as parseArgv, b as ReservedAliasError, c as validateCommand, d as validateDuplicateFields, f as validateDuplicateNegations, g as DuplicateAliasError, h as CaseVariantCollisionError, i as formatValidationErrors, l as validateCrossSchemaCollisions, m as validateReservedAliases, n as runMain, o as formatCommandValidationErrors, p as validatePositionalConfig, s as validateCaseVariantCollisions, t as runCommand, u as validateDuplicateAliases, v as DuplicateNegationError, w as createDualCaseProxy, x as generateHelp, y as PositionalConfigError } from "./runner-BCMB67GV.js";
2
2
  import { t as arg } from "./arg-registry-BeLLAW5-.js";
3
3
  import { n as defineCommand, t as createDefineCommand } from "./command-B4yA4LXX.js";
4
4
  import { a as toCamelCase, f as isLazyCommand, i as getUnknownKeysMode, o as toKebabCase, p as lazy, t as extractFields } from "./schema-extractor-CVHWm23M.js";
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry-DDJpsUea.js";
1
+ import { P as PromptResolver } from "../../arg-registry-BN3I-XON.js";
2
2
 
3
3
  //#region src/prompt/clack/index.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { J as ResolvedFieldMeta, q as ExtractedFields } from "../arg-registry-DDJpsUea.js";
1
+ import { J as ResolvedFieldMeta, q as ExtractedFields } from "../arg-registry-BN3I-XON.js";
2
2
 
3
3
  //#region src/prompt/types.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { P as PromptResolver } from "../../arg-registry-DDJpsUea.js";
1
+ import { P as PromptResolver } from "../../arg-registry-BN3I-XON.js";
2
2
 
3
3
  //#region src/prompt/inquirer/index.d.ts
4
4
  /**
@@ -1421,6 +1421,78 @@ function formatCommandValidationErrors(errors) {
1421
1421
  return lines.join("\n");
1422
1422
  }
1423
1423
 
1424
+ //#endregion
1425
+ //#region src/parser/long-option-resolver.ts
1426
+ function resolveLongOption(arg, lookup) {
1427
+ const withoutDashes = arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2);
1428
+ if (!arg.includes("=")) {
1429
+ const negatedField = lookup.negationMap.get(withoutDashes);
1430
+ if (negatedField && lookup.booleanFlags.has(negatedField)) return {
1431
+ resolvedName: negatedField,
1432
+ withoutDashes,
1433
+ isNegated: true,
1434
+ isCustomNegation: true,
1435
+ isSuppressedNegation: false
1436
+ };
1437
+ }
1438
+ const hasEquals = arg.includes("=");
1439
+ if (!hasEquals && withoutDashes.startsWith("no-")) {
1440
+ const flagName = withoutDashes.slice(3);
1441
+ if (flagName === flagName.toLowerCase()) {
1442
+ const resolvedName = lookup.aliasMap.get(flagName) ?? flagName;
1443
+ if (lookup.booleanFlags.has(resolvedName)) {
1444
+ const asIsResolved = lookup.aliasMap.get(withoutDashes) ?? withoutDashes;
1445
+ if (!lookup.definedNames.has(asIsResolved)) {
1446
+ if (lookup.customNegatedFields.has(resolvedName)) return {
1447
+ resolvedName,
1448
+ withoutDashes,
1449
+ isNegated: false,
1450
+ isCustomNegation: false,
1451
+ isSuppressedNegation: true
1452
+ };
1453
+ return {
1454
+ resolvedName,
1455
+ withoutDashes,
1456
+ isNegated: true,
1457
+ isCustomNegation: false,
1458
+ isSuppressedNegation: false
1459
+ };
1460
+ }
1461
+ }
1462
+ }
1463
+ }
1464
+ if (!hasEquals && withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2])) {
1465
+ const camelFlagName = withoutDashes[2].toLowerCase() + withoutDashes.slice(3);
1466
+ const resolvedName = lookup.aliasMap.get(camelFlagName) ?? camelFlagName;
1467
+ if (lookup.booleanFlags.has(resolvedName)) {
1468
+ const asIsResolved = lookup.aliasMap.get(withoutDashes) ?? withoutDashes;
1469
+ if (!lookup.definedNames.has(asIsResolved)) {
1470
+ if (lookup.customNegatedFields.has(resolvedName)) return {
1471
+ resolvedName,
1472
+ withoutDashes,
1473
+ isNegated: false,
1474
+ isCustomNegation: false,
1475
+ isSuppressedNegation: true
1476
+ };
1477
+ return {
1478
+ resolvedName,
1479
+ withoutDashes,
1480
+ isNegated: true,
1481
+ isCustomNegation: false,
1482
+ isSuppressedNegation: false
1483
+ };
1484
+ }
1485
+ }
1486
+ }
1487
+ return {
1488
+ resolvedName: lookup.aliasMap.get(withoutDashes) ?? withoutDashes,
1489
+ withoutDashes,
1490
+ isNegated: false,
1491
+ isCustomNegation: false,
1492
+ isSuppressedNegation: false
1493
+ };
1494
+ }
1495
+
1424
1496
  //#endregion
1425
1497
  //#region src/parser/argv-parser.ts
1426
1498
  /**
@@ -1446,6 +1518,13 @@ function formatCommandValidationErrors(errors) {
1446
1518
  */
1447
1519
  function parseArgv(argv, options = {}) {
1448
1520
  const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set(), negationMap = /* @__PURE__ */ new Map(), customNegatedFields = /* @__PURE__ */ new Set() } = options;
1521
+ const longOptionLookup = {
1522
+ aliasMap,
1523
+ booleanFlags,
1524
+ definedNames,
1525
+ negationMap,
1526
+ customNegatedFields
1527
+ };
1449
1528
  const result = {
1450
1529
  options: {},
1451
1530
  positionals: [],
@@ -1476,39 +1555,11 @@ function parseArgv(argv, options = {}) {
1476
1555
  }
1477
1556
  if (arg.startsWith("--")) {
1478
1557
  const withoutDashes = arg.slice(2);
1479
- if (!withoutDashes.includes("=")) {
1480
- const negatedField = negationMap.get(withoutDashes);
1481
- if (negatedField && booleanFlags.has(negatedField)) {
1482
- setOption(negatedField, false);
1483
- i++;
1484
- continue;
1485
- }
1486
- }
1487
- if (withoutDashes.startsWith("no-")) {
1488
- const flagName = withoutDashes.slice(3);
1489
- if (flagName === flagName.toLowerCase()) {
1490
- const resolvedName = aliasMap.get(flagName) ?? flagName;
1491
- if (booleanFlags.has(resolvedName) && !customNegatedFields.has(resolvedName)) {
1492
- const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
1493
- if (!definedNames.has(asIsResolved)) {
1494
- setOption(flagName, false);
1495
- i++;
1496
- continue;
1497
- }
1498
- }
1499
- }
1500
- }
1501
- if (withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2])) {
1502
- const camelFlagName = withoutDashes[2].toLowerCase() + withoutDashes.slice(3);
1503
- const resolvedName = aliasMap.get(camelFlagName) ?? camelFlagName;
1504
- if (booleanFlags.has(resolvedName) && !customNegatedFields.has(resolvedName)) {
1505
- const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
1506
- if (!definedNames.has(asIsResolved)) {
1507
- setOption(camelFlagName, false);
1508
- i++;
1509
- continue;
1510
- }
1511
- }
1558
+ const resolution = resolveLongOption(arg, longOptionLookup);
1559
+ if (resolution.isNegated) {
1560
+ setOption(resolution.resolvedName, false);
1561
+ i++;
1562
+ continue;
1512
1563
  }
1513
1564
  const eqIndex = withoutDashes.indexOf("=");
1514
1565
  if (eqIndex !== -1) {
@@ -1638,12 +1689,13 @@ function mergeWithPositionals(parsed, extracted) {
1638
1689
  * Shared by scanForSubcommand, separateGlobalArgs, and findFirstPositional.
1639
1690
  */
1640
1691
  function buildGlobalFlagLookup(globalExtracted) {
1641
- const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), negationMap = /* @__PURE__ */ new Map(), customNegatedFields = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
1692
+ const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set(), negationMap = /* @__PURE__ */ new Map(), customNegatedFields = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
1642
1693
  const shortAliases = /* @__PURE__ */ new Set();
1643
1694
  for (const field of globalExtracted.fields) for (const alias of getAllAliases(field)) if (alias.length === 1) shortAliases.add(alias);
1644
1695
  return {
1645
1696
  aliasMap,
1646
1697
  booleanFlags,
1698
+ definedNames,
1647
1699
  flagNames: new Set(globalExtracted.fields.map((f) => f.name)),
1648
1700
  cliNames: new Set(globalExtracted.fields.map((f) => f.cliName)),
1649
1701
  aliases: shortAliases,
@@ -1662,37 +1714,21 @@ function buildGlobalFlagLookup(globalExtracted) {
1662
1714
  * trailing subcommand is still detected) even though they no longer negate.
1663
1715
  */
1664
1716
  function resolveGlobalLongOption(arg, lookup) {
1665
- const withoutDashes = arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2);
1666
- const customNegated = !arg.includes("=") ? lookup.negationMap.get(withoutDashes) : void 0;
1667
- if (customNegated) return {
1668
- resolvedName: customNegated,
1717
+ const { resolvedName, withoutDashes, isNegated, isCustomNegation, isSuppressedNegation } = resolveLongOption(arg, lookup);
1718
+ if (isSuppressedNegation) return {
1719
+ resolvedName,
1669
1720
  withoutDashes,
1670
- isNegated: true,
1671
- isGlobal: lookup.flagNames.has(customNegated),
1672
- isSuppressedNegation: false
1721
+ isNegated: false,
1722
+ isGlobal: false,
1723
+ isSuppressedNegation
1673
1724
  };
1674
- const kebabNegated = withoutDashes.startsWith("no-");
1675
- const camelNegated = !kebabNegated && withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2]);
1676
- if (kebabNegated || camelNegated) {
1677
- const literalResolved = lookup.aliasMap.get(withoutDashes) ?? withoutDashes;
1678
- if (lookup.flagNames.has(literalResolved) || lookup.cliNames.has(withoutDashes)) return {
1679
- resolvedName: literalResolved,
1680
- withoutDashes,
1681
- isNegated: false,
1682
- isGlobal: true,
1683
- isSuppressedNegation: false
1684
- };
1685
- }
1686
- const defaultIsNegated = kebabNegated || camelNegated;
1687
- const flagName = kebabNegated ? withoutDashes.slice(3) : camelNegated ? withoutDashes[2].toLowerCase() + withoutDashes.slice(3) : withoutDashes;
1688
- const resolvedName = lookup.aliasMap.get(flagName) ?? flagName;
1689
- const suppressDefaultNegation = defaultIsNegated && lookup.customNegatedFields.has(resolvedName);
1725
+ const flagName = isNegated && !isCustomNegation ? withoutDashes.startsWith("no-") ? withoutDashes.slice(3) : withoutDashes[2].toLowerCase() + withoutDashes.slice(3) : withoutDashes;
1690
1726
  return {
1691
1727
  resolvedName,
1692
1728
  withoutDashes,
1693
- isNegated: defaultIsNegated && !suppressDefaultNegation,
1694
- isGlobal: !suppressDefaultNegation && (lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName)),
1695
- isSuppressedNegation: suppressDefaultNegation
1729
+ isNegated,
1730
+ isGlobal: lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName),
1731
+ isSuppressedNegation: false
1696
1732
  };
1697
1733
  }
1698
1734
  /**
@@ -1808,6 +1844,7 @@ function findFirstPositionalIndex(argv, globalExtracted) {
1808
1844
  const lookup = globalExtracted ? buildGlobalFlagLookup(globalExtracted) : {
1809
1845
  aliasMap: /* @__PURE__ */ new Map(),
1810
1846
  booleanFlags: /* @__PURE__ */ new Set(),
1847
+ definedNames: /* @__PURE__ */ new Set(),
1811
1848
  flagNames: /* @__PURE__ */ new Set(),
1812
1849
  cliNames: /* @__PURE__ */ new Set(),
1813
1850
  aliases: /* @__PURE__ */ new Set(),
@@ -1875,6 +1912,7 @@ function parseArgs(argv, command, options = {}) {
1875
1912
  remainingArgs: scanResult.tokensAfterSubcommand,
1876
1913
  rawArgs: {},
1877
1914
  positionals: [],
1915
+ rest: [],
1878
1916
  unknownFlags: scanResult.suppressedTokens,
1879
1917
  rawGlobalArgs
1880
1918
  };
@@ -1889,6 +1927,7 @@ function parseArgs(argv, command, options = {}) {
1889
1927
  remainingArgs: argv.slice(1),
1890
1928
  rawArgs: {},
1891
1929
  positionals: [],
1930
+ rest: [],
1892
1931
  unknownFlags: []
1893
1932
  };
1894
1933
  }
@@ -1920,6 +1959,7 @@ function parseArgs(argv, command, options = {}) {
1920
1959
  remainingArgs: [],
1921
1960
  rawArgs: {},
1922
1961
  positionals: [],
1962
+ rest: [],
1923
1963
  unknownFlags: []
1924
1964
  };
1925
1965
  let commandArgv = argv;
@@ -1929,17 +1969,21 @@ function parseArgs(argv, command, options = {}) {
1929
1969
  commandArgv = separated;
1930
1970
  rawGlobalArgs = globalParsed;
1931
1971
  }
1932
- if (!extracted) return {
1933
- helpRequested: false,
1934
- helpAllRequested: false,
1935
- versionRequested: false,
1936
- subCommand: void 0,
1937
- remainingArgs: [],
1938
- rawArgs: {},
1939
- positionals: [],
1940
- unknownFlags: [],
1941
- rawGlobalArgs
1942
- };
1972
+ if (!extracted) {
1973
+ const ddIdx = commandArgv.indexOf("--");
1974
+ return {
1975
+ helpRequested: false,
1976
+ helpAllRequested: false,
1977
+ versionRequested: false,
1978
+ subCommand: void 0,
1979
+ remainingArgs: [],
1980
+ rawArgs: {},
1981
+ positionals: ddIdx >= 0 ? commandArgv.slice(0, ddIdx) : commandArgv,
1982
+ rest: ddIdx >= 0 ? commandArgv.slice(ddIdx + 1) : [],
1983
+ unknownFlags: [],
1984
+ rawGlobalArgs
1985
+ };
1986
+ }
1943
1987
  const parserOptions = buildParserOptions(extracted);
1944
1988
  const parsed = parseArgv(commandArgv, parserOptions);
1945
1989
  const rawArgs = mergeWithPositionals(parsed, extracted);
@@ -1972,6 +2016,7 @@ function parseArgs(argv, command, options = {}) {
1972
2016
  remainingArgs: [],
1973
2017
  rawArgs,
1974
2018
  positionals: parsed.positionals,
2019
+ rest: parsed.rest,
1975
2020
  unknownFlags,
1976
2021
  extractedFields: extracted,
1977
2022
  rawGlobalArgs
@@ -2161,7 +2206,8 @@ var runner_exports = /* @__PURE__ */ __exportAll({
2161
2206
  */
2162
2207
  const defaultLogger = {
2163
2208
  log: (message) => console.log(message),
2164
- error: (message) => console.error(message)
2209
+ error: (message) => console.error(message),
2210
+ warn: (message) => console.warn(message)
2165
2211
  };
2166
2212
  /**
2167
2213
  * Run a command with the given arguments (programmatic/test usage)
@@ -2308,7 +2354,7 @@ async function runMain(command, options = {}) {
2308
2354
  effectiveOptions = rest;
2309
2355
  }
2310
2356
  const globalExtracted = extractAndValidateGlobal(effectiveOptions);
2311
- if (effectiveOptions.onUnknownSubcommand && !isInternalSubcommandInvocation(command, argv, globalExtractedForBypass)) {
2357
+ if (effectiveOptions.onUnknownSubcommand && !command.run && !isInternalSubcommandInvocation(command, argv, globalExtractedForBypass)) {
2312
2358
  const knownSubCommands = listSubCommandNamesWithAliases(command);
2313
2359
  if (knownSubCommands.size > 0) {
2314
2360
  const positionalIndex = findFirstPositionalIndex(argv, globalExtracted);
@@ -2401,7 +2447,7 @@ async function runCommandInternal(command, argv, options = {}) {
2401
2447
  ...parseResult.rawGlobalArgs
2402
2448
  };
2403
2449
  const nestedCommandPath = context.commandPath ?? [];
2404
- if (options.onUnknownSubcommand && nestedCommandPath.length > 0) {
2450
+ if (options.onUnknownSubcommand && !command.run && nestedCommandPath.length > 0) {
2405
2451
  const knownSubCommands = listSubCommandNamesWithAliases(command);
2406
2452
  if (knownSubCommands.size > 0) {
2407
2453
  const positionalIndex = findFirstPositionalIndex(argv, options._globalExtracted);
@@ -2516,7 +2562,12 @@ async function runCommandInternal(command, argv, options = {}) {
2516
2562
  });
2517
2563
  }
2518
2564
  }
2519
- if (listSubCommands(command).length > 0 && !parseResult.subCommand && !command.run) {
2565
+ const positionalFields = parseResult.extractedFields?.fields.filter((f) => f.positional) ?? [];
2566
+ const hasArrayPositional = positionalFields.some((f) => f.type === "array");
2567
+ const allPositionals = [...parseResult.positionals, ...parseResult.rest];
2568
+ const extraPositionals = hasArrayPositional ? [] : allPositionals.slice(positionalFields.length);
2569
+ const unconsumedRegulars = hasArrayPositional ? [] : parseResult.positionals.slice(positionalFields.length);
2570
+ if (listSubCommands(command).length > 0 && !parseResult.subCommand && !command.run && extraPositionals.length === 0) {
2520
2571
  const help = generateHelp(command, {
2521
2572
  showSubcommands: options.showSubcommands ?? true,
2522
2573
  context
@@ -2543,6 +2594,33 @@ async function runCommandInternal(command, argv, options = {}) {
2543
2594
  };
2544
2595
  } else if (unknownKeysMode === "strip") for (const flag of parseResult.unknownFlags) logger.error(formatUnknownFlagWarning(flag, knownFlags));
2545
2596
  }
2597
+ if (extraPositionals.length > 0) {
2598
+ const subCmdNames = listSubCommandNamesWithAliases(command);
2599
+ if (subCmdNames.size > 0) {
2600
+ const unknownCmd = unconsumedRegulars.find((t) => !t.startsWith("-") && !subCmdNames.has(t));
2601
+ if (unknownCmd) {
2602
+ const similar = findSimilar(unknownCmd, [...subCmdNames]);
2603
+ const suggestion = similar.length > 0 ? ` Did you mean: ${similar.join(", ")}?` : "";
2604
+ collector?.stop();
2605
+ return {
2606
+ success: false,
2607
+ error: /* @__PURE__ */ new Error(`Unknown subcommand: ${unknownCmd}${suggestion ? `.${suggestion}` : ""}`),
2608
+ exitCode: 1,
2609
+ logs: getCurrentLogs()
2610
+ };
2611
+ }
2612
+ }
2613
+ const unknownKeysMode = parseResult.extractedFields?.unknownKeysMode ?? "strip";
2614
+ if (unknownKeysMode === "strict") {
2615
+ collector?.stop();
2616
+ return {
2617
+ success: false,
2618
+ error: /* @__PURE__ */ new Error(`Unexpected positional argument${extraPositionals.length > 1 ? "s" : ""}: ${extraPositionals.join(", ")}`),
2619
+ exitCode: 1,
2620
+ logs: getCurrentLogs()
2621
+ };
2622
+ } else if (unknownKeysMode === "strip") for (const positional of extraPositionals) (logger.warn ?? logger.error)(`Warning: Unexpected positional argument: ${positional}`);
2623
+ }
2546
2624
  let validatedGlobalArgs = {};
2547
2625
  const isCompletionInvocation = command.name === "__complete";
2548
2626
  if (options.globalArgs && options._globalExtracted && !isCompletionInvocation) {
@@ -2649,4 +2727,4 @@ function extractAndValidateGlobal(options) {
2649
2727
 
2650
2728
  //#endregion
2651
2729
  export { renderMarkdown as C, renderInline as S, DuplicateFieldError as _, parseArgv as a, ReservedAliasError as b, validateCommand as c, validateDuplicateFields as d, validateDuplicateNegations as f, DuplicateAliasError as g, CaseVariantCollisionError as h, formatValidationErrors as i, validateCrossSchemaCollisions as l, validateReservedAliases as m, runMain as n, formatCommandValidationErrors as o, validatePositionalConfig as p, runner_exports as r, validateCaseVariantCollisions as s, runCommand as t, validateDuplicateAliases as u, DuplicateNegationError as v, createDualCaseProxy as w, generateHelp as x, PositionalConfigError as y };
2652
- //# sourceMappingURL=runner-BmWR9TLM.js.map
2730
+ //# sourceMappingURL=runner-BCMB67GV.js.map
@@ -1,4 +1,4 @@
1
- import { _ as AnyCommand } from "../arg-registry-DDJpsUea.js";
1
+ import { _ as AnyCommand } from "../arg-registry-BN3I-XON.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/skill/frontmatter.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "politty",
3
- "version": "0.9.2",
3
+ "version": "0.10.1",
4
4
  "description": "A lightweight CLI framework inspired by citty with zod v4 registry integration for type-safe metadata management",
5
5
  "keywords": [
6
6
  "argument-parser",
@@ -69,18 +69,18 @@
69
69
  "@inquirer/prompts": "8.5.2",
70
70
  "@quansync/fs": "1.0.0",
71
71
  "@types/node": "25.9.3",
72
- "@typescript/native-preview": "7.0.0-dev.20260611.2",
73
- "@vitest/coverage-v8": "4.1.8",
74
- "knip": "6.16.1",
72
+ "@typescript/native-preview": "7.0.0-dev.20260617.2",
73
+ "@vitest/coverage-v8": "4.1.9",
74
+ "knip": "6.17.1",
75
75
  "lefthook": "2.1.9",
76
76
  "organize-imports-cli": "1.0.2",
77
- "oxfmt": "0.54.0",
78
- "oxlint": "1.69.0",
77
+ "oxfmt": "0.55.0",
78
+ "oxlint": "1.70.0",
79
79
  "quansync": "1.0.0",
80
- "tsdown": "0.22.2",
80
+ "tsdown": "0.22.3",
81
81
  "tsx": "4.22.4",
82
82
  "typescript": "6.0.3",
83
- "vitest": "4.1.8",
83
+ "vitest": "4.1.9",
84
84
  "zod": "4.4.3"
85
85
  },
86
86
  "peerDependencies": {