package mnotty
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Declaring terminals with Miou
Install
dune-project
Dependency
Authors
Maintainers
Sources
notty-miou-0.0.2.tbz
sha256=9a3463ea08b15da19bb5b65887baa17a093c33d0948b41fb3f47da1ff02e7d30
sha512=222cc5ed72d2a82fbc3b033c18dd170e4332d5600ed17a324eaf3ab4380eb8bd1b8167fe2602927b4625c68ffec55c923344ee9e864d2ef5018b67a5796e02a4
doc/src/mnotty/mnotty.ml.html
Source file mnotty.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162module Stop = struct type t = { mutex: Miou.Mutex.t ; condition: Miou.Condition.t ; mutable value: bool } let create () = let mutex = Miou.Mutex.create () and condition = Miou.Condition.create () in { mutex; condition; value= false } let switch t = Miou.Mutex.protect t.mutex @@ fun () -> t.value <- true; Miou.Condition.broadcast t.condition let wait t = Miou.Mutex.protect t.mutex @@ fun () -> while not t.value do Miou.Condition.wait t.condition t.mutex done end module Signal = struct type dim = int * int type t = (dim, dim) Flux.Bqueue.t let create () = Flux.Bqueue.(create infinite 0x7ff) let wait t = Flux.Bqueue.get t let signal t dim = Flux.Bqueue.put t dim (* NOTE(dinosaure): [Signal] is really poor in the sense that if several processes are waiting for the signal and it appears only once, only **one** of the processes will be released (this is not a [Condition.broadcast]!). In this case, there is only one process attempting to "consume"/wait (see [resize]) for the signal, so it doesn't matter, but it's important to bear this in mind. *) end open Notty module Term = struct type t = { oc: string -> unit ; trm: Notty.Tmachine.t ; buf: Buffer.t ; mutable src: [ Unescape.event | `Resize of dim ] Flux.source ; stop: Stop.t } and dim = int * int exception Stop exception Timeout let consume_and_put ic stop q = let flt = Unescape.create () in let buf = Bytes.create 0x7ff in let rec next () = match Unescape.next flt with | #Unescape.event as ev -> Flux.Bqueue.put q ev; next () | `End -> Flux.Bqueue.close q | `Await -> begin let prm0 = Miou.async ic in let prm1 = Miou.async @@ fun () -> Stop.wait stop; raise Stop in match Miou.await_first [ prm0; prm1 ] with | Error Stop -> Flux.Bqueue.close q | Error _exn -> Flux.Bqueue.close q | Ok None -> Unescape.input flt buf 0 0; next () | Ok (Some str) -> let rec go (str, str_off, str_len) = if str_len > 0 then begin let len = Int.min (Bytes.length buf) str_len in Bytes.blit_string str str_off buf 0 len; Unescape.input flt buf 0 len; go (str, str_off + len, str_len - len) end in go (str, 0, String.length str); next () end in next let write t = Tmachine.output t.trm t.buf; let out = Buffer.contents t.buf in Buffer.clear t.buf; t.oc out let refresh t = Tmachine.refresh t.trm; write t let image t image = Tmachine.image t.trm image; write t let cursor t curs = Tmachine.cursor t.trm curs; write t let set_size t dim = Tmachine.set_size t.trm dim let size t = Tmachine.size t.trm let release t = if Tmachine.release t.trm then begin Stop.switch t.stop; write t end let resize sigwinch stop on_resize = (* NOTE(dinosaure): The aim here is to "debounce" the SIGWINCH signal, which can occur several times in succession. When a user manually resizes a window, a multitude of SIGWINCH events are triggered (100x80, 100x79, 100x78, 100x77, ... 100x50). Instead of resizing each time, we wait 1000 ns; if no further SIGWINCH signals have occurred after these 1000 ns, it means the user has finished resizing and is therefore reporting the new window size. *) let rec delay dim = let prm0 = Miou.async @@ fun () -> Signal.wait sigwinch in let prm1 = Miou.async @@ fun () -> Mkernel.sleep 1000; raise Timeout in let prm2 = Miou.async @@ fun () -> Stop.wait stop; raise Stop in match Miou.await_first [ prm0; prm1; prm2 ] with | Ok dim -> delay dim | Error Timeout -> on_resize dim; start () | Error Stop -> () | Error _exn -> () and start () = let prm0 = Miou.async @@ fun () -> Signal.wait sigwinch in let prm1 = Miou.async @@ fun () -> Stop.wait stop; raise Stop in match Miou.await_first [ prm0; prm1 ] with | Ok dim -> delay dim | Error Stop -> () | Error _exn -> () in Miou.async start let create ?(bpaste = true) ?(mouse = true) ?stop (size, sigwinch) ic oc = let stop = match stop with Some stop -> stop | None -> Stop.create () in let rec t = lazy { trm= Tmachine.create ~mouse ~bpaste Cap.ansi ; oc ; buf= Buffer.create 0x7ff ; stop ; src= Flux.Source.with_task ~size:0x7ff task } and task q = let on_resize dim = let t = Lazy.force t in Buffer.reset t.buf; set_size t dim; Flux.Bqueue.put q (`Resize dim) in let prm = resize sigwinch stop on_resize in consume_and_put ic stop q (); Miou.cancel prm in let t = Lazy.force t in set_size t size; write t; t let events t = match Flux.Source.next t.src with | Some (ev, src) -> t.src <- src; Some ev | None -> None let source { src; _ } = src end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>