summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 20:56:14 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit04b047fb366ea2c595708fb62467f690fce4b9ec (patch)
treeb2b765cbca96bcfd1785a39f60f0e0398a6aabb2 /src/pardes.zig
parent9554cc4c544632b01f740f895fd6db9f9952c02e (diff)
downloadpardes-04b047fb366ea2c595708fb62467f690fce4b9ec.tar.gz
pardes-04b047fb366ea2c595708fb62467f690fce4b9ec.zip
Terminal.zig is terminal.zig: a file of functions and no fields takes a namespace's lowercase name
The last of the deferred renames, now that the tty and theme agents have landed: panes.terminal at its importers, the alias lines in Text.zig and File.zig and panes.zig's own uses following. dump.zig's Terminal struct, a dump record, is not this. The served sources list and docs/design.typ name the new file. test/perf.zig's references change, so the three perf baselines take its new harness id with their numbers as recorded. No behaviour changes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig106
1 files changed, 53 insertions, 53 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index 141b214e..623af3c9 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -1195,9 +1195,9 @@ test "Tty9p marks only the new Linux terminal for a mounted shell" {
try std.testing.expect(pane.v9fs_on_spawn);
try std.testing.expect(!pane.greet);
try std.testing.expect(!exec.takesCommandLine(p, p.active));
- panes.Terminal.feedOutput(p, pane, "\x1b]133;A\x07$ \x1b]133;B\x07");
+ panes.terminal.feedOutput(p, pane, "\x1b]133;A\x07$ \x1b]133;B\x07");
try std.testing.expect(exec.takesCommandLine(p, p.active));
- panes.Terminal.feedOutput(p, pane, "\x1b]133;C\x07");
+ panes.terminal.feedOutput(p, pane, "\x1b]133;C\x07");
try std.testing.expect(!exec.takesCommandLine(p, p.active));
}
@@ -1558,7 +1558,7 @@ test "a command of several lines keeps its tag one row, and its echo does not st
_ = exec.execute(p, 1, two);
while (p.nextEffect()) |_| {}
_ = try p.render(frame.allocator());
- const body = try panes.Terminal.screenTextAlloc(pane, gpa);
+ const body = try panes.terminal.screenTextAlloc(pane, gpa);
defer gpa.free(body);
try std.testing.expect(std.mem.indexOf(u8, body, "% def greet(name):\n return name") != null);
}
@@ -1878,7 +1878,7 @@ test "a command pane shows how its command ended, and the next command there run
const pane = p.panes[dst].?;
// Its first command is echoed as every later one is.
{
- const first = try panes.Terminal.screenTextAlloc(pane, gpa);
+ const first = try panes.terminal.screenTextAlloc(pane, gpa);
defer gpa.free(first);
try std.testing.expect(std.mem.startsWith(u8, first, "% make -j8"));
}
@@ -1909,16 +1909,16 @@ test "a command pane shows how its command ended, and the next command there run
// A program that crashed out of its full screen leaves the emulator
// in its modes; the next command starts clear of them.
p.update(.{ .output = .{ .pane = @intCast(dst), .bytes = "\x1b[?1049h\x1b[?2004h\x1b[?1000h" } });
- try std.testing.expect(panes.Terminal.bracketedPaste(pane));
+ try std.testing.expect(panes.terminal.bracketedPaste(pane));
// Done, the directory's next command runs there, below what it showed.
try std.testing.expectEqual(@as(?usize, dst), exec.execute(p, 1, "make test"));
- try std.testing.expect(!panes.Terminal.bracketedPaste(pane));
+ try std.testing.expect(!panes.terminal.bracketedPaste(pane));
var respawned = false;
while (p.nextEffect()) |effect| if (effect == .spawn and effect.spawn.pane == dst) {
respawned = true;
};
try std.testing.expect(respawned);
- const body = try panes.Terminal.screenTextAlloc(pane, gpa);
+ const body = try panes.terminal.screenTextAlloc(pane, gpa);
defer gpa.free(body);
const said = std.mem.indexOf(u8, body, "compiled") orelse return error.OutputLost;
const ended = std.mem.indexOf(u8, body, "exit 2") orelse return error.ExitLost;
@@ -4394,7 +4394,7 @@ pub const Pardes = struct {
settings: config.Runtime = .{ .font = .{ .tagline_percent = config.gui_tagline_font_percent } },
locations_config: locations.Config = .{},
locations_cache: locations.Cache = .{},
- tty_filter_palette: panes.Terminal.FilterPalette = .{},
+ tty_filter_palette: panes.terminal.FilterPalette = .{},
font_request_taken: bool = false,
custom_theme: ?Theme = null,
/// bodyChrome's: the theme it was worked out for, and it.
@@ -4580,8 +4580,8 @@ pub const Pardes = struct {
/// that still own their loop pass their own arena to `render` instead.
frame_arena: std.heap.ArenaAllocator,
/// the terminal motion surface, memoized against the pane it was built
- /// for — see panes.Terminal.RowsCache for the lifetime rule
- shell_rows: panes.Terminal.RowsCache = .{},
+ /// for — see panes.terminal.RowsCache for the lifetime rule
+ shell_rows: panes.terminal.RowsCache = .{},
/// The message row's entry points, called from everywhere as
/// `p.setMessage(...)`; they live with the rest of it in Messages.zig.
@@ -4944,7 +4944,7 @@ pub const Pardes = struct {
}
p.shell_rows.dropPane(pane);
for (0..pane.pointer_selections.len) |slot| pane.clearPointerSelection(slot);
- panes.Terminal.deinitPendingCommand(pane);
+ panes.terminal.deinitPendingCommand(pane);
if (pane.command) |line| p.gpa.free(line);
if (pane.shell) |bin| p.gpa.free(bin);
if (pane.image) |*iv| {
@@ -4957,7 +4957,7 @@ pub const Pardes = struct {
pane.tag.deinit(p.gpa);
pane.input.deinit(p.gpa);
pane.jump.deinit(p.gpa);
- panes.Terminal.deinitEmulator(pane, p.gpa);
+ panes.terminal.deinitEmulator(pane, p.gpa);
pane.clearCwd();
pane.fs.deinit(p.gpa);
p.gpa.destroy(pane);
@@ -4986,12 +4986,12 @@ pub const Pardes = struct {
pub fn newShell(p: *Pardes, id: usize, cwd: []const u8) !*Pane {
std.debug.assert(p.panes[id] == null);
if (cwd.len > limits.host_path_cap) return error.PathTooLong;
- const pane = try panes.Terminal.create(p.gpa, p.screen_w, p.screen_h);
+ const pane = try panes.terminal.create(p.gpa, p.screen_w, p.screen_h);
// Named by the directory it is started in from the first, so the
// shell saying it is there is no rename (`new N /` then `rename`);
// out of memory for it, the shell names it when it says.
if (cwd.len > 0) pane.setOwnedCwd(cwd) catch {};
- panes.Terminal.armShellSpawn(pane);
+ panes.terminal.armShellSpawn(pane);
p.installPane(id, pane);
p.emitSpawn(id, pane.serial, cwd);
return pane;
@@ -5017,7 +5017,7 @@ pub const Pardes = struct {
if (cwd.len > limits.host_path_cap) return error.PathTooLong;
const owned = try p.gpa.dupe(u8, line);
errdefer p.gpa.free(owned);
- const pane = try panes.Terminal.create(p.gpa, p.screen_w, p.screen_h);
+ const pane = try panes.terminal.create(p.gpa, p.screen_w, p.screen_h);
pane.command = owned;
pane.command_pty = true;
pane.body.mode = .tty;
@@ -5031,7 +5031,7 @@ pub const Pardes = struct {
pub fn newDocPane(p: *Pardes, id: usize) !*Pane {
std.debug.assert(p.panes[id] == null);
- const pane = try panes.Terminal.createDoc(p.gpa, p.screen_w, p.screen_h);
+ const pane = try panes.terminal.createDoc(p.gpa, p.screen_w, p.screen_h);
p.installPane(id, pane);
return pane;
}
@@ -5223,7 +5223,7 @@ pub const Pardes = struct {
} else |_| {}
}
};
- if (id < MAX_PANES) panes.Terminal.shellSpawned(p, id, prompt_marks);
+ if (id < MAX_PANES) panes.terminal.shellSpawned(p, id, prompt_marks);
if (p.settings.shell.effective.set(executable))
p.settings.shell.pending = false;
}
@@ -5358,7 +5358,7 @@ pub const Pardes = struct {
/// The pane a session word runs with in an empty window.
pub fn standIn(p: *Pardes) ?*Pane {
- if (p.stand_in == null) p.stand_in = panes.Terminal.createDoc(p.gpa, p.screen_w, p.screen_h) catch null;
+ if (p.stand_in == null) p.stand_in = panes.terminal.createDoc(p.gpa, p.screen_w, p.screen_h) catch null;
return p.stand_in;
}
@@ -5627,7 +5627,7 @@ pub const Pardes = struct {
return;
}
if (!pane.isTerminal()) return;
- const text = panes.Terminal.screenTextAlloc(pane, p.gpa) catch return;
+ const text = panes.terminal.screenTextAlloc(pane, p.gpa) catch return;
defer p.gpa.free(text);
p.hostWriteFile(st.pane, st.path.slice(), text);
},
@@ -5839,7 +5839,7 @@ pub const Pardes = struct {
const pane = p.panes[o.pane] orelse return;
pane.shell_spoke = true;
ctlfs.events.notePtyOutput(p, o.pane, o.bytes);
- panes.Terminal.feedOutput(p, pane, o.bytes);
+ panes.terminal.feedOutput(p, pane, o.bytes);
ctlfs.pty.noteMarks(p, o.pane, pane);
exec.flushReplEnter(p, o.pane, true);
},
@@ -5944,7 +5944,7 @@ pub const Pardes = struct {
.normal => edit.enterInsert(p, &pane.body, .at, 1),
.insert => {
edit.exitInsert(p, &pane.body);
- if (pane.isTerminal()) panes.Terminal.enterTty(p, id);
+ if (pane.isTerminal()) panes.terminal.enterTty(p, id);
},
}
}
@@ -5960,7 +5960,7 @@ pub const Pardes = struct {
if (pane.body.mode == .tty) {
pane.body.mode = .normal;
pane.body.normal.clear();
- } else panes.Terminal.enterTty(p, id);
+ } else panes.terminal.enterTty(p, id);
}
/// Type `keys` again (a macro, `.`): through the modal handling as
@@ -6079,7 +6079,7 @@ pub const Pardes = struct {
return exec.runBuiltin(p, .Last, p.active, "", null);
if (key.cp == Key.escape and !key.ctrl and !key.alt and !key.shift and exec.takesCommandLine(p, p.active))
return exec.runBuiltin(p, .Last, p.active, "", null);
- panes.Terminal.followOutput(pane); // typing snaps back to live output
+ panes.terminal.followOutput(pane); // typing snaps back to live output
// Paste stays the window's, the one exception to forwarding a raw
// tty's keys: Ctrl-V types the register at the program and
// Ctrl-Shift-V asks the desktop for its clipboard first. Forwarded,
@@ -6094,7 +6094,7 @@ pub const Pardes = struct {
// Ctrl-V a black hole in every full-screen application.
if (p.registers.text(p.gpa, Registers.default)) |text| return edit.typeToTty(p, p.active, pane, text);
}
- return panes.Terminal.forwardKey(p, p.active, key);
+ return panes.terminal.forwardKey(p, p.active, key);
}
if (p.leader_on) return p.leaderKey(key);
if (p.ctrl_w_pending) {
@@ -6247,7 +6247,7 @@ pub const Pardes = struct {
edit.exitInsert(p, t)
else
edit.handleInsert(p, t, key),
- .tty => panes.Terminal.forwardKey(p, p.active, key),
+ .tty => panes.terminal.forwardKey(p, p.active, key),
}
// `.`'s log: the keys of the normal command that entered insert
// mode, then everything typed until it is left
@@ -6738,7 +6738,7 @@ pub const Pardes = struct {
errdefer p.gpa.free(path);
const history = try panes.File.History.create(p.gpa);
errdefer p.gpa.destroy(history);
- const pane = try panes.Terminal.createDoc(p.gpa, p.screen_w, p.screen_h);
+ const pane = try panes.terminal.createDoc(p.gpa, p.screen_w, p.screen_h);
errdefer p.gpa.destroy(pane);
try p.deinitPane(p.panes[0].?);
p.panes[0] = null;
@@ -7086,7 +7086,7 @@ pub const Pardes = struct {
// doc panes have no pty/emulator grid to reflow; just record
// the size so bodyText renders the right number of rows
if (pane.isTerminal()) {
- panes.Terminal.resizeGrid(pane, p.gpa, cols, rows);
+ panes.terminal.resizeGrid(pane, p.gpa, cols, rows);
p.shell_rows.markStale(pane); // reflow moved every row
p.emit(.{ .resize_pty = .{ .pane = @intCast(id), .cols = cols, .rows = rows } });
pane.fs.winsize = null;
@@ -7095,12 +7095,12 @@ pub const Pardes = struct {
pane.rows = rows;
if (pane.file) |*file| file.syntax_dirty = true;
}
- panes.Terminal.releasePendingCommandIfReady(p, id, pane);
+ panes.terminal.releasePendingCommandIfReady(p, id, pane);
// The greeting `ls` of a new terminal in a directory is typed at
// its shell's FIRST prompt, or never: typed later it would land
// in whatever runs then, or in the middle of a line someone
- // typed (panes.Terminal.greeting).
- if (pane.greet and pane.isTerminal() and p.resize_count > 0) switch (panes.Terminal.greeting(pane)) {
+ // typed (panes.terminal.greeting).
+ if (pane.greet and pane.isTerminal() and p.resize_count > 0) switch (panes.terminal.greeting(pane)) {
.wait => {},
.never => pane.greet = false,
.now => {
@@ -7381,7 +7381,7 @@ test "argv naming nothing boots an errors pane rather than failing the launch" {
}
test "raw terminal cursor obeys visibility without hiding modal and tag cursors" {
- if (comptime !panes.Terminal.enabled) return error.SkipZigTest;
+ if (comptime !panes.terminal.enabled) return error.SkipZigTest;
const gpa = std.testing.allocator;
const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 40, .rows = 12 });
defer p.deinit();
@@ -7426,7 +7426,7 @@ test "raw terminal cursor obeys visibility without hiding modal and tag cursors"
}
test "raw terminal cursor follows its active row only while that row is visible" {
- if (comptime !panes.Terminal.enabled) return error.SkipZigTest;
+ if (comptime !panes.terminal.enabled) return error.SkipZigTest;
const gpa = std.testing.allocator;
for ([_]bool{ false, true }) |tag_bottom| {
const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 40, .rows = 12 });
@@ -7445,13 +7445,13 @@ test "raw terminal cursor follows its active row only while that row is visible"
try std.testing.expectEqual(rect.x + config.GUTTER + 3, live.x);
try std.testing.expectEqual(body_y + 2, live.y);
- panes.Terminal.scrollGrid(pane, -1);
+ panes.terminal.scrollGrid(pane, -1);
const scrolled = (try p.render(frame.allocator())).cursor orelse return error.MissingCursor;
try std.testing.expectEqual(live.x, scrolled.x);
try std.testing.expectEqual(live.y + 1, scrolled.y);
- panes.Terminal.scrollGrid(pane, -@as(i32, pane.rows));
+ panes.terminal.scrollGrid(pane, -@as(i32, pane.rows));
try std.testing.expect((try p.render(frame.allocator())).cursor == null);
- panes.Terminal.followOutput(pane);
+ panes.terminal.followOutput(pane);
const returned = (try p.render(frame.allocator())).cursor orelse return error.MissingCursor;
try std.testing.expectEqual(live.x, returned.x);
try std.testing.expectEqual(live.y, returned.y);
@@ -7895,31 +7895,31 @@ test "tty output follows only from the bottom" {
p.update(.{ .output = .{ .pane = @intCast(shell), .bytes = std.fmt.bufPrint(&buf, "line {d}\r\n", .{i}) catch unreachable } });
}
p.sync();
- const bottom = panes.Terminal.scrollbar(sp).offset;
+ const bottom = panes.terminal.scrollbar(sp).offset;
try std.testing.expect(bottom > 0);
// Scrolled back, the reader stays put however much the shell prints.
sp.scrollBy(-10);
p.sync();
- const parked = panes.Terminal.scrollbar(sp).offset;
+ const parked = panes.terminal.scrollbar(sp).offset;
try std.testing.expect(parked < bottom);
for (60..70) |i| {
var buf: [32]u8 = undefined;
p.update(.{ .output = .{ .pane = @intCast(shell), .bytes = std.fmt.bufPrint(&buf, "line {d}\r\n", .{i}) catch unreachable } });
}
p.sync();
- try std.testing.expectEqual(parked, panes.Terminal.scrollbar(sp).offset);
+ try std.testing.expectEqual(parked, panes.terminal.scrollbar(sp).offset);
// Typing snaps back to live output, so nobody types blind.
p.update(.{ .key = .{ .cp = 'x', .text = "x" } });
p.sync();
- try std.testing.expect(panes.Terminal.scrollbar(sp).offset > parked);
+ try std.testing.expect(panes.terminal.scrollbar(sp).offset > parked);
// ...and from there output follows again.
- const live = panes.Terminal.scrollbar(sp).offset;
+ const live = panes.terminal.scrollbar(sp).offset;
p.update(.{ .output = .{ .pane = @intCast(shell), .bytes = "tail\r\n" } });
p.sync();
- try std.testing.expect(panes.Terminal.scrollbar(sp).offset > live);
+ try std.testing.expect(panes.terminal.scrollbar(sp).offset > live);
}
test "Esc back into a file leaves its view where it was" {
@@ -8135,7 +8135,7 @@ test "an unasked desktop paste reaches a tty pane's program, not its buffer" {
_ = drainWrites(p, &buf);
const pane = p.panes[0].?;
- panes.Terminal.enterTty(p, 0);
+ panes.terminal.enterTty(p, 0);
// No request behind it: the window manager's own paste, or SDL answering a
// Ctrl-Shift-V the desktop handled. It still has to reach the shell.
p.update(.{ .paste = "ls -la" });
@@ -8153,7 +8153,7 @@ test "a paste larger than the effect ring reaches the program whole and in order
const buf = try gpa.alloc(u8, 1 << 20);
defer gpa.free(buf);
_ = drainWrites(p, buf);
- panes.Terminal.enterTty(p, 0);
+ panes.terminal.enterTty(p, 0);
const text = try gpa.alloc(u8, 300 * 1024);
defer gpa.free(text);
@@ -8166,7 +8166,7 @@ test "a paste larger than the effect ring reaches the program whole and in order
test "a bracketed paste larger than the ring still closes its bracket" {
if (platform == .web) return;
- if (comptime !panes.Terminal.enabled) return;
+ if (comptime !panes.terminal.enabled) return;
const gpa = std.testing.allocator;
const p = try Pardes.init(gpa, .{ .tty_only = true, .cols = 80, .rows = 24 });
defer p.deinit();
@@ -8174,10 +8174,10 @@ test "a bracketed paste larger than the ring still closes its bracket" {
const buf = try gpa.alloc(u8, 1 << 20);
defer gpa.free(buf);
_ = drainWrites(p, buf);
- panes.Terminal.enterTty(p, 0);
+ panes.terminal.enterTty(p, 0);
p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b[?2004h" } });
- try std.testing.expect(panes.Terminal.bracketedPaste(p.panes[0].?));
+ try std.testing.expect(panes.terminal.bracketedPaste(p.panes[0].?));
const text = try gpa.alloc(u8, 300 * 1024);
defer gpa.free(text);
@memset(text, 'z');
@@ -8197,7 +8197,7 @@ test "pasted bytes still queued at shutdown are freed, not leaked" {
const buf = try gpa.alloc(u8, 1 << 20);
defer gpa.free(buf);
_ = drainWrites(p, buf);
- panes.Terminal.enterTty(p, 0);
+ panes.terminal.enterTty(p, 0);
const text = try gpa.alloc(u8, 300 * 1024);
defer gpa.free(text);
@@ -8227,14 +8227,14 @@ test "leaving tty hides the prompt and keeps the command typed at it" {
const rowOf = struct {
fn at(pp: *Pardes, pane: *Pane, needle: []const u8) ?[]const u8 {
- const rows = panes.Terminal.shellRows(pp, pane) catch return null;
+ const rows = panes.terminal.shellRows(pp, pane) catch return null;
for (rows) |r| if (std.mem.indexOf(u8, r, needle) != null) return r;
return null;
}
}.at;
const bodyRowOf = struct {
fn at(pp: *Pardes, pane: *Pane, needle: []const u8) ?[]const u8 {
- const body = panes.Terminal.bodyText(pp.scratch.allocator(), pane) catch return null;
+ const body = panes.terminal.bodyText(pp.scratch.allocator(), pane) catch return null;
var it = std.mem.splitScalar(u8, body, '\n');
while (it.next()) |r| if (std.mem.indexOf(u8, r, needle) != null) return r;
return null;
@@ -8290,7 +8290,7 @@ test "entering tty walks the shell cursor to the column clicked past the prompt"
p.shell_rows.stale = true;
// The command shows LEFT-HUGGED, so its column 3 is the '3'...
- const rows = try panes.Terminal.shellRows(p, sp);
+ const rows = try panes.terminal.shellRows(p, sp);
var row: i32 = 0;
const at = for (rows, 0..) |r, i| {
if (std.mem.indexOf(u8, r, "0123456789") != null) break i;
@@ -8304,7 +8304,7 @@ test "entering tty walks the shell cursor to the column clicked past the prompt"
sp.body.cur_col = 3;
sp.body.cur_pinned = true;
while (p.nextEffect()) |_| {}
- panes.Terminal.enterTty(p, shell);
+ panes.terminal.enterTty(p, shell);
// The walk is arrow keys the shell understands. Seven lefts: readline's
// cursor sits past the '9' and the click was on the '3'.
@@ -8347,7 +8347,7 @@ test "board heap: every inline ring the board pays for still fits its budget" {
const effect_ring = 128 * @sizeOf(Effect);
// ...and the undo history, the largest in `Pane` once the terminal is out:
// 16 snapshots on the board against 256 on a desktop.
- const undo_history = 2 * 16 * @sizeOf(panes.Terminal.Snapshot);
+ const undo_history = 2 * 16 * @sizeOf(panes.terminal.Snapshot);
const grid = @as(usize, board_cols) * board_rows * (2 * @sizeOf(Cell) + @sizeOf(PanelCellDiff));
// Each of the three separately, so a failure names the one that grew
@@ -8475,7 +8475,7 @@ test "jump history terminal rectangle follows output and clears on reflow" {
try std.testing.expectEqualStrings("alpha", try edit.selectionText(p, pane, pane.sel[0]));
for (0..40) |_| p.update(.{ .output = .{ .pane = 0, .bytes = "more output\r\n" } });
try std.testing.expectEqualStrings("alpha", try edit.selectionText(p, pane, pane.sel[0]));
- panes.Terminal.resizeGrid(pane, p.gpa, pane.cols - 1, pane.rows);
+ panes.terminal.resizeGrid(pane, p.gpa, pane.cols - 1, pane.rows);
try std.testing.expect(pane.pointerSelection(pane.sel[0]) == null);
try std.testing.expectEqual(.none, pane.sel[0].state);
}