Files
ghostty-rs/docs/rewrite/notes/ghostty-terminal-pagelist-requests.md
T
2026-10-11 22:39:16 +02:00

3.2 KiB

Requests for page.rs / page_list.rs (from the Screen port)

  1. Pin-based iterators (Zig PageList.zig ~5100-5170): Pin::{row_iterator, cell_iterator, page_iterator, prompt_iterator}(direction, limit: Option<Pin>). The limit pin is inclusive and applies at row granularity. Screen uses a local copy in pin_iter.rs.
  2. PageList::set_tracked_pin validity: it rejects pins with y >= node.size.rows. Zig writes the pin raw; Screen::split_for_capacity temporarily restores the cursor to the pre-split node, which may have shrunk. Worked around with a clamped stand-in.
  3. Cross-page row clone: Zig Page.cloneRowFrom(other_page, ...) between two nodes of one list needs two page borrows. Screen implements it with export_cell/import_cell (Screen::clone_row_between). A PageList::clone_row_between(src_pin, dst_pin) would be better.
  4. String allocator probing: Page.string_alloc is private; Zig cursorSetHyperlink probes it before growing. Screen instead re-adds the cursor hyperlink after increase_capacity. Also insert_hyperlink allocates strings before checking set dedup, so near-full pages can fail needlessly.
  5. fixup_viewport must handle Viewport::Top after erase_rows (Zig PageList.zig ~3043-3070). Worked around in Screen::erase_rows.
  6. Resize reflow / no-reflow fewer rows must drop trailing blank rows, including rows holding only bg-color cells (Zig resizeCols/resizeWithoutReflow). Three Screen tests are #[ignore = "pagelist: ..."]: screen_resize_no_reflow_less_rows_trims_blank_lines, screen_resize_less_cols_with_reflow_but_row_space, screen_resize_less_cols_to_wrap_wide_char.
  7. PageList::reset and erase_rows return Result; erase_rows with an empty history start point returns InvalidCoordinate (Zig would assert). Screen guards/ignores.
  • (T3/p4) erase_row_bounded must reset row flags on the blanked row: after rotating, the final row is cleared with Page::clear_cells, which leaves row.hyperlink/styled/grapheme set. Zig's row is left with the flags cleared (test Terminal: index bottom of scroll region clear hyperlinks expects !row.hyperlink; ignored as terminal_index_bottom_of_scroll_region_clear_hyperlinks).
  • (T3/p8) Reflow to fewer cols with a pending-wrap cursor: 4x2 screen printed "0123", resize(2,2) with reflow gives screen contents "01\n23" but the active area/viewport dump is only "23" (active top is one row too low; Zig yields "01\n23"). Ignored test: terminal_resize_with_wraparound_on.
  • (T3/p1) Page::set_graphemes / Page::append_grapheme must not mark the row dirty (Zig Page.appendGrapheme leaves dirty untouched; callers like Terminal.print mark dirty explicitly). Terminal works around it for the zero-width path (test terminal_ignored_vs16_doesnt_mark_dirty).
  • (T3/terminal) PageList::clone_partial_row_between(src_pin, dst_pin, left, right): Terminal insert_lines/delete_lines need Zig's Page.clonePartialRowFrom between two different page nodes of one list (needs two page borrows). terminal.rs::clone_partial_row_between re-implements it via export_cell/import_cell (now pub(crate) use) plus the row-metadata merge from Page::clone_partial_row_from.