@@ -48,6 +48,108 @@ const RAINBOW = [RED, ORANGE, YELLOW, NGREEN, BLUE, VIOLET];
4848
4949const BRAILLE = [ "⠋" , "⠙" , "⠹" , "⠸" , "⠼" , "⠴" , "⠦" , "⠧" , "⠇" , "⠏" ] ;
5050
51+ function * queryCursor ( ) : Operation < CursorEvent > {
52+ let parser = yield * until ( createInput ( { escLatency : 100 } ) ) ;
53+ write ( DSR ( ) ) ;
54+
55+ let buf = new Uint8Array ( 32 ) ;
56+ while ( true ) {
57+ let n = Deno . stdin . readSync ( buf ) ;
58+ if ( n === null ) continue ;
59+ let result = parser . scan ( buf . subarray ( 0 , n ) ) ;
60+ for ( let ev of result . events ) {
61+ if ( ev . type === "cursor" ) {
62+ return ev ;
63+ }
64+ }
65+ }
66+ }
67+
68+ function waitKey ( ) {
69+ let buf = new Uint8Array ( 32 ) ;
70+ while ( true ) {
71+ let n = Deno . stdin . readSync ( buf ) ;
72+ if ( n === null ) continue ;
73+ for ( let i = 0 ; i < n ; i ++ ) {
74+ if ( buf [ i ] === 0x03 ) {
75+ Deno . stdin . setRaw ( false ) ;
76+ write ( SHOWCURSOR ( ) ) ;
77+ Deno . exit ( 0 ) ;
78+ }
79+ }
80+ return ;
81+ }
82+ }
83+
84+ function box ( msg : string , fg : number , border : number ) : Op [ ] {
85+ return [
86+ open ( "root" , {
87+ layout : { width : grow ( ) , height : grow ( ) , direction : "ttb" } ,
88+ } ) ,
89+ open ( "box" , {
90+ layout : {
91+ width : grow ( ) ,
92+ height : grow ( ) ,
93+ direction : "ttb" ,
94+ padding : { left : 1 } ,
95+ alignY : "center" ,
96+ } ,
97+ border : {
98+ color : border ,
99+ left : 1 ,
100+ right : 1 ,
101+ top : 1 ,
102+ bottom : 1 ,
103+ } ,
104+ cornerRadius : { tl : 1 , tr : 1 , bl : 1 , br : 1 } ,
105+ } ) ,
106+ text ( msg , { color : fg } ) ,
107+ close ( ) ,
108+ close ( ) ,
109+ ] ;
110+ }
111+
112+ function * transaction (
113+ height : number ,
114+ renderFrame : ( frame : number ) => Op [ ] ,
115+ frames : number ,
116+ interval : number ,
117+ ) : Operation < void > {
118+ let { columns } = Deno . consoleSize ( ) ;
119+
120+ write ( encode ( "\n" . repeat ( height ) ) ) ;
121+
122+ let pos = yield * queryCursor ( ) ;
123+ /** 1-based terminal row where the region starts */
124+ let row = pos . row - height + 1 ;
125+
126+ write ( ESC ( "7" ) ) ;
127+ let tty = settings ( cursor ( false ) ) ;
128+ write ( tty . apply ) ;
129+
130+ let term = validated (
131+ yield * until ( createTerm ( { width : columns , height } ) ) ,
132+ ) ;
133+ for ( let i = 0 ; i < frames ; i ++ ) {
134+ let result = term . render ( renderFrame ( i ) , { row } ) ;
135+ write ( new Uint8Array ( result . output ) ) ;
136+ yield * sleep ( interval ) ;
137+ }
138+
139+ write ( tty . revert ) ;
140+ write ( ESC ( "8" ) ) ;
141+ write ( encode ( "\n" ) ) ;
142+ }
143+
144+ function say ( msg : string ) {
145+ write ( encode ( msg + "\n" ) ) ;
146+ }
147+
148+ function pause ( ) {
149+ waitKey ( ) ;
150+ write ( encode ( "\n" ) ) ;
151+ }
152+
51153await main ( function * ( ) {
52154 let { columns } = terminalSize ( ) ;
53155 setRawMode ( true ) ;
0 commit comments