diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 01:09:05 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | f48ab559a4d257137a3aae987a4962f9d74ede23 (patch) | |
| tree | 99b233f7386673ee7a84031f4e5ff1b3011adae0 /src/edit.zig | |
| parent | fb72c2402fa1b1ae99be64fe7b2947ea5dd42623 (diff) | |
| download | pardes-f48ab559a4d257137a3aae987a4962f9d74ede23.tar.gz pardes-f48ab559a4d257137a3aae987a4962f9d74ede23.zip | |
Have Text.pane return nothing for a header instead of trapping
A column's or the workspace's tag has no pane, and asking one for it hit
unreachable; every caller guarded against that by checking `what` first.
An optional makes each caller say what it does without a pane, so a
forgotten guard no longer compiles into a crash.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/edit.zig')
| -rw-r--r-- | src/edit.zig | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/src/edit.zig b/src/edit.zig index 42032168..837a22c6 100644 --- a/src/edit.zig +++ b/src/edit.zig @@ -315,7 +315,7 @@ pub fn paneCursorLines(p: *Pardes, t: *Text) ![]const []const u8 { for (lines) |*line| line.* = it.next().?; return lines; } - const pane = t.pane(); + const pane = t.pane() orelse return &.{}; if (pane.file) |*f| return panes.File.cursorLines(arena, pane, f); if (pane.hasPdf()) { if (comptime pdf_enabled) return panes.Pdf.textLines(&pane.pdf.?, p.pdf_gpa, arena); @@ -325,8 +325,8 @@ pub fn paneCursorLines(p: *Pardes, t: *Text) ![]const []const u8 { } pub fn paneByteAtDisplay(p: *Pardes, t: *Text, row: i32, from_raw: i32, display_col: i32) i32 { - if (t.what == .body and t.pane().file != null) - return panes.File.byteAtRowDisplay(t.pane(), row, from_raw, display_col); + if (t.what == .body) if (t.pane()) |pane| if (pane.file != null) + return panes.File.byteAtRowDisplay(pane, row, from_raw, display_col); const lines = paneCursorLines(p, t) catch return @max(0, from_raw + display_col); const local = row; if (local < 0 or @as(usize, @intCast(local)) >= lines.len) @@ -347,7 +347,7 @@ pub fn pinPaneCursor(p: *Pardes, t: *Text) void { t.cur_pinned = true; return; } - const pane = t.pane(); + const pane = t.pane() orelse return; pane.pinCursor(); if (pane.file == null and !pane.hasPdf()) t.cur_col = paneByteAtDisplay(p, t, t.cur_row, 0, t.cur_col); @@ -356,11 +356,11 @@ pub fn pinPaneCursor(p: *Pardes, t: *Text) void { pub fn flatSurface(p: *Pardes, t: *Text) ![]const u8 { switch (t.what) { .body => {}, - .tag => return tagline.curTail(t.pane()), + .tag => return if (t.pane()) |pane| tagline.curTail(pane) else "", .input => return t.own orelse "", .column, .workspace => return t.own orelse tagline.headerDefault(p, t.what), } - const pane = t.pane(); + const pane = t.pane() orelse return ""; if (pane.file) |f| return f.content; if (pane.hasPdf()) { if (comptime pdf_enabled) return pane.pdf.?.ensureText(p.pdf_gpa); @@ -372,7 +372,7 @@ pub fn flatSurface(p: *Pardes, t: *Text) ![]const u8 { pub fn paneWrapWidth(p: *const Pardes, t: *Text) usize { if (t.what != .body) return 0; - const pane = t.pane(); + const pane = t.pane() orelse return 0; if (pane.file == null) return 0; return panes.File.wrapWidth(pane, p.settings.wrap); } @@ -385,7 +385,7 @@ fn editText(p: *Pardes, t: *Text, lo: i32, hi: i32, col: i32) ?panes.EditText { if (t.what != .body and t.what != .input and t.own == null) t.own = p.gpa.dupe(u8, flatSurface(p, t) catch return null) catch return null; if (t.what != .body) return .{ .text = t.own orelse &.{}, .row0 = 0 }; - const pane = t.pane(); + const pane = t.pane() orelse return null; if (pane.file) |f| return .{ .text = f.content, .row0 = 0 }; if (pane.image != null or pane.hasPdf()) return null; return panes.Terminal.editText(p, pane, lo, hi, col); @@ -406,7 +406,7 @@ fn setEditText(p: *Pardes, t: *Text, new: []u8) void { t.own = new; return; } - const pane = t.pane(); + const pane = t.pane() orelse return p.gpa.free(new); if (pane.file) |*f| return panes.File.setContent(p, f, new); panes.Terminal.setEditText(p, pane, new); } @@ -417,7 +417,7 @@ pub const InsertAt = enum { at, append, line_start, line_end, open_below, open_a /// Terminal overlays can materialize virtual rows/columns, so keep those. pub fn clampFileCursor(t: *Text) bool { if (t.what != .body) return false; - const pane = t.pane(); + const pane = t.pane() orelse return false; const file = if (pane.file) |*file| file else return false; const old_row = t.cur_row; const old_col = t.cur_col; @@ -429,7 +429,7 @@ pub fn clampFileCursor(t: *Text) bool { } pub fn enterInsert(p: *Pardes, t: *Text, where: InsertAt, cnt: usize) void { - if (t.what == .body and t.pane().hasPdf()) return; + if (t.what == .body) if (t.pane()) |pane| if (pane.hasPdf()) return; pinPaneCursor(p, t); _ = clampFileCursor(t); // snapshot once per insert session (WITH the pre-insert selection) so @@ -563,7 +563,7 @@ pub fn insertKey(p: *Pardes, t: *Text, key: Key) void { const flat = flatSurface(p, t) catch return; const range = t.primaryRange(flat, 0); if (t.what != .body) return; - const step: i32 = @intCast(@max(1, t.pane().rows)); + const step: i32 = @intCast(@max(1, (t.pane() orelse return).rows)); t.scrollViewMove(flat, range, if (key.cp == Key.page_down) step else -step); return; }, @@ -710,7 +710,7 @@ pub fn insertKey(p: *Pardes, t: *Text, key: Key) void { const ln = modal.lineSlice(text, c.row); if (!p.multi_on and c.col > 0 and c.col <= ln.len and ln[c.col - 1] == '.') dot: { if (t.what != .body) break :dot; - const f = t.pane().file orelse break :dot; + const f = (t.pane() orelse break :dot).file orelse break :dot; if (f.output != null or !lsp.speaks(f.path)) break :dot; const seq = p.lsp_seq; p.lspRequest(p.active, .completion, ""); @@ -849,7 +849,7 @@ pub fn normalDelete(p: *Pardes, t: *Text, yank: bool) void { pub fn normalYank(p: *Pardes, t: *Text) void { t.select = false; - if (t.what == .body) if (t.pane().rawPointerText(t.pane().sel[sel_slot])) |text| { + if (t.what == .body) if (t.pane()) |pane| if (pane.rawPointerText(pane.sel[sel_slot])) |text| { setYank(p, text); return; }; @@ -1324,7 +1324,8 @@ pub fn normalToggleComment(p: *Pardes, t: *Text) void { } next = @max(next, end); } - const ext = if (t.what != .body) "" else if (t.pane().file) |f| std.fs.path.extension(f.path) else ""; + const file = if (t.what != .body) null else if (t.pane()) |pane| pane.file else null; + const ext = if (file) |f| std.fs.path.extension(f.path) else ""; var token: []const u8 = config.comment_token_default; lang: for (config.comment_tokens) |row| { for (row.exts) |e| if (std.ascii.eqlIgnoreCase(ext, e)) { @@ -1567,7 +1568,7 @@ pub fn pushUndo(p: *Pardes, t: *Text) void { // a prompt's answer is typed once and gone; it keeps no history .input => return, } - const pane = t.pane(); + const pane = t.pane() orelse return; if (pane.file != null) return panes.File.pushUndo(p, pane); panes.Terminal.pushUndo(p, pane); } @@ -1575,7 +1576,7 @@ pub fn pushUndo(p: *Pardes, t: *Text) void { pub fn doUndo(p: *Pardes, t: *Text) void { if (t.what == .tag or t.what == .column or t.what == .workspace) return stepOwn(p, t, true); if (t.what != .body) return; - const pane = t.pane(); + const pane = t.pane() orelse return; if (pane.file != null) return panes.File.undo(p, pane); panes.Terminal.undo(p, pane); } @@ -1583,7 +1584,7 @@ pub fn doUndo(p: *Pardes, t: *Text) void { pub fn doRedo(p: *Pardes, t: *Text) void { if (t.what == .tag or t.what == .column or t.what == .workspace) return stepOwn(p, t, false); if (t.what != .body) return; - const pane = t.pane(); + const pane = t.pane() orelse return; if (pane.file != null) return panes.File.redo(p, pane); panes.Terminal.redo(p, pane); } |
