@@ -87,7 +87,7 @@ pub const ParsedCommand = union(Command) {
8787 shell : ShellType ,
8888 },
8989 version ,
90- help ,
90+ help : ? Command ,
9191};
9292
9393/// Global flags that apply before the command (e.g., --color).
@@ -147,7 +147,7 @@ pub fn parse(allocator: std.mem.Allocator, init: std.process.Init.Minimal) !stru
147147 } else if (std .mem .cutPrefix (u8 , arg , "--color=" )) | val | {
148148 if (parseColorValue (val )) | c | global_flags .color = c ;
149149 } else if (std .mem .eql (u8 , arg , "--help" ) or std .mem .eql (u8 , arg , "-h" )) {
150- return .{ .global = global_flags , .cmd = .help };
150+ return .{ .global = global_flags , .cmd = .{ . help = null } };
151151 } else if (std .mem .eql (u8 , arg , "--version" ) or std .mem .eql (u8 , arg , "-v" )) {
152152 return .{ .global = global_flags , .cmd = .version };
153153 } else {
@@ -158,7 +158,7 @@ pub fn parse(allocator: std.mem.Allocator, init: std.process.Init.Minimal) !stru
158158 }
159159 }
160160
161- const cmd = maybe_cmd orelse return .{ .global = global_flags , .cmd = .help };
161+ const cmd = maybe_cmd orelse return .{ .global = global_flags , .cmd = .{ . help = null } };
162162
163163 // Check if the raw command name implies --all
164164 const auto_all = if (cmd_raw ) | raw |
@@ -179,7 +179,7 @@ pub fn parse(allocator: std.mem.Allocator, init: std.process.Init.Minimal) !stru
179179 .proxy = > try parseProxy (allocator , & args ),
180180 .completion = > try parseCompletion (& args ),
181181 .version = > ParsedCommand .version ,
182- .help = > ParsedCommand .help ,
182+ .help = > ParsedCommand { .help = null } ,
183183 };
184184
185185 return .{ .global = global_flags , .cmd = parsed };
@@ -203,11 +203,19 @@ fn parseColorValue(val: []const u8) ?bool {
203203 return null ;
204204}
205205
206+ fn checkHelp (comptime cmd : Command , arg : []const u8 ) ? ParsedCommand {
207+ if (std .mem .eql (u8 , arg , "--help" ) or std .mem .eql (u8 , arg , "-h" )) {
208+ return .{ .help = cmd };
209+ }
210+ return null ;
211+ }
212+
206213fn parseInstall (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
207214 var flags : InstallFlags = .{};
208215 var version : ? []const u8 = null ;
209216
210217 while (args .next ()) | arg | {
218+ if (checkHelp (.install , arg )) | h | return h ;
211219 if (std .mem .eql (u8 , arg , "--force" ) or std .mem .eql (u8 , arg , "-f" )) {
212220 flags .force = true ;
213221 } else if (std .mem .eql (u8 , arg , "--zls" )) {
@@ -232,6 +240,7 @@ fn parseUse(allocator: std.mem.Allocator, args: anytype) !ParsedCommand {
232240 var version : ? []const u8 = null ;
233241
234242 while (args .next ()) | arg | {
243+ if (checkHelp (.use , arg )) | h | return h ;
235244 if (std .mem .eql (u8 , arg , "--sync" )) {
236245 flags .sync = true ;
237246 } else {
@@ -249,6 +258,7 @@ fn parseList(args: anytype, auto_all: bool) ParsedCommand {
249258 var flags : ListFlags = .{ .all = auto_all };
250259
251260 while (args .next ()) | arg | {
261+ if (checkHelp (.list , arg )) | h | return h ;
252262 if (std .mem .eql (u8 , arg , "--all" ) or std .mem .eql (u8 , arg , "-a" )) {
253263 flags .all = true ;
254264 } else if (std .mem .eql (u8 , arg , "--vmu" )) {
@@ -261,13 +271,15 @@ fn parseList(args: anytype, auto_all: bool) ParsedCommand {
261271
262272fn parseUninstall (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
263273 const version = args .next () orelse return error .MissingArgument ;
274+ if (checkHelp (.uninstall , version )) | h | return h ;
264275 return .{ .uninstall = .{
265276 .version = try allocator .dupe (u8 , version ),
266277 } };
267278}
268279
269280fn parseRun (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
270281 const version = args .next () orelse return error .MissingArgument ;
282+ if (checkHelp (.run , version )) | h | return h ;
271283
272284 var run_args : std .ArrayList ([]const u8 ) = .empty ;
273285 errdefer run_args .deinit (allocator );
@@ -284,6 +296,7 @@ fn parseRun(allocator: std.mem.Allocator, args: anytype) !ParsedCommand {
284296
285297fn parseVmu (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
286298 const subcmd = args .next () orelse return error .MissingArgument ;
299+ if (checkHelp (.vmu , subcmd )) | h | return h ;
287300 const value = args .next () orelse return error .MissingArgument ;
288301
289302 const target : VmuTarget = if (std .mem .eql (u8 , subcmd , "zig" ))
@@ -301,20 +314,25 @@ fn parseVmu(allocator: std.mem.Allocator, args: anytype) !ParsedCommand {
301314
302315fn parseMirrorlist (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
303316 const url = args .next ();
304- return .{ .mirrorlist = .{
305- .url = if (url ) | u | try allocator .dupe (u8 , u ) else null ,
306- } };
317+ if (url ) | u | {
318+ if (checkHelp (.mirrorlist , u )) | h | return h ;
319+ return .{ .mirrorlist = .{ .url = try allocator .dupe (u8 , u ) } };
320+ }
321+ return .{ .mirrorlist = .{ .url = null } };
307322}
308323
309324fn parseProxy (allocator : std.mem.Allocator , args : anytype ) ! ParsedCommand {
310325 const url = args .next ();
311- return .{ .proxy = .{
312- .url = if (url ) | u | try allocator .dupe (u8 , u ) else null ,
313- } };
326+ if (url ) | u | {
327+ if (checkHelp (.proxy , u )) | h | return h ;
328+ return .{ .proxy = .{ .url = try allocator .dupe (u8 , u ) } };
329+ }
330+ return .{ .proxy = .{ .url = null } };
314331}
315332
316333fn parseCompletion (args : anytype ) ! ParsedCommand {
317334 const shell_str = args .next () orelse return error .MissingArgument ;
335+ if (checkHelp (.completion , shell_str )) | h | return h ;
318336 const shell : ShellType = if (std .mem .eql (u8 , shell_str , "zsh" ))
319337 .zsh
320338 else if (std .mem .eql (u8 , shell_str , "bash" ))
@@ -470,6 +488,17 @@ pub fn printCommandHelp(writer: *std.Io.Writer, cmd: Command) !void {
470488 \\ zvm proxy Show current proxy setting
471489 \\
472490 ),
491+ .completion = > try writer .writeAll (
492+ \\Generate shell completion script.
493+ \\
494+ \\Usage:
495+ \\ zvm completion <shell>
496+ \\
497+ \\Supported shells:
498+ \\ zsh
499+ \\ bash
500+ \\
501+ ),
473502 .version , .help = > printHelp (writer ) catch {},
474503 }
475504 try writer .flush ();
0 commit comments