From cdb6144c0036d592024de2b717af02252754cdbf Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 10 Jun 2026 09:03:44 +0000 Subject: [PATCH] feat!: print the help overview when boo runs with no arguments Zero-arg boo previously attached the most recently active session, or created one if none existed. That implicit behavior is gone: boo with no arguments now prints the help overview and exits 0, creating nothing. Use 'boo new' and 'boo attach' explicitly. Bump version to 0.3.0. --- README.md | 1 - build.zig.zon | 2 +- src/help.zig | 5 ++--- src/main.zig | 15 ++------------- test/integration.zig | 35 ++++++++++------------------------- 5 files changed, 15 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 826ef6d..92e83fc 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,6 @@ automatically (pinned in `build.zig.zon`). ## Usage ```sh -boo # attach the most recent session, or start one boo new # new session running $SHELL, attached boo new work # named session boo new work -d -- make # create detached, running a command diff --git a/build.zig.zon b/build.zig.zon index 1bada97..c5781e9 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,6 +1,6 @@ .{ .name = .boo, - .version = "0.2.0", + .version = "0.3.0", .fingerprint = 0x8b7acdfd255f0e34, .minimum_zig_version = "0.15.2", .dependencies = .{ diff --git a/src/help.zig b/src/help.zig index 1acfe0b..98c371c 100644 --- a/src/help.zig +++ b/src/help.zig @@ -20,10 +20,9 @@ pub const overview = \\human would see them. \\ \\usage: - \\ boo [command] [arguments] + \\ boo [arguments] \\ - \\ With no arguments, boo attaches the most recently active - \\ session, or starts a new one if none exist. + \\ With no arguments, boo prints this overview. \\ \\commands: \\ new [name] [-d] [-- cmd...] start a session (attach unless -d) diff --git a/src/main.zig b/src/main.zig index e34ca73..ac72418 100644 --- a/src/main.zig +++ b/src/main.zig @@ -10,7 +10,7 @@ const help = @import("help.zig"); const paths = @import("paths.zig"); const protocol = @import("protocol.zig"); -pub const version = "0.2.0"; +pub const version = "0.3.0"; /// Exit codes, documented in `boo help`. const exit_runtime: u8 = 1; @@ -52,7 +52,7 @@ pub fn main() !void { defer std.process.argsFree(alloc, argv); const args: []const [:0]const u8 = @ptrCast(argv[1..]); - if (args.len == 0) return cmdAuto(alloc); + if (args.len == 0) return stdoutWrite(help.overview); const cmd = args[0]; const rest = args[1..]; @@ -239,17 +239,6 @@ fn mustControl( // -- Commands ------------------------------------------------------------- -/// Zero-argument boo: attach the most recent session, else create one. -fn cmdAuto(alloc: std.mem.Allocator) !void { - const dir = try paths.socketDir(alloc); - defer alloc.free(dir); - if (try pickMostRecent(alloc, dir)) |name| { - defer alloc.free(name); - return attachLoop(alloc, dir, name); - } - return createSession(alloc, dir, null, false, &.{}); -} - fn cmdNew(alloc: std.mem.Allocator, args: []const [:0]const u8) !void { var name: ?[]const u8 = null; var detached = false; diff --git a/test/integration.zig b/test/integration.zig index 0ec35c3..99d6daf 100644 --- a/test/integration.zig +++ b/test/integration.zig @@ -869,38 +869,23 @@ test "wait --for and --idle observe session output" { try h.runExit(&.{ "wait", "w1", "--for", "NEVER-APPEARS", "--timeout", "300ms" }, 4); } -test "zero-arg boo creates a session, then reattaches it" { +test "zero-arg boo prints the help overview" { const alloc = std.testing.allocator; var h = try Harness.init(alloc); defer h.deinit(); - // No sessions: boo starts one running the default shell. Wait - // for the attach repaint before typing; input sent before the - // client enters raw mode is flushed by tcsetattr. - var first = try PtyClient.spawn(&h, &.{}, 24, 80); - defer first.deinit(); - try first.waitFor("\x1b[H\x1b[2J"); - try first.send("echo Z-MARK-$((70+7))\r"); - try first.waitFor("Z-MARK-77"); - try first.send("\x01d"); - try first.waitFor("detached from"); - try std.testing.expectEqual(@as(u32, 0), try first.waitExit()); + const result = try h.run(&.{}); + defer alloc.free(result.stdout); + defer alloc.free(result.stderr); + try std.testing.expect(result.term == .Exited and result.term.Exited == 0); + try std.testing.expect(std.mem.indexOf(u8, result.stdout, "usage:") != null); + try std.testing.expect(std.mem.indexOf(u8, result.stdout, "commands:") != null); - const ls = try h.run(&.{ "ls", "--json" }); + // Unlike earlier versions, no session is created or attached. + const ls = try h.run(&.{"ls"}); defer alloc.free(ls.stdout); defer alloc.free(ls.stderr); - var parsed = try std.json.parseFromSlice(std.json.Value, alloc, ls.stdout, .{}); - defer parsed.deinit(); - try std.testing.expectEqual(@as(usize, 1), parsed.value.array.items.len); - - // One live session: zero-arg boo attaches it instead of creating - // another; the repaint proves it is the same session. - var second = try PtyClient.spawn(&h, &.{}, 24, 80); - defer second.deinit(); - try second.waitFor("Z-MARK-77"); - try second.send("\x01d"); - try second.waitFor("detached from"); - try std.testing.expectEqual(@as(u32, 0), try second.waitExit()); + try std.testing.expect(std.mem.indexOf(u8, ls.stdout, "No sessions") != null); } test "exorcise banishes every session" {