From f2091c52e06b0935f69914ac2d76941361cbb969 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 15:35:43 -0300 Subject: 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 --- src/exec.zig | 22 ++++++++++++++-------- src/pardes.zig | 6 ++++++ 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src') 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 ` or `exit ` 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")); -- cgit v1.3