123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147typestyle=[`Block|`Line|`Underline]typet={(* Desired State *)mutablerow:int;mutablecol:int;mutablehas_pos:bool;mutablestyle:style;mutableblinking:bool;mutablecolor:(int*int*int)option;mutablevisible:bool;(* Applied State (Snapshot of last emit) None = unknown terminal state, forces
re-emission *)mutablelast_visible:booloption;mutablelast_style:styleoption;mutablelast_blink:booloption;mutablelast_color:(int*int*int)option;}typesnapshot={row:int;col:int;has_position:bool;style:style;blinking:bool;color:(int*int*int)option;visible:bool;}letcreate()={row=1;col=1;has_pos=false;style=`Block;blinking=true;color=None;visible=true;(* Initialize all applied state as unknown to force emission on first use *)last_visible=None;last_style=None;last_blink=None;last_color=None;}letreset(t:t)=(* Mark all applied state as unknown to force full re-emission *)t.last_visible<-None;t.last_style<-None;t.last_blink<-None;t.last_color<-Noneletsnapshot(t:t)={row=t.row;col=t.col;has_position=t.has_pos;style=t.style;blinking=t.blinking;color=t.color;visible=t.visible;}letset_position(t:t)~row~col=t.row<-max1row;t.col<-max1col;t.has_pos<-trueletclear_position(t:t)=t.has_pos<-falseletset_style(t:t)~style~blinking=t.style<-style;t.blinking<-blinkingletset_color(t:t)c=t.color<-cletset_visible(t:t)v=t.visible<-vletis_visible(t:t)=t.visibleletclamp_to_bounds(t:t)~max_row~max_col=ift.has_posthen(t.row<-max1(minmax_rowt.row);t.col<-max1(minmax_colt.col))letcursor_style_seqstyleblinking=match(style,blinking)with|`Block,true->Ansi.cursor_style~shape:`Blinking_block|`Block,false->Ansi.cursor_style~shape:`Block|`Line,true->Ansi.cursor_style~shape:`Blinking_bar|`Line,false->Ansi.cursor_style~shape:`Bar|`Underline,true->Ansi.cursor_style~shape:`Blinking_underline|`Underline,false->Ansi.cursor_style~shape:`Underlinelethide_temporarily(t:t)w=(* Hide cursor if it's visible or in unknown state. When state is unknown, we
hide to be safe during render. *)matcht.last_visiblewith|Somefalse->()(* Already hidden, nothing to do *)|Sometrue|None->Ansi.emitAnsi.(disableCursor_visible)w;t.last_visible<-Somefalseletemit(t:t)~row_offsetw=(* 1. Visibility Check *)ifnott.visiblethen((* Hide cursor if visible or unknown *)matcht.last_visiblewith|Somefalse->()(* Already hidden *)|Sometrue|None->Ansi.emitAnsi.(disableCursor_visible)w;t.last_visible<-Somefalse;(* Clear attributes so they re-apply if we show cursor again *)t.last_style<-None;t.last_blink<-None;t.last_color<-None)else((* 2. Positioning *)(ift.has_posthenletr=max1(t.row+row_offset)inletc=max1t.colinAnsi.cursor_position~row:r~col:cw);(* 3. Style Changes *)letstyle_changed=match(t.last_style,t.last_blink)with|Somes,Somebwhens=t.style&&b=t.blinking->false|_->trueinifstyle_changedthen(Ansi.emit(cursor_style_seqt.stylet.blinking)w;t.last_style<-Somet.style;t.last_blink<-Somet.blinking);(* 4. Color Changes *)ift.color<>t.last_colorthen((matcht.colorwith|Some(r,g,b)->Ansi.emit(Ansi.cursor_color~r~g~b)w|None->Ansi.emitAnsi.reset_cursor_colorw;Ansi.emitAnsi.reset_cursor_color_fallbackw);t.last_color<-t.color);(* 5. Ensure Visible (if it was hidden by hide_temporarily or unknown) *)matcht.last_visiblewith|Sometrue->()(* Already visible *)|Somefalse|None->Ansi.emitAnsi.(enableCursor_visible)w;t.last_visible<-Sometrue)