summaryrefslogtreecommitdiff
path: root/src/Terminal.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Terminal.zig')
-rw-r--r--src/Terminal.zig114
1 files changed, 57 insertions, 57 deletions
diff --git a/src/Terminal.zig b/src/Terminal.zig
index cb752613..fbe7bfc0 100644
--- a/src/Terminal.zig
+++ b/src/Terminal.zig
@@ -200,7 +200,7 @@ pub const Snapshot = struct {
ovl: ?EditBuffer,
cur_row: i32,
cur_col: i32,
- vsel: Pane.CharSel,
+ vsel: panes.Text.CharSel,
};
pub const PendingCommand = struct {
@@ -677,16 +677,16 @@ pub fn feedOutput(p: *Pardes, pane: *Pane, bytes: []const u8) void {
// There are no pty reads at all without an emulator to parse them into.
if (comptime !enabled) return;
if (pane.terminal == null) return;
- const has_positions = pane.ovl != null or pane.cur_pinned or pane.vsel.active or
- pane.msel.active or pane.nsel > 0 or pane.append_at != null or pane.look_at != null or
- pane.ed_undo_len > 0 or pane.ed_redo_len > 0 or pointerRowCount(pane) > 0;
+ const has_positions = pane.ovl != null or pane.body.cur_pinned or pane.body.vsel.active or
+ pane.body.msel.active or pane.body.nsel > 0 or pane.body.append_at != null or pane.look_at != null or
+ pane.body.ed_undo_len > 0 or pane.body.ed_redo_len > 0 or pointerRowCount(pane) > 0;
// Sticky bottom, as every other terminal does it: output drags the
// viewport down only when the viewport was already on the last row, so
// a reader scrolled back into the scrollback stays where they scrolled.
const at_bottom = atBottom(pane);
if (has_positions) ingestWithPositions(pane, bytes) else ingest(pane, bytes);
p.shell_rows.markStale(pane);
- const body_mode = if (pane.tag_edit) pane.tag_mode else pane.mode;
+ const body_mode = if (pane.tag_edit) pane.tag_mode else pane.body.mode;
if (body_mode == .tty and at_bottom) followOutput(pane);
}
@@ -752,15 +752,15 @@ fn ingestWithPositions(pane: *Pane, bytes: []const u8) void {
const key = screens.active_key;
const generation = screens.generation(key);
const pages = &screens.active.pages;
- const Group = struct { overlay: ?*EditBuffer, cursor: *i32, selection: *Pane.CharSel };
+ const Group = struct { overlay: ?*EditBuffer, cursor: *i32, selection: *panes.Text.CharSel };
var groups: [history_max * 2 + 1]Group = undefined;
groups[0] = .{
.overlay = if (pane.ovl) |*overlay| overlay else null,
- .cursor = &pane.cur_row,
- .selection = &pane.vsel,
+ .cursor = &pane.body.cur_row,
+ .selection = &pane.body.vsel,
};
var ngroups: usize = 1;
- for ([_][]Snapshot{ pane.ed_undo[0..pane.ed_undo_len], pane.ed_redo[0..pane.ed_redo_len] }) |history| {
+ for ([_][]Snapshot{ pane.body.ed_undo[0..pane.body.ed_undo_len], pane.body.ed_redo[0..pane.body.ed_redo_len] }) |history| {
for (history) |*snapshot| {
groups[ngroups] = .{
.overlay = if (snapshot.ovl) |*overlay| overlay else null,
@@ -773,7 +773,7 @@ fn ingestWithPositions(pane: *Pane, bytes: []const u8) void {
const Span = struct { overlay: *EditBuffer, start: RowPin, end: RowPin };
var spans: [groups.len]Span = undefined;
var nspans: usize = 0;
- var positions: [groups.len * 2 + Pane.max_selections * 2 + 4]PositionPin = undefined;
+ var positions: [groups.len * 2 + panes.Text.max_selections * 2 + 4]PositionPin = undefined;
var npositions: usize = 0;
var failed = false;
for (groups[0..ngroups]) |group| {
@@ -793,19 +793,19 @@ fn ingestWithPositions(pane: *Pane, bytes: []const u8) void {
}
}
const overlay = groups[0].overlay;
- var extra: [Pane.max_selections * 2 + 4]*i32 = undefined;
+ var extra: [panes.Text.max_selections * 2 + 4]*i32 = undefined;
var nextra: usize = 0;
- if (pane.msel.active) {
- extra[nextra] = &pane.msel.r0;
- extra[nextra + 1] = &pane.msel.r1;
+ if (pane.body.msel.active) {
+ extra[nextra] = &pane.body.msel.r0;
+ extra[nextra + 1] = &pane.body.msel.r1;
nextra += 2;
}
- for (pane.sels[0..pane.nsel]) |*selection| {
+ for (pane.body.sels[0..pane.body.nsel]) |*selection| {
extra[nextra] = &selection.row;
extra[nextra + 1] = &selection.arow;
nextra += 2;
}
- if (pane.append_at) |*at| {
+ if (pane.body.append_at) |*at| {
extra[nextra] = &at.row;
nextra += 1;
}
@@ -883,7 +883,7 @@ test "raw terminal output needs no position tracking allocations" {
const p = try Pardes.init(failing.allocator(), .{ .tty_only = true, .cols = 80, .rows = 24 });
defer p.deinit();
const pane = p.panes[0].?;
- pane.mode = .tty;
+ pane.body.mode = .tty;
feedOutput(p, pane, "warm");
const allocations = failing.alloc_index;
failing.fail_index = allocations;
@@ -1045,13 +1045,13 @@ pub fn forwardKey(p: *Pardes, id: usize, key: Key) void {
pub fn enterTty(p: *Pardes, id: usize) void {
const pane = p.panes[id] orelse return;
const selected = pane.rawPointerText(pane.sel[@intFromEnum(config.select_button)]) != null;
- if (comptime enabled) if (!selected and pane.terminal != null and pane.cur_pinned and pane.terminal.?.vt.cursorIsAtPrompt()) handoff: {
+ if (comptime enabled) if (!selected and pane.terminal != null and pane.body.cur_pinned and pane.terminal.?.vt.cursorIsAtPrompt()) handoff: {
const screen = pane.terminal.?.vt.screens.active;
const goff: i32 = @intCast(screen.pages.scrollbar().offset);
- const vp_row = pane.gridRow(pane.cur_row) - goff;
+ const vp_row = pane.gridRow(pane.body.cur_row) - goff;
if (vp_row < 0) break :handoff;
- var grid_col: i32 = @max(0, pane.cur_col);
+ var grid_col: i32 = @max(0, pane.body.cur_col);
if (screen.pages.pin(.{ .viewport = .{ .x = 0, .y = @intCast(vp_row) } })) |row_pin| {
if (row_pin.rowAndCell().row.semantic_prompt != .none) switch (promptCut(row_pin)) {
.cut => |cols| grid_col += @intCast(cols),
@@ -1070,18 +1070,18 @@ pub fn enterTty(p: *Pardes, id: usize) void {
for (0..moves.right) |_| p.emitWrite(id, "\x1b[C");
};
- pane.mode = .tty;
+ pane.body.mode = .tty;
followOutput(pane); // entering raw mode is a request for the live shell
- pane.msel.active = false;
- pane.vsel.active = false;
- pane.nsel = 0;
+ pane.body.msel.active = false;
+ pane.body.vsel.active = false;
+ pane.body.nsel = 0;
// The raw renderer follows the live cursor. A captured mouse selection
// keeps its modal endpoint for the next return to editor mode.
- pane.cur_pinned = selected;
- pane.select = false;
- pane.append_at = null;
- pane.sticky_col = -1;
- pane.normal.clear();
+ pane.body.cur_pinned = selected;
+ pane.body.select = false;
+ pane.body.append_at = null;
+ pane.body.sticky_col = -1;
+ pane.body.normal.clear();
}
// Returned slices remain valid until the next cache rebuild or reset.
@@ -1397,7 +1397,7 @@ pub fn dumpPane(
var skip: i32 = 0;
while (lines.next()) |raw| : (row += 1) {
// Hidden overlay rows still consume prompt pins to keep them aligned.
- const prompt = if (pane.mode != .tty) prompts.next() else null;
+ const prompt = if (pane.body.mode != .tty) prompts.next() else null;
if (skip > 0) {
skip -= 1;
continue;
@@ -1406,7 +1406,7 @@ pub fn dumpPane(
stream[len] = '\n';
len += 1;
}
- if (pane.mode != .tty) if (pane.ovl) |overlay| if (row == overlay.row) {
+ if (pane.body.mode != .tty) if (pane.ovl) |overlay| if (row == overlay.row) {
@memcpy(stream[len..][0..overlay.text.len], overlay.text);
len += overlay.text.len;
skip = overlay.rows - 1;
@@ -1493,7 +1493,7 @@ pub fn bodyText(arena: std.mem.Allocator, pane: *Pane) ![]const u8 {
var lines = std.mem.splitScalar(u8, raw, '\n');
var n: usize = 0;
while (lines.next()) |ln| {
- vp[n] = if (pane.mode != .tty)
+ vp[n] = if (pane.body.mode != .tty)
if (prompts.next()) |pin|
if (pin.rowAndCell().row.semantic_prompt != .none) promptRow(pin, ln) else ln
else
@@ -1535,7 +1535,7 @@ const BodyWalk = struct {
return .{
.pane = pane,
.goff = goff,
- .g = if (pane.mode == .tty) goff else pane.gridRow(off),
+ .g = if (pane.body.mode == .tty) goff else pane.gridRow(off),
.skip = if (pane.ovl) |o| @intCast(@max(0, off - pane.surfRow(o.row))) else 0,
};
}
@@ -1562,7 +1562,7 @@ const BodyWalk = struct {
w.lines = null;
continue;
}
- if (w.pane.mode != .tty) if (w.pane.ovl) |o| if (w.g == o.row) {
+ if (w.pane.body.mode != .tty) if (w.pane.ovl) |o| if (w.g == o.row) {
w.lines = std.mem.splitScalar(u8, o.text, '\n');
w.covered = o.rows;
w.line_idx = 0;
@@ -1759,7 +1759,7 @@ pub fn recolorAnsi(p: *Pardes, pane: *Pane, r: pardes.Rect, tx: u16, tw: u16, bo
const vi = anchor.row;
if (vi < 0 or vi >= vp_rows) continue;
const row_pin = pages.pin(.{ .viewport = .{ .y = @intCast(vi) } }) orelse continue;
- const cut: u16 = if (pane.mode == .tty) 0 else cut: {
+ const cut: u16 = if (pane.body.mode == .tty) 0 else cut: {
if (row_pin.rowAndCell().row.semantic_prompt == .none) break :cut 0;
break :cut switch (promptCut(row_pin)) {
.keep => 0,
@@ -2388,13 +2388,13 @@ test "tty ansi colors follow the prompt hug into normal mode" {
const blue: pardes.Color = .{ .rgb = p.theme().palette.?[4] };
// tty mode projects the emulator's ansi colours cell for cell.
- pane.mode = .tty;
+ pane.body.mode = .tty;
p.shell_rows.stale = true;
const tty = try p.render(frame.allocator());
try testing.expectEqual(red, tty.at(tx + 2, body_y).style.fg);
try testing.expectEqual(blue, tty.at(tx + 3, body_y).style.fg);
- pane.mode = .normal;
+ pane.body.mode = .normal;
p.shell_rows.stale = true;
_ = frame.reset(.retain_capacity);
const norm = try p.render(frame.allocator());
@@ -2411,7 +2411,7 @@ test "a prompt row hidden end to end paints nothing at all" {
while (p.nextEffect()) |_| {}
const pane = p.panes[0].?;
pane.tty_filter = false;
- pane.mode = .normal;
+ pane.body.mode = .normal;
p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;A\x1b\\\x1b[32maaaaaaaaa\x1b]133;B\x1b\\\x1b[41;36m\u{754C}\x1b[0m\r\n" } });
var frame = std.heap.ArenaAllocator.init(testing.allocator);
@@ -2467,7 +2467,7 @@ pub fn padOutputBelowEdits(p: *Pardes, id: usize) void {
pub fn snap(p: *Pardes, pane: *Pane) ?Snapshot {
var ovl: ?EditBuffer = null;
if (pane.ovl) |o| ovl = .{ .row = o.row, .rows = o.rows, .text = p.gpa.dupe(u8, o.text) catch return null };
- return .{ .ovl = ovl, .cur_row = pane.cur_row, .cur_col = pane.cur_col, .vsel = pane.vsel };
+ return .{ .ovl = ovl, .cur_row = pane.body.cur_row, .cur_col = pane.body.cur_col, .vsel = pane.body.vsel };
}
/// undo/redo restores the selection recorded with the snapshot (helix
@@ -2475,11 +2475,11 @@ pub fn snap(p: *Pardes, pane: *Pane) ?Snapshot {
pub fn restoreSnap(p: *Pardes, pane: *Pane, s: Snapshot) void {
if (pane.ovl) |o| p.gpa.free(o.text);
pane.ovl = s.ovl;
- pane.cur_row = s.cur_row;
- pane.cur_col = s.cur_col;
- pane.cur_pinned = true;
- pane.vsel = s.vsel;
- pane.msel.active = false;
+ pane.body.cur_row = s.cur_row;
+ pane.body.cur_col = s.cur_col;
+ pane.body.cur_pinned = true;
+ pane.body.vsel = s.vsel;
+ pane.body.msel.active = false;
pane.ensureCursorVisible();
}
@@ -2495,32 +2495,32 @@ fn pushHistory(gpa: std.mem.Allocator, slots: []Snapshot, len: *usize, value: Sn
pub fn pushUndo(p: *Pardes, pane: *Pane) void {
const current = pane.ovl orelse EditBuffer{ .rows = 0 };
- if (pane.ed_undo_len > 0) {
- const top = pane.ed_undo[pane.ed_undo_len - 1];
+ if (pane.body.ed_undo_len > 0) {
+ const top = pane.body.ed_undo[pane.body.ed_undo_len - 1];
const same = if (top.ovl) |overlay| pane.ovl != null and overlay.row == current.row and
overlay.rows == current.rows and std.mem.eql(u8, overlay.text, current.text) else pane.ovl == null;
if (same) return;
}
const value = snap(p, pane) orelse return;
- pushHistory(p.gpa, &pane.ed_undo, &pane.ed_undo_len, value);
- for (pane.ed_redo[0..pane.ed_redo_len]) |item| if (item.ovl) |overlay| p.gpa.free(overlay.text);
- pane.ed_redo_len = 0;
+ pushHistory(p.gpa, &pane.body.ed_undo, &pane.body.ed_undo_len, value);
+ for (pane.body.ed_redo[0..pane.body.ed_redo_len]) |item| if (item.ovl) |overlay| p.gpa.free(overlay.text);
+ pane.body.ed_redo_len = 0;
}
pub fn undo(p: *Pardes, pane: *Pane) void {
- if (pane.ed_undo_len == 0) return;
+ if (pane.body.ed_undo_len == 0) return;
const current = snap(p, pane) orelse return;
- pushHistory(p.gpa, &pane.ed_redo, &pane.ed_redo_len, current);
- pane.ed_undo_len -= 1;
- restoreSnap(p, pane, pane.ed_undo[pane.ed_undo_len]);
+ pushHistory(p.gpa, &pane.body.ed_redo, &pane.body.ed_redo_len, current);
+ pane.body.ed_undo_len -= 1;
+ restoreSnap(p, pane, pane.body.ed_undo[pane.body.ed_undo_len]);
}
pub fn redo(p: *Pardes, pane: *Pane) void {
- if (pane.ed_redo_len == 0) return;
+ if (pane.body.ed_redo_len == 0) return;
const current = snap(p, pane) orelse return;
- pushHistory(p.gpa, &pane.ed_undo, &pane.ed_undo_len, current);
- pane.ed_redo_len -= 1;
- restoreSnap(p, pane, pane.ed_redo[pane.ed_redo_len]);
+ pushHistory(p.gpa, &pane.body.ed_undo, &pane.body.ed_undo_len, current);
+ pane.body.ed_redo_len -= 1;
+ restoreSnap(p, pane, pane.body.ed_redo[pane.body.ed_redo_len]);
}
pub fn ptyReport(handler: *ghostty_vt.TerminalStream.Handler, data: [:0]const u8) void {