feat(terminal): bring PageList to full parity with Ghostty
Second pass over the page memory model (done by Codex/gpt-6-astra in an isolated worktree, reviewed and merged here): - Resize/reflow now port Zig's incremental ReflowCursor algorithm with page backfill and the same capacity growth/split sequence, instead of rebuilding a snapshot, so page boundaries, pruning and tracked-pin remapping match Ghostty. - Point<->pin conversion for the active area starts at the list tail and the viewport offset is cached, so hot-path operations no longer walk the whole scrollback from the head. - RefCountedSet reproduces Zig's observable ID reuse and error points. - All 202 PageList tests are ported (plus 13 extra regressions). With this, the five Screen/Terminal tests previously ignored as blocked on PageList behaviour pass and are re-enabled. Test Plan: - cargo test -p ghostty-terminal (913 passed, 0 ignored) - cargo clippy -p ghostty-terminal --all-targets -- -D warnings
This commit is contained in:
1 parent
d24b40cf2b
commit
83c10debe6
9 files changed
+4613
-1770
No files matched your search
@@ -119,6 +119,51 @@ pub struct Fg<'a> {
|
||||
pub bold: Option<BoldColor>,
|
||||
}
|
||||
impl Style {
|
||||
/// Ghostty's packed-style hash: fold the exact 128-bit representation and
|
||||
/// apply Zig's 64-bit integer hash. This determines page-local probe order.
|
||||
pub(crate) fn zig_hash(&self) -> u64 {
|
||||
const MULTIPLIER: u64 = 0xbea225f9eb34556d;
|
||||
let mut packed = 0u128;
|
||||
for (index, color) in [self.fg_color, self.bg_color, self.underline_color]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
{
|
||||
let (tag, data) = match color {
|
||||
Color::None => (0, 0),
|
||||
Color::Palette(value) => (1, u32::from(value)),
|
||||
Color::Rgb(rgb) => (
|
||||
2,
|
||||
u32::from(rgb.r) | u32::from(rgb.g) << 8 | u32::from(rgb.b) << 16,
|
||||
),
|
||||
};
|
||||
packed |= (tag as u128) << (index * 8);
|
||||
packed |= u128::from(data) << (24 + index * 24);
|
||||
}
|
||||
let flags = self.flags;
|
||||
let mut bits = 0u16;
|
||||
for (index, value) in [
|
||||
flags.bold,
|
||||
flags.italic,
|
||||
flags.faint,
|
||||
flags.blink,
|
||||
flags.inverse,
|
||||
flags.invisible,
|
||||
flags.strikethrough,
|
||||
flags.overline,
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
{
|
||||
bits |= u16::from(value) << index;
|
||||
}
|
||||
bits |= (flags.underline as u16) << 8;
|
||||
packed |= u128::from(bits) << 96;
|
||||
let mut hash = packed as u64 ^ (packed >> 64) as u64;
|
||||
hash = (hash ^ (hash >> 32)).wrapping_mul(MULTIPLIER);
|
||||
hash = (hash ^ (hash >> 29)).wrapping_mul(MULTIPLIER);
|
||||
hash = (hash ^ (hash >> 32)).wrapping_mul(MULTIPLIER);
|
||||
hash ^ (hash >> 29)
|
||||
}
|
||||
/// True for default styling.
|
||||
pub fn is_default(self) -> bool {
|
||||
self == Self::default()
|
||||
|
||||
Reference in new issue
Block a user