summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 17:42:30 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit73050ca20405fc14c2e3a53b692954b1771dfe24 (patch)
treeaa2df4bd0a6ac8202fd105b06f2f7811a94aca3e
parentb196f602a6bbb53e0025140c7a3f9cbb9f23bcd2 (diff)
downloadpardes-73050ca20405fc14c2e3a53b692954b1771dfe24.tar.gz
pardes-73050ca20405fc14c2e3a53b692954b1771dfe24.zip
fs.md says a body write to a terminal is typed input, never a bracketed paste
A write to a terminal's body goes to its child as typed keys: no bracketed-paste marks around it, even when the program set 2004, so a newline in it is Enter and a shell runs each line. fs.md did not say which, and a script cannot guess. It does now, and a test writes to a terminal whose program asked for bracketed paste and checks the bytes sent are only the ones written. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--docs/fs.md4
-rw-r--r--src/ninep/ctl.zig14
2 files changed, 17 insertions, 1 deletions
diff --git a/docs/fs.md b/docs/fs.md
index 1c496c5f..5c952403 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -402,7 +402,9 @@ component. A directory (`/`, `~`, `foo/`) is no file name: refused, EISDIR
**`body`** reads the text; a write appends; `>` (OTRUNC) replaces it all.
A terminal's body is its history as plain text in logical lines (wrapped
-rows joined), frozen per open; writing it sends input to the child. A PDF's
+rows joined), frozen per open; writing it sends input to the child as typed
+keys, never a paste: no bracketed-paste marks around it, even when the
+program asked for them, so a newline in it is Enter. A PDF's
body is the text layer of the page shown; images and PDFs take no write
(`this pane has no text`).
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 10336e38..118b6488 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -1633,6 +1633,20 @@ test "get reloads the pane from disk and reports a missing file without losing d
try testing.expect(pane_files.dirtyOf(pane));
}
+test "a body write to a terminal is typed input, not a paste, even to a program that asked for bracketed paste" {
+ const p = try Pardes.init(testing.allocator, .{ .cols = 90, .rows = 30 });
+ defer p.deinit();
+ while (p.nextEffect()) |_| {}
+ const term = for (p.panes, 0..) |slot, id| {
+ if (slot) |pane| if (pane.isTerminal()) break id;
+ } else return error.SkipZigTest;
+ p.update(.{ .output = .{ .pane = @intCast(term), .bytes = "\x1b[?2004h" } });
+ while (p.nextEffect()) |_| {}
+ const w = wr(p, Node.of(p.panes[term].?.serial, .body), "ls\n");
+ try testing.expectEqual(Status.ok, w.reply.status);
+ try testing.expectEqualStrings("ls\n", w.pty_buf[0..w.pty_len]);
+}
+
test "Save path of a file pane logs a save record naming that path" {
const p = try withFile(testing.allocator, "one\n");
defer p.deinit();