diff options
| author | Gabriel Schneider <[email protected]> | 2026-07-31 11:42:18 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-01 15:02:08 -0300 |
| commit | 911215846f1d5a9b2e37a00e74fb9266d4a0884a (patch) | |
| tree | 31413ca3336cbbd1933d9dc3e24f09a3b8ef46b4 | |
| parent | 0b7a480bef38b209741c520e2478d178767a9e51 (diff) | |
| download | pardes-911215846f1d5a9b2e37a00e74fb9266d4a0884a.tar.gz pardes-911215846f1d5a9b2e37a00e74fb9266d4a0884a.zip | |
a Look path can name a range, and search selects what it found
file:LINE:COL-ENDLINE:ENDCOL, with the two short forms people actually type
reading naturally: file:412:9-21 on one line, file:412-418 whole ones. Ends are
inclusive. A path feature, not a search feature — a ranged path typed in a tag
or middle-clicked out of a shell's output selects just the same; search is only
its first consumer.
The dash is the fussy part. `-` was already a file char, so a ranged word
survives click expansion whole, but a range needs a number on BOTH sides or
my-file:10, build-2 and 2026-07-30 would stop being paths. Table-driven test in
look.zig for exactly that.
Selecting goes through the cellRange/setPaneRange pair the multi-cursor work
left, and hxOff clamps both ends, so a stale range selects what still exists
rather than crashing or reaching past EOF — pinned with an 8:6-400:9 range in a
nine-line file.
Producers: / search, Grep, and five LSP sites through a new spanRow — goto,
references, rename tokens and both symbol lists were throwing away real
protocol ranges at path:line:col. Left alone deliberately: Find rows are bare
paths with nothing to span, a jump is a spot not a span, and the diagnostic and
format paths only ever have a point, where half a range would be worse than
none.
One knock-on worth knowing: n now leaves an EXPLICIT selection, so a topbar
execute chords it. grep.snap's no-match step was silently becoming
`Grep TARGET`; it runs from the leader path now, which never chords, and the
dedicated chord steps stayed where they were.
| -rw-r--r-- | docs/lsp.md | 11 | ||||
| -rw-r--r-- | src/builtins.zig | 2 | ||||
| -rw-r--r-- | src/config.zig | 21 | ||||
| -rw-r--r-- | src/look.zig | 144 | ||||
| -rw-r--r-- | src/lsp/lsp.zig | 36 | ||||
| -rw-r--r-- | src/lsp/lsp_zls.zig | 10 | ||||
| -rw-r--r-- | src/main.zig | 2 | ||||
| -rw-r--r-- | src/pardes.zig | 93 | ||||
| -rw-r--r-- | src/tutor.txt | 15 | ||||
| -rw-r--r-- | test/snapshots/fsearch.golden | 58 | ||||
| -rw-r--r-- | test/snapshots/fsearch.snap | 15 | ||||
| -rw-r--r-- | test/snapshots/grep.golden | 58 | ||||
| -rw-r--r-- | test/snapshots/grep.snap | 19 | ||||
| -rw-r--r-- | test/snapshots/lookrange.golden | 496 | ||||
| -rw-r--r-- | test/snapshots/lookrange.snap | 70 | ||||
| -rw-r--r-- | test/snapshots/lsp.golden | 26 | ||||
| -rw-r--r-- | test/snapshots/lsp.snap | 3 | ||||
| -rw-r--r-- | test/snapshots/lspdebug.golden | 2 | ||||
| -rw-r--r-- | test/snapshots/psearch.golden | 64 | ||||
| -rw-r--r-- | test/snapshots/psearch.snap | 12 | ||||
| -rw-r--r-- | test/snapshots/rsearch.golden | 16 | ||||
| -rw-r--r-- | test/snapshots/rsearch.snap | 4 |
22 files changed, 975 insertions, 202 deletions
diff --git a/docs/lsp.md b/docs/lsp.md index a22a4c52..c89c42f7 100644 --- a/docs/lsp.md +++ b/docs/lsp.md @@ -51,11 +51,16 @@ Three rules make it safe: Every backend renders into one format: ``` -/abs/path/to/file.zig:LINE:COL text +/abs/path/to/file.zig:LINE:COL text +/abs/path/to/file.zig:LINE:COL-ENDCOL text ``` -1-based line and column, absolute path. This is the format `look.zig` already -resolves, `runSearch` already produces and `n`/`N` already step — so: +1-based line and column, absolute path. The second form carries the answer's +RANGE where the protocol gave one on a single line (a token, a symbol's name), +and a look on it SELECTS that span rather than parking at its first cell — so +`gd` lands on the whole name and `gr` steps references with each one +highlighted. This is the format `look.zig` already resolves, `runSearch` +already produces and `n`/`N` already step — so: - **one row from a goto** → jump straight there (`lookAt`) - **several rows** → an output buffer, which `n`/`N` walk diff --git a/src/builtins.zig b/src/builtins.zig index 6593be7d..7378e395 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -460,7 +460,7 @@ pub const Last = struct { while (i > 0) { i -= 1; const j = c.p.jumps[i]; - if (j.pane != c.id) return c.p.focusPaneLine(j.pane, j.line, j.col); + if (j.pane != c.id) return c.p.focusPaneLine(j.pane, .{ .line = j.line, .col = j.col }); } } }; diff --git a/src/config.zig b/src/config.zig index 8f2175f6..2603a40c 100644 --- a/src/config.zig +++ b/src/config.zig @@ -430,6 +430,27 @@ pub fn wordBounds(line: []const u8, col: usize) struct { lo: usize, hi: usize } /// place. pub const line_col_sep: u8 = ':'; +/// ...and separates that spot from the END of a RANGE. A look at a ranged path +/// SELECTS the span rather than just parking on its first cell, which is what +/// lets a search result carry the text it matched and `n` land ON it. +/// +/// Three spellings. The long one subsumes the other two, but the short ones +/// are what a person actually types and what a grep-alike emits, so all three +/// parse: +/// main.zig:412-418 lines 412 through 418, whole +/// main.zig:412:9-21 line 412, columns 9 through 21 +/// main.zig:412:9-418:1 line 412 column 9 through line 418 column 1 +/// Both ends are INCLUSIVE and 1-based, like the spot they extend — `412-418` +/// reads as seven lines, not six. `main.zig:412` and `main.zig:412:9` keep +/// meaning exactly what they always did. +/// +/// Must be an isFileChar member, same as the separator above, or a click would +/// expand to half a range. That is also why reading it is FUSSY (look.zig, +/// parsePathLine): ordinary paths are full of dashes, so the suffix counts as +/// a range only when a NUMBER follows the dash — `my-file:10` and `build-2` +/// stay the paths they are. +pub const range_sep: u8 = '-'; + /// `@p7:10:5` — pane 7, line 10, column 5. The one look target that names a /// live pane instead of a path, because terminals and output buffers have no /// file for a location to point at. Both the writer (a `/` result row) and the diff --git a/src/look.zig b/src/look.zig index c4d04576..9df2b485 100644 --- a/src/look.zig +++ b/src/look.zig @@ -55,41 +55,125 @@ pub fn openLink(url: []const u8) void { _ = libc.waitpid(pid, null, 0); } -/// peel a trailing :LINE[:COL] suffix (both 1-based, 0 = absent): -/// main.zig:100 -> {main.zig, 100, 0} -/// main.zig:100:7 -> {main.zig, 100, 7} -/// main.zig:100: -> {main.zig, 100, 0} grep -n's trailing delimiter -pub fn parsePathLine(tok: []const u8) struct { path: []const u8, line: usize, col: usize } { +/// WHERE in a pane a look word points. A spot (`:LINE:COL`) — or a SPAN, when +/// the word carries a range (config.range_sep), which a look SELECTS instead +/// of merely parking on. Everything is 1-based and 0 means absent, so a bare +/// path is the all-zero Spot and `end_line == 0` is the question "is this a +/// range". +pub const Spot = struct { + line: usize = 0, + col: usize = 0, + end_line: usize = 0, + /// 0 with a live `end_line` is the whole-lines form: through the END of + /// end_line, newline included, which is what helix's `x` selects. + end_col: usize = 0, +}; + +/// digits at `i` and where they end; `end == i` means there were none. Four +/// numbers now come out of the same token, and spelling the scan four times +/// is how one of them ends up subtly different from the others. +fn num(tok: []const u8, i: usize) struct { v: usize, end: usize } { + var v: usize = 0; + var j = i; + while (j < tok.len and std.ascii.isDigit(tok[j])) : (j += 1) v = v * 10 + (tok[j] - '0'); + return .{ .v = v, .end = j }; +} + +/// peel a trailing :LINE[:COL] spot, or one of the three range spellings, off +/// a look word (config.line_col_sep / config.range_sep own both characters): +/// main.zig:100 -> line 100 +/// main.zig:100:7 -> line 100, col 7 +/// main.zig:100: -> line 100 grep -n's trailing delimiter +/// main.zig:100-104 -> lines 100..104 whole +/// main.zig:100:7-21 -> line 100, cols 7..21 +/// main.zig:100:7-104:3 -> line 100 col 7 .. line 104 col 3 +/// +/// A tail that does not parse leaves the token a plain PATH, which is the rule +/// that keeps the dash safe: `a-b`, `build-2:3` and `x:1-y` are all paths (the +/// last one goes back to hunting for a later ':' and finds none), because a +/// range needs a number on both sides of its dash. +pub fn parsePathLine(tok: []const u8) struct { path: []const u8, at: Spot } { var sep: usize = 0; while (sep < tok.len) : (sep += 1) { if (tok[sep] != config.line_col_sep) continue; - var j = sep + 1; - var line: usize = 0; - while (j < tok.len and std.ascii.isDigit(tok[j])) : (j += 1) line = line * 10 + (tok[j] - '0'); - if (j == sep + 1) continue; // no digits after ':' - if (j < tok.len and tok[j] != config.line_col_sep) continue; // junk after the number - var col: usize = 0; - if (j < tok.len) { - var k = j + 1; - while (k < tok.len and std.ascii.isDigit(tok[k])) : (k += 1) col = col * 10 + (tok[k] - '0'); - // digits, and nothing but a delimiter after them, or no column - if (k == j + 1 or (k < tok.len and tok[k] != config.line_col_sep)) col = 0; + const l = num(tok, sep + 1); + if (l.end == sep + 1) continue; // no digits after ':' + const path = tok[0..sep]; + var i = l.end; + // `:LINE-ENDLINE`: whole lines, no column anywhere in the form + if (i < tok.len and tok[i] == config.range_sep) { + const e = num(tok, i + 1); + if (e.end == i + 1) continue; // a dash with no number is not a range + if (e.end < tok.len and tok[e.end] != config.line_col_sep) continue; // junk after it + return .{ .path = path, .at = .{ .line = l.v, .end_line = e.v } }; } - return .{ .path = tok[0..sep], .line = line, .col = col }; + if (i < tok.len and tok[i] != config.line_col_sep) continue; // junk after the number + var at: Spot = .{ .line = l.v }; + if (i == tok.len) return .{ .path = path, .at = at }; + // `:COL`. A column that does not parse is dropped and the LINE still + // stands, which is how this has always read a half-mangled suffix. + const c = num(tok, i + 1); + if (c.end == i + 1) return .{ .path = path, .at = at }; + if (c.end < tok.len and tok[c.end] != config.line_col_sep and tok[c.end] != config.range_sep) + return .{ .path = path, .at = at }; + at.col = c.v; + i = c.end; + if (i == tok.len or tok[i] != config.range_sep) return .{ .path = path, .at = at }; + // `-ENDCOL` on this same line, unless a `:ENDCOL` follows — then that + // first number was the end LINE all along. One lookahead, and it is + // what lets the two-number and four-number forms share a spelling. + const e = num(tok, i + 1); + if (e.end == i + 1) return .{ .path = path, .at = at }; + at.end_line = at.line; + at.end_col = e.v; + if (e.end < tok.len and tok[e.end] == config.line_col_sep) { + const e2 = num(tok, e.end + 1); + if (e2.end > e.end + 1) { + at.end_line = at.end_col; + at.end_col = e2.v; + } + } + return .{ .path = path, .at = at }; + } + return .{ .path = tok, .at = .{} }; +} + +test "parsePathLine: spots, ranges, and the paths that merely look like them" { + const cases = [_]struct { tok: []const u8, path: []const u8, at: Spot }{ + .{ .tok = "main.zig", .path = "main.zig", .at = .{} }, + .{ .tok = "main.zig:100", .path = "main.zig", .at = .{ .line = 100 } }, + .{ .tok = "main.zig:100:", .path = "main.zig", .at = .{ .line = 100 } }, + .{ .tok = "main.zig:100:7", .path = "main.zig", .at = .{ .line = 100, .col = 7 } }, + .{ .tok = "main.zig:100-104", .path = "main.zig", .at = .{ .line = 100, .end_line = 104 } }, + .{ .tok = "main.zig:100:7-21", .path = "main.zig", .at = .{ .line = 100, .col = 7, .end_line = 100, .end_col = 21 } }, + .{ .tok = "main.zig:100:7-104:3", .path = "main.zig", .at = .{ .line = 100, .col = 7, .end_line = 104, .end_col = 3 } }, + // the dash cases that must stay ORDINARY PATHS + .{ .tok = "my-file.zig", .path = "my-file.zig", .at = .{} }, + .{ .tok = "my-file:10", .path = "my-file", .at = .{ .line = 10 } }, + .{ .tok = "x:1-y", .path = "x:1-y", .at = .{} }, + .{ .tok = "a-b-c", .path = "a-b-c", .at = .{} }, + .{ .tok = "2026-07-30", .path = "2026-07-30", .at = .{} }, + // a mangled tail still yields what parsed (unchanged behaviour) + .{ .tok = "main.zig:100x", .path = "main.zig:100x", .at = .{} }, + .{ .tok = "main.zig:100:7x", .path = "main.zig", .at = .{ .line = 100 } }, + }; + for (cases) |c| { + const got = parsePathLine(c.tok); + try std.testing.expectEqualStrings(c.path, got.path); + try std.testing.expectEqual(c.at, got.at); } - return .{ .path = tok, .line = 0, .col = 0 }; } pub const Target = union(enum) { none, dir: []const u8, // resolved absolute path, in caller's buf - file: struct { path: []const u8, line: usize, col: usize }, + file: struct { path: []const u8, at: Spot }, image: struct { path: []const u8 }, url: []const u8, /// `@p7:10:5` — pane 7, line 10, column 5 (0 = unspecified). The one /// target that names a live pane instead of a path, because terminals and /// output buffers have no file for a location to point at. - pane: struct { id: usize, line: usize, col: usize }, + pane: struct { id: usize, at: Spot }, }; pub fn isImagePath(path: []const u8) bool { @@ -114,7 +198,7 @@ pub fn resolve(word_raw: []const u8, cwd: []const u8, realbuf: *[4096]u8) Target for (word[config.pane_addr.len..]) |c| { if (!std.ascii.isDigit(c)) break; id = id * 10 + (c - '0'); - } else return .{ .pane = .{ .id = id, .line = pl.line, .col = pl.col } }; + } else return .{ .pane = .{ .id = id, .at = pl.at } }; } // a URL is a URL everywhere: no filesystem can answer it, so it leaves the @@ -134,12 +218,12 @@ pub fn resolve(word_raw: []const u8, cwd: []const u8, realbuf: *[4096]u8) Target const resolved = std.mem.span(rp); if (isDir(rp)) return .{ .dir = resolved }; if (isImagePath(resolved)) return .{ .image = .{ .path = resolved } }; - return .{ .file = .{ .path = resolved, .line = pl.line, .col = pl.col } }; + return .{ .file = .{ .path = resolved, .at = pl.at } }; } else { // web: tracked Zig sources resolve inside the build-generated, // read-only source filesystem. if (resolveEmbedded(word, cwd, realbuf)) |source| - return .{ .file = .{ .path = source.path, .line = pl.line, .col = pl.col } }; + return .{ .file = .{ .path = source.path, .at = pl.at } }; return .none; } } @@ -280,10 +364,12 @@ pub fn find(arena: std.mem.Allocator, dir: []const u8, pat: []const u8, out: *st const grep_max_bytes = 256 * 1024; const grep_max_files = 20_000; -/// every line of `text` holding `pat`, as `path:LINE:COL text` rows — the -/// shared half of grep(), and the shape every result row in pardes has: the -/// leading word is a look target, so n/N walk the hits. Returns the rows -/// written, at most `budget`. +/// every line of `text` holding `pat`, as `path:LINE:COL-ENDCOL text` rows — +/// the shared half of grep(), and the shape every result row in pardes has: +/// the leading word is a look target, so n/N walk the hits. The row names the +/// MATCH's span and not just its first cell, so stepping onto one selects the +/// text that matched (config.range_sep). Returns the rows written, at most +/// `budget`. fn grepText(arena: std.mem.Allocator, path: []const u8, text: []const u8, pat: []const u8, out: *std.ArrayList(u8), budget: usize) usize { var n: usize = 0; var line: usize = 0; @@ -298,7 +384,9 @@ fn grepText(arena: std.mem.Allocator, path: []const u8, text: []const u8, pat: [ const ln = std.mem.trimEnd(u8, raw, " \t\r"); var cut = @min(ln.len, 200); while (cut > 0 and cut < ln.len and ln[cut] & 0xc0 == 0x80) cut -= 1; - const row = std.fmt.allocPrint(arena, "{s}:{d}:{d} {s}\n", .{ path, line, at + 1, ln[0..cut] }) catch break; + const row = std.fmt.allocPrint(arena, "{s}:{d}:{d}{c}{d} {s}\n", .{ + path, line, at + 1, config.range_sep, at + pat.len, ln[0..cut], + }) catch break; out.appendSlice(arena, row) catch break; n += 1; } diff --git a/src/lsp/lsp.zig b/src/lsp/lsp.zig index abb91874..b8356724 100644 --- a/src/lsp/lsp.zig +++ b/src/lsp/lsp.zig @@ -7,10 +7,12 @@ //! language query is just another thing that answers later. //! //! Every backend renders into ONE format: `+Search` rows. A location is -//! `path:LINE:COL text`, which is what look.zig already resolves and what n/N -//! already steps, so a multi-result answer IS helix's picker and a single -//! result IS a jump — with no picker UI written for it. Free text (hover, -//! a rename's diff) rides the same buffer as plain lines. +//! `path:LINE:COL text` — or `path:LINE:COL-ENDCOL text` where the protocol +//! answered with a real range, which a look then SELECTS — and that is what +//! look.zig already resolves and what n/N already steps, so a multi-result +//! answer IS helix's picker and a single result IS a jump, with no picker UI +//! written for it. Free text (hover, a rename's diff) rides the same buffer as +//! plain lines. //! //! `query` is the ONLY thing an implementation supplies. Swapping backends is //! swapping this one function, which is also how the three competing @@ -101,6 +103,32 @@ pub fn row( }) catch {}; } +/// The same row for a protocol RANGE: `path:LINE:COL-ENDCOL`, which a look +/// SELECTS rather than parking on its first cell — so `gd` lands on the whole +/// name and a references list steps symbol by symbol with each one highlighted +/// (config.range_sep spells the dash; `-` is written out here for the same +/// reason `:` is). +/// +/// `end_col` is the protocol's own EXCLUSIVE end character, which is already +/// the 1-based inclusive column pardes wants, so the conversion is the absence +/// of one. A span that is empty or crosses lines falls back to the point row: +/// the only multi-line ranges here are whole declarations, and a goto onto one +/// wants the cursor at its name, not its body painted. +pub fn spanRow( + out: *std.Io.Writer, + path: []const u8, + line: usize, + col: usize, + end_line: usize, + end_col: usize, + text: []const u8, +) void { + if (end_line != line or end_col <= col) return row(out, path, line, col, text); + out.print("{s}:{d}:{d}-{d} {s}\n", .{ + path, line + 1, col + 1, end_col, std.mem.trim(u8, text, " \t\r\n"), + }) catch {}; +} + /// Byte offset -> (line, column), both 0-based. Every backend needs it to turn /// an AST token into a row, so it lives here rather than three times over. pub fn lineCol(source: []const u8, offset: usize) struct { line: usize, col: usize } { diff --git a/src/lsp/lsp_zls.zig b/src/lsp/lsp_zls.zig index 8a36a151..6090af1a 100644 --- a/src/lsp/lsp_zls.zig +++ b/src/lsp/lsp_zls.zig @@ -484,7 +484,7 @@ fn rowForToken(arena: std.mem.Allocator, th: Analyser.TokenWithHandle, out: *std if (th.token >= tree.tokens.len) return; const r = offsets.tokenToRange(tree, th.token, enc); const path = th.handle.uri.toFsPath(arena) catch return; - lsp.row(out, path, r.start.line, r.start.character, lineAt(tree.source, r.start.line)); + lsp.spanRow(out, path, r.start.line, r.start.character, r.end.line, r.end.character, lineAt(tree.source, r.start.line)); } // ---------------------------------------------------------------- goto @@ -632,7 +632,7 @@ fn goto( const t2 = &nd.handle.tree; const rr = offsets.nodeToRange(t2, nd.node, enc); const path = nd.handle.uri.toFsPath(arena) catch continue; - lsp.row(out, path, rr.start.line, rr.start.character, lineAt(t2.source, rr.start.line)); + lsp.spanRow(out, path, rr.start.line, rr.start.character, rr.end.line, rr.end.character, lineAt(t2.source, rr.start.line)); }, } } @@ -703,7 +703,7 @@ fn emitSymbols( try std.fmt.allocPrint(arena, "{s} {s}", .{ name, d }) else name; - lsp.row(out, path, s.selectionRange.start.line, s.selectionRange.start.character, text); + lsp.spanRow(out, path, s.selectionRange.start.line, s.selectionRange.start.character, s.selectionRange.end.line, s.selectionRange.end.character, text); if (s.children) |kids| try emitSymbols(gpa, arena, path, kids, name, n, out); } } @@ -752,7 +752,7 @@ fn filterSymbols( try std.fmt.allocPrint(arena, "{s}.{s}", .{ prefix, s.name }); if (containsIgnoreCase(s.name, needle)) { n.* += 1; - lsp.row(out, path, s.selectionRange.start.line, s.selectionRange.start.character, name); + lsp.spanRow(out, path, s.selectionRange.start.line, s.selectionRange.start.character, s.selectionRange.end.line, s.selectionRange.end.character, name); } if (s.children) |kids| try filterSymbols(gpa, arena, path, kids, name, needle, n, out); } @@ -824,7 +824,7 @@ fn references( try std.fmt.allocPrint(arena, "{s} -> {s} {s}", .{ want, nn, std.mem.trim(u8, lines.line(r.start.line), " \t") }) else lines.line(r.start.line); - lsp.row(out, handle.uri.toFsPath(arena) catch return, r.start.line, r.start.character, text); + lsp.spanRow(out, handle.uri.toFsPath(arena) catch return, r.start.line, r.start.character, r.end.line, r.end.character, text); } } diff --git a/src/main.zig b/src/main.zig index 436cf938..1a2510de 100644 --- a/src/main.zig +++ b/src/main.zig @@ -142,7 +142,7 @@ fn nativeMain(init: std.process.Init) !void { switch (@import("look.zig").resolve(a, std.mem.span(@as([*:0]u8, @ptrCast(cwd))), &realbuf)) { .file => |t| { opts.file = try arena.dupe(u8, t.path); - opts.file_line = t.line; + opts.file_line = t.at.line; }, .image => |t| opts.file = try arena.dupe(u8, t.path), else => return error.BadArgs, diff --git a/src/pardes.zig b/src/pardes.zig index fbf48f05..eb2c8402 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -3665,8 +3665,12 @@ pub const Pardes = struct { /// path when it has a real file, else `@pN`. /// find — the pane's DIRECTORY, walked like fd. Rows are bare paths. /// grep — the CONTENTS of every file under every pane's directory, - /// walked like `grep -R`. Rows are `path:LINE:COL text`, the path - /// relative to THIS pane's directory (absolute for a hit outside it). + /// walked like `grep -R`. Rows are `path:LINE:COL-ENDCOL text`, the + /// path relative to THIS pane's directory (absolute for a hit outside + /// it). + /// Both searches that match TEXT name the match's whole span, so looking a + /// row — which is all n/N do — selects what matched rather than parking on + /// its first cell. Find's rows are bare paths and have nothing to span. /// No matches = an empty buffer. pub fn runSearch(p: *Pardes, id: usize, pat_raw: []const u8, kind: Search) void { const pane = p.panes[id] orelse return; @@ -3720,8 +3724,10 @@ pub const Pardes = struct { std.fmt.bufPrint(&idbuf, config.pane_addr ++ "{d}", .{id}) catch return; for (pl.lines, 0..) |ln, i| { const at = std.ascii.indexOfIgnoreCase(ln, pat) orelse continue; - const row = std.fmt.allocPrint(arena, "{s}:{d}:{d} {s}\n", .{ - loc, i + 1, at + 1, std.mem.trimEnd(u8, ln, " \t"), + // the row names the MATCH's span, not just its first cell, so + // n/N land ON the hit with it selected (config.range_sep) + const row = std.fmt.allocPrint(arena, "{s}:{d}:{d}{c}{d} {s}\n", .{ + loc, i + 1, at + 1, config.range_sep, at + pat.len, std.mem.trimEnd(u8, ln, " \t"), }) catch return; out.appendSlice(arena, row) catch return; } @@ -6058,18 +6064,19 @@ pub const Pardes = struct { // ---- the ONE dispatcher: look (right/Enter) and execute (middle/Tab) ---- - /// Focus pane `id` and, for a nonzero 1-based `line`, put its modal cursor - /// there (`col` likewise, 0 = line start): files recenter the view on it, - /// terminals ride their scrollback to it. Both look targets that name a - /// live pane land here — a path a pane already holds, and `@pN:LINE:COL`. - pub fn focusPaneLine(p: *Pardes, id: usize, line: usize, col: usize) void { + /// Focus pane `id` and, for a nonzero 1-based `at.line`, put its modal + /// cursor there (`at.col` likewise, 0 = line start): files recenter the + /// view on it, terminals ride their scrollback to it. Both look targets + /// that name a live pane land here — a path a pane already holds, and + /// `@pN:LINE:COL`. A RANGED spot selects (selectSpan below). + pub fn focusPaneLine(p: *Pardes, id: usize, at: look.Spot) void { if (id >= MAX_PANES) return; const pane = p.panes[id] orelse return; p.active = id; - if (line == 0) return; + if (at.line == 0) return; if (pane.file) |*f| { - if (line > file_pane.nlines(p.gpa, f)) return; - const next = (line - 1) -| pane.rows / 2; // center, clamp at top + if (at.line > file_pane.nlines(p.gpa, f)) return; + const next = (at.line - 1) -| pane.rows / 2; // center, clamp at top if (next != f.scroll) { f.scroll = next; f.syntax_dirty = true; @@ -6078,16 +6085,44 @@ pub const Pardes = struct { // land the modal cursor on the target line (and keep // ensureCursorVisible agreeing with the recenter — a stale cursor // would yank the view right back) - pane.cur_row = @intCast(line - 1); - pane.cur_col = if (col > 0) @intCast(col - 1) else 0; + pane.cur_row = @intCast(at.line - 1); + pane.cur_col = if (at.col > 0) @intCast(at.col - 1) else 0; pane.cur_pinned = true; + if (at.end_line != 0) return p.selectSpan(pane, at); pane.ensureCursorVisible(); } + /// Select the span a RANGED look word names (config.range_sep): the two + /// ends are block-cursor CELLS, so this is the same cellRange/setPaneRange + /// pair every motion writes back through — the cursor lands on the span's + /// last cell with the anchor on its first, which is where helix leaves you + /// after a search too. + /// + /// EXPLICIT, so the acme chords act on it like a v/x selection: the whole + /// point of `n` selecting a hit is being able to chord the match straight + /// into the next command. + /// + /// Everything clamps, because a range is a claim about a file that may + /// have changed underneath it: hxOff pins a row past the end to the last + /// line and a column past the end to that line's terminator, so a stale + /// row selects what is still there instead of crashing or highlighting + /// garbage. A whole-lines range (no end column) runs to the terminator by + /// asking for a column no line can have, which is helix's own `x`. + fn selectSpan(p: *Pardes, pane: *Pane, at: look.Spot) void { + const pl = p.paneCursorLines(pane) catch return; + const text = p.flatSurface(pane, pl) catch return; + // saturating, not `- 1`: `f.zig:0-5` is a legal thing to type and a + // 1-based zero is the same nothing an absent number is + const acol: i32 = @intCast(at.col -| 1); + const ecol: i32 = if (at.end_col > 0) @intCast(at.end_col - 1) else std.math.maxInt(i32); + const r = cellRange(text, @intCast(at.line -| 1), acol, @intCast(at.end_line -| 1), ecol); + setPaneRange(pane, pl, text, r, true); + } + /// focus the pane already loaded on `path` (exact match), if any: file /// panes recenter on a :NN line like the look dedup always has, image /// panes just focus. Returns false when no pane holds that path. - fn focusPaneByPath(p: *Pardes, path: []const u8, line: usize, col: usize) bool { + fn focusPaneByPath(p: *Pardes, path: []const u8, at: look.Spot) bool { for (p.panes, 0..) |slot, i| { const tt = slot orelse continue; if (tt.image) |iv| if (std.mem.eql(u8, iv.path, path)) { @@ -6096,7 +6131,7 @@ pub const Pardes = struct { }; const ff = if (tt.file) |*f| f else continue; if (!std.mem.eql(u8, ff.path, path)) continue; - p.focusPaneLine(i, line, col); + p.focusPaneLine(i, at); return true; } return false; @@ -6126,7 +6161,7 @@ pub const Pardes = struct { // canonical (realpath'd or dump-given), so match the word as-is // here and joined onto each directory below. const pl = look.parsePathLine(trimmed); - if (pl.path.len > 0 and p.focusPaneByPath(pl.path, pl.line, pl.col)) return; + if (pl.path.len > 0 and p.focusPaneByPath(pl.path, pl.at)) return; // The word is resolved against the pane DIRECTORIES in access // order: the pane the click came from FIRST — its answer is the // one taken, so nothing that resolves today moves — then every @@ -6155,7 +6190,7 @@ pub const Pardes = struct { if (pl.path.len > 0 and pl.path[0] != '/') { var joinbuf: [2048]u8 = undefined; if (std.fmt.bufPrint(&joinbuf, "{s}/{s}", .{ dir, pl.path }) catch null) |j| - if (p.focusPaneByPath(j, pl.line, pl.col)) return; + if (p.focusPaneByPath(j, pl.at)) return; } found = look.resolve(txt, dir, &realbuf); if (found != .none or pl.path.len == 0 or pl.path[0] == '/') break; @@ -6175,7 +6210,7 @@ pub const Pardes = struct { // `@p7:10:5`: pane 7, line 10, column 5 — how a search result // points at a terminal or an output buffer, neither of which // has a path. - .pane => |t| p.focusPaneLine(t.id, t.line, t.col), + .pane => |t| p.focusPaneLine(t.id, t.at), .url => |u| if (u.len <= 256) p.emit(.{ .open_link = .from(u) }), .dir => |dir| { // focus an existing terminal on this dir, else fork one below @@ -6197,19 +6232,29 @@ pub const Pardes = struct { }, .file => |target| { // focus an existing pane on this path (rescrolled), else open - if (p.focusPaneByPath(target.path, target.line, target.col)) return; + if (p.focusPaneByPath(target.path, target.at)) return; const free = p.freeSlot() orelse return; - const nt = file_pane.open(p, free, target.path, target.line) catch return; - if (target.col > 0) nt.cur_col = @intCast(target.col - 1); + const nt = file_pane.open(p, free, target.path, target.at.line) catch return; + if (target.at.col > 0) nt.cur_col = @intCast(target.at.col - 1); p.placeDoc(id, free, nt); // center the target line: the pane's real body height only // exists after placement, so lay out now and pull the // scroll up by half a body (line 0 opens stay at the top) p.computeGeom(); nt.file.?.scroll -|= @max(1, p.rects[free].h -| BOX_H) / 2; + // ...and only THEN select a range, restoring that scroll: + // setPaneRange keeps its cursor visible, and a pane this fresh + // has no true geometry yet for it to judge against (pane.rows + // is only refreshed in sync), so the centering just computed is + // the answer and ensureCursorVisible's is not. + if (target.at.end_line != 0) { + const centered = nt.file.?.scroll; + p.selectSpan(nt, target.at); + nt.file.?.scroll = centered; + } }, .image => |target| { - if (p.focusPaneByPath(target.path, 0, 0)) return; + if (p.focusPaneByPath(target.path, .{})) return; const free = p.freeSlot() orelse return; // petscii by default when the host has no kitty graphics const nt = p.openImageView(free, target.path, !p.kitty_ok) catch return; @@ -6716,7 +6761,7 @@ pub const Pardes = struct { if (p.njumps == 0 or next < 0 or next >= p.njumps) return; p.jcur = @intCast(next); const j = p.jumps[p.jcur]; - p.focusPaneLine(j.pane, j.line, j.col); + p.focusPaneLine(j.pane, .{ .line = j.line, .col = j.col }); } /// Recompute geometry, push grid-size changes to each emulator + pty, fire diff --git a/src/tutor.txt b/src/tutor.txt index 2d0e951a..ee6f9f79 100644 --- a/src/tutor.txt +++ b/src/tutor.txt @@ -166,11 +166,16 @@ pane's directory searches for it — acme's button 3 — except in tty mode, where the click belongs to the program on the other end. On a shell with no search armed, n/N instead step the lookable tokens in its output. - A hit in a file reads `path:LINE:COL`, the ordinary look target. A hit in - a shell or an output buffer has no file to name, so it reads `@pN:LINE:COL` - — pane N, line LINE, column COL. Looking either one goes there; the column - is optional (`main.zig:100`, `@p3:12`) and you can type one yourself - anywhere text lives. + A hit in a file reads `path:LINE:COL-ENDCOL`, the ordinary look target + carrying the SPAN that matched. A hit in a shell or an output buffer has no + file to name, so it reads `@pN:LINE:COL-ENDCOL` — pane N, then the place in + it. Looking either one goes there and SELECTS the span, which is why n/N + land ON a hit rather than beside it. + The range is part of the PATH syntax and not part of search: type one + anywhere text lives and a look on it selects. `main.zig:412-418` is whole + lines, `main.zig:412:9-21` is columns on one line, `main.zig:412:9-418:1` + is the general form, and the shorter spellings still mean what they always + did — `main.zig:100`, `main.zig:100:7`, `@p3:12`, all of them optional. FIND: the "Find" builtin (SPC f f) arms the same tag input, but Enter walks the pane's DIRECTORY instead of its text — `fd`, in-core — and writes one matching PATH per row into the same "+Search" buffer. Rows are look diff --git a/test/snapshots/fsearch.golden b/test/snapshots/fsearch.golden index 02176d84..d89cd743 100644 --- a/test/snapshots/fsearch.golden +++ b/test/snapshots/fsearch.golden @@ -88,10 +88,10 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c -== snap first grid=180x30 cursor=7,3 +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c +== snap first grid=180x30 cursor=10,3 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -119,14 +119,14 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c == style first |0: 0-52 #949494,#121212, 53-179 d,#121212, |1: 0-1 d,#626262, 2-48 #949494,#121212, 49-59 d,#121212, 60-61 d,#262626, 62-97 #949494,#121212, 98-119 d,#121212, 120-121 d,#262626, 122-157 #949494,#121212, 158-179 d,#121212, |2: 0-1 d,#444444, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, -|3: 0-1 d,#444444, 2-6 #949494,#121212, 7-12 #bdbdbd,#080808, 13-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #949494,#121212, 7-10 #d8c8a8,#4a3a1e, 11-12 #bdbdbd,#080808, 13-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, |4: 0-1 d,#444444, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, |5: 0-1 d,#444444, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, |6: 0-1 d,#444444, 2-6 #626262,#080808, 7-8 #bdbdbd,#080808, 9-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, @@ -151,9 +151,9 @@ |25: 0-1 d,#444444, 2-6 #626262,#080808, 7-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, |26: 0-1 d,#262626, 2-45 #949494,#121212, 46-59 d,#121212, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, |27: 0-1 d,#444444, 2-6 #626262,#080808, 7-59 #d8c8a8,#4a3a1e, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, -|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, -|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-23 #bdbdbd,#080808, 24-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, -== snap second grid=180x30 cursor=7,7 +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, +|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-25 #bdbdbd,#080808, 26-59 d,#080808, 60-61 d,#444444, 62-119 #bdbdbd,#080808, 120-121 d,#444444, 122-179 #bdbdbd,#080808, +== snap second grid=180x30 cursor=10,7 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -181,10 +181,10 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c -== snap third grid=180x30 cursor=7,11 +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c +== snap third grid=180x30 cursor=10,11 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -212,10 +212,10 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c | 4 -== snap back grid=180x30 cursor=7,7 +== snap back grid=180x30 cursor=10,7 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -243,10 +243,10 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c -== snap cancel grid=180x30 cursor=7,7 +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c +== snap cancel grid=180x30 cursor=10,7 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -274,10 +274,10 @@ | | | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c -== snap nomatch grid=180x30 cursor=7,7 +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c +== snap nomatch grid=180x30 cursor=10,7 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/fsearch/cwd/g.txt Save Del NOR /tmp/pardes-snap/fsearch/cwd Del NOR /tmp/pardes-snap/fsearch/cwd Del | 1 l1 @@ -305,6 +305,6 @@ | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/fsearch/cwd/+Search Del -| 1 g.txt:2:1 MARK a -| 2 g.txt:6:1 MARK b -| 3 g.txt:10:1 MARK c +| 1 g.txt:2:1-4 MARK a +| 2 g.txt:6:1-4 MARK b +| 3 g.txt:10:1-4 MARK c diff --git a/test/snapshots/fsearch.snap b/test/snapshots/fsearch.snap index d27d6f08..af1363dd 100644 --- a/test/snapshots/fsearch.snap +++ b/test/snapshots/fsearch.snap @@ -1,8 +1,9 @@ # `/` file search: the pattern types into the tag (persistent, no popup); -# Enter searches the buffer in-core and writes `path:NNN: text` into a +Search -# OUTPUT BUFFER (a file pane with no file behind it — no Save in its tag); -# n/N select the next/prev row there and look it, so the file pane scrolls to -# path:NNN. Esc abandons the input; a no-match search opens an EMPTY buffer +# Enter searches the buffer in-core and writes `path:LINE:COL-ENDCOL text` into +# a +Search OUTPUT BUFFER (a file pane with no file behind it — no Save in its +# tag); n/N select the next/prev row there and look it, so the file pane +# scrolls to the hit AND SELECTS IT — the row names the match's whole span, not +# just where it starts. Esc abandons the input; a no-match search opens an EMPTY buffer # (every search gets its own, stacked under the pane) and leaves n with # nowhere to go. file g.txt l1\nMARK a\nl3\nl4\nl5\nMARK b\nl7\nl8\nl9\nMARK c\nl11\nl12 @@ -30,10 +31,12 @@ text MARK stable 400 5000 snap typing key enter -wait 10000 g.txt:2:1 MARK +wait 10000 g.txt:2:1-4 MARK stable 700 10000 snap results -# n selects result 1 in the results buffer + scrolls the file to line 2 +# n selects result 1 in the results buffer, scrolls the file to line 2 and +# selects the four cells the pattern matched there — the styles below are what +# prove the second half of that key n stable 700 15000 snap first diff --git a/test/snapshots/grep.golden b/test/snapshots/grep.golden index 768c56dc..8ea45e14 100644 --- a/test/snapshots/grep.golden +++ b/test/snapshots/grep.golden @@ -88,10 +88,10 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub -== snap first grid=180x30 cursor=13,2 +| 1 a.txt:1:7-12 hello TARGET one +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub +== snap first grid=180x30 cursor=18,2 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/grep/cwd/a.txt Save Del NOR /tmp/pardes-snap/grep/cwd Del NOR /tmp/pardes-snap/grep/cwd Del | 1 hello TARGET one @@ -119,10 +119,10 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub -== snap opened-hit grid=180x30 cursor=12,4 +| 1 a.txt:1:7-12 hello TARGET one +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub +== snap opened-hit grid=180x30 cursor=17,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/grep/cwd/a.txt Save Del NOR /tmp/pardes-snap/grep/cwd Del NOR /tmp/pardes-snap/grep/cwd Del | 1 hello TARGET one @@ -150,10 +150,10 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub | 4 -== snap nomatch grid=180x30 cursor=13,2 +== snap nomatch grid=180x30 cursor=17,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/grep/cwd/a.txt Save Del NOR /tmp/pardes-snap/grep/cwd Del NOR /tmp/pardes-snap/grep/cwd Del | 1 hello TARGET one @@ -163,9 +163,9 @@ | | a.txt | -| NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line +| +| +| | NOR /tmp/pardes-snap/grep/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/grep/cwd/sub/b.txt Save Del @@ -181,8 +181,8 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub | 4 == snap chordsel grid=180x30 cursor=19,2 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help @@ -194,9 +194,9 @@ | | a.txt | -| NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line +| +| +| | NOR /tmp/pardes-snap/grep/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/grep/cwd/sub/b.txt Save Del @@ -212,8 +212,8 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub | 4 == snap chord grid=180x30 cursor=19,2 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help @@ -221,13 +221,13 @@ | 1 hello TARGET one | 2 nothing here a.txt noise.txt sub a.txt noise.txt sub | 3 last TARGET line +| +| +| a.txt | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line a.txt -| 3 sub/b.txt:2:1 TARGET inside sub -| NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 1 a.txt:1:7 hello TARGET one -| 2 a.txt:3:6 last TARGET line +| 1 a.txt:1:7-12 hello TARGET one +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub | NOR /tmp/pardes-snap/grep/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/grep/cwd/sub/b.txt Save Del @@ -243,6 +243,6 @@ | | | NOR /tmp/pardes-snap/grep/cwd/+Search Del -| 2 a.txt:3:6 last TARGET line -| 3 sub/b.txt:2:1 TARGET inside sub +| 2 a.txt:3:6-11 last TARGET line +| 3 sub/b.txt:2:1-6 TARGET inside sub | 4 diff --git a/test/snapshots/grep.snap b/test/snapshots/grep.snap index 12ff2c70..af05f2d8 100644 --- a/test/snapshots/grep.snap +++ b/test/snapshots/grep.snap @@ -2,7 +2,8 @@ # SAME tag input `/` and Find use, but the walk reads file CONTENTS under every # pane's directory at once — minus any directory another pane's already # contains, so a tree two panes sit in is searched ONCE and every hit appears -# once. A row is `path:LINE:COL text` with the path RELATIVE to the directory +# once. A row is `path:LINE:COL-ENDCOL text` — the match's whole span, so +# looking it SELECTS the hit — with the path RELATIVE to the directory # of the pane that asked — the same directory its results buffer is named in, # so the short name resolves; only a hit from outside that tree stays absolute. # n/N walk the rows like any other result list, and a row pointing into a file @@ -43,7 +44,8 @@ key enter wait 10000 sub/b.txt:2:1 stable 700 15000 snap results -# n looks the first row: absolute path, line 1, column 7 (the `T`) +# n looks the first row: absolute path, line 1, columns 7..12 (`TARGET`), and +# those six cells come up selected key n stable 700 15000 snap first @@ -54,9 +56,16 @@ key n wait 10000 TARGET inside sub stable 700 15000 snap opened-hit -# a pattern nothing holds: an empty list of its own, n has nowhere to go -press middle 45 1 -release middle 45 1 +# a pattern nothing holds: an empty list of its own, n has nowhere to go. +# Armed from the LEADER, not the topbar word: the n above left the hit +# SELECTED in a.txt (a ranged result row is one a look selects), and a topbar +# execute chords whatever is selected into its argument — so a middle-click +# here would run `Grep TARGET` and never ask for a pattern at all. The leader +# path runs the builtin with no argument, which is what this step is about; the +# chord itself is the last two snaps below. +key space +key f +key g stable 400 5000 text zzqq key enter diff --git a/test/snapshots/lookrange.golden b/test/snapshots/lookrange.golden new file mode 100644 index 00000000..f8b5795e --- /dev/null +++ b/test/snapshots/lookrange.golden @@ -0,0 +1,496 @@ +== snap opened grid=150x30 cursor=7,2 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +| +== snap wholelines grid=150x30 cursor=11,21 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 1 aaaa +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| +| +== style wholelines +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #949494,#121212, 7-11 #d8c8a8,#4a3a1e, 12-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap onelinespan grid=150x30 cursor=15,23 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 1 aaaa +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| +| +== style onelinespan +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #949494,#121212, 7-9 #bdbdbd,#080808, 10-15 #d8c8a8,#4a3a1e, 16-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap fullspan grid=150x30 cursor=9,21 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 1 aaaa +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| +| +== style fullspan +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-7 #bdbdbd,#080808, 8-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #949494,#121212, 7-9 #d8c8a8,#4a3a1e, 10-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap stale grid=150x30 cursor=10,24 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| +| +| +== style stale +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#121212, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #626262,#080808, 7-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-11 #bdbdbd,#080808, 12-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #949494,#121212, 7-10 #d8c8a8,#4a3a1e, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap results grid=150x30 cursor=10,24 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/+Search Del +| 1 r.txt:7:4-9 gg NEEDLE gg +| 2 r.txt:8:6-11 hhhh NEEDLE +== snap hit1 grid=150x30 cursor=15,22 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/+Search Del +| 1 r.txt:7:4-9 gg NEEDLE gg +| 2 r.txt:8:6-11 hhhh NEEDLE +== style hit1 +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#121212, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #949494,#121212, 7-9 #bdbdbd,#080808, 10-15 #d8c8a8,#4a3a1e, 16-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#262626, 2-47 #949494,#121212, 48-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap hit2 grid=150x30 cursor=17,22 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/+Search Del +| 1 r.txt:7:4-9 gg NEEDLE gg +| 2 r.txt:8:6-11 hhhh NEEDLE +== style hit2 +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#121212, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#121212, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #626262,#080808, 7-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #949494,#121212, 7-11 #bdbdbd,#080808, 12-17 #d8c8a8,#4a3a1e, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#262626, 2-47 #949494,#121212, 48-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +== snap back grid=150x30 cursor=15,22 +|Kill Newcol Tutor Debug NextColor Dump Find Grep Help +| NOR /tmp/pardes-snap/lookrange/cwd/look.txt Save Del NOR /tmp/pardes-snap/lookrange/cwd Del +| 1 r.txt:3-5 +| 2 r.txt:7:4-9 look.txt r.txt +| 3 r.txt:3:2-5:3 +| 4 r.txt:8:6-99:9 +| +| +| +| +| +| +| +| +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/r.txt Save Del +| 2 bbbb +| 3 cccc dccc +| 4 dddd +| 5 eeee +| 6 ffff +| 7 gg NEEDLE gg +| 8 hhhh NEEDLE +| 9 iiii +| +| +| NOR /tmp/pardes-snap/lookrange/cwd/+Search Del +| 1 r.txt:7:4-9 gg NEEDLE gg +| 2 r.txt:8:6-11 hhhh NEEDLE +== style back +|0: 0-52 #949494,#121212, 53-149 d,#121212, +|1: 0-1 d,#262626, 2-53 #949494,#121212, 54-74 d,#121212, 75-76 d,#262626, 77-114 #949494,#121212, 115-149 d,#121212, +|2: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|4: 0-1 d,#444444, 2-6 #626262,#080808, 7-19 #bdbdbd,#080808, 20-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|5: 0-1 d,#444444, 2-6 #626262,#080808, 7-20 #bdbdbd,#080808, 21-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|6: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|7: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|8: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|9: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|10: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|11: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|12: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|13: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|14: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|15: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|16: 0-1 d,#626262, 2-50 #949494,#121212, 51-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|17: 0-1 d,#121212, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|18: 0-1 d,#444444, 2-6 #626262,#080808, 7-15 #bdbdbd,#080808, 16-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|19: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|20: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|21: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|22: 0-1 d,#444444, 2-6 #949494,#121212, 7-9 #bdbdbd,#080808, 10-15 #d8c8a8,#4a3a1e, 16-18 #bdbdbd,#080808, 19-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|23: 0-1 d,#444444, 2-6 #626262,#080808, 7-17 #bdbdbd,#080808, 18-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|24: 0-1 d,#444444, 2-6 #626262,#080808, 7-10 #bdbdbd,#080808, 11-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|25: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|26: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|27: 0-1 d,#262626, 2-47 #949494,#121212, 48-74 d,#121212, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-74 #d8c8a8,#4a3a1e, 75-76 d,#444444, 77-149 #bdbdbd,#080808, +|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-30 #bdbdbd,#080808, 31-74 d,#080808, 75-76 d,#444444, 77-149 #bdbdbd,#080808, diff --git a/test/snapshots/lookrange.snap b/test/snapshots/lookrange.snap new file mode 100644 index 00000000..d1a86e0c --- /dev/null +++ b/test/snapshots/lookrange.snap @@ -0,0 +1,70 @@ +# RANGED LOOK PATHS. `path:LINE:COL` says where to PARK; a range says what to +# SELECT, and it belongs to the PATH (config.range_sep) rather than to the +# search that is merely the first thing writing one. So this script right- +# clicks the three spellings as ordinary words sitting in a file: +# r.txt:3-5 whole lines 3 through 5 +# r.txt:7:4-9 line 7, columns 4 through 9 +# r.txt:3:2-5:3 line 3 column 2 through line 5 column 3 +# ...and only then presses `/`, whose result rows are exactly this syntax — +# which is how n/N step to a hit with the matched text selected. +# +# `snapstyle` is the assertion that matters: the grid TEXT after a ranged look +# is the same text a plain `:LINE:COL` look leaves, so the selection only shows +# in the styles. +file r.txt aaaa\nbbbb\ncccc dccc\ndddd\neeee\nffff\ngg NEEDLE gg\nhhhh NEEDLE\niiii +file look.txt r.txt:3-5\nr.txt:7:4-9\nr.txt:3:2-5:3\nr.txt:8:6-99:9 +start 30 150 look.txt +wait 8000 r.txt:3-5 +stable 700 20000 +snap opened +# --- form 1: whole lines. r.txt opens BELOW look.txt (an ordinary look) with +# lines 3, 4 and 5 selected whole, terminators included — helix's own `x`. +press right 10 3 +release right 10 3 +wait 10000 cccc dccc +stable 700 15000 +snap wholelines +snapstyle wholelines +# --- form 2: one line, a column span. r.txt is open now, so this re-uses that +# pane (focusPaneByPath) — the same route a `/` result row takes. +press right 12 4 +release right 12 4 +stable 700 15000 +snap onelinespan +snapstyle onelinespan +# --- form 3: the general one, across both lines and columns +press right 12 5 +release right 12 5 +stable 700 15000 +snap fullspan +snapstyle fullspan +# --- a STALE range: line 99 of a nine-line file, which is what a result row +# looks like once the file has changed underneath it. It must CLAMP — no crash, +# no garbage highlight — landing on the last cell that really exists. +press right 12 6 +release right 12 6 +stable 700 15000 +snap stale +snapstyle stale +# --- and now the first consumer. The look above left r.txt focused, so `/` +# arms on it: the rows it writes carry the match's span, and n/N therefore step +# to each hit with the word itself selected. +key / +text NEEDLE +key enter +wait 10000 r.txt:7:4-9 gg NEEDLE +stable 700 15000 +snap results +key n +stable 700 15000 +snap hit1 +snapstyle hit1 +key n +stable 700 15000 +snap hit2 +snapstyle hit2 +# N walks back onto the first hit, still selected +key N +stable 700 15000 +snap back +snapstyle back diff --git a/test/snapshots/lsp.golden b/test/snapshots/lsp.golden index 32d5b6d0..85c5c9ce 100644 --- a/test/snapshots/lsp.golden +++ b/test/snapshots/lsp.golden @@ -80,7 +80,7 @@ | | | -== snap definition grid=120x40 cursor=10,4 +== snap definition grid=120x40 cursor=15,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/lsp/cwd/a.zig Save Del NOR /tmp/pardes-snap/lsp/cwd Del | 1 const std = @import("std"); @@ -121,7 +121,7 @@ | | | -== snap hover grid=120x40 cursor=10,4 +== snap hover grid=120x40 cursor=15,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/lsp/cwd/a.zig Save Del NOR /tmp/pardes-snap/lsp/cwd Del | 1 const std = @import("std"); @@ -162,7 +162,7 @@ | NOR /tmp/pardes-snap/lsp/cwd/+Hover Del | 1 fn helper(x: u32) u32 | 2 (fn (u32) u32) -== snap symbols grid=120x40 cursor=10,4 +== snap symbols grid=120x40 cursor=15,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/lsp/cwd/a.zig Save Del NOR /tmp/pardes-snap/lsp/cwd Del | 1 const std = @import("std"); @@ -197,13 +197,13 @@ | | | NOR /tmp/pardes-snap/lsp/cwd/+Search Del -| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7 std -| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4 helper fn helper( -| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8 main fn main() vo +| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7-9 std +| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4-9 helper fn helpe +| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8-11 main fn main() | NOR /tmp/pardes-snap/lsp/cwd/+Hover Del | 1 fn helper(x: u32) u32 | 2 (fn (u32) u32) -== snap step grid=120x40 cursor=13,2 +== snap step grid=120x40 cursor=15,2 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/lsp/cwd/a.zig Save Del NOR /tmp/pardes-snap/lsp/cwd Del | 1 const std = @import("std"); @@ -238,9 +238,9 @@ | | | NOR /tmp/pardes-snap/lsp/cwd/+Search Del -| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7 std -| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4 helper fn helper( -| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8 main fn main() vo +| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7-9 std +| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4-9 helper fn helpe +| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8-11 main fn main() | NOR /tmp/pardes-snap/lsp/cwd/+Hover Del | 1 fn helper(x: u32) u32 | 2 (fn (u32) u32) @@ -279,9 +279,9 @@ | | | NOR /tmp/pardes-snap/lsp/cwd/+Search Del -| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7 std -| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4 helper fn helper( -| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8 main fn main() vo +| 1 /tmp/pardes-snap/lsp/cwd/a.zig:1:7-9 std +| 2 /tmp/pardes-snap/lsp/cwd/a.zig:3:4-9 helper fn helpe +| 3 /tmp/pardes-snap/lsp/cwd/a.zig:7:8-11 main fn main() | NOR /tmp/pardes-snap/lsp/cwd/+Hover Del | 1 fn helper(x: u32) u32 | 2 (fn (u32) u32) diff --git a/test/snapshots/lsp.snap b/test/snapshots/lsp.snap index a1cc056c..79acaee8 100644 --- a/test/snapshots/lsp.snap +++ b/test/snapshots/lsp.snap @@ -21,7 +21,8 @@ release left 18 10 stable 400 5000 snap cursor # gd on a call: exactly one location comes back, so it JUMPS rather than -# opening a picker — the cursor lands on the definition's name token, line 3. +# opening a picker — and lands SELECTING the definition's name token on line 3, +# because ZLS answers with a range and a ranged row is one a look selects. # The jumplist is pinned first, so ctrl-o comes back. key g key d diff --git a/test/snapshots/lspdebug.golden b/test/snapshots/lspdebug.golden index bb0fee41..67421629 100644 --- a/test/snapshots/lspdebug.golden +++ b/test/snapshots/lspdebug.golden @@ -43,7 +43,7 @@ | | | -== snap ctrlclick grid=120x44 cursor=10,4 +== snap ctrlclick grid=120x44 cursor=15,4 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/lspdebug/cwd/z.zig Save Del NOR /tmp/pardes-snap/lspdebug/cwd Del | 1 const std = @import("std"); diff --git a/test/snapshots/psearch.golden b/test/snapshots/psearch.golden index 2bd9fc81..7456db00 100644 --- a/test/snapshots/psearch.golden +++ b/test/snapshots/psearch.golden @@ -88,10 +88,10 @@ | | | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c -== snap first grid=140x30 cursor=4,3 +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c +== snap first grid=140x30 cursor=7,3 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/psearch/cwd Del | @@ -119,14 +119,14 @@ | | | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c == style first |0: 0-52 #949494,#121212, 53-139 d,#121212, |1: 0-1 d,#626262, 2-37 #949494,#121212, 38-139 d,#121212, |2: 0-1 d,#444444, 2-139 #bdbdbd,#080808, -|3: 0-1 d,#444444, 2-139 #bdbdbd,#080808, +|3: 0-1 d,#444444, 2-3 #bdbdbd,#080808, 4-7 #d8c8a8,#4a3a1e, 8-139 #bdbdbd,#080808, |4: 0-1 d,#444444, 2-139 #bdbdbd,#080808, |5: 0-1 d,#444444, 2-139 #bdbdbd,#080808, |6: 0-1 d,#444444, 2-139 #bdbdbd,#080808, @@ -151,9 +151,9 @@ |25: 0-1 d,#444444, 2-139 #bdbdbd,#080808, |26: 0-1 d,#262626, 2-45 #949494,#121212, 46-139 d,#121212, |27: 0-1 d,#444444, 2-6 #626262,#080808, 7-139 #d8c8a8,#4a3a1e, -|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-139 d,#080808, -|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-22 #bdbdbd,#080808, 23-139 d,#080808, -== snap second grid=140x30 cursor=4,5 +|28: 0-1 d,#444444, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808, +|29: 0-1 d,#121212, 2-6 #626262,#080808, 7-24 #bdbdbd,#080808, 25-139 d,#080808, +== snap second grid=140x30 cursor=7,5 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/psearch/cwd Del | @@ -181,10 +181,10 @@ | | | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c -== snap back grid=140x30 cursor=4,3 +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c +== snap back grid=140x30 cursor=7,3 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/psearch/cwd Del | @@ -212,10 +212,10 @@ | | | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c -== snap nomatch grid=140x30 cursor=4,3 +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c +== snap nomatch grid=140x30 cursor=7,3 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/psearch/cwd Del | @@ -243,9 +243,9 @@ | NOR /tmp/pardes-snap/psearch/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c == snap ttyinert grid=140x30 cursor=4,8 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | TTY /tmp/pardes-snap/psearch/cwd Del @@ -274,10 +274,10 @@ | NOR /tmp/pardes-snap/psearch/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c -== snap rightsearch grid=140x30 cursor=4,3 +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c +== snap rightsearch grid=140x30 cursor=7,3 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/psearch/cwd Del | @@ -299,12 +299,12 @@ | | | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c | NOR /tmp/pardes-snap/psearch/cwd/+Search Del | 1 | NOR /tmp/pardes-snap/psearch/cwd/+Search Del -| 1 @p0:2:3 x MARK a -| 2 @p0:4:3 x MARK b -| 3 @p0:6:3 x MARK c +| 1 @p0:2:3-6 x MARK a +| 2 @p0:4:3-6 x MARK b +| 3 @p0:6:3-6 x MARK c diff --git a/test/snapshots/psearch.snap b/test/snapshots/psearch.snap index fb721c7d..e2ea1aea 100644 --- a/test/snapshots/psearch.snap +++ b/test/snapshots/psearch.snap @@ -1,9 +1,10 @@ # `/` search on a TERMINAL pane: the same tag input as a file pane, searching # the shell's own scrollback (the plain text view Look reads, prompt rows # hidden). Results land in a +Search OUTPUT BUFFER — a file pane with no file -# behind it, so its tag has no Save — and point at `@p0:LINE`, the look target -# that names a live pane, since a terminal has no path. n/N walk the buffer -# and look each row, scrolling the terminal to that line of its scrollback. +# behind it, so its tag has no Save — and point at `@p0:LINE:COL-ENDCOL`, the +# look target that names a live pane, since a terminal has no path. n/N walk +# the buffer and look each row, scrolling the terminal to that line of its +# scrollback and selecting the span the row names. # PLACEMENT, and this script is the proof: an output buffer is NOT a document # — it is the result list of the pane that asked for it — so even here, with no # doc pane in the session for it to join, it does NOT take a column of its own. @@ -34,8 +35,9 @@ key enter wait 10000 @p0:2:3 stable 700 15000 snap results -# n looks result 1: the terminal's cursor lands on that scrollback line, at -# the matched COLUMN (3, past the leading "x ") — not the start of the line +# n looks result 1: the terminal's cursor lands on that scrollback line, on +# the matched SPAN (cols 3..6, past the leading "x ") — not the start of the +# line, and selected rather than merely parked on key n stable 700 15000 snap first diff --git a/test/snapshots/rsearch.golden b/test/snapshots/rsearch.golden index ee2a1cb4..39b9f57d 100644 --- a/test/snapshots/rsearch.golden +++ b/test/snapshots/rsearch.golden @@ -58,8 +58,8 @@ | | | NOR /tmp/pardes-snap/rsearch/cwd/+Search Del -| 1 code.txt:1:5 run count_x now -| 2 code.txt:3:1 count_x again +| 1 code.txt:1:5-11 run count_x now +| 2 code.txt:3:1-7 count_x again == snap select grid=180x30 cursor=7,2 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/rsearch/cwd/code.txt Save Del NOR /tmp/pardes-snap/rsearch/cwd Del NOR /tmp/pardes-snap/rsearch/cwd Del @@ -87,10 +87,10 @@ | | | NOR /tmp/pardes-snap/rsearch/cwd/+Search Del -| 1 code.txt:4:1 pick two words +| 1 code.txt:4:1-8 pick two words | NOR /tmp/pardes-snap/rsearch/cwd/+Search Del -| 1 code.txt:1:5 run count_x now -| 2 code.txt:3:1 count_x again +| 1 code.txt:1:5-11 run count_x now +| 2 code.txt:3:1-7 count_x again == snap path-open grid=180x30 cursor=7,16 |Kill Newcol Tutor Debug NextColor Dump Find Grep Help | NOR /tmp/pardes-snap/rsearch/cwd/code.txt Save Del NOR /tmp/pardes-snap/rsearch/cwd Del NOR /tmp/pardes-snap/rsearch/cwd Del @@ -118,7 +118,7 @@ | | | NOR /tmp/pardes-snap/rsearch/cwd/+Search Del -| 1 code.txt:4:1 pick two words +| 1 code.txt:4:1-8 pick two words | NOR /tmp/pardes-snap/rsearch/cwd/+Search Del -| 1 code.txt:1:5 run count_x now -| 2 code.txt:3:1 count_x again +| 1 code.txt:1:5-11 run count_x now +| 2 code.txt:3:1-7 count_x again diff --git a/test/snapshots/rsearch.snap b/test/snapshots/rsearch.snap index 738afc23..a6dcd167 100644 --- a/test/snapshots/rsearch.snap +++ b/test/snapshots/rsearch.snap @@ -28,7 +28,7 @@ snap opened # file, so the click searches for it: the results list both lines containing it. press right 15 3 release right 15 3 -wait 10000 code.txt:1:5 run count_x +wait 10000 code.txt:1:5-11 run count_x stable 700 15000 snap search # right-SELECT `pick two` (line 4, sweep cols 8..15): a multi-word span passes @@ -36,7 +36,7 @@ snap search press right 8 6 drag right 15 6 release right 15 6 -wait 10000 code.txt:4:1 pick two +wait 10000 code.txt:4:1-8 pick two stable 700 15000 snap select # right-CLICK the path `sub/dep.txt:3` (line 2, col 18): isFileChar keeps / . : |
