diff options
| author | Gabriel Schneider <[email protected]> | 2026-10-01 01:21:23 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 01:35:12 -0300 |
| commit | ea28dbf4ce827ee5544562bd19453c68599d912f (patch) | |
| tree | d3803102715fce8b010ff0ea44840a1a6954dc38 | |
| parent | 77bda7e14e0ea81db5da54c233fc30d218773f47 (diff) | |
| download | pardes-ea28dbf4ce827ee5544562bd19453c68599d912f.tar.gz pardes-ea28dbf4ce827ee5544562bd19453c68599d912f.zip | |
A +PdfSections row's first number is the page: a section that is not there, or is on another page, is a miss said, not a silent success
A look at `file.pdf:P:S` in +PdfSections went to section S whatever P
said, and one past the last section did nothing and answered ok. The
row's page is now held to: a section not in the outline, or on another
page than the row names, fails with which, as every other miss does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | src/pdf_view.zig | 15 | ||||
| -rw-r--r-- | test/pdf.zig | 37 |
2 files changed, 51 insertions, 1 deletions
diff --git a/src/pdf_view.zig b/src/pdf_view.zig index 09c06356..b307d1f3 100644 --- a/src/pdf_view.zig +++ b/src/pdf_view.zig @@ -2248,7 +2248,14 @@ pub fn lookSection( std.fmt.bufPrint(&joined_path, "{s}{s}{s}", .{ output_dir, separator, path }) catch return true; if (!std.mem.eql(u8, owner.state.path, target_path)) return true; - const destination = owner.state.sectionDestination(core.pdf_gpa, at.col - 1) orelse return true; + // A row is `file:PAGE:SECTION`, its first number the page as in every + // other location: a section there is none, or one on another page, is + // a miss said, never a silent jump. + var said: [160]u8 = undefined; + const destination = owner.state.sectionDestination(core.pdf_gpa, at.col - 1) orelse + return failSection(core, output_id, std.fmt.bufPrint(&said, "PdfSections: {s} has no section {d}", .{ std.fs.path.basename(owner.state.path), at.col }) catch "PdfSections: no such section"); + if (destination == .internal and destination.internal.page + 1 != at.line) + return failSection(core, output_id, std.fmt.bufPrint(&said, "PdfSections: section {d} of {s} is on page {d}, not {d}", .{ at.col, std.fs.path.basename(owner.state.path), destination.internal.page + 1, at.line }) catch "PdfSections: that section is on another page"); switch (destination) { .internal => |internal| { look.clearNavigationSelection(core, owner.pane); @@ -2261,6 +2268,12 @@ pub fn lookSection( return true; } +fn failSection(core: *pardes.Pardes, id: usize, text: []const u8) bool { + core.look_missed = true; + core.reportFailure(id, text); + return true; +} + pub fn resetPageChrome(pane: *pardes.Pane) void { pane.body.cur_row = 0; pane.body.cur_col = 0; diff --git a/test/pdf.zig b/test/pdf.zig index d1dd5bb0..d91f50a7 100644 --- a/test/pdf.zig +++ b/test/pdf.zig @@ -315,6 +315,43 @@ test "PDF dump fallback remains a byte-preserving file" { try std.testing.expectEqualStrings(" Keep Del", pane.tag.own.?); } +test "a +PdfSections row's first number is the page: a section not there, or on another page, is a miss said" { + if (!pdf_enabled or platform == .web) return; + const gpa = std.testing.allocator; + var tmp = std.testing.tmpDir(.{}); + defer tmp.cleanup(); + const fixture = try pdf_impl.makeOutlineTestPdf(gpa); + defer gpa.free(fixture); + try tmp.dir.writeFile(std.testing.io, .{ .sub_path = "outline.pdf", .data = fixture }); + var path_buf: [256]u8 = undefined; + const path = try std.fmt.bufPrint(&path_buf, ".zig-cache/tmp/{s}/outline.pdf", .{tmp.sub_path}); + const p = try Pardes.init(gpa, .{ .file = path, .cols = 80, .rows = 28 }); + defer p.deinit(); + panes.Pdf.openSections(p, 0); + const out_id = p.panes[0].?.search_pane orelse return error.MissingPdfSectionsOutput; + const out = p.panes[out_id].?; + const row = std.mem.sliceTo(out.file.?.content, '\n'); + const place = row[0 .. std.mem.indexOfScalar(u8, row, ' ') orelse row.len]; // outline.pdf:P:1 + var fields = std.mem.splitScalar(u8, place, ':'); + _ = fields.next(); + const page = try std.fmt.parseInt(usize, fields.next().?, 10); + var line: [128]u8 = undefined; + // As listed: found, no miss. + p.look_missed = false; + pardes.look.lookAt(p, out_id, place); + try std.testing.expect(!p.look_missed); + // The section on another page than the row says, and one not there. + for ([_][]const u8{ try std.fmt.bufPrint(&line, "outline.pdf:{d}:1", .{page + 1}), "outline.pdf:1:999" }) |bad| { + var copy: [128]u8 = undefined; + @memcpy(copy[0..bad.len], bad); + p.look_missed = false; + const failures = p.fs.failures; + pardes.look.lookAt(p, out_id, copy[0..bad.len]); + try std.testing.expect(p.look_missed); + try std.testing.expect(p.fs.failures != failures); + } +} + test "PdfSections Look follows the exact owning PDF, not an equal path" { if (!pdf_enabled or platform == .web) return; const gpa = std.testing.allocator; |
