Commit 0ba19cd
Amir B.
·
2026-05-16 20:32:03 -0400 EDT
parent a28c87a
fix: handle run help flag (#152) Extends the --help/-h check to all subcommands that accept a session name or other positional args, so users don't accidentally create a session named "--help" or trigger confusing errors. Covers: list, completions, history, attach, send, print, write, kill, wait, tail.
2 files changed,
+67,
-2
+40,
-2
1@@ -98,10 +98,19 @@ pub fn main() !void {
2 } else if (std.mem.eql(u8, cmd, "help") or std.mem.eql(u8, cmd, "h") or std.mem.eql(u8, cmd, "-h")) {
3 return help();
4 } else if (std.mem.eql(u8, cmd, "list") or std.mem.eql(u8, cmd, "l") or std.mem.eql(u8, cmd, "ls")) {
5- const short = if (args.next()) |arg| std.mem.eql(u8, arg, "--short") else false;
6+ var short = false;
7+ if (args.next()) |arg| {
8+ if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
9+ return help();
10+ }
11+ short = std.mem.eql(u8, arg, "--short");
12+ }
13 return list(&cfg, short);
14 } else if (std.mem.eql(u8, cmd, "completions") or std.mem.eql(u8, cmd, "c")) {
15 const arg = args.next() orelse return;
16+ if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
17+ return help();
18+ }
19 const shell = completions.Shell.fromString(arg) orelse return;
20 return printCompletions(shell);
21 } else if (std.mem.eql(u8, cmd, "detach") or std.mem.eql(u8, cmd, "d")) {
22@@ -110,7 +119,9 @@ pub fn main() !void {
23 var session_name: ?[]const u8 = null;
24 var format: util.HistoryFormat = .plain;
25 while (args.next()) |arg| {
26- if (std.mem.eql(u8, arg, "--vt")) {
27+ if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
28+ return help();
29+ } else if (std.mem.eql(u8, arg, "--vt")) {
30 format = .vt;
31 } else if (std.mem.eql(u8, arg, "--html")) {
32 format = .html;
33@@ -124,6 +135,9 @@ pub fn main() !void {
34 return history(&cfg, sesh, format);
35 } else if (std.mem.eql(u8, cmd, "attach") or std.mem.eql(u8, cmd, "a")) {
36 const session_name = args.next() orelse "";
37+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
38+ return help();
39+ }
40
41 var command_args: std.ArrayList([]const u8) = .empty;
42 defer command_args.deinit(alloc);
43@@ -163,6 +177,9 @@ pub fn main() !void {
44 return attach(&daemon);
45 } else if (std.mem.eql(u8, cmd, "run") or std.mem.eql(u8, cmd, "r")) {
46 const session_name = args.next() orelse "";
47+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
48+ return help();
49+ }
50
51 var cmd_args_raw: std.ArrayList([]const u8) = .empty;
52 defer cmd_args_raw.deinit(alloc);
53@@ -203,6 +220,9 @@ pub fn main() !void {
54 return run(&daemon, detached, cmd_args_raw.items);
55 } else if (std.mem.eql(u8, cmd, "send") or std.mem.eql(u8, cmd, "s")) {
56 const session_name = args.next() orelse "";
57+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
58+ return help();
59+ }
60 if (session_name.len == 0) return error.SessionNameRequired;
61
62 var text_parts: std.ArrayList([]const u8) = .empty;
63@@ -220,6 +240,9 @@ pub fn main() !void {
64 return send(&cfg, sesh, socket_path, text_parts.items, .Input);
65 } else if (std.mem.eql(u8, cmd, "print") or std.mem.eql(u8, cmd, "p")) {
66 const session_name = args.next() orelse "";
67+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
68+ return help();
69+ }
70 if (session_name.len == 0) return error.SessionNameRequired;
71
72 var text_parts: std.ArrayList([]const u8) = .empty;
73@@ -249,6 +272,9 @@ pub fn main() !void {
74 }
75 var force = false;
76 while (args.next()) |session_name| {
77+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
78+ return help();
79+ }
80 if (std.mem.eql(u8, session_name, "--force")) {
81 force = true;
82 continue;
83@@ -292,6 +318,9 @@ pub fn main() !void {
84 matchers.deinit(alloc);
85 }
86 while (args.next()) |session_name| {
87+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
88+ return help();
89+ }
90 const m = try parseSessionArg(alloc, session_name);
91 try matchers.append(alloc, m);
92 }
93@@ -308,6 +337,9 @@ pub fn main() !void {
94 matchers.deinit(alloc);
95 }
96 while (args.next()) |session_name| {
97+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
98+ return help();
99+ }
100 const m = try parseSessionArg(alloc, session_name);
101 try matchers.append(alloc, m);
102 }
103@@ -375,8 +407,14 @@ pub fn main() !void {
104 _ = try tail(client_socket_fds, false, false);
105 } else if (std.mem.eql(u8, cmd, "write") or std.mem.eql(u8, cmd, "wr")) {
106 const session_name = args.next() orelse "";
107+ if (std.mem.eql(u8, session_name, "--help") or std.mem.eql(u8, session_name, "-h")) {
108+ return help();
109+ }
110 if (session_name.len == 0) return error.SessionNameRequired;
111 const file_path = args.next() orelse "";
112+ if (std.mem.eql(u8, file_path, "--help") or std.mem.eql(u8, file_path, "-h")) {
113+ return help();
114+ }
115 if (file_path.len == 0) return error.FilePathRequired;
116
117 var cwd_buf: [std.fs.max_path_bytes]u8 = undefined;
+27,
-0
1@@ -50,6 +50,33 @@ load test_helper
2 [ "$status" -ne 0 ]
3 }
4
5+@test "run --help shows help without creating a session" {
6+ run "$ZMX" run --help
7+ [ "$status" -eq 0 ]
8+ [[ "$output" == *"Usage:"* ]]
9+
10+ run "$ZMX" list --short
11+ [ "$status" -eq 0 ]
12+ [[ "$output" != *"--help"* ]]
13+}
14+
15+@test "subcommands handle --help and -h without side effects" {
16+ for cmd in attach send print write kill wait tail history list completions; do
17+ run "$ZMX" "$cmd" --help
18+ [ "$status" -eq 0 ]
19+ [[ "$output" == *"Usage:"* ]]
20+
21+ run "$ZMX" "$cmd" -h
22+ [ "$status" -eq 0 ]
23+ [[ "$output" == *"Usage:"* ]]
24+ done
25+
26+ run "$ZMX" list --short
27+ [ "$status" -eq 0 ]
28+ [[ "$output" != *"--help"* ]]
29+ [[ "$output" != *"-h"* ]]
30+}
31+
32 # ============================================================================
33 # Send (raw PTY input)
34 # ============================================================================