diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-30 13:59:25 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:17 -0300 |
| commit | 9ca008a27c4ab83a29c1798f4eb081eef372624c (patch) | |
| tree | 53723e46dd928d566ffa6b625911f755d53d83c0 /src/look.zig | |
| parent | e8fc2964acdf7156ab0c9961b7bf83d74f152192 (diff) | |
| download | pardes-9ca008a27c4ab83a29c1798f4eb081eef372624c.tar.gz pardes-9ca008a27c4ab83a29c1798f4eb081eef372624c.zip | |
A look at file:3:0 is refused as addr 3:0 is: a column counts from 1
addr refuses a column 0 with EINVAL, "address out of range: a column
counts from 1". A look took `file:3:0` as line 3 with no column, since
the parser holds no column as 0, and succeeded. Now a look whose column,
or end column, is written as 0 is refused with addr's words and errno.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/look.zig')
| -rw-r--r-- | src/look.zig | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/look.zig b/src/look.zig index 36eae75c..de51804d 100644 --- a/src/look.zig +++ b/src/look.zig @@ -1233,6 +1233,25 @@ fn missedLine(p: *Pardes, id: usize, path: []const u8, line: anytype) void { missed(p, id, "{s} has no line {d}", .{ missText(path, &cut), line }); } +/// Whether `:line:col`, `:line:col-col` or `:line:col-line:col` after a +/// path names a column 0, which parsePathLine reads as no column. +fn zeroColumn(rest: []const u8) bool { + var fields = std.mem.splitScalar(u8, rest, ':'); + _ = fields.next(); // before the first ':' + _ = fields.next() orelse return false; // the line + const col = fields.next() orelse return false; + var ends = std.mem.splitScalar(u8, col, '-'); + if (std.mem.eql(u8, ends.next().?, "0")) return true; + if (ends.next()) |end| if (std.mem.eql(u8, end, "0")) return true; + if (fields.next()) |end_col| if (std.mem.eql(u8, end_col, "0")) return true; + return false; +} + +test "a zero column after a path is found, in every spelling a look takes" { + for ([_][]const u8{ ":3:0", ":3:0-4", ":3:2-0", ":3:2-5:0" }) |rest| try std.testing.expect(zeroColumn(rest)); + for ([_][]const u8{ "", ":3", ":3:1", ":3:2-5", ":3:2-5:7", ":30:10" }) |rest| try std.testing.expect(!zeroColumn(rest)); +} + fn missed(p: *Pardes, id: usize, comptime fmt: []const u8, args: anytype) void { p.look_missed = true; var said: [miss_path_cap + 64]u8 = undefined; @@ -1504,6 +1523,9 @@ pub fn lookAt(p: *Pardes, id: usize, operand: []const u8) void { // the colon, evaluated in that file from its dot (openfile, look.c:675). if (addressed(trimmed)) |ad| return lookAddress(p, id, ad.path, ad.expr); const pl = parsePathLine(trimmed); + // `file:3:0`: columns count from 1, as addr's do, and a zero is refused + // in addr's words rather than taken as no column. + if (pl.at.line != 0 and zeroColumn(trimmed[pl.path.len..])) return p.reportFailure(id, @import("ninep/addr.zig").e_col_zero); if (comptime pdf_enabled) if (pane.hasPdf()) clearNavigationSelection(p, pane); if (comptime pdf_enabled) if (panes.Pdf.lookSection(p, id, pl.path, pl.at)) return; var realbuf: [4096]u8 = undefined; |
