From af435ba7e4fd34dd5eab17bd21ce535b6f9b8413 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 15 Sep 2026 17:44:34 -0300 Subject: Align search and LSP results in groups of eight matches --- test/output.zig | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'test') diff --git a/test/output.zig b/test/output.zig index f1d9d4e0..b0f964ee 100644 --- a/test/output.zig +++ b/test/output.zig @@ -1146,3 +1146,126 @@ test "Look ignores slash-only comment markers while retaining root and real path try std.testing.expect(look.resolve(null, doubled, ".", &realbuf) == .dir); try std.testing.expect(look.resolve(null, "https://example.com/path", ".", &realbuf) == .url); } + +test "result alignment chunks keep seventeen matches independent and refresh stable" { + for ([_]panes.Output.Origin{ .search, .{ .query = .references } }) |origin| { + for ([_]usize{ 7, 8 }) |long_at| { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true }); + defer p.deinit(); + const source = try p.setTestFile("notes\n"); + p.locations_config = .{ .context = 0, .tscontext = false }; + var input: std.ArrayList(u8) = .empty; + defer input.deinit(p.gpa); + var widths: [17]usize = undefined; + for (0..17) |reverse| { + const index = 16 - reverse; + const label = try std.fmt.allocPrint(p.gpa, "/r{d:0>2}{s}.zig:3:1", .{ index, if (index == long_at) "-界-very-long-path-name" else "-é" }); + defer p.gpa.free(label); + widths[index] = panes.File.displayWidth(label); + try input.appendSlice(p.gpa, label); + try input.appendSlice(p.gpa, " \t return 7;\n"); + } + try panes.Output.fillResults(p, 0, "/", origin, "chunks", try p.gpa.dupe(u8, input.items), 0); + const result_id = source.search_pane.?; + const result = p.panes[result_id].?; + const file = &result.file.?; + try std.testing.expectEqual(@as(usize, 17), file.location_rows.len); + try std.testing.expectEqual(@as(usize, 16), source.search_row.?); + var starts: [17]usize = undefined; + for (file.location_rows, 0..) |row, index| { + const line = modal.lineSlice(file.content, index); + const first = index / 8 * 8; + var width: usize = 0; + for (widths[first..@min(first + 8, widths.len)]) |label_width| width = @max(width, label_width); + try std.testing.expectEqual(width, panes.File.displayWidth(line[0 .. row.code_start - 1])); + try std.testing.expectEqual(@as(u8, '\t'), line[row.code_start - 1]); + try std.testing.expectEqualStrings("\t return 7;", line[row.code_start..]); + try std.testing.expectEqualStrings(row.path, line[0 .. row.location_end - ":3:1".len]); + starts[index] = row.code_start; + } + const content = file.content.ptr; + const revision = file.revision; + const index = try panes.File.lineIndex(p.gpa, file); + result.cur_row = 8; + result.cur_col = @intCast(file.location_rows[8].code_start); + try panes.Output.fillResults(p, 0, "/", origin, "chunks", try p.gpa.dupe(u8, input.items), 8); + try std.testing.expectEqual(result_id, source.search_pane.?); + try std.testing.expectEqual(content, file.content.ptr); + try std.testing.expectEqual(revision, file.revision); + try std.testing.expectEqual(index.ptr, file.line_starts.ptr); + try std.testing.expectEqual(@as(usize, 8), source.search_row.?); + try std.testing.expectEqual(@as(i32, 8), result.cur_row); + for (file.location_rows, starts) |row, start| try std.testing.expectEqual(start, row.code_start); + + // Simulate a restored view made by the previous global-padding + // formatter. Its metadata still describes the same result bytes. + const expected = try p.gpa.dupe(u8, file.content); + defer p.gpa.free(expected); + var global_width: usize = 0; + for (widths) |width| global_width = @max(global_width, width); + var legacy: std.ArrayList(u8) = .empty; + defer legacy.deinit(p.gpa); + for (file.location_rows, 0..) |*row, row_index| { + const line = modal.lineSlice(file.content, row_index); + const label = line[0..row.location_end]; + const code = line[row.code_start..]; + try legacy.appendSlice(p.gpa, label); + const padding = global_width - panes.File.displayWidth(label); + try legacy.appendNTimes(p.gpa, ' ', padding); + try legacy.append(p.gpa, '\t'); + try legacy.appendSlice(p.gpa, code); + try legacy.append(p.gpa, '\n'); + row.code_start = row.location_end + padding + 1; + } + const retained_rows = file.location_rows; + file.location_rows = &.{}; + panes.File.setContent(p, file, try legacy.toOwnedSlice(p.gpa)); + file.location_rows = retained_rows; + try std.testing.expect(!std.mem.eql(u8, expected, file.content)); + try panes.Output.fillResults(p, 0, "/", origin, "chunks", try p.gpa.dupe(u8, input.items), 8); + try std.testing.expectEqual(result_id, source.search_pane.?); + try std.testing.expectEqualStrings(expected, file.content); + for (file.location_rows, starts) |row, start| try std.testing.expectEqual(start, row.code_start); + } + } +} + +test "result alignment chunks assign boundary context to nearest match with previous ties" { + for ([_]panes.Output.Origin{ .search, .{ .query = .references } }) |origin| { + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true }); + defer p.deinit(); + var source_text: std.ArrayList(u8) = .empty; + defer source_text.deinit(p.gpa); + for (0..14) |_| try source_text.appendSlice(p.gpa, "\t source();\n"); + const source = try p.setTestFile(source_text.items); + p.gpa.free(source.file.?.path); + source.file.?.path = try p.gpa.dupe(u8, "/chunk-boundary-界.txt"); + p.locations_config = .{ .context = 2, .tscontext = false }; + var input: std.ArrayList(u8) = .empty; + defer input.deinit(p.gpa); + for ([_]usize{ 1, 2, 3, 4, 5, 6, 7, 8, 12 }) |line| { + const entry = try std.fmt.allocPrint(p.gpa, "{s}:{d}:1 \t source();\n", .{ source.file.?.path, line }); + defer p.gpa.free(entry); + try input.appendSlice(p.gpa, entry); + } + try panes.Output.fillResults(p, 0, "/", origin, "context chunks", try p.gpa.dupe(u8, input.items), 8); + const file = &p.panes[source.search_pane.?].?.file.?; + try std.testing.expectEqual(@as(usize, 14), file.location_rows.len); + try std.testing.expectEqual(@as(usize, 11), source.search_row.?); + const first_label = try std.fmt.allocPrint(p.gpa, "{s}:8:1", .{source.file.?.path}); + defer p.gpa.free(first_label); + const next_label = try std.fmt.allocPrint(p.gpa, "{s}:12:1", .{source.file.?.path}); + defer p.gpa.free(next_label); + for (file.location_rows, 0..) |row, index| { + const line = modal.lineSlice(file.content, index); + try std.testing.expectEqual(index + 1, row.at.line); + const expected = if (row.at.line <= 10) first_label else next_label; + try std.testing.expectEqual(panes.File.displayWidth(expected), panes.File.displayWidth(line[0 .. row.code_start - 1])); + try std.testing.expectEqualStrings("\t source();", line[row.code_start..]); + if (row.at.line >= 9 and row.at.line != 12) { + try std.testing.expectEqual(.context, row.kind); + try std.testing.expectEqual(@as(usize, 0), row.location_end); + } else try std.testing.expectEqual(.match, row.kind); + } + } +} -- cgit v1.3