diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-28 18:29:28 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 00298cc24e12432a4120f4efb68728c008d9620f (patch) | |
| tree | 00b877bf32b2490191b7b797ca69491d2b9c0572 /src/ninep/addr.zig | |
| parent | 805197e5955a86afbb47bdb482a9ebb7cfa1d171 (diff) | |
| download | pardes-00298cc24e12432a4120f4efb68728c008d9620f.tar.gz pardes-00298cc24e12432a4120f4efb68728c008d9620f.zip | |
addr takes line:col, as Look's file:12:5 does
A script that knows a line and column had to count bytes to write #n. `12:5` is now the point at line 12, column 5 (bytes from 1, clamped to the line's end and snapped to a character's start, as Look's cursor is), and it composes like any simple address. A pardes extension, documented as one; sam reads it as a syntax error.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/addr.zig')
| -rw-r--r-- | src/ninep/addr.zig | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/src/ninep/addr.zig b/src/ninep/addr.zig index ccb08924..f57c62bd 100644 --- a/src/ninep/addr.zig +++ b/src/ninep/addr.zig @@ -91,6 +91,26 @@ pub const Addr = struct { if (d < '0' or d > '9') break; n = @min(n * 10 + (d - '0'), std.math.maxInt(u32)); } + // pardes's `line:col`, Look's `file:12:5` spelling (look.zig + // parsePathLine): the point at that column of that line, the + // column in bytes from 1, clamped to the line's end and snapped + // to a character's start as Look's cursor is. Not sam's. + if (size == .line and dir == 0 and a.i + 1 < a.expr.len and a.expr[a.i] == ':' and + a.expr[a.i + 1] >= '0' and a.expr[a.i + 1] <= '9') + { + a.i += 1; + var col: u64 = 0; + while (a.i < a.expr.len and a.expr[a.i] >= '0' and a.expr[a.i] <= '9') : (a.i += 1) + col = @min(col * 10 + (a.expr[a.i] - '0'), std.math.maxInt(u32)); + const lines = modal.cursorLineCount(a.text); + if (n == 0 or n > lines or col == 0) { + a.err = e_range; + return null; + } + const q = clip(modal.offsetAt(a.text, .{ .row = @intCast(n - 1), .col = @intCast(col - 1) })); + r = .{ .q0 = q, .q1 = q }; + continue; + } r = a.number(r, @intCast(n), dir, size) orelse return null; dir = 0; size = .line; @@ -393,6 +413,11 @@ test "the address language, form by form" { .{ .expr = "/two/", .q0 = 4, .q1 = 7 }, .{ .expr = "/t.o/", .q0 = 4, .q1 = 7 }, .{ .expr = "1\n", .q0 = 0, .q1 = 4 }, + // pardes's line:col, composing like any simple address. + .{ .expr = "2:2", .q0 = 5, .q1 = 5 }, + .{ .expr = "2:99", .q0 = 7, .q1 = 7 }, + .{ .expr = "2:2,3:1", .q0 = 5, .q1 = 8 }, + .{ .expr = "2:2+#3", .q0 = 8, .q1 = 8 }, }) |c| { _ = th.wr(p, addr, "#0"); const w = th.wr(p, addr, c.expr); @@ -441,7 +466,7 @@ test "the address language, form by form" { for ([_][2][]const u8{ .{ "zzz", e_syntax }, .{ "/nomatch/", e_no_match }, .{ "99", e_range }, .{ "#999", e_range }, .{ "/a[/", e_regexp }, .{ "/(a/", e_regexp }, - .{ "/*a/", e_regexp }, + .{ "/*a/", e_regexp }, .{ "99:1", e_range }, .{ "2:0", e_range }, }) |c| { _ = th.wr(p, addr, "#0"); try testing.expectEqualStrings(c[1], th.wr(p, addr, c[0]).reply.ename); |
