Skip to content

Commit c46ee68

Browse files
committed
lint
1 parent d773928 commit c46ee68

File tree

6 files changed

+109
-93
lines changed

6 files changed

+109
-93
lines changed

demo.cac.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
1-
import cac from "cac";
2-
import tab from "./src/cac";
1+
import cac from 'cac';
2+
import tab from './src/cac';
33

4-
const cli = cac("vite");
4+
const cli = cac('vite');
55

66
cli
7-
.option("-c, --config <file>", `Use specified config file`)
8-
.option("-m, --mode <mode>", `Set env mode`)
9-
.option("-l, --logLevel <level>", `info | warn | error | silent`);
7+
.option('-c, --config <file>', `Use specified config file`)
8+
.option('-m, --mode <mode>', `Set env mode`)
9+
.option('-l, --logLevel <level>', `info | warn | error | silent`);
1010

1111
cli
12-
.command("dev", "Start dev server")
13-
.option("--host [host]", `Specify hostname`)
14-
.option("--port <port>", `Specify port`)
12+
.command('dev', 'Start dev server')
13+
.option('--host [host]', `Specify hostname`)
14+
.option('--port <port>', `Specify port`)
1515
.action((options) => {});
1616

17-
cli
18-
.command("dev build", "Build project")
19-
.action((options) => {});
17+
cli.command('dev build', 'Build project').action((options) => {});
2018

21-
cli
22-
.command("lint [...files]", "Lint project")
23-
.action((files, options) => {});
19+
cli.command('lint [...files]', 'Lint project').action((files, options) => {});
2420

2521
const completion = await tab(cli);
2622

demo.citty.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ const devCommand = defineCommand({
3131
host: { type: 'string', description: 'Specify hostname' },
3232
port: { type: 'string', description: 'Specify port' },
3333
},
34-
run(ctx) {
35-
},
34+
run(ctx) {},
3635
});
3736

3837
devCommand.subCommands = {
@@ -53,8 +52,7 @@ const lintCommand = defineCommand({
5352
args: {
5453
files: { type: 'positional', description: 'Files to lint' },
5554
},
56-
run(ctx) {
57-
},
55+
run(ctx) {},
5856
});
5957

6058
main.subCommands = {
@@ -65,7 +63,6 @@ main.subCommands = {
6563
const completion = await tab(main);
6664

6765
for (const command of completion.commands.values()) {
68-
6966
if (command.name === 'lint') {
7067
command.handler = () => {
7168
return [

index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
export * from './src/index';
2-
export * from './src/citty';
3-
export * from './src/cac';
1+
export * from './src/index';
2+
export * from './src/citty';
3+
export * from './src/cac';

src/cac.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
import * as zsh from "./zsh";
2-
import * as bash from "./bash";
3-
import * as fish from "./fish";
4-
import * as powershell from "./powershell";
5-
import type { CAC } from "cac";
6-
import { Completion } from "./";
1+
import * as zsh from './zsh';
2+
import * as bash from './bash';
3+
import * as fish from './fish';
4+
import * as powershell from './powershell';
5+
import type { CAC } from 'cac';
6+
import { Completion } from './';
77

88
const execPath = process.execPath;
99
const processArgs = process.argv.slice(1);
1010
const quotedExecPath = quoteIfNeeded(execPath);
1111
const quotedProcessArgs = processArgs.map(quoteIfNeeded);
1212
const quotedProcessExecArgs = process.execArgv.map(quoteIfNeeded);
1313

14-
const x = `${quotedExecPath} ${quotedProcessExecArgs.join(" ")} ${quotedProcessArgs[0]}`;
14+
const x = `${quotedExecPath} ${quotedProcessExecArgs.join(' ')} ${quotedProcessArgs[0]}`;
1515

1616
function quoteIfNeeded(path: string): string {
17-
return path.includes(" ") ? `'${path}'` : path;
17+
return path.includes(' ') ? `'${path}'` : path;
1818
}
1919

2020
// export default function tab(instance: CAC): void {
@@ -300,8 +300,9 @@ export default function tab(instance: CAC): Completion {
300300
if (cmd.name === 'complete') continue; // Skip completion command
301301

302302
// Get positional args info from command usage
303-
const args = (cmd.rawName.match(/\[.*?\]|\<.*?\>/g) || [])
304-
.map(arg => arg.startsWith('[')); // true if optional (wrapped in [])
303+
const args = (cmd.rawName.match(/\[.*?\]|\<.*?\>/g) || []).map((arg) =>
304+
arg.startsWith('[')
305+
); // true if optional (wrapped in [])
305306

306307
// Add command to completion
307308
const commandName = completion.addCommand(
@@ -322,30 +323,30 @@ export default function tab(instance: CAC): Completion {
322323
}
323324
}
324325

325-
instance.command("complete [shell]").action(async (shell, extra) => {
326+
instance.command('complete [shell]').action(async (shell, extra) => {
326327
switch (shell) {
327-
case "zsh": {
328+
case 'zsh': {
328329
const script = zsh.generate(instance.name, x);
329330
console.log(script);
330331
break;
331332
}
332-
case "bash": {
333+
case 'bash': {
333334
const script = bash.generate(instance.name, x);
334335
console.log(script);
335336
break;
336337
}
337-
case "fish": {
338+
case 'fish': {
338339
const script = fish.generate(instance.name, x);
339340
console.log(script);
340341
break;
341342
}
342-
case "powershell": {
343+
case 'powershell': {
343344
const script = powershell.generate(instance.name, x);
344345
console.log(script);
345346
break;
346347
}
347348
default: {
348-
const args: string[] = extra["--"];
349+
const args: string[] = extra['--'];
349350
instance.showHelpOnExit = false;
350351

351352
// Parse current command context
@@ -363,4 +364,4 @@ export default function tab(instance: CAC): Completion {
363364
});
364365

365366
return completion;
366-
}
367+
}

src/index.ts

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ type Option = {
8080
type Command = {
8181
name: string;
8282
description: string;
83-
args: boolean[]
83+
args: boolean[];
8484
handler: Handler;
8585
options: Map<string, Option>;
8686
parent?: Command;
8787
};
8888

8989
export class Completion {
9090
commands = new Map<string, Command>();
91-
completions: Item[] = []
91+
completions: Item[] = [];
9292
directive = ShellCompDirective.ShellCompDirectiveDefault;
9393

9494
// vite <entry> <another> [...files]
@@ -129,37 +129,37 @@ export class Completion {
129129

130130
// TODO: this should be aware of boolean args and stuff
131131
private stripOptions(args: string[]): string[] {
132-
const parts: string[] = []
132+
const parts: string[] = [];
133133
let option = false;
134134
for (const k of args) {
135135
if (k.startsWith('-')) {
136136
option = true;
137-
continue
137+
continue;
138138
}
139139
if (option) {
140140
option = false;
141-
continue
141+
continue;
142142
}
143-
parts.push(k)
143+
parts.push(k);
144144
}
145-
return parts
145+
return parts;
146146
}
147147

148148
private matchCommand(args: string[]): [Command, string[]] {
149149
args = this.stripOptions(args);
150150
let parts: string[] = [];
151151
let remaining: string[] = [];
152-
let matched: Command = this.commands.get('')!
152+
let matched: Command = this.commands.get('')!;
153153
for (let i = 0; i < args.length; i++) {
154154
const k = args[i];
155155
parts.push(k);
156-
const potential = this.commands.get(parts.join(' '))
157-
156+
const potential = this.commands.get(parts.join(' '));
157+
158158
if (potential) {
159159
matched = potential;
160160
} else {
161161
remaining = args.slice(i, args.length);
162-
break
162+
break;
163163
}
164164
}
165165
return [matched, remaining];
@@ -188,31 +188,27 @@ export class Completion {
188188
if (this.shouldCompleteFlags(lastPrevArg, toComplete, endsWithSpace)) {
189189
await this.handleFlagCompletion(
190190
matchedCommand,
191-
previousArgs,
191+
previousArgs,
192192
toComplete,
193193
endsWithSpace,
194-
lastPrevArg,
194+
lastPrevArg
195195
);
196-
}
197-
else {
196+
} else {
198197
// 2. Handle command/subcommand completion
199198
if (this.shouldCompleteCommands(toComplete, endsWithSpace)) {
200-
await this.handleCommandCompletion(
201-
previousArgs,
202-
toComplete,
203-
);
199+
await this.handleCommandCompletion(previousArgs, toComplete);
204200
}
205201
// 3. Handle positional arguments
206202
if (matchedCommand && matchedCommand.args.length > 0) {
207203
await this.handlePositionalCompletion(
208204
matchedCommand,
209205
previousArgs,
210206
toComplete,
211-
endsWithSpace,
207+
endsWithSpace
212208
);
213209
}
214210
}
215-
this.complete(toComplete)
211+
this.complete(toComplete);
216212
}
217213

218214
private complete(toComplete: string) {
@@ -226,24 +222,33 @@ export class Completion {
226222
return true;
227223
})
228224
.filter((comp) => comp.value.startsWith(toComplete))
229-
.forEach((comp) => console.log(`${comp.value}\t${comp.description ?? ''}`));
225+
.forEach((comp) =>
226+
console.log(`${comp.value}\t${comp.description ?? ''}`)
227+
);
230228
console.log(`:${this.directive}`);
231229
}
232230

233-
private shouldCompleteFlags(lastPrevArg: string | undefined, toComplete: string, endsWithSpace: boolean): boolean {
234-
return (lastPrevArg?.startsWith('--')) || toComplete.startsWith('--');
231+
private shouldCompleteFlags(
232+
lastPrevArg: string | undefined,
233+
toComplete: string,
234+
endsWithSpace: boolean
235+
): boolean {
236+
return lastPrevArg?.startsWith('--') || toComplete.startsWith('--');
235237
}
236238

237-
private shouldCompleteCommands(toComplete: string, endsWithSpace: boolean): boolean {
239+
private shouldCompleteCommands(
240+
toComplete: string,
241+
endsWithSpace: boolean
242+
): boolean {
238243
return !toComplete.startsWith('-');
239244
}
240245

241246
private async handleFlagCompletion(
242247
command: Command,
243-
previousArgs: string[],
248+
previousArgs: string[],
244249
toComplete: string,
245250
endsWithSpace: boolean,
246-
lastPrevArg: string | undefined,
251+
lastPrevArg: string | undefined
247252
) {
248253
// Handle flag value completion
249254
let flagName: string | undefined;
@@ -262,12 +267,16 @@ export class Completion {
262267
if (flagName) {
263268
const option = command.options.get(flagName);
264269
if (option) {
265-
const suggestions = await option.handler(previousArgs, valueToComplete, endsWithSpace);
270+
const suggestions = await option.handler(
271+
previousArgs,
272+
valueToComplete,
273+
endsWithSpace
274+
);
266275
if (toComplete.includes('=')) {
267276
// Reconstruct the full flag=value format
268-
this.completions = suggestions.map(suggestion => ({
277+
this.completions = suggestions.map((suggestion) => ({
269278
value: `${flagName}=${suggestion.value}`,
270-
description: suggestion.description
279+
description: suggestion.description,
271280
}));
272281
} else {
273282
this.completions.push(...suggestions);
@@ -282,7 +291,7 @@ export class Completion {
282291
if (name.startsWith(toComplete)) {
283292
this.completions.push({
284293
value: name,
285-
description: option.description
294+
description: option.description,
286295
});
287296
}
288297
}
@@ -291,27 +300,27 @@ export class Completion {
291300

292301
private async handleCommandCompletion(
293302
previousArgs: string[],
294-
toComplete: string,
303+
toComplete: string
295304
) {
296305
const commandParts = [...previousArgs];
297306

298307
for (const k of this.commands.keys()) {
299308
if (k === '') continue;
300309
const parts = k.split(' ');
301310
let match = true;
302-
311+
303312
let i = 0;
304313
while (i < commandParts.length) {
305314
if (parts[i] !== commandParts[i]) {
306315
match = false;
307-
break
316+
break;
308317
}
309318
i++;
310319
}
311320
if (match && parts[i]?.startsWith(toComplete)) {
312321
this.completions.push({
313322
value: parts[i],
314-
description: this.commands.get(k)!.description
323+
description: this.commands.get(k)!.description,
315324
});
316325
}
317326
}
@@ -321,9 +330,13 @@ export class Completion {
321330
command: Command,
322331
previousArgs: string[],
323332
toComplete: string,
324-
endsWithSpace: boolean,
333+
endsWithSpace: boolean
325334
) {
326-
const suggestions = await command.handler(previousArgs, toComplete, endsWithSpace);
335+
const suggestions = await command.handler(
336+
previousArgs,
337+
toComplete,
338+
endsWithSpace
339+
);
327340
this.completions.push(...suggestions);
328341
}
329342
}

0 commit comments

Comments
 (0)