Terminal styling and layout widgets for OCaml (tables, trees, panels, colors)
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-tty: enable MDX on lib/progress.mli

Run mdx on lib/progress.mli so the five {[ ... ]} odoc blocks now
type-check.

Five blocks each with a different shape:
- Functional core: chained `let s = ... in let s = ...` rewritten as
toplevel let bindings.
- Imperative wrapper and multi-phase: the for-loop/Progress.update
flow goes inside `let run_imperative () = ...` and
`let run_phases () = ...` so the actual progress rendering doesn't
fire at mdx test time.
- Animation daemon: wrapped in `let animate ~sw ~clock bar = ...`
so the fiber-daemon spawn shows the API shape without taking a
switch.
- logs_reporter: bound to `let install_logs_reporter () = ...` for
the same reason.

All Progress paths qualified to `Tty.Progress.X` so the toploop
resolves them through the `nox-tty` package.

+28 -23
+2 -2
lib/dune
··· 7 7 (names winsize))) 8 8 9 9 (mdx 10 - (files tree.mli) 11 - (libraries nox-tty)) 10 + (files tree.mli progress.mli) 11 + (libraries nox-tty logs logs.fmt eio eio.core eio.unix))
+26 -21
lib/progress.mli
··· 14 14 full control or integration with an existing render loop. 15 15 16 16 {[ 17 - let cfg = Progress.config () in 18 - let s = Progress.state ~total:100 "Downloading" in 19 - let s = Progress.incr s in 20 - let line = Progress.render ~frame:0 cfg s in 21 - print_string ("\r" ^ line) 17 + let cfg = Tty.Progress.config () 18 + let s = Tty.Progress.state ~total:100 "Downloading" 19 + let s = Tty.Progress.incr s 20 + let line = Tty.Progress.render ~frame:0 cfg s 21 + let () = print_string ("\r" ^ line) 22 22 ]} 23 23 24 24 {2 Imperative Wrapper} ··· 26 26 Convenient mutable wrapper that handles rendering automatically. 27 27 28 28 {[ 29 - let bar = Progress.v ~total:100 "Downloading" in 30 - for _ = 1 to 100 do 31 - Progress.tick bar 32 - done; 33 - Progress.finish bar 29 + let run_imperative () = 30 + let bar = Tty.Progress.v ~total:100 "Downloading" in 31 + for _ = 1 to 100 do 32 + Tty.Progress.tick bar 33 + done; 34 + Tty.Progress.finish bar 34 35 ]} 35 36 36 37 {2 Multi-phase Operations} 37 38 38 39 {[ 39 - let bar = Progress.v ~total:10 "Working" in 40 - Progress.update bar ~phase:"Fetch" ~msg:"file1.txt"; 41 - Progress.update bar ~phase:"Build" ~msg:"compiling"; 42 - Progress.finish bar 40 + let run_phases () = 41 + let bar = Tty.Progress.v ~total:10 "Working" in 42 + Tty.Progress.update bar ~phase:"Fetch" ~msg:"file1.txt"; 43 + Tty.Progress.update bar ~phase:"Build" ~msg:"compiling"; 44 + Tty.Progress.finish bar 43 45 ]} *) 44 46 45 47 (** {1 Functional Core} *) ··· 121 123 This module is scheduler-agnostic. To animate the spinner without advancing 122 124 position, spawn a loop that calls {!redraw} on your own scheduler: 123 125 {[ 124 - Eio.Fiber.fork_daemon ~sw (fun () -> 125 - while not (Progress.is_finished bar) do 126 - Eio.Time.sleep clock 0.1; 127 - Progress.redraw bar 128 - done; 129 - `Stop_daemon) 126 + let animate ~sw ~clock bar = 127 + Eio.Fiber.fork_daemon ~sw (fun () -> 128 + while not (Tty.Progress.is_finished bar) do 129 + Eio.Time.sleep clock 0.1; 130 + Tty.Progress.redraw bar 131 + done; 132 + `Stop_daemon) 130 133 ]} *) 131 134 132 135 val redraw : t -> unit ··· 187 190 (** [logs_reporter r] wraps reporter [r] so that log messages auto-suspend any 188 191 active progress bar. Use as: 189 192 {[ 190 - Logs.set_reporter (Progress.logs_reporter (Logs_fmt.reporter ())) 193 + let install_logs_reporter () = 194 + Logs.set_reporter 195 + (Tty.Progress.logs_reporter (Logs_fmt.reporter ())) 191 196 ]} *)