summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 14:28:27 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit010b123a88aa5278c499f83098c00bdbdb0093ce (patch)
tree0c90aab9ff023a3967225377994d4244d187c828 /src/pardes.zig
parente7c181d6238dae4b08a02c1a9828917c2497f89d (diff)
downloadpardes-010b123a88aa5278c499f83098c00bdbdb0093ce.tar.gz
pardes-010b123a88aa5278c499f83098c00bdbdb0093ce.zip
A terminal's Tty word names its shell, Tty+fish, and a click on it opens another
A terminal's tag said Tty whatever shell it ran. The host's acknowledgement of the shell it forked now sets the word to Tty+<shell>, tinted like the tag's name. Word+arg is taken as Word arg, one word a tag can hold and a click can take whole (+ is a word character), so Tty+fish opens a terminal on fish, as Tty fish does; Tty takes the shell as its argument, which the host forks for that pane instead of the configured one. Every snapshot whose screen shows a terminal's tag changes: 69 goldens, re-recorded by name, whose 297 changed lines are all Tty becoming Tty+bash (the harness runs bash), the cursor columns and style spans that moved with it, or that text cut at a pane's width. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index 1bb13e3d..e92fb3f7 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -631,8 +631,9 @@ test "pane-tag Exec prefers Tty and argument builtins before shell fallback" {
while (p.nextEffect()) |_| {} // initial shell spawn/geometry
p.acknowledgeShell(0, "/bin/sh", false);
+ // The Tty word names the shell the host ran, and opens another of it.
const pane = p.panes[0].?;
- try std.testing.expectEqualStrings(tagline.terminal_pane_tail, tagline.curTail(pane));
+ try std.testing.expectEqualStrings(" Tty+sh" ++ tagline.terminal_pane_tail[" Tty".len..], tagline.curTail(pane));
const tag_x = p.rects[0].x + TAG_TEXT_INSET;
const tag_y = p.rects[0].y;
@@ -654,6 +655,7 @@ test "pane-tag Exec prefers Tty and argument builtins before shell fallback" {
};
try std.testing.expectEqual(panes_before + 1, panes_after);
try std.testing.expect(p.panes[p.active].?.isTerminal());
+ try std.testing.expectEqualStrings("sh", p.panes[p.active].?.shell.?);
// Argument-taking builtins use the same gesture path: a tag sweep is the
// complete command line, and Theme consumes its tail without a PTY write.
@@ -1359,6 +1361,17 @@ test "Exec in a terminal whose tty is taken runs as a command pane instead of ty
try std.testing.expect(spawned);
}
+test "Tty+fish, one word a tag can hold, opens a terminal on that shell" {
+ const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ try std.testing.expect(p.executeBuiltinLine(0, "Tty+fish"));
+ try std.testing.expect(p.active != 0);
+ try std.testing.expectEqualStrings("fish", p.panes[p.active].?.shell.?);
+ p.acknowledgeShell(p.active, "/usr/bin/fish", true);
+ try std.testing.expect(std.mem.startsWith(u8, tagline.curTail(p.panes[p.active].?), " Tty+fish "));
+}
+
test "a command pane shows how its command ended, and the next command there runs below it" {
const gpa = std.testing.allocator;
const p = try Pardes.init(gpa, .{});
@@ -4188,6 +4201,7 @@ pub const Pardes = struct {
for (0..pane.pointer_selections.len) |slot| pane.clearPointerSelection(slot);
panes.Terminal.deinitPendingCommand(pane);
if (pane.command) |line| p.gpa.free(line);
+ if (pane.shell) |bin| p.gpa.free(bin);
if (pane.image) |*iv| {
iv.deinit(p.image_gpa);
}
@@ -4371,6 +4385,15 @@ pub const Pardes = struct {
if (id < MAX_PANES) if (p.panes[id]) |pane| {
ctlfs.pty.shellGone(p, pane, true); // a respawn replaced whatever ran
pane.fs.unmarked = !prompt_marks;
+ // The tag's Tty word names the shell the host ran, and a click
+ // on it (`Tty+fish`) opens another of the same.
+ if (pane.command == null) {
+ const base = std.fs.path.basename(executable);
+ const rest = tagline.terminal_pane_tail[" Tty".len..];
+ if (std.fmt.bufPrint(&pane.shell_tail, " Tty+{s}{s}", .{ base, rest })) |tail| {
+ pane.shell_tail_len = @intCast(tail.len);
+ } else |_| {}
+ }
};
if (id < MAX_PANES) panes.Terminal.shellSpawned(p, id, prompt_marks);
if (p.settings.shell.effective.set(executable))