diff options
Diffstat (limited to 'src/Terminal.zig')
| -rw-r--r-- | src/Terminal.zig | 114 |
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 { |
