Skip to content

Commit 00e485c

Browse files
committed
huge wip
1 parent 3af114f commit 00e485c

File tree

15 files changed

+1583
-254
lines changed

15 files changed

+1583
-254
lines changed

bin/cli.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const shells = ['zsh', 'bash', 'fish', 'powershell'];
1212
async function main() {
1313
const cli = cac('tab');
1414

15+
// TODO: aren't these conditions are already handled by cac?
1516
const args = process.argv.slice(2);
1617
if (args.length >= 2 && args[1] === 'complete') {
1718
const packageManager = args[0];
@@ -26,6 +27,7 @@ async function main() {
2627

2728
const dashIndex = process.argv.indexOf('--');
2829
if (dashIndex !== -1) {
30+
// TOOD: there's no Completion anymore
2931
const completion = new Completion();
3032
setupCompletionForPackageManager(packageManager, completion);
3133
const toComplete = process.argv.slice(dashIndex + 1);
@@ -63,7 +65,7 @@ async function main() {
6365
generateCompletionScript(packageManager, shell);
6466
});
6567

66-
const completion = tab(cli);
68+
tab(cli);
6769

6870
cli.parse();
6971
}

bin/completion-handlers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// TODO: i do not see any completion functionality in this file. nothing is being provided for the defined commands of these package managers. this is a blocker for release. every each of them should be handled.
12
import { Completion } from '../src/index.js';
23
import { execSync } from 'child_process';
34

@@ -71,6 +72,7 @@ export function setupCompletionForPackageManager(
7172
setupBunCompletions(completion);
7273
}
7374

75+
// TODO: the core functionality of tab should have nothing related to package managers. even though completion is not there anymore, but this is something to consider.
7476
completion.setPackageManager(packageManager);
7577
}
7678

@@ -83,6 +85,7 @@ export function setupPnpmCompletions(completion: Completion) {
8385
[],
8486
async () => []
8587
);
88+
// TODO: empty functions should be replaced with noop functions rather than creating that many empty functions
8689
completion.addCommand('update', 'Update packages', [], async () => []);
8790
completion.addCommand('exec', 'Execute a command', [], async () => []);
8891
completion.addCommand('run', 'Run a script', [], async () => []);

examples/demo.cac.ts

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import cac from 'cac';
22
import tab from '../src/cac';
3+
import type { Command, Option, OptionsMap } from '../src/t';
34

45
const cli = cac('vite');
56

@@ -8,6 +9,8 @@ cli
89
.option('-m, --mode <mode>', `Set env mode`)
910
.option('-l, --logLevel <level>', `info | warn | error | silent`);
1011

12+
13+
1114
cli
1215
.command('dev', 'Start dev server')
1316
.option('-H, --host [host]', `Specify hostname`)
@@ -22,64 +25,65 @@ cli
2225

2326
cli.command('dev build', 'Build project').action((options) => {});
2427

25-
cli.command('lint [...files]', 'Lint project').action((files, options) => {});
28+
cli.command('copy <source> <destination>', 'Copy files').action((source, destination, options) => {});
2629

27-
const completion = await tab(cli);
28-
29-
for (const command of completion.commands.values()) {
30-
if (command.name === 'lint') {
31-
command.handler = () => {
32-
return [
33-
{ value: 'main.ts', description: 'Main file' },
34-
{ value: 'index.ts', description: 'Index file' },
35-
];
36-
};
37-
}
30+
cli.command('lint [...files]', 'Lint project').action((files, options) => {});
3831

39-
for (const [o, config] of command.options.entries()) {
40-
if (o === '--port') {
41-
config.handler = () => {
42-
return [
43-
{ value: '3000', description: 'Development server port' },
44-
{ value: '8080', description: 'Alternative port' },
45-
];
46-
};
47-
}
48-
if (o === '--host') {
49-
config.handler = () => {
50-
return [
51-
{ value: 'localhost', description: 'Localhost' },
52-
{ value: '0.0.0.0', description: 'All interfaces' },
53-
];
54-
};
55-
}
56-
if (o === '--config') {
57-
config.handler = () => {
58-
return [
59-
{ value: 'vite.config.ts', description: 'Vite config file' },
60-
{ value: 'vite.config.js', description: 'Vite config file' },
61-
];
62-
};
63-
}
64-
if (o === '--mode') {
65-
config.handler = () => {
66-
return [
67-
{ value: 'development', description: 'Development mode' },
68-
{ value: 'production', description: 'Production mode' },
69-
];
70-
};
71-
}
72-
if (o === '--logLevel') {
73-
config.handler = () => {
74-
return [
75-
{ value: 'info', description: 'Info level' },
76-
{ value: 'warn', description: 'Warn level' },
77-
{ value: 'error', description: 'Error level' },
78-
{ value: 'silent', description: 'Silent level' },
79-
];
80-
};
81-
}
82-
}
83-
}
32+
// Note: With the new t.ts API, handlers are configured through the completionConfig parameter
33+
// rather than by modifying the returned completion object directly
34+
await tab(cli, {
35+
subCommands: {
36+
copy: {
37+
args: {
38+
source: function(complete) {
39+
complete('src/', 'Source directory');
40+
complete('dist/', 'Distribution directory');
41+
complete('public/', 'Public assets');
42+
},
43+
destination: function(complete) {
44+
complete('build/', 'Build output');
45+
complete('release/', 'Release directory');
46+
complete('backup/', 'Backup location');
47+
},
48+
},
49+
},
50+
lint: {
51+
args: {
52+
files: function(complete) {
53+
complete('main.ts', 'Main file');
54+
complete('index.ts', 'Index file');
55+
},
56+
},
57+
},
58+
dev: {
59+
options: {
60+
port: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
61+
complete('3000', 'Development server port');
62+
complete('8080', 'Alternative port');
63+
},
64+
host: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
65+
complete('localhost', 'Localhost');
66+
complete('0.0.0.0', 'All interfaces');
67+
},
68+
},
69+
},
70+
},
71+
options: {
72+
config: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
73+
complete('vite.config.ts', 'Vite config file');
74+
complete('vite.config.js', 'Vite config file');
75+
},
76+
mode: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
77+
complete('development', 'Development mode');
78+
complete('production', 'Production mode');
79+
},
80+
logLevel: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
81+
complete('info', 'Info level');
82+
complete('warn', 'Warn level');
83+
complete('error', 'Error level');
84+
complete('silent', 'Silent level');
85+
},
86+
},
87+
});
8488

8589
cli.parse();

examples/demo.citty.ts

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defineCommand, createMain, CommandDef, ArgsDef } from 'citty';
1+
import { defineCommand, createMain, type CommandDef, type ArgsDef } from 'citty';
22
import tab from '../src/citty';
33

44
const main = defineCommand({
@@ -8,6 +8,11 @@ const main = defineCommand({
88
description: 'Vite CLI',
99
},
1010
args: {
11+
project: {
12+
type: 'positional',
13+
description: 'Project name',
14+
required: true,
15+
},
1116
config: {
1217
type: 'string',
1318
description: 'Use specified config file',
@@ -55,6 +60,26 @@ const buildCommand = defineCommand({
5560
run: () => {},
5661
});
5762

63+
const copyCommand = defineCommand({
64+
meta: {
65+
name: 'copy',
66+
description: 'Copy files',
67+
},
68+
args: {
69+
source: {
70+
type: 'positional',
71+
description: 'Source file or directory',
72+
required: true,
73+
},
74+
destination: {
75+
type: 'positional',
76+
description: 'Destination file or directory',
77+
required: true,
78+
},
79+
},
80+
run: () => {},
81+
});
82+
5883
const lintCommand = defineCommand({
5984
meta: {
6085
name: 'lint',
@@ -73,53 +98,67 @@ const lintCommand = defineCommand({
7398
main.subCommands = {
7499
dev: devCommand,
75100
build: buildCommand,
101+
copy: copyCommand,
76102
lint: lintCommand,
77103
} as Record<string, CommandDef<ArgsDef>>;
78104

79105
const completion = await tab(main, {
106+
args: {
107+
project: function(complete) {
108+
complete('my-app', 'My application');
109+
complete('my-lib', 'My library');
110+
complete('my-tool', 'My tool');
111+
},
112+
},
80113
options: {
81-
config: {
82-
handler: () => [
83-
{ value: 'vite.config.ts', description: 'Vite config file' },
84-
{ value: 'vite.config.js', description: 'Vite config file' },
85-
],
114+
config: function(this: any, complete) {
115+
complete('vite.config.ts', 'Vite config file');
116+
complete('vite.config.js', 'Vite config file');
86117
},
87-
mode: {
88-
handler: () => [
89-
{ value: 'development', description: 'Development mode' },
90-
{ value: 'production', description: 'Production mode' },
91-
],
118+
mode: function(this: any, complete) {
119+
complete('development', 'Development mode');
120+
complete('production', 'Production mode');
92121
},
93-
logLevel: {
94-
handler: () => [
95-
{ value: 'info', description: 'Info level' },
96-
{ value: 'warn', description: 'Warn level' },
97-
{ value: 'error', description: 'Error level' },
98-
{ value: 'silent', description: 'Silent level' },
99-
],
122+
logLevel: function(this: any, complete) {
123+
complete('info', 'Info level');
124+
complete('warn', 'Warn level');
125+
complete('error', 'Error level');
126+
complete('silent', 'Silent level');
100127
},
101128
},
102129

103130
subCommands: {
131+
copy: {
132+
args: {
133+
source: function(complete) {
134+
complete('src/', 'Source directory');
135+
complete('dist/', 'Distribution directory');
136+
complete('public/', 'Public assets');
137+
},
138+
destination: function(complete) {
139+
complete('build/', 'Build output');
140+
complete('release/', 'Release directory');
141+
complete('backup/', 'Backup location');
142+
},
143+
},
144+
},
104145
lint: {
105-
handler: () => [
106-
{ value: 'main.ts', description: 'Main file' },
107-
{ value: 'index.ts', description: 'Index file' },
108-
],
146+
args: {
147+
files: function(complete) {
148+
complete('main.ts', 'Main file');
149+
complete('index.ts', 'Index file');
150+
},
151+
},
109152
},
110153
dev: {
111154
options: {
112-
port: {
113-
handler: () => [
114-
{ value: '3000', description: 'Development server port' },
115-
{ value: '8080', description: 'Alternative port' },
116-
],
155+
port: function(this: any, complete) {
156+
complete('3000', 'Development server port');
157+
complete('8080', 'Alternative port');
117158
},
118-
host: {
119-
handler: () => [
120-
{ value: 'localhost', description: 'Localhost' },
121-
{ value: '0.0.0.0', description: 'All interfaces' },
122-
],
159+
host: function(this: any, complete) {
160+
complete('localhost', 'Localhost');
161+
complete('0.0.0.0', 'All interfaces');
123162
},
124163
},
125164
},

examples/demo.commander.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,5 @@ for (const command of completion.commands.values()) {
107107
}
108108
}
109109

110-
// Test completion directly if the first argument is "test-completion"
111-
if (process.argv[2] === 'test-completion') {
112-
const args = process.argv.slice(3);
113-
console.log('Testing completion with args:', args);
114-
completion.parse(args).then(() => {
115-
// Done
116-
});
117-
} else {
118-
// Parse command line arguments
119-
program.parse();
120-
}
110+
// Parse command line arguments
111+
program.parse();

0 commit comments

Comments
 (0)