diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-16 11:53:11 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | 0b54c599fa5e26fb1754ca0aab53da5fa0e14af1 (patch) | |
| tree | 69d940d085f0043f19d4196d1d23593619b11dd4 /test/macos_e2e.swift | |
| parent | 71c273b7777ed17bc72c11df1a9221a9e645c714 (diff) | |
| download | pardes-0b54c599fa5e26fb1754ca0aab53da5fa0e14af1.tar.gz pardes-0b54c599fa5e26fb1754ca0aab53da5fa0e14af1.zip | |
Composite tag layers into the macOS e2e captures
Tag text stopped living in the frame grid when the core moved the topbar, the
column bar and every pane tag into tag layers of their own; the grid keeps the
chrome and the physical grips. readFrame still read the grid alone, so every
capture recorded blank header rows and each script timed out waiting for text
that was on screen but not in the dump. Flatten the layers back over the grid
at one cell per column — the tty backend's spelling, which these goldens exist
to stay comparable with — and follow pardes_font_take to its size out-param.
The goldens were recorded before the column bar and before the tag gap, so
they are rerecorded here: the captures now agree column for column with what
the tty renderer paints today.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Diffstat (limited to 'test/macos_e2e.swift')
| -rw-r--r-- | test/macos_e2e.swift | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/test/macos_e2e.swift b/test/macos_e2e.swift index 427d8314..58ad5206 100644 --- a/test/macos_e2e.swift +++ b/test/macos_e2e.swift @@ -266,8 +266,9 @@ private final class Driver: PardesViewDelegate { // The app does exactly this on every pump (AppDelegate.pump). Without // it the `Font` builtin would set a path nobody ever collects, and a // script asserting the new face would be asserting the old one. - if let view, let wanted = pardes_font_take() { - view.adoptFont(path: String(cString: wanted)) + var fontSize: UInt16 = 0 + if let view, let wanted = pardes_font_take(&fontSize) { + view.adoptFont(path: String(cString: wanted), sizeHundredths: fontSize) } } @@ -353,34 +354,63 @@ private final class Driver: PardesViewDelegate { return Frame(cols: cols, rows: rows, cursorX: cursorX, cursorY: cursorY, lines: []) } - var lines: [String] = [] - lines.reserveCapacity(rows) + var grid = [[String]](repeating: [String](repeating: " ", count: cols), count: rows) for row in 0..<rows { - var line = "" - line.reserveCapacity(cols) for col in 0..<cols { let cell = cells[row * cols + col] // A never-painted cell is background only, and a zero-length one // is the tail half of a wide glyph. Both read as a space, which // is what the tty oracle's emulator hands back for them too. - if cell.flags & UInt8(PARDES_CELL_DEFAULT) != 0 || cell.len == 0 { - line.append(" ") - continue - } - // prefix clamps, so a bogus len cannot walk off the eight bytes, - // and String(decoding:) substitutes U+FFFD rather than trapping - // on invalid UTF-8 — a capture has to be able to RECORD garbage, - // not die of it. - let text = withUnsafeBytes(of: cell.text) { raw in - String(decoding: raw.prefix(Int(cell.len)), as: UTF8.self) - } - line.append(text.isEmpty ? " " : text) + if cell.flags & UInt8(PARDES_CELL_DEFAULT) != 0 || cell.len == 0 { continue } + grid[row][col] = cellText(cell) } - lines.append(trimTrailingSpaces(line)) } + compositeTagLayers(into: &grid, cols: cols, rows: rows) + let lines = grid.map { trimTrailingSpaces($0.joined()) } return Frame(cols: cols, rows: rows, cursorX: cursorX, cursorY: cursorY, lines: lines) } + /// prefix clamps, so a bogus len cannot walk off the eight bytes, and + /// String(decoding:) substitutes U+FFFD rather than trapping on invalid + /// UTF-8 — a capture has to be able to RECORD garbage, not die of it. + private func cellText(_ cell: pardes_cell_s) -> String { + let text = withUnsafeBytes(of: cell.text) { raw in + String(decoding: raw.prefix(Int(cell.len)), as: UTF8.self) + } + return text.isEmpty ? " " : text + } + + /// Tag text is not in the frame grid any more. The core paints the topbar, + /// the column bar and every pane tag into tag layers of their own so a GUI + /// shell can set them at the smaller tagline pitch (Pardes.renderTagLayers); + /// the grid keeps only the chrome under them and the physical grips. A + /// capture that reads the grid alone therefore records blank header rows. + /// + /// Flatten the layers back over the grid at ONE cell per column. That is + /// the tty backend's spelling, and these goldens exist to stay comparable + /// with the tty ones row for row — the sub-cell pitch the layers carry is a + /// pixel concern with nowhere to live in a character grid. + private func compositeTagLayers(into grid: inout [[String]], cols: Int, rows: Int) { + for index in 0..<pardes_tag_layer_limit() { + let layerCols = Int(pardes_tag_layer_value(index, 0)) + guard layerCols > 0, let cells = pardes_tag_layer_cells(index) else { continue } + let x = Int(pardes_tag_layer_value(index, 4)) + let y = Int(pardes_tag_layer_value(index, 5)) + // A layer is allocated wide enough for text the viewport may crop, + // so the viewport — not the cell count — decides what is on screen. + let width = Int(pardes_tag_layer_value(index, 6)) + guard y >= 0, y < rows else { continue } + for col in 0..<min(layerCols, width) { + let at = x + col + if at < 0 { continue } + if at >= cols { break } + let cell = cells[col] + if cell.flags & UInt8(PARDES_CELL_DEFAULT) != 0 || cell.len == 0 { continue } + grid[y][at] = cellText(cell) + } + } + } + // MARK: - captures private func snap(_ label: String) { |
