package miaou-core
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Miaou core/widgets (no drivers, no SDL)
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.5.2.tar.gz
md5=60a3b9f181f24572a06a9492532bfdda
sha512=fcc35a275066be2900e6201782faf47503076fa4640f08cf78067835a6f447b74613009e55b2ac799adb7ca46f1bffa261fc5971753f2cc3c6bef327511c7ef6
doc/src/miaou_widgets_layout/progress_widget.ml.html
Source file progress_widget.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(*****************************************************************************) (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2025 Nomadic Labs <contact@nomadic-labs.com> *) (* Copyright (c) 2026 Mathias Bourgoin <mathias.bourgoin@atacama.tech> *) (* *) (*****************************************************************************) [@@@warning "-32-34-37-69"] (* A small, Bubble Tea–styled progress bar using the palette gradient. *) type t = { width : int; (* visible columns of the bar portion *) progress : float; (* 0.0 .. 1.0 *) label : string option; (* optional label shown to the left *) title : string option; (* used for centered/modal variants *) } let clamp01 x = if x < 0. then 0. else if x > 1. then 1. else x let open_inline ~width ?label () = {width = max 1 width; progress = 0.; label; title = None} let open_centered ~title ~width () = {width = max 1 width; progress = 0.; label = None; title = Some title} let set_progress w p = {w with progress = clamp01 p} let get_progress w = w.progress let set_label w l = {w with label = l} (* Use centralized helpers for ANSI/UTF-8 handling via display Widgets. *) let visible_length = Miaou_helpers.Helpers.visible_chars_count let render_bar ~width ~progress : string = let left = if Lazy.force Miaou_widgets_display.Widgets.use_ascii_borders then "[" else "▕" in let right = if Lazy.force Miaou_widgets_display.Widgets.use_ascii_borders then "]" else "▏" in let inner_w = max 1 (width - 2) in if Lazy.force Miaou_widgets_display.Widgets.use_ascii_borders then let filled = int_of_float (floor (float_of_int inner_w *. progress)) in let empty = max 0 (inner_w - filled) in let filled_str = String.make filled '#' in let empty_str = String.make empty ' ' in left ^ filled_str ^ empty_str ^ right else let exact_filled_len = float_of_int inner_w *. progress in let whole_cells = int_of_float exact_filled_len in let remainder = exact_filled_len -. float_of_int whole_cells in let partial_blocks = [|""; "▏"; "▎"; "▍"; "▌"; "▋"; "▊"; "▉"|] in let partial_idx = int_of_float (remainder *. float_of_int (Array.length partial_blocks)) in let tip_char = if whole_cells < inner_w then partial_blocks.(partial_idx) else "" in let filled_uncolored = let buf = Buffer.create ((whole_cells + 2) * 3) in for _ = 1 to whole_cells do Buffer.add_string buf "█" done ; Buffer.add_string buf tip_char ; Buffer.contents buf in let filled_colored = Miaou_widgets_display.Palette.purple_gradient_line Miaou_widgets_display.Palette.Right filled_uncolored in let filled_visible_w = whole_cells + if tip_char = "" then 0 else 1 in let empty_w = max 0 (inner_w - filled_visible_w) in let empty_str = String.make empty_w ' ' in left ^ filled_colored ^ empty_str ^ right let render_terminal w ~cols:_ = let bar = render_bar ~width:w.width ~progress:w.progress in let pct = int_of_float (floor ((100. *. w.progress) +. 0.5)) in let pct_s = Printf.sprintf "%3d%%" pct in let pct_colored = Miaou_widgets_display.Widgets.themed_muted pct_s in let bar_and_pct = bar ^ " " ^ pct_colored in match (w.label, w.title) with | Some lbl, _ -> (* Render label to the left, clipped to avoid wrapping. *) let clip_to n s = if visible_length s <= n then s else let idx = Miaou_helpers.Helpers.visible_byte_index_of_pos s (max 0 (n - 1)) in String.sub s 0 idx ^ "…" in let lbl' = clip_to 24 (Miaou_widgets_display.Widgets.themed_secondary lbl) in lbl' ^ " " ^ bar_and_pct | None, Some t -> (* Centered variant: include a small title header line. Outer centering is handled by caller. *) let title = Miaou_widgets_display.Widgets.titleize t in let buf = Buffer.create (String.length title + String.length bar_and_pct + 1) in Buffer.add_string buf title ; Buffer.add_char buf '\n' ; Buffer.add_string buf bar_and_pct ; Buffer.contents buf | None, None -> bar_and_pct let render w ~cols = match Miaou_widgets_display.Widgets.get_backend () with | `Sdl -> Progress_widget_sdl.render ~width:w.width ~progress:w.progress ~label:w.label ~title:w.title ~cols | `Terminal -> render_terminal w ~cols let handle_key w ~key:_ = w let () = Miaou_registry.register ~name:"progress" ~mli:[%blob "progress_widget.mli"] ()
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>