@optique/core 0.1.0-dev.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.
package/dist/usage.cjs ADDED
@@ -0,0 +1,242 @@
1
+
2
+ //#region src/usage.ts
3
+ /**
4
+ * Formats a usage description into a human-readable string representation
5
+ * suitable for command-line help text.
6
+ *
7
+ * This function converts a structured {@link Usage} description into a
8
+ * formatted string that follows common CLI conventions. It supports various
9
+ * formatting options including colors and compact option display.
10
+ * @param programName The name of the program or command for which the usage
11
+ * description is being formatted. This is typically the
12
+ * name of the executable or script that the user will run.
13
+ * @param usage The usage description to format, consisting of an array
14
+ * of usage terms representing the command-line structure.
15
+ * @param options Optional formatting options to customize the output.
16
+ * See {@link UsageFormatOptions} for available options.
17
+ * @returns A formatted string representation of the usage description.
18
+ */
19
+ function formatUsage(programName, usage, options = {}) {
20
+ usage = normalizeUsage(usage);
21
+ if (options.expandCommands) {
22
+ const lastTerm = usage.at(-1);
23
+ if (usage.length > 0 && usage.slice(0, -1).every((t) => t.type === "command") && lastTerm.type === "exclusive" && lastTerm.terms.every((t) => t.length > 0 && (t[0].type === "command" || t[0].type === "option" || t[0].type === "argument" || t[0].type === "optional" && t[0].terms.length === 1 && (t[0].terms[0].type === "command" || t[0].terms[0].type === "option" || t[0].terms[0].type === "argument")))) {
24
+ const lines = [];
25
+ for (let command of lastTerm.terms) {
26
+ if (usage.length > 1) command = [...usage.slice(0, -1), ...command];
27
+ lines.push(formatUsage(programName, command, options));
28
+ }
29
+ return lines.join("\n");
30
+ }
31
+ }
32
+ let output = options.colors ? `\x1b[1m${programName}\x1b[0m ` : `${programName} `;
33
+ let lineWidth = programName.length + 1;
34
+ for (const { text, width } of formatUsageTerms(usage, options)) {
35
+ if (options.maxWidth != null && lineWidth + width > options.maxWidth) {
36
+ output += "\n";
37
+ lineWidth = 0;
38
+ if (text === " ") continue;
39
+ }
40
+ output += text;
41
+ lineWidth += width;
42
+ }
43
+ return output;
44
+ }
45
+ /**
46
+ * Normalizes a usage description by flattening nested exclusive terms,
47
+ * sorting terms for better readability, and ensuring consistent structure
48
+ * throughout the usage tree.
49
+ *
50
+ * This function performs two main operations:
51
+ *
52
+ * 1. *Flattening*: Recursively processes all usage terms and merges any
53
+ * nested exclusive terms into their parent exclusive term to avoid
54
+ * redundant nesting. For example, an exclusive term containing another
55
+ * exclusive term will have its nested terms flattened into the parent.
56
+ *
57
+ * 2. *Sorting*: Reorders terms to improve readability by placing:
58
+ * - Commands (subcommands) first
59
+ * - Options and other terms in the middle
60
+ * - Positional arguments last (including optional/multiple wrappers around
61
+ * arguments)
62
+ *
63
+ * The sorting logic also recognizes when optional or multiple terms contain
64
+ * positional arguments and treats them as arguments for sorting purposes.
65
+ *
66
+ * @param usage The usage description to normalize.
67
+ * @returns A normalized usage description with flattened exclusive terms
68
+ * and terms sorted for optimal readability.
69
+ */
70
+ function normalizeUsage(usage) {
71
+ const terms = usage.map(normalizeUsageTerm);
72
+ terms.sort((a, b) => {
73
+ const aCmd = a.type === "command";
74
+ const bCmd = b.type === "command";
75
+ const aArg = a.type === "argument" || (a.type === "optional" || a.type === "multiple") && a.terms.at(-1)?.type === "argument";
76
+ const bArg = b.type === "argument" || (b.type === "optional" || b.type === "multiple") && b.terms.at(-1)?.type === "argument";
77
+ return aCmd === bCmd ? aArg === bArg ? 0 : aArg ? 1 : -1 : aCmd ? -1 : 1;
78
+ });
79
+ return terms;
80
+ }
81
+ function normalizeUsageTerm(term) {
82
+ if (term.type === "optional") return {
83
+ type: "optional",
84
+ terms: normalizeUsage(term.terms)
85
+ };
86
+ else if (term.type === "multiple") return {
87
+ type: "multiple",
88
+ terms: normalizeUsage(term.terms),
89
+ min: term.min
90
+ };
91
+ else if (term.type === "exclusive") {
92
+ const terms = [];
93
+ for (const usage of term.terms) {
94
+ const normalized = normalizeUsage(usage);
95
+ if (normalized.length === 1 && normalized[0].type === "exclusive") for (const subUsage of normalized[0].terms) terms.push(subUsage);
96
+ else terms.push(normalized);
97
+ }
98
+ return {
99
+ type: "exclusive",
100
+ terms
101
+ };
102
+ } else return term;
103
+ }
104
+ function* formatUsageTerms(terms, options) {
105
+ let i = 0;
106
+ for (const t of terms) {
107
+ if (i > 0) yield {
108
+ text: " ",
109
+ width: 1
110
+ };
111
+ yield* formatUsageTermInternal(t, options);
112
+ i++;
113
+ }
114
+ }
115
+ /**
116
+ * Formats a single {@link UsageTerm} into a string representation
117
+ * suitable for command-line help text.
118
+ * @param term The usage term to format, which can be an argument,
119
+ * option, command, optional term, exclusive term, or multiple term.
120
+ * @param options Optional formatting options to customize the output.
121
+ * See {@link UsageTermFormatOptions} for available options.
122
+ * @returns A formatted string representation of the usage term.
123
+ */
124
+ function formatUsageTerm(term, options = {}) {
125
+ let lineWidth = 0;
126
+ let output = "";
127
+ for (const { text, width } of formatUsageTermInternal(term, options)) {
128
+ if (options.maxWidth != null && lineWidth + width > options.maxWidth) {
129
+ output += "\n";
130
+ lineWidth = 0;
131
+ if (text === " ") continue;
132
+ }
133
+ output += text;
134
+ lineWidth += width;
135
+ }
136
+ return output;
137
+ }
138
+ function* formatUsageTermInternal(term, options) {
139
+ const optionsSeparator = options.optionsSeparator ?? "/";
140
+ if (term.type === "argument") yield {
141
+ text: options?.colors ? `\x1b[4m${term.metavar}\x1b[0m` : term.metavar,
142
+ width: term.metavar.length
143
+ };
144
+ else if (term.type === "option") if (options?.onlyShortestOptions) {
145
+ const shortestName = term.names.reduce((a, b) => a.length <= b.length ? a : b);
146
+ yield {
147
+ text: options?.colors ? `\x1b[3m${shortestName}\x1b[0m` : shortestName,
148
+ width: shortestName.length
149
+ };
150
+ } else {
151
+ let i = 0;
152
+ for (const optionName of term.names) {
153
+ if (i > 0) yield {
154
+ text: options?.colors ? `\x1b[2m${optionsSeparator}\x1b[0m` : optionsSeparator,
155
+ width: optionsSeparator.length
156
+ };
157
+ yield {
158
+ text: options?.colors ? `\x1b[3m${optionName}\x1b[0m` : optionName,
159
+ width: optionName.length
160
+ };
161
+ i++;
162
+ }
163
+ if (term.metavar != null) {
164
+ yield {
165
+ text: " ",
166
+ width: 1
167
+ };
168
+ yield {
169
+ text: options?.colors ? `\x1b[4m\x1b[2m${term.metavar}\x1b[0m` : term.metavar,
170
+ width: term.metavar.length
171
+ };
172
+ }
173
+ }
174
+ else if (term.type === "command") yield {
175
+ text: options?.colors ? `\x1b[1m${term.name}\x1b[0m` : term.name,
176
+ width: term.name.length
177
+ };
178
+ else if (term.type === "optional") {
179
+ yield {
180
+ text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
181
+ width: 1
182
+ };
183
+ yield* formatUsageTerms(term.terms, options);
184
+ yield {
185
+ text: options?.colors ? `\x1b[2m]\x1b[0m` : "]",
186
+ width: 1
187
+ };
188
+ } else if (term.type === "exclusive") {
189
+ yield {
190
+ text: options?.colors ? `\x1b[2m(\x1b[0m` : "(",
191
+ width: 1
192
+ };
193
+ let i = 0;
194
+ for (const termGroup of term.terms) {
195
+ if (i > 0) {
196
+ yield {
197
+ text: " ",
198
+ width: 1
199
+ };
200
+ yield {
201
+ text: "|",
202
+ width: 1
203
+ };
204
+ yield {
205
+ text: " ",
206
+ width: 1
207
+ };
208
+ }
209
+ yield* formatUsageTerms(termGroup, options);
210
+ i++;
211
+ }
212
+ yield {
213
+ text: options?.colors ? `\x1b[2m)\x1b[0m` : ")",
214
+ width: 1
215
+ };
216
+ } else if (term.type === "multiple") {
217
+ if (term.min < 1) yield {
218
+ text: options?.colors ? `\x1b[2m[\x1b[0m` : "[",
219
+ width: 1
220
+ };
221
+ for (let i = 0; i < Math.max(1, term.min); i++) {
222
+ if (i > 0) yield {
223
+ text: " ",
224
+ width: 1
225
+ };
226
+ yield* formatUsageTerms(term.terms, options);
227
+ }
228
+ yield {
229
+ text: options?.colors ? `\x1b[2m...\x1b[0m` : "...",
230
+ width: 3
231
+ };
232
+ if (term.min < 1) yield {
233
+ text: options?.colors ? `\x1b[2m]\x1b[0m` : "]",
234
+ width: 1
235
+ };
236
+ } else throw new TypeError(`Unknown usage term type: ${term["type"]}.`);
237
+ }
238
+
239
+ //#endregion
240
+ exports.formatUsage = formatUsage;
241
+ exports.formatUsageTerm = formatUsageTerm;
242
+ exports.normalizeUsage = normalizeUsage;
@@ -0,0 +1,217 @@
1
+ //#region src/usage.d.ts
2
+ /**
3
+ * Represents the name of a command-line option. There are four types of
4
+ * option syntax:
5
+ *
6
+ * - GNU-style long options (`--option`)
7
+ * - POSIX-style short options (`-o`) or Java-style options (`-option`)
8
+ * - MS-DOS-style options (`/o`, `/option`)
9
+ * - Plus-prefixed options (`+o`)
10
+ */
11
+ type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
12
+ /**
13
+ * Represents a single term in a command-line usage description.
14
+ */
15
+ type UsageTerm =
16
+ /**
17
+ * An argument term, which represents a positional argument in
18
+ * the command-line usage.
19
+ */
20
+ {
21
+ /**
22
+ * The type of the term, which is always `"argument"` for this term.
23
+ */
24
+ readonly type: "argument";
25
+ /**
26
+ * The name of the argument, which is used to identify it in
27
+ * the command-line usage.
28
+ */
29
+ readonly metavar: string;
30
+ }
31
+ /**
32
+ * An option term, which represents a command-line option that can
33
+ * be specified by the user.
34
+ */ | {
35
+ /**
36
+ * The type of the term, which is always `"option"` for this term.
37
+ */
38
+ readonly type: "option";
39
+ /**
40
+ * The names of the option, which can include multiple
41
+ * short and long forms.
42
+ */
43
+ readonly names: readonly OptionName[];
44
+ /**
45
+ * An optional metavariable name for the option, which is used
46
+ * to indicate what value the option expects.
47
+ */
48
+ readonly metavar?: string;
49
+ }
50
+ /**
51
+ * A command term, which represents a subcommand in the command-line
52
+ * usage.
53
+ */ | {
54
+ /**
55
+ * The type of the term, which is always `"command"` for this term.
56
+ */
57
+ readonly type: "command";
58
+ /**
59
+ * The name of the command, which is used to identify it
60
+ * in the command-line usage.
61
+ */
62
+ readonly name: string;
63
+ }
64
+ /**
65
+ * An optional term, which represents an optional component
66
+ * in the command-line usage.
67
+ */ | {
68
+ /**
69
+ * The type of the term, which is always `"optional"` for this term.
70
+ */
71
+ readonly type: "optional";
72
+ /**
73
+ * The terms that are optional, which can be an argument, an option,
74
+ * a command, or another usage term.
75
+ */
76
+ readonly terms: Usage;
77
+ }
78
+ /**
79
+ * A term of multiple occurrences, which allows a term to be specified
80
+ * multiple times in the command-line usage.
81
+ */ | {
82
+ /**
83
+ * The type of the term, which is always `"multiple"` for this term.
84
+ */
85
+ readonly type: "multiple";
86
+ /**
87
+ * The terms that can occur multiple times, which can be an argument,
88
+ * an option, a command, or another usage term.
89
+ */
90
+ readonly terms: Usage;
91
+ /**
92
+ * The minimum number of times the term must occur.
93
+ */
94
+ readonly min: number;
95
+ } |
96
+ /**
97
+ * An exclusive term, which represents a group of terms that are mutually
98
+ * exclusive, meaning that only one of the terms in the group can be
99
+ * specified at a time.
100
+ */
101
+ {
102
+ /**
103
+ * The type of the term, which is always `"exclusive"` for this term.
104
+ */
105
+ readonly type: "exclusive";
106
+ /**
107
+ * The terms that are mutually exclusive, which can include
108
+ * arguments, options, commands, or other usage terms.
109
+ */
110
+ readonly terms: readonly Usage[];
111
+ };
112
+ /**
113
+ * Represents a command-line usage description, which is a sequence of
114
+ * {@link UsageTerm} objects. This type is used to describe how a command-line
115
+ * parser expects its input to be structured, including the required and
116
+ * optional components, as well as any exclusive groups of terms.
117
+ */
118
+ type Usage = readonly UsageTerm[];
119
+ /**
120
+ * Options for formatting usage descriptions.
121
+ */
122
+ interface UsageFormatOptions {
123
+ /**
124
+ * When `true`, expands commands in the usage description
125
+ * to multiple lines, showing each command on a new line.
126
+ * This is useful for commands with many subcommands, making it easier
127
+ * to read and understand the available commands.
128
+ * @default `false`
129
+ */
130
+ readonly expandCommands?: boolean;
131
+ /**
132
+ * When `true`, only shows the shortest option name for each option
133
+ * instead of showing all aliases separated by `/`.
134
+ * For example, `--verbose/-v` becomes just `-v`.
135
+ * @default `false`
136
+ */
137
+ readonly onlyShortestOptions?: boolean;
138
+ /**
139
+ * When `true`, applies ANSI color codes to the output for better readability.
140
+ * Different elements (options, arguments, commands, etc.) will be styled
141
+ * with different colors and formatting.
142
+ * @default `false`
143
+ */
144
+ readonly colors?: boolean;
145
+ /**
146
+ * The maximum width of the formatted output. If specified, the output
147
+ * will be wrapped to fit within this width, breaking lines as necessary.
148
+ * If not specified, the output will not be wrapped.
149
+ * @default `undefined`
150
+ */
151
+ readonly maxWidth?: number;
152
+ }
153
+ /**
154
+ * Formats a usage description into a human-readable string representation
155
+ * suitable for command-line help text.
156
+ *
157
+ * This function converts a structured {@link Usage} description into a
158
+ * formatted string that follows common CLI conventions. It supports various
159
+ * formatting options including colors and compact option display.
160
+ * @param programName The name of the program or command for which the usage
161
+ * description is being formatted. This is typically the
162
+ * name of the executable or script that the user will run.
163
+ * @param usage The usage description to format, consisting of an array
164
+ * of usage terms representing the command-line structure.
165
+ * @param options Optional formatting options to customize the output.
166
+ * See {@link UsageFormatOptions} for available options.
167
+ * @returns A formatted string representation of the usage description.
168
+ */
169
+ declare function formatUsage(programName: string, usage: Usage, options?: UsageFormatOptions): string;
170
+ /**
171
+ * Normalizes a usage description by flattening nested exclusive terms,
172
+ * sorting terms for better readability, and ensuring consistent structure
173
+ * throughout the usage tree.
174
+ *
175
+ * This function performs two main operations:
176
+ *
177
+ * 1. *Flattening*: Recursively processes all usage terms and merges any
178
+ * nested exclusive terms into their parent exclusive term to avoid
179
+ * redundant nesting. For example, an exclusive term containing another
180
+ * exclusive term will have its nested terms flattened into the parent.
181
+ *
182
+ * 2. *Sorting*: Reorders terms to improve readability by placing:
183
+ * - Commands (subcommands) first
184
+ * - Options and other terms in the middle
185
+ * - Positional arguments last (including optional/multiple wrappers around
186
+ * arguments)
187
+ *
188
+ * The sorting logic also recognizes when optional or multiple terms contain
189
+ * positional arguments and treats them as arguments for sorting purposes.
190
+ *
191
+ * @param usage The usage description to normalize.
192
+ * @returns A normalized usage description with flattened exclusive terms
193
+ * and terms sorted for optimal readability.
194
+ */
195
+ declare function normalizeUsage(usage: Usage): Usage;
196
+ /**
197
+ * Options for formatting a single {@link UsageTerm}.
198
+ */
199
+ interface UsageTermFormatOptions extends UsageFormatOptions {
200
+ /**
201
+ * A string that separates multiple option names in the formatted output.
202
+ * @default `"/"`
203
+ */
204
+ readonly optionsSeparator?: string;
205
+ }
206
+ /**
207
+ * Formats a single {@link UsageTerm} into a string representation
208
+ * suitable for command-line help text.
209
+ * @param term The usage term to format, which can be an argument,
210
+ * option, command, optional term, exclusive term, or multiple term.
211
+ * @param options Optional formatting options to customize the output.
212
+ * See {@link UsageTermFormatOptions} for available options.
213
+ * @returns A formatted string representation of the usage term.
214
+ */
215
+ declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
216
+ //#endregion
217
+ export { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, formatUsage, formatUsageTerm, normalizeUsage };
@@ -0,0 +1,217 @@
1
+ //#region src/usage.d.ts
2
+ /**
3
+ * Represents the name of a command-line option. There are four types of
4
+ * option syntax:
5
+ *
6
+ * - GNU-style long options (`--option`)
7
+ * - POSIX-style short options (`-o`) or Java-style options (`-option`)
8
+ * - MS-DOS-style options (`/o`, `/option`)
9
+ * - Plus-prefixed options (`+o`)
10
+ */
11
+ type OptionName = `--${string}` | `-${string}` | `/${string}` | `+${string}`;
12
+ /**
13
+ * Represents a single term in a command-line usage description.
14
+ */
15
+ type UsageTerm =
16
+ /**
17
+ * An argument term, which represents a positional argument in
18
+ * the command-line usage.
19
+ */
20
+ {
21
+ /**
22
+ * The type of the term, which is always `"argument"` for this term.
23
+ */
24
+ readonly type: "argument";
25
+ /**
26
+ * The name of the argument, which is used to identify it in
27
+ * the command-line usage.
28
+ */
29
+ readonly metavar: string;
30
+ }
31
+ /**
32
+ * An option term, which represents a command-line option that can
33
+ * be specified by the user.
34
+ */ | {
35
+ /**
36
+ * The type of the term, which is always `"option"` for this term.
37
+ */
38
+ readonly type: "option";
39
+ /**
40
+ * The names of the option, which can include multiple
41
+ * short and long forms.
42
+ */
43
+ readonly names: readonly OptionName[];
44
+ /**
45
+ * An optional metavariable name for the option, which is used
46
+ * to indicate what value the option expects.
47
+ */
48
+ readonly metavar?: string;
49
+ }
50
+ /**
51
+ * A command term, which represents a subcommand in the command-line
52
+ * usage.
53
+ */ | {
54
+ /**
55
+ * The type of the term, which is always `"command"` for this term.
56
+ */
57
+ readonly type: "command";
58
+ /**
59
+ * The name of the command, which is used to identify it
60
+ * in the command-line usage.
61
+ */
62
+ readonly name: string;
63
+ }
64
+ /**
65
+ * An optional term, which represents an optional component
66
+ * in the command-line usage.
67
+ */ | {
68
+ /**
69
+ * The type of the term, which is always `"optional"` for this term.
70
+ */
71
+ readonly type: "optional";
72
+ /**
73
+ * The terms that are optional, which can be an argument, an option,
74
+ * a command, or another usage term.
75
+ */
76
+ readonly terms: Usage;
77
+ }
78
+ /**
79
+ * A term of multiple occurrences, which allows a term to be specified
80
+ * multiple times in the command-line usage.
81
+ */ | {
82
+ /**
83
+ * The type of the term, which is always `"multiple"` for this term.
84
+ */
85
+ readonly type: "multiple";
86
+ /**
87
+ * The terms that can occur multiple times, which can be an argument,
88
+ * an option, a command, or another usage term.
89
+ */
90
+ readonly terms: Usage;
91
+ /**
92
+ * The minimum number of times the term must occur.
93
+ */
94
+ readonly min: number;
95
+ } |
96
+ /**
97
+ * An exclusive term, which represents a group of terms that are mutually
98
+ * exclusive, meaning that only one of the terms in the group can be
99
+ * specified at a time.
100
+ */
101
+ {
102
+ /**
103
+ * The type of the term, which is always `"exclusive"` for this term.
104
+ */
105
+ readonly type: "exclusive";
106
+ /**
107
+ * The terms that are mutually exclusive, which can include
108
+ * arguments, options, commands, or other usage terms.
109
+ */
110
+ readonly terms: readonly Usage[];
111
+ };
112
+ /**
113
+ * Represents a command-line usage description, which is a sequence of
114
+ * {@link UsageTerm} objects. This type is used to describe how a command-line
115
+ * parser expects its input to be structured, including the required and
116
+ * optional components, as well as any exclusive groups of terms.
117
+ */
118
+ type Usage = readonly UsageTerm[];
119
+ /**
120
+ * Options for formatting usage descriptions.
121
+ */
122
+ interface UsageFormatOptions {
123
+ /**
124
+ * When `true`, expands commands in the usage description
125
+ * to multiple lines, showing each command on a new line.
126
+ * This is useful for commands with many subcommands, making it easier
127
+ * to read and understand the available commands.
128
+ * @default `false`
129
+ */
130
+ readonly expandCommands?: boolean;
131
+ /**
132
+ * When `true`, only shows the shortest option name for each option
133
+ * instead of showing all aliases separated by `/`.
134
+ * For example, `--verbose/-v` becomes just `-v`.
135
+ * @default `false`
136
+ */
137
+ readonly onlyShortestOptions?: boolean;
138
+ /**
139
+ * When `true`, applies ANSI color codes to the output for better readability.
140
+ * Different elements (options, arguments, commands, etc.) will be styled
141
+ * with different colors and formatting.
142
+ * @default `false`
143
+ */
144
+ readonly colors?: boolean;
145
+ /**
146
+ * The maximum width of the formatted output. If specified, the output
147
+ * will be wrapped to fit within this width, breaking lines as necessary.
148
+ * If not specified, the output will not be wrapped.
149
+ * @default `undefined`
150
+ */
151
+ readonly maxWidth?: number;
152
+ }
153
+ /**
154
+ * Formats a usage description into a human-readable string representation
155
+ * suitable for command-line help text.
156
+ *
157
+ * This function converts a structured {@link Usage} description into a
158
+ * formatted string that follows common CLI conventions. It supports various
159
+ * formatting options including colors and compact option display.
160
+ * @param programName The name of the program or command for which the usage
161
+ * description is being formatted. This is typically the
162
+ * name of the executable or script that the user will run.
163
+ * @param usage The usage description to format, consisting of an array
164
+ * of usage terms representing the command-line structure.
165
+ * @param options Optional formatting options to customize the output.
166
+ * See {@link UsageFormatOptions} for available options.
167
+ * @returns A formatted string representation of the usage description.
168
+ */
169
+ declare function formatUsage(programName: string, usage: Usage, options?: UsageFormatOptions): string;
170
+ /**
171
+ * Normalizes a usage description by flattening nested exclusive terms,
172
+ * sorting terms for better readability, and ensuring consistent structure
173
+ * throughout the usage tree.
174
+ *
175
+ * This function performs two main operations:
176
+ *
177
+ * 1. *Flattening*: Recursively processes all usage terms and merges any
178
+ * nested exclusive terms into their parent exclusive term to avoid
179
+ * redundant nesting. For example, an exclusive term containing another
180
+ * exclusive term will have its nested terms flattened into the parent.
181
+ *
182
+ * 2. *Sorting*: Reorders terms to improve readability by placing:
183
+ * - Commands (subcommands) first
184
+ * - Options and other terms in the middle
185
+ * - Positional arguments last (including optional/multiple wrappers around
186
+ * arguments)
187
+ *
188
+ * The sorting logic also recognizes when optional or multiple terms contain
189
+ * positional arguments and treats them as arguments for sorting purposes.
190
+ *
191
+ * @param usage The usage description to normalize.
192
+ * @returns A normalized usage description with flattened exclusive terms
193
+ * and terms sorted for optimal readability.
194
+ */
195
+ declare function normalizeUsage(usage: Usage): Usage;
196
+ /**
197
+ * Options for formatting a single {@link UsageTerm}.
198
+ */
199
+ interface UsageTermFormatOptions extends UsageFormatOptions {
200
+ /**
201
+ * A string that separates multiple option names in the formatted output.
202
+ * @default `"/"`
203
+ */
204
+ readonly optionsSeparator?: string;
205
+ }
206
+ /**
207
+ * Formats a single {@link UsageTerm} into a string representation
208
+ * suitable for command-line help text.
209
+ * @param term The usage term to format, which can be an argument,
210
+ * option, command, optional term, exclusive term, or multiple term.
211
+ * @param options Optional formatting options to customize the output.
212
+ * See {@link UsageTermFormatOptions} for available options.
213
+ * @returns A formatted string representation of the usage term.
214
+ */
215
+ declare function formatUsageTerm(term: UsageTerm, options?: UsageTermFormatOptions): string;
216
+ //#endregion
217
+ export { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, formatUsage, formatUsageTerm, normalizeUsage };