summaryrefslogtreecommitdiff
path: root/src/edit.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 01:09:05 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commitf48ab559a4d257137a3aae987a4962f9d74ede23 (patch)
tree99b233f7386673ee7a84031f4e5ff1b3011adae0 /src/edit.zig
parentfb72c2402fa1b1ae99be64fe7b2947ea5dd42623 (diff)
downloadpardes-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.zig37
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);
}