Skip to content

Commit 8caf381

Browse files
committed
some progress, tests next
1 parent 40498be commit 8caf381

File tree

11 files changed

+990
-862
lines changed

11 files changed

+990
-862
lines changed

demo.citty.ts

Lines changed: 138 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,18 @@
11
import { defineCommand, createMain, CommandDef, CommandMeta, ArgDef, PositionalArgDef } from "citty";
2-
import { flagMap, positionalMap } from "./src/shared";
3-
// import {tab} from ""
2+
import tab from "./src/citty";
43

5-
export const main = defineCommand({
4+
const main = defineCommand({
65
meta: {
76
name: "vite",
87
description: "Vite CLI tool",
98
},
109
args: {
1110
config: { type: "string", description: "Use specified config file", alias: "c" },
12-
base: { type: "string", description: "Public base path (default: /)" },
13-
logLevel: { type: "string", description: "info | warn | error | silent", alias: "l" },
14-
clearScreen: { type: "boolean", description: "Allow/disable clear screen when logging" },
15-
debug: { type: "string", description: "Show debug logs", alias: "d" },
16-
filter: { type: "string", description: "Filter debug logs", alias: "f" },
1711
mode: { type: "string", description: "Set env mode", alias: "m" },
12+
logLevel: { type: "string", description: "info | warn | error | silent", alias: "l" },
1813
},
1914
run(ctx) {
20-
const firstArg = ctx.args._?.[0];
21-
if (firstArg && devCommand?.run) {
22-
devCommand.run({
23-
rawArgs: ctx.rawArgs,
24-
cmd: devCommand,
25-
subCommand: undefined,
26-
data: ctx.data,
27-
args: {
28-
root: firstArg,
29-
host: "",
30-
port: "",
31-
open: false,
32-
cors: false,
33-
strictPort: false,
34-
force: false,
35-
_: ctx.args._,
36-
},
37-
});
38-
}
3915
}
40-
4116
});
4217

4318
const devCommand = defineCommand({
@@ -46,101 +21,156 @@ const devCommand = defineCommand({
4621
description: "Start dev server",
4722
},
4823
args: {
49-
root: { type: "positional", description: "Root directory", default: "." },
5024
host: { type: "string", description: "Specify hostname" },
5125
port: { type: "string", description: "Specify port" },
52-
open: { type: "boolean", description: "Open browser on startup" },
53-
cors: { type: "boolean", description: "Enable CORS" },
54-
strictPort: { type: "boolean", description: "Exit if specified port is already in use" },
55-
force: { type: "boolean", description: "Force the optimizer to ignore the cache and re-bundle" },
5626
},
5727
run({ args }) { },
5828
});
5929

30+
devCommand.subCommands = {
31+
build: defineCommand({
32+
meta: {
33+
name: "build",
34+
description: "Build project",
35+
},
36+
run({ args }) { },
37+
})
38+
}
39+
6040
main.subCommands = {
6141
dev: devCommand
6242
} as Record<string, CommandDef<any>>;
6343

64-
for (const command of [main as CommandDef<any>, ...Object.values(main.subCommands as Record<string, CommandDef<any>>)]) {
65-
const meta = command.meta as CommandMeta;
66-
const commandName = meta.name;
44+
const completion = await tab(main)
6745

68-
for (const [argName, argConfig] of Object.entries(command.args || {}) as [string, ArgDef][]) {
69-
const optionKey = `--${argName}`;
46+
for (const command of completion.commands.values()) {
7047

71-
if (argName === "port") {
72-
flagMap.set(optionKey, async (_, toComplete) => {
73-
const options = [
74-
{ action: "3000", description: "Development server port" },
75-
{ action: "8080", description: "Alternative port" },
76-
];
77-
return toComplete
78-
? options.filter(comp => comp.action.startsWith(toComplete))
79-
: options;
80-
});
81-
} else if (argName === "host") {
82-
flagMap.set(optionKey, async (_, toComplete) => {
83-
const options = [
84-
{ action: "localhost", description: "Localhost" },
85-
{ action: "0.0.0.0", description: "All interfaces" },
86-
];
87-
return toComplete
88-
? options.filter(comp => comp.action.startsWith(toComplete))
89-
: options;
90-
});
91-
} else if (argName === "config") {
92-
flagMap.set(optionKey, async (_, toComplete) => {
93-
const configFiles = ["vite.config.ts", "vite.config.js"].filter(
94-
(file) => file.startsWith(toComplete)
95-
);
96-
return configFiles.map((file) => ({ action: file }));
97-
});
98-
} else if (argName === "mode") {
99-
flagMap.set(optionKey, async (_, toComplete) => {
100-
const options = [
101-
{ action: "development", description: "Development mode" },
102-
{ action: "production", description: "Production mode" },
103-
];
104-
return toComplete
105-
? options.filter(comp => comp.action.startsWith(toComplete))
106-
: options;
107-
});
108-
} else {
109-
flagMap.set(optionKey, async (_, toComplete) => {
110-
const flag = optionKey.startsWith("--") ? optionKey.slice(2) : optionKey;
111-
if (!toComplete || optionKey.startsWith(toComplete)) {
112-
return [{ action: optionKey, description: argConfig.description }];
113-
}
114-
return [];
115-
});
48+
for (const [o, config] of command.options.entries()) {
49+
if (o === "--port") {
50+
config.handler = () => {
51+
return [
52+
{ value: "3000", description: "Development server port" },
53+
{ value: "8080", description: "Alternative port" },
54+
]
55+
}
56+
}
57+
if (o === "--host") {
58+
config.handler = () => {
59+
return [
60+
{ value: "localhost", description: "Localhost" },
61+
{ value: "0.0.0.0", description: "All interfaces" },
62+
]
63+
}
64+
}
65+
if (o === "--config") {
66+
config.handler = () => {
67+
return [
68+
{ value: "vite.config.ts", description: "Vite config file" },
69+
{ value: "vite.config.js", description: "Vite config file" },
70+
]
71+
}
72+
}
73+
if (o === "--mode") {
74+
config.handler = () => {
75+
return [
76+
{ value: "development", description: "Development mode" },
77+
{ value: "production", description: "Production mode" },
78+
]
79+
}
80+
}
81+
if (o === "--logLevel") {
82+
config.handler = () => {
83+
return [
84+
{ value: "info", description: "Info level" },
85+
{ value: "warn", description: "Warn level" },
86+
{ value: "error", description: "Error level" },
87+
{ value: "silent", description: "Silent level" },
88+
]
89+
}
11690
}
117-
}
118-
119-
if (command.args) {
120-
const positionals = Object.entries(command.args)
121-
.filter(([, config]) => (config as any).type === "positional")
122-
.map(([argName, argConfig]) => {
123-
const conf = argConfig as PositionalArgDef;
124-
return {
125-
value: argName,
126-
variadic: false,
127-
required: !!conf.required,
128-
completion: async (_, toComplete) => {
129-
const options = [
130-
{ action: "src/", description: "Source directory" },
131-
{ action: "./", description: "Current directory" },
132-
];
133-
return toComplete
134-
? options.filter(comp => comp.action.startsWith(toComplete))
135-
: options;
136-
},
137-
};
138-
});
139-
positionalMap.set(commandName!, positionals);
14091
}
14192
}
14293

94+
// for (const command of [main as CommandDef<any>, ...Object.values(main.subCommands as Record<string, CommandDef<any>>)]) {
95+
// const meta = command.meta as CommandMeta;
96+
// const commandName = meta.name;
97+
98+
// for (const [argName, argConfig] of Object.entries(command.args || {}) as [string, ArgDef][]) {
99+
// const optionKey = `--${argName}`;
100+
101+
// if (argName === "port") {
102+
// flagMap.set(optionKey, async (_, toComplete) => {
103+
// const options = [
104+
// { action: "3000", description: "Development server port" },
105+
// { action: "8080", description: "Alternative port" },
106+
// ];
107+
// return toComplete
108+
// ? options.filter(comp => comp.action.startsWith(toComplete))
109+
// : options;
110+
// });
111+
// } else if (argName === "host") {
112+
// flagMap.set(optionKey, async (_, toComplete) => {
113+
// const options = [
114+
// { action: "localhost", description: "Localhost" },
115+
// { action: "0.0.0.0", description: "All interfaces" },
116+
// ];
117+
// return toComplete
118+
// ? options.filter(comp => comp.action.startsWith(toComplete))
119+
// : options;
120+
// });
121+
// } else if (argName === "config") {
122+
// flagMap.set(optionKey, async (_, toComplete) => {
123+
// const configFiles = ["vite.config.ts", "vite.config.js"].filter(
124+
// (file) => file.startsWith(toComplete)
125+
// );
126+
// return configFiles.map((file) => ({ action: file }));
127+
// });
128+
// } else if (argName === "mode") {
129+
// flagMap.set(optionKey, async (_, toComplete) => {
130+
// const options = [
131+
// { action: "development", description: "Development mode" },
132+
// { action: "production", description: "Production mode" },
133+
// ];
134+
// return toComplete
135+
// ? options.filter(comp => comp.action.startsWith(toComplete))
136+
// : options;
137+
// });
138+
// } else {
139+
// flagMap.set(optionKey, async (_, toComplete) => {
140+
// const flag = optionKey.startsWith("--") ? optionKey.slice(2) : optionKey;
141+
// if (!toComplete || optionKey.startsWith(toComplete)) {
142+
// return [{ action: optionKey, description: argConfig.description }];
143+
// }
144+
// return [];
145+
// });
146+
// }
147+
// }
148+
149+
// if (command.args) {
150+
// const positionals = Object.entries(command.args)
151+
// .filter(([, config]) => (config as any).type === "positional")
152+
// .map(([argName, argConfig]) => {
153+
// const conf = argConfig as PositionalArgDef;
154+
// return {
155+
// value: argName,
156+
// variadic: false,
157+
// required: !!conf.required,
158+
// completion: async (_, toComplete) => {
159+
// const options = [
160+
// { action: "src/", description: "Source directory" },
161+
// { action: "./", description: "Current directory" },
162+
// ];
163+
// return toComplete
164+
// ? options.filter(comp => comp.action.startsWith(toComplete))
165+
// : options;
166+
// },
167+
// };
168+
// });
169+
// positionalMap.set(commandName!, positionals);
170+
// }
171+
// }
172+
173+
174+
const cli = createMain(main);
143175

144-
export const cli = createMain(main);
145-
// tab(main)
146176
cli();

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
},
2020
"dependencies": {
2121
"mri": "^1.2.0"
22-
}
22+
},
23+
"packageManager": "pnpm@9.15.0+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c"
2324
}

0 commit comments

Comments
 (0)