summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 15:35:43 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commitf2091c52e06b0935f69914ac2d76941361cbb969 (patch)
tree18e19eec9765ae5b114779848dec02c58d1faa1f /src
parent830e936da4aca7ea802a6a862fa40c0086defd2f (diff)
downloadpardes-f2091c52e06b0935f69914ac2d76941361cbb969.tar.gz
pardes-f2091c52e06b0935f69914ac2d76941361cbb969.zip
A command pane echoes its first command as it does the later ones
Only a reused pane showed '% line' above its command, so the first command's output stood with nothing saying what made it. Every command is echoed now, the first too. The goldens of chordcut, cmdexit, cmdword and layout-open gain that line and the rows below it move down one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/exec.zig22
-rw-r--r--src/pardes.zig6
2 files changed, 20 insertions, 8 deletions
diff --git a/src/exec.zig b/src/exec.zig
index 84a0ad5f..fa915b16 100644
--- a/src/exec.zig
+++ b/src/exec.zig
@@ -534,14 +534,7 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
// shown, then a soft reset (DECSTR) for the rest.
if (panes.Terminal.onAlternateScreen(pane)) panes.Terminal.feedOutput(p, pane, "\x1b[?1049l");
panes.Terminal.feedOutput(p, pane, "\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l\x1b[?2004l\x1b[?25h\x1b[!p");
- // The line as it runs, its newlines the terminal's, so a multi-line
- // command does not staircase.
- var buf: [2 * command_max + 8]u8 = undefined;
- var w = std.Io.Writer.fixed(&buf);
- w.writeAll(if (panes.Terminal.gridCursor(pane).x != 0) "\r\n% " else "% ") catch {};
- for (line) |c| (if (c == '\n') w.writeAll("\r\n") else w.writeByte(c)) catch {};
- w.writeAll("\r\n") catch {};
- panes.Terminal.feedOutput(p, pane, w.buffered());
+ echoCommand(p, pane, line);
p.emit(.{ .spawn = .{ .pane = @intCast(id), .serial = pane.serial, .cwd = .from(pane.cwdSlice()) } });
noteRun(p, pane, "run", line);
return id;
@@ -554,6 +547,7 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
p.reportError(from, "exec", err);
return null;
};
+ echoCommand(p, pane, line);
const rc = if (p.ncol > 0) p.ncol - 1 else 0;
if (p.col_n[rc] > 0) {
const parent = layout.splitParent(p, p.col_panes[rc][p.col_n[rc] - 1]);
@@ -565,6 +559,18 @@ fn runCommand(p: *Pardes, from: usize, line: []const u8) ?usize {
return free;
}
+/// `% line` above a command's output, every command, as a shell echoes
+/// what it was given; its newlines the terminal's, so a multi-line command
+/// does not staircase.
+fn echoCommand(p: *Pardes, pane: *Pane, line: []const u8) void {
+ var buf: [2 * command_max + 8]u8 = undefined;
+ var w = std.Io.Writer.fixed(&buf);
+ w.writeAll(if (panes.Terminal.gridCursor(pane).x != 0) "\r\n% " else "% ") catch {};
+ for (line) |c| (if (c == '\n') w.writeAll("\r\n") else w.writeByte(c)) catch {};
+ w.writeAll("\r\n") catch {};
+ panes.Terminal.feedOutput(p, pane, w.buffered());
+}
+
/// `run <serial> <word>` or `exit <serial> <N|?>` in the log.
fn noteRun(p: *Pardes, pane: *Pane, what: []const u8, said: []const u8) void {
var buf: [96]u8 = undefined;
diff --git a/src/pardes.zig b/src/pardes.zig
index 80a20a0d..5e86f0fd 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -1538,6 +1538,12 @@ test "a command pane shows how its command ended, and the next command there run
const dst = exec.execute(p, 1, "make -j8") orelse return error.NoCommandPane;
while (p.nextEffect()) |_| {}
const pane = p.panes[dst].?;
+ // Its first command is echoed as every later one is.
+ {
+ const first = try panes.Terminal.screenTextAlloc(pane, gpa);
+ defer gpa.free(first);
+ try std.testing.expect(std.mem.startsWith(u8, first, "% make -j8"));
+ }
var frame = std.heap.ArenaAllocator.init(gpa);
defer frame.deinit();
try std.testing.expect(std.mem.endsWith(u8, try tagline.tagPrefix(p, pane), "(make -j8) running"));