char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
6334b24
main
1import { assert , assertEquals } from "@std/assert" ; 2import { existsSync } from "node:fs" ; 3import { Ghostty , type KeyInput } from "./ghostty.ts" ; 4 5const WASM = new URL ( "./ghostty-vt.wasm" , import . meta. url ); 6const built = existsSync ( WASM ); 7const load = async () => await Ghostty . load ( await Deno . readFile ( WASM )); 8const encode = ( text :string ) => new TextEncoder (). encode ( text ); 9const decode = ( bytes :Uint8Array | null ) => bytes && new TextDecoder (). decode ( bytes ); 10const press = ( code :string , key :string , mods :Partial < KeyInput > = {}) :KeyInput => ({ 11 code, 12 key, 13shiftKey :false , 14ctrlKey :false , 15altKey :false , 16metaKey :false , 17repeat :false , 18 ...mods , 19}); 20 21Deno . test ({ 22name :"a terminal draws what it is written in runs of one style, and then only what changes" , 23ignore :! built , 24async fn () { 25const terminal = ( await load ()). terminal ( 20 , 4 ); 26terminal . write ( encode ( "plain \x1b[1;31mbold red\x1b[0m\r\n\x1b[7minverse\x1b[0m 🦀 x " )); 27const first = terminal . frame (); 28assertEquals ( first . cols , 20 ); 29assertEquals ( first . rows , 4 ); 30assertEquals ( first . changed . size , 4 ); 31assertEquals ( first . changed . get ( 0 ), [ 32{ text :"plain " }, 33{ text :"bold red" , bold :true , fg :first . changed . get ( 0 ) ! [ 1 ]. fg }, 34]); 35const red = first . changed . get ( 0 ) ! [ 1 ]. fg ! ; 36assert ( red [ 0 ] > red [ 1 ] && red [ 0 ] > red [ 2 ], "red is red" ); 37const [ inverse , space , crab , rest ] = first . changed . get ( 1 ) ! ; 38assertEquals ( inverse . text , "inverse" ); 39assert ( inverse . fg && inverse . bg , "inverse swaps in the defaults" ); 40assertEquals ([ space . text , crab , rest . text ], [ " " , { text :"🦀" , wide :true }, " x" ]); 41assertEquals ( first . changed . get ( 2 ), []); 42assertEquals ( first . cursor , { x :15 , y :1 , style :"block" }); 43 44assertEquals ( terminal . frame (). changed . size , 0 ); 45terminal . write ( encode ( "\r\nnext" )); 46assertEquals ([ ...terminal . frame (). changed . keys ()], [ 1 , 2 ]); 47terminal . free (); 48}, 49}); 50 51Deno . test ({ 52name :"a snapshot carries a terminal, scrollback and unfinished sequences included, to another" , 53ignore :! built , 54async fn () { 55const ghostty = await load (); 56const terminal = ghostty . terminal ( 10 , 2 ); 57terminal . write ( encode ( "one\r\ntwo\r\nthree\r\n\x1b[3" )); 58const restored = ghostty . restore ( terminal . snapshot ()); 59assertEquals ( restored . text (), terminal . text ()); 60// the half-written sequence finishes in the copy, as it would have in the original 61restored . write ( encode ( "1mred" )); 62assertEquals ( restored . frame (). changed . get ( 1 ) ! . at ( - 1 ) ! . text , "red" ); 63restored . scroll ( - 1 ); 64assertEquals ( restored . frame (). changed . get ( 0 ), [{ text :"two" }]); 65}, 66}); 67 68Deno . test ({ 69name : 70"keys encode as the program's modes ask, pastes bracket when asked, and queries are answered" , 71ignore :! built , 72async fn () { 73const terminal = ( await load ()). terminal ( 80 , 24 ); 74assertEquals ( decode ( terminal . key ( press ( "KeyA" , "a" ))), "a" ); 75assertEquals ( decode ( terminal . key ( press ( "KeyC" , "c" , { ctrlKey :true }))), "\x03" ); 76assertEquals ( decode ( terminal . key ( press ( "ArrowUp" , "ArrowUp" ))), "\x1b[A" ); 77assertEquals ( decode ( terminal . key ( press ( "Enter" , "Enter" ))), "\r" ); 78assertEquals ( terminal . key ( press ( "ShiftLeft" , "Shift" , { shiftKey :true })), null ); 79assertEquals ( decode ( terminal . paste ( "ls" )), "ls" ); 80 81const answers :string [] = []; 82terminal . answer (( data ) => answers . push ( decode ( data ) ! )); 83terminal . write ( encode ( "\x1b[?1h\x1b[?2004h\x1b[c" )); 84assertEquals ( decode ( terminal . key ( press ( "ArrowUp" , "ArrowUp" ))), "\x1bOA" ); 85assertEquals ( decode ( terminal . paste ( "ls" )), "\x1b[200~ls\x1b[201~" ); 86assertEquals ( answers . length , 1 ); 87assert ( answers [ 0 ]. startsWith ( "\x1b[?" ), "a device attributes report" ); 88}, 89});