brewery
notashelf /
efd11f15fd3fea65a643e1f108bd9dd0dbc39263

beer

public

A terminal worth pouring time into

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/beer.git

Commit efd11f15fd3f

tarball

NotAShelf <raf@notashelf.dev> · 2026-06-26 21:51 UTC

unverified2 files changed+33-4
beer/vt: verify Kitty graphics scroll-to-fit placement

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I3530522a469e0729042f1d5591768dc76a6a6964
diff --git a/crates/beer/src/grid/mod.rs b/crates/beer/src/grid/mod.rsindex 85dec08..1f70609 100644--- a/crates/beer/src/grid/mod.rs+++ b/crates/beer/src/grid/mod.rs@@ -786,10 +786,7 @@ impl Grid {         // Scroll the screen to make vertical room for the image. Only scroll         // when the full screen is the active scroll region; a DECSTBM region         // or the alternate screen keeps the image clipped as before.-        let y0 = if self.top == 0-            && self.bottom == self.rows - 1-            && self.alt_saved.is_none()-        {+        let y0 = if self.top == 0 && self.bottom == self.rows - 1 && self.alt_saved.is_none() {             let y0_initial = self.cursor.y;             let scroll_n = (y0_initial + rows)                 .saturating_sub(self.rows)diff --git a/crates/beer/src/vt/mod.rs b/crates/beer/src/vt/mod.rsindex 9656472..06c8aa5 100644--- a/crates/beer/src/vt/mod.rs+++ b/crates/beer/src/vt/mod.rs@@ -697,6 +697,38 @@ mod tests {     }      #[test]+    fn kitty_graphics_scrolls_to_fit_image() {+        // 20x4 terminal, cursor at the last row. An image 3 cells tall needs+        // 3 rows; only 1 is available, so the grid should scroll up 2 rows to+        // make room, then place the image in the bottom 3 rows.+        let mut t = Term::new(20, 4);+        // Move cursor to last row.+        feed(&mut t, b"\x1b[4;1H"); // CSI 4;1 H = row 4, col 1 (1-based)+        assert_eq!(t.grid().cursor(), (0, 3));++        // A 16x48 RGBA image: 2 cells wide, 3 cells tall at 8x16 cell size.+        let px = vec![0xffu8; 16 * 48 * 4];+        let b64 = beer_protocols::codec::base64_encode(&px);+        let seq = format!("\x1b_Ga=T,f=32,s=16,v=48,i=2;{b64}\x1b\\");+        feed(&mut t, seq.as_bytes());++        // The grid should have scrolled 2 rows; cursor is now on row 3 (last),+        // and image rows start at row 1 (dy=0 there, dy=2 at row 3).+        let top_cell = t.grid().cell(0, 1);+        assert_eq!(+            top_cell.image.map(|r| (r.image, r.dy)),+            Some((2, 0)),+            "top row of image should be at grid row 1 after scroll"+        );+        let bot_cell = t.grid().cell(0, 3);+        assert_eq!(+            bot_cell.image.map(|r| (r.image, r.dy)),+            Some((2, 2)),+            "bottom row of image should be at grid row 3"+        );+    }++    #[test]     fn reports_pixel_geometry_for_graphics_clients() {         // The test harness feeds with an 8x16 cell. A 20x4 grid is then 160x64         // pixels. These answers are what an image client needs to size images.