diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-15 14:46:38 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-15 17:24:42 -0300 |
| commit | 40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1 (patch) | |
| tree | 642150be8703f1d9a0766ff18516f06bfdc8801a /test | |
| parent | 379f4fe55c7c9c7c8cc7b97dc921c83e2c24698b (diff) | |
| download | pardes-40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1.tar.gz pardes-40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1.zip | |
Add optional compact tagline styling for source context
Diffstat (limited to 'test')
| -rw-r--r-- | test/panes.zig | 55 | ||||
| -rw-r--r-- | test/web-snapshots/touch.mjs | 39 |
2 files changed, 94 insertions, 0 deletions
diff --git a/test/panes.zig b/test/panes.zig index a452bcfb..16e40ee3 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -190,6 +190,60 @@ const TagNavigationTests = struct { } }; +const BodyHitTests = struct { + fn mouse(layer: *const pardes.BodyLayer, row: u16, col: u16, kind: pardes.Mouse.Kind) pardes.Mouse { + const width: f32 = if (row < layer.context_rows) 8 else 10; + const x = @as(f32, @floatFromInt(layer.viewport.x)) * 10 + (@as(f32, @floatFromInt(col)) + 0.5) * width; + const y = layer.rowTop(row, 20, 10) + layer.rowHeight(row, 20, 10) / 2; + return .{ .button = .left, .kind = kind, .col = @intFromFloat(x / 10), .row = @intFromFloat(y / 20), .body_hit = layer.hitAt(x, y, 10, 20, 8, 10).? }; + } + + test "compact TreeContext mouse follows source rows in reclaimed space" { + if (!syntax.enabled) return error.SkipZigTest; + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 64, .rows = 18 }); + defer p.deinit(); + p.row_metrics = .{ .body_w = 10, .body_h = 20, .tagline_w = 8, .tagline_h = 10 }; + const pane = try TreeContextTests.setZigFile(p, "const Box = struct {\n pub fn work(\n value: usize,\n ) void {\n" ++ " // body\n" ** 60 ++ " }\n};\n"); + try std.testing.expect(p.executeBuiltinLine(0, "TreeContext")); + pane.scrollBy(10); + var frame = std.heap.ArenaAllocator.init(p.gpa); + defer frame.deinit(); + _ = try p.render(frame.allocator()); + const layer = &p.surface.body_layers[0]; + try std.testing.expect(layer.context_rows >= 4); + try std.testing.expect(layer.rows > pane.rows); + const first = mouse(layer, 0, 2, .press); + const second = mouse(layer, 1, 2, .press); + try std.testing.expectEqual(first.row, second.row); + const top = pane.scroll(); + for ([_]u16{ 0, 1 }) |row| { + const expected = pane.wrapAt(row).line; + p.update(.{ .mouse = mouse(layer, row, 2, .press) }); + p.update(.{ .mouse = mouse(layer, row, 2, .release) }); + try std.testing.expectEqual(expected, pane.cur_row); + try std.testing.expectEqual(top, pane.scroll()); + } + const last = pane.body_visible_rows - 1; + try std.testing.expect(last >= pane.rows); + const expected = pane.wrapAt(last).line; + const prefix = panes.File.gutterWidth(pane); + p.update(.{ .mouse = mouse(layer, last - 1, prefix + 11, .press) }); + // Release at a different source row without an intermediate drag event. + p.update(.{ .mouse = mouse(layer, last, prefix + 14, .release) }); + try std.testing.expectEqualStrings("body\nbody", pardes.test_api.heldSelection(p, 0).?); + p.update(.{ .mouse = mouse(layer, last, 10, .press) }); + p.update(.{ .mouse = mouse(layer, last, 10, .release) }); + try std.testing.expectEqual(expected, pane.cur_row); + var stale = mouse(layer, 0, 2, .press); + stale.body_hit.?.serial +%= 1; + p.update(.{ .mouse = stale }); + try std.testing.expectEqual(expected, pane.cur_row); + p.update(.{ .key = .{ .cp = 'i' } }); + p.update(.{ .key = .{ .cp = 'X', .text = "X" } }); + try std.testing.expect(std.mem.indexOfScalar(u8, modal.lineSlice(pane.file.?.content, @intCast(expected)), 'X') != null); + } +}; + const TreeContextTests = struct { const source = "const Box = struct {\n" ++ " pub fn work(\n" ++ @@ -3556,6 +3610,7 @@ test { _ = TagNavigationTests; _ = TagNameTintTests; _ = TreeContextTests; + _ = BodyHitTests; _ = TtySelectionTests; _ = ClickCursorTests; _ = JumpSelectionTests; diff --git a/test/web-snapshots/touch.mjs b/test/web-snapshots/touch.mjs index 8c34b185..4dde2fa4 100644 --- a/test/web-snapshots/touch.mjs +++ b/test/web-snapshots/touch.mjs @@ -42,6 +42,42 @@ function styled(frame) { export default async function ({ grid, touch, wait, stable, delay, evaluate, mouse }) { await stable(100, 5000); + const compactGeometry = await evaluate(`(() => { + const root = document.createElement("div"); + root.className = "pardes"; + root.style.cssText = "position:fixed;left:0;top:0;width:20px;height:40px"; + document.body.append(root); + const memory = new WebAssembly.Memory({initial:1}); + const bytes = new Uint8Array(memory.buffer), data = new DataView(memory.buffer); + for (const [base,count] of [[0,4],[1024,6]]) for(let i=0;i<count;i++) { + const off=base+i*20; bytes[off]=65+i; bytes[off+18]=1; + data.setUint32(off+8,0xffffff,true); data.setUint32(off+12,0x123456,true); + if(base && i<2) data.setUint16(off+16,128,true); + } + const values=[3,2,1,0,0,2,2,42,0,2,1]; + const wasm={memory,pardes_gui_tagline_font_percent:()=>50,pardes_frame:()=>4, + pardes_pointer_shape:()=>0,pardes_frame_cols:()=>2,pardes_frame_rows:()=>2, + pardes_frame_ptr:()=>0,pardes_cursor_x:()=>65535,pardes_cursor_y:()=>65535,pardes_cursor_bar:()=>0, + pardes_body_layer_limit:()=>1,pardes_body_layer_value:(_,field)=>values[field],pardes_body_layer_cells:()=>1024}; + const renderer=new pardes.runtime.renderer.constructor(root,wasm); + Object.assign(renderer,{cellWidth:10,cellHeight:20,taglineWidth:5,taglineHeight:10}); + renderer.render(); + const layer=renderer.layerRoot.firstChild, rect=layer.getBoundingClientRect(); + const bands=[...layer.children].slice(0,3).map(node=>{ + const box=node.getBoundingClientRect();return [box.y-rect.y,box.height]; + }); + const cursor=layer.querySelector('.is-cursor'); + renderer.render(); + const result={bands,height:rect.height,clipped:getComputedStyle(layer).overflow, + cursor:cursor?.textContent,cached:renderer.layerRoot.firstChild===layer}; + root.remove();return result; + })()`); + assert.deepEqual(compactGeometry.bands, [[0,10],[10,20],[30,20]], "compact headers release real height to additional body rows"); + assert.equal(compactGeometry.height,40); + assert.equal(compactGeometry.clipped,"hidden"); + assert.equal(compactGeometry.cursor,"E"); + assert(compactGeometry.cached,"unchanged compact layers reuse their DOM nodes"); + let frame = await grid(); assert.equal(tags(frame).length, 1); styled(frame); @@ -118,6 +154,9 @@ export default async function ({ grid, touch, wait, stable, delay, evaluate, mou runtime.wasm = { ...wasm, pardes_mouse: (...args) => { events.push(args.slice(0, 2)); wasm.pardes_mouse(...args); + }, pardes_mouse_pixel: (...args) => { + events.push(args.slice(0, 2)); + wasm.pardes_mouse_pixel(...args); } }; const observe = (event) => { if (event.type === "pointerdown") pointerDownCanceled.push(event.defaultPrevented); |
