From c1eb9495a83c956ee765b30cb3f058431b1c8877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sacha-=C3=89lie=20Ayoun?= Date: Tue, 3 Jun 2025 15:21:18 +0100 Subject: [PATCH 1/8] Remove use of Vector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sacha-Élie Ayoun --- dune-project | 3 +-- examples/cargo.ml | 10 ++++----- examples/dune | 2 +- examples/utils.ml | 6 +++--- examples/utils.mli | 2 +- progress.opam | 3 +-- src/progress/engine/dune | 3 +-- src/progress/engine/import.ml | 22 ++++++++++---------- src/progress/engine/renderer.ml | 36 ++++++++++++++++----------------- 9 files changed, 42 insertions(+), 45 deletions(-) diff --git a/dune-project b/dune-project index 6007007..804f467 100644 --- a/dune-project +++ b/dune-project @@ -17,14 +17,13 @@ progress bar formats. Supports rendering multiple progress bars simultaneously.\ ") (documentation https://CraigFe.github.io/progress/) (depends - (ocaml (>= 4.08.0)) + (ocaml (>= 5.2.0)) (terminal (= :version)) (fmt (>= 0.8.5)) (logs (>= 0.7.0)) (mtime (>= 2.0.0)) (uucp (>= 2.0.0)) (uutf (>= 1.0.0)) - vector (optint (>= 0.1.0)) (alcotest (and :with-test (>= 1.4.0))) (astring :with-test))) diff --git a/examples/cargo.ml b/examples/cargo.ml index 4d546fb..535dfdd 100644 --- a/examples/cargo.ml +++ b/examples/cargo.ml @@ -31,7 +31,7 @@ let packages = ; ("yojson", "1.7.0") ; ("zarith", "1.9.1") ] - |> Vector.of_list ~dummy:("", "") + |> Dynarray.of_list let setup_logs () = let reporter = Progress.logs_reporter () in @@ -41,7 +41,7 @@ let setup_logs () = let bar = let open Progress.Line in - let total = Vector.length packages in + let total = Dynarray.length packages in list [ constf " %a" Fmt.(styled `Cyan string) "Building" ; using fst @@ -54,9 +54,9 @@ let bar = ] let rec package_worker (active_packages, reporter) = - match Vector.pop packages with - | exception Vector.Empty -> () - | package, version -> + match Dynarray.pop_last_opt packages with + | None -> () + | Some (package, version) -> active_packages := package :: !active_packages; Logs.app (fun f -> f " %a %s %s" Fmt.(styled `Green string) "Compiling" package version); diff --git a/examples/dune b/examples/dune index e99cc1c..48f883c 100644 --- a/examples/dune +++ b/examples/dune @@ -3,7 +3,7 @@ (modules (:standard \ main)) (libraries progress unix logs logs.fmt logs.threaded fmt fmt.tty mtime - mtime.clock.os vector threads.posix)) + mtime.clock.os threads.posix)) (executable (name main) diff --git a/examples/utils.ml b/examples/utils.ml index e111e26..2efaded 100644 --- a/examples/utils.ml +++ b/examples/utils.ml @@ -1,5 +1,5 @@ -let ( .%() ) v i = Vector.get v i -let ( .%()<- ) v i x = Vector.set v i x +let ( .%() ) v i = Dynarray.get v i +let ( .%()<- ) v i x = Dynarray.set v i x let shuffle_vector = let shuffle_subvector rand_int v i j = @@ -10,7 +10,7 @@ let shuffle_vector = v.%(k) <- tmp done in - fun v -> shuffle_subvector Random.int v 0 (Vector.length v) + fun v -> shuffle_subvector Random.int v 0 (Dynarray.length v) let colors = (* import matplotlib.cm diff --git a/examples/utils.mli b/examples/utils.mli index 8edc6ff..029e947 100644 --- a/examples/utils.mli +++ b/examples/utils.mli @@ -1,2 +1,2 @@ -val shuffle_vector : _ Vector.t -> unit +val shuffle_vector : _ Dynarray.t -> unit val colour_picker : unit -> unit -> Progress.Color.t diff --git a/progress.opam b/progress.opam index 4e60ada..67ab18f 100644 --- a/progress.opam +++ b/progress.opam @@ -12,14 +12,13 @@ doc: "https://CraigFe.github.io/progress/" bug-reports: "https://github.com/CraigFe/progress/issues" depends: [ "dune" {>= "2.7"} - "ocaml" {>= "4.08.0"} + "ocaml" {>= "5.2.0"} "terminal" {= version} "fmt" {>= "0.8.5"} "logs" {>= "0.7.0"} "mtime" {>= "2.0.0"} "uucp" {>= "2.0.0"} "uutf" {>= "1.0.0"} - "vector" "optint" {>= "0.1.0"} "alcotest" {with-test & >= "1.4.0"} "astring" {with-test} diff --git a/src/progress/engine/dune b/src/progress/engine/dune index b1ff394..936391f 100644 --- a/src/progress/engine/dune +++ b/src/progress/engine/dune @@ -7,5 +7,4 @@ fmt logs logs.fmt - terminal_ansi - vector)) + terminal_ansi)) diff --git a/src/progress/engine/import.ml b/src/progress/engine/import.ml index 78c460e..1533591 100644 --- a/src/progress/engine/import.ml +++ b/src/progress/engine/import.ml @@ -12,20 +12,20 @@ module Mtime = struct let span_to_s span = Mtime.Span.to_float_ns span *. 1e-9 end -module Vector = struct - include Vector +module Dynarray = struct + include Dynarray let iter ~f t = iter f t let iteri_from ~f i t = for i = i to length t - 1 do - f i (unsafe_get t i) + f i (get t i) done let rec find_map_from i t ~f = if i >= length t then None else - let a = unsafe_get t i in + let a = get t i in match f a with | Some _ as some -> some | None -> find_map_from (i + 1) t ~f @@ -33,17 +33,17 @@ module Vector = struct let find_map t ~f = find_map_from 0 t ~f let insert t k v = - Vector.push t v (* Dummy insertion to expand *); - for i = Vector.length t - 1 downto k + 1 do - Vector.set t i (Vector.get t (pred i)) + Dynarray.add_last t v (* Dummy insertion to expand *); + for i = Dynarray.length t - 1 downto k + 1 do + Dynarray.set t i (Dynarray.get t (pred i)) done; - Vector.set t k v + Dynarray.set t k v let remove (type a) (t : a t) k = - for i = k to Vector.length t - 2 do - Vector.set t i (Vector.get t (succ i)) + for i = k to Dynarray.length t - 2 do + Dynarray.set t i (Dynarray.get t (succ i)) done; - ignore (Vector.pop t : a) + ignore (Dynarray.pop_last t : a) let get_exn = get let get = `shadowed diff --git a/src/progress/engine/renderer.ml b/src/progress/engine/renderer.ml index 45f0a70..218a339 100644 --- a/src/progress/engine/renderer.ml +++ b/src/progress/engine/renderer.ml @@ -143,7 +143,7 @@ end = struct { config : Config.t ; uid : Unique_id.t ; bars : (Bar_id.t, some_bar) Hashtbl.t - ; rows : some_bar option Vector.t + ; rows : some_bar option Dynarray.t } let config t = t.config @@ -155,11 +155,11 @@ end = struct | None -> None | Some renderer -> Some (E { renderer; latest_width = 0; position = i }) in - Bar_list.mapi bars ~f:{ f } |> Vector.of_list ~dummy:None + Bar_list.mapi bars ~f:{ f } |> Dynarray.of_list in let bar_count = Bar_list.length bars in let bars = Hashtbl.create bar_count in - Vector.iter rows + Dynarray.iter rows ~f: (Option.iter (fun (E { renderer; _ } as t) -> Hashtbl.add bars ~key:(Bar_renderer.id renderer) ~data:t)); @@ -190,8 +190,8 @@ end = struct let rerender_all_from_top ~stage ~starting_at ~unconditional ({ config = { ppf; _ }; rows; _ } as t) = - let total_rows = Vector.length rows in - Vector.iteri_from starting_at rows ~f:(fun idx slot -> + let total_rows = Dynarray.length rows in + Dynarray.iteri_from starting_at rows ~f:(fun idx slot -> let is_last = idx = total_rows - 1 in let () = match slot with @@ -227,7 +227,7 @@ end = struct match data with | `Clean _ -> () | `Dirty data -> - let distance_from_base = Vector.length rows - bar.position - 1 in + let distance_from_base = Dynarray.length rows - bar.position - 1 in (* NOTE: we add an initial carriage return to avoid overflowing the line if the user has typed into the terminal between renders. *) @@ -242,13 +242,13 @@ end = struct Hashtbl.remove t.bars uid let add_line ?(above = 0) t renderer = - let position = Vector.length t.rows - above in + let position = Dynarray.length t.rows - above in let key = Bar_renderer.id renderer in let bar = E { renderer; latest_width = 0; position } in Hashtbl.add t.bars ~key ~data:bar; - Vector.insert t.rows position (Some bar); - Vector.iteri_from (position + 1) t.rows ~f:(fun i -> function + Dynarray.insert t.rows position (Some bar); + Dynarray.iteri_from (position + 1) t.rows ~f:(fun i -> function | None -> () | Some (E bar) -> bar.position <- i); @@ -267,7 +267,7 @@ end = struct (* This can either mean that the line has already been finalised, or that this key is unknown. *) match - Vector.find_map t.rows ~f:(function + Dynarray.find_map t.rows ~f:(function | None -> None | Some (E bar) as some_bar -> if Bar_id.equal key (Bar_renderer.id bar.renderer) then @@ -278,8 +278,8 @@ end = struct | None -> failwith "No such line in display") in if Hashtbl.mem t.bars key then Hashtbl.remove t.bars key; - Vector.remove t.rows position; - Vector.iteri_from position t.rows ~f:(fun i -> function + Dynarray.remove t.rows position; + Dynarray.iteri_from position t.rows ~f:(fun i -> function | None -> () | Some (E bar) -> bar.position <- i); @@ -287,7 +287,7 @@ end = struct position for a re-render of the affected suffix of the display. *) Format.pp_print_string t.config.ppf Terminal.Ansi.erase_display_suffix; Terminal.Ansi.move_up t.config.ppf 1; - Terminal.Ansi.move_up t.config.ppf (Vector.length t.rows - position - 1); + Terminal.Ansi.move_up t.config.ppf (Dynarray.length t.rows - position - 1); rerender_all_from_top ~stage:`update ~starting_at:position ~unconditional:true t @@ -298,10 +298,10 @@ end = struct let handle_width_change ({ config = { ppf; _ }; rows; _ } as display) new_width = - let row_count = Vector.length rows in + let row_count = Dynarray.length rows in let latest_widths = Array.init row_count ~f:(fun i -> - Vector.get_exn rows i + Dynarray.get_exn rows i |> Option.fold ~none:0 ~some:(fun (E t) -> t.latest_width)) in let overflows = @@ -319,12 +319,12 @@ end = struct display let tick ({ config = { ppf; _ }; rows; _ } as t) = - Terminal.Ansi.move_up ppf (Vector.length rows - 1); + Terminal.Ansi.move_up ppf (Dynarray.length rows - 1); rerender_all_from_top ~stage:`tick ~starting_at:0 ~unconditional:false t let pause { config = { ppf; _ }; rows; _ } = Format.fprintf ppf "%s%!" Terminal.Ansi.erase_line; - for _ = 1 to Vector.length rows - 1 do + for _ = 1 to Dynarray.length rows - 1 do Format.fprintf ppf "%a%s%!" Terminal.Ansi.move_up 1 Terminal.Ansi.erase_line done @@ -342,7 +342,7 @@ end = struct let finalise ({ config = { ppf; hide_cursor; persistent; _ }; rows; _ } as display) = - Terminal.Ansi.move_up ppf (Vector.length rows - 1); + Terminal.Ansi.move_up ppf (Dynarray.length rows - 1); if persistent then ( rerender_all_from_top ~stage:`finalise ~starting_at:0 ~unconditional:true display; From be029798d04e6cf432f2876c1f1d94b08ea433b5 Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Wed, 13 Aug 2025 14:39:22 +0100 Subject: [PATCH 2/8] Compatible with 4.08, install Vector if < 5.2.0 Signed-off-by: Sacha Ayoun --- dune-project | 68 ++++++++++++------------- examples/cargo.ml | 8 +-- examples/utils.ml | 25 ++++----- examples/utils.mli | 9 +++- progress.opam | 3 +- src/progress/engine/dune | 7 ++- src/progress/engine/import.ml | 36 ------------- src/progress/engine/pvector.dynarray.ml | 34 +++++++++++++ src/progress/engine/pvector.vector.ml | 34 +++++++++++++ src/progress/engine/renderer.ml | 36 ++++++------- 10 files changed, 154 insertions(+), 106 deletions(-) create mode 100644 src/progress/engine/pvector.dynarray.ml create mode 100644 src/progress/engine/pvector.vector.ml diff --git a/dune-project b/dune-project index 804f467..150d7fc 100644 --- a/dune-project +++ b/dune-project @@ -2,43 +2,43 @@ (name progress) (implicit_transitive_deps false) -(generate_opam_files true) +; (generate_opam_files true) (source (github CraigFe/progress)) (license MIT) (maintainers "Craig Ferguson ") (authors "Craig Ferguson ") -(package - (name progress) - (synopsis "User-definable progress bars") - (description "\ -A progress bar library for OCaml, featuring a DSL for declaratively specifying -progress bar formats. Supports rendering multiple progress bars simultaneously.\ -") - (documentation https://CraigFe.github.io/progress/) - (depends - (ocaml (>= 5.2.0)) - (terminal (= :version)) - (fmt (>= 0.8.5)) - (logs (>= 0.7.0)) - (mtime (>= 2.0.0)) - (uucp (>= 2.0.0)) - (uutf (>= 1.0.0)) - (optint (>= 0.1.0)) - (alcotest (and :with-test (>= 1.4.0))) - (astring :with-test))) +; (package +; (name progress) +; (synopsis "User-definable progress bars") +; (description "\ +; A progress bar library for OCaml, featuring a DSL for declaratively specifying +; progress bar formats. Supports rendering multiple progress bars simultaneously.\ +; ") +; (documentation https://CraigFe.github.io/progress/) +; (depends +; (ocaml (>= 4.08.0)) +; (terminal (= :version)) +; (fmt (>= 0.8.5)) +; (logs (>= 0.7.0)) +; (mtime (>= 2.0.0)) +; (uucp (>= 2.0.0)) +; (uutf (>= 1.0.0)) +; (optint (>= 0.1.0)) +; (alcotest (and :with-test (>= 1.4.0))) +; (astring :with-test))) -(package - (name terminal) - (synopsis "Basic utilities for interacting with terminals") - (description "Basic utilities for interacting with terminals") - (documentation https://CraigFe.github.io/progress/) - (depends - (ocaml (>= 4.03.0)) - (uucp (>= 2.0.0)) - (uutf (>= 1.0.0)) - stdlib-shims - (alcotest (and :with-test (>= 1.4.0))) - (fmt :with-test) - (astring :with-test) - (mtime (and :with-test (>= 2.0.0))))) +; (package +; (name terminal) +; (synopsis "Basic utilities for interacting with terminals") +; (description "Basic utilities for interacting with terminals") +; (documentation https://CraigFe.github.io/progress/) +; (depends +; (ocaml (>= 4.03.0)) +; (uucp (>= 2.0.0)) +; (uutf (>= 1.0.0)) +; stdlib-shims +; (alcotest (and :with-test (>= 1.4.0))) +; (fmt :with-test) +; (astring :with-test) +; (mtime (and :with-test (>= 2.0.0))))) diff --git a/examples/cargo.ml b/examples/cargo.ml index 535dfdd..1072c77 100644 --- a/examples/cargo.ml +++ b/examples/cargo.ml @@ -1,3 +1,5 @@ +open Utils + let packages = [ ("0install-solver", "2.17") ; ("afl-persistent", "1.3") @@ -31,7 +33,7 @@ let packages = ; ("yojson", "1.7.0") ; ("zarith", "1.9.1") ] - |> Dynarray.of_list + |> Dynlist.of_list let setup_logs () = let reporter = Progress.logs_reporter () in @@ -41,7 +43,7 @@ let setup_logs () = let bar = let open Progress.Line in - let total = Dynarray.length packages in + let total = Dynlist.length packages in list [ constf " %a" Fmt.(styled `Cyan string) "Building" ; using fst @@ -54,7 +56,7 @@ let bar = ] let rec package_worker (active_packages, reporter) = - match Dynarray.pop_last_opt packages with + match Dynlist.pop_opt packages with | None -> () | Some (package, version) -> active_packages := package :: !active_packages; diff --git a/examples/utils.ml b/examples/utils.ml index 2efaded..d5dc28a 100644 --- a/examples/utils.ml +++ b/examples/utils.ml @@ -1,16 +1,17 @@ -let ( .%() ) v i = Dynarray.get v i -let ( .%()<- ) v i x = Dynarray.set v i x +module Dynlist = struct + type 'a t = 'a list ref -let shuffle_vector = - let shuffle_subvector rand_int v i j = - for k = j - 1 downto i + 1 do - let l = rand_int (k + 1) in - let tmp = v.%(l) in - v.%(l) <- v.%(k); - v.%(k) <- tmp - done - in - fun v -> shuffle_subvector Random.int v 0 (Dynarray.length v) + let of_list l = ref l + + let pop_opt l = + match !l with + | [] -> None + | x :: xs -> + l := xs; + Some x + + let length l = List.length !l +end let colors = (* import matplotlib.cm diff --git a/examples/utils.mli b/examples/utils.mli index 029e947..c3fe3a6 100644 --- a/examples/utils.mli +++ b/examples/utils.mli @@ -1,2 +1,9 @@ -val shuffle_vector : _ Dynarray.t -> unit +module Dynlist : sig + type 'a t + + val of_list : 'a list -> 'a t + val length : 'a t -> int + val pop_opt : 'a t -> 'a option +end + val colour_picker : unit -> unit -> Progress.Color.t diff --git a/progress.opam b/progress.opam index 67ab18f..25481e6 100644 --- a/progress.opam +++ b/progress.opam @@ -12,7 +12,8 @@ doc: "https://CraigFe.github.io/progress/" bug-reports: "https://github.com/CraigFe/progress/issues" depends: [ "dune" {>= "2.7"} - "ocaml" {>= "5.2.0"} + "ocaml" {>= "4.08.0"} + ("ocaml" {>= "5.2.0"} | "vector") "terminal" {= version} "fmt" {>= "0.8.5"} "logs" {>= "0.7.0"} diff --git a/src/progress/engine/dune b/src/progress/engine/dune index 936391f..a9ccca8 100644 --- a/src/progress/engine/dune +++ b/src/progress/engine/dune @@ -7,4 +7,9 @@ fmt logs logs.fmt - terminal_ansi)) + terminal_ansi + (select + pvector.ml + from + (vector -> pvector.vector.ml) + (!vector -> pvector.dynarray.ml)))) diff --git a/src/progress/engine/import.ml b/src/progress/engine/import.ml index 1533591..24c7773 100644 --- a/src/progress/engine/import.ml +++ b/src/progress/engine/import.ml @@ -12,42 +12,6 @@ module Mtime = struct let span_to_s span = Mtime.Span.to_float_ns span *. 1e-9 end -module Dynarray = struct - include Dynarray - - let iter ~f t = iter f t - - let iteri_from ~f i t = - for i = i to length t - 1 do - f i (get t i) - done - - let rec find_map_from i t ~f = - if i >= length t then None - else - let a = get t i in - match f a with - | Some _ as some -> some - | None -> find_map_from (i + 1) t ~f - - let find_map t ~f = find_map_from 0 t ~f - - let insert t k v = - Dynarray.add_last t v (* Dummy insertion to expand *); - for i = Dynarray.length t - 1 downto k + 1 do - Dynarray.set t i (Dynarray.get t (pred i)) - done; - Dynarray.set t k v - - let remove (type a) (t : a t) k = - for i = k to Dynarray.length t - 2 do - Dynarray.set t i (Dynarray.get t (succ i)) - done; - ignore (Dynarray.pop_last t : a) - - let get_exn = get - let get = `shadowed -end (*———————————————————————————————————————————————————————————————————————————— Copyright (c) 2020–2021 Craig Ferguson diff --git a/src/progress/engine/pvector.dynarray.ml b/src/progress/engine/pvector.dynarray.ml new file mode 100644 index 0000000..ae2c28b --- /dev/null +++ b/src/progress/engine/pvector.dynarray.ml @@ -0,0 +1,34 @@ +include Dynarray + +let iter ~f t = iter f t + +let iteri_from ~f i t = + for i = i to length t - 1 do + f i (get t i) + done + +let of_list ~dummy:_ l = Dynarray.of_list l + +let rec find_map_from i t ~f = + if i >= length t then None + else + let a = get t i in + match f a with Some _ as some -> some | None -> find_map_from (i + 1) t ~f + +let find_map t ~f = find_map_from 0 t ~f + +let insert t k v = + Dynarray.add_last t v (* Dummy insertion to expand *); + for i = Dynarray.length t - 1 downto k + 1 do + Dynarray.set t i (Dynarray.get t (pred i)) + done; + Dynarray.set t k v + +let remove (type a) (t : a t) k = + for i = k to Dynarray.length t - 2 do + Dynarray.set t i (Dynarray.get t (succ i)) + done; + ignore (Dynarray.pop_last t : a) + +let get_exn = get +let get = `shadowed diff --git a/src/progress/engine/pvector.vector.ml b/src/progress/engine/pvector.vector.ml new file mode 100644 index 0000000..8804358 --- /dev/null +++ b/src/progress/engine/pvector.vector.ml @@ -0,0 +1,34 @@ + include Vector + + let iter ~f t = iter f t + + let iteri_from ~f i t = + for i = i to length t - 1 do + f i (unsafe_get t i) + done + + let rec find_map_from i t ~f = + if i >= length t then None + else + let a = unsafe_get t i in + match f a with + | Some _ as some -> some + | None -> find_map_from (i + 1) t ~f + + let find_map t ~f = find_map_from 0 t ~f + + let insert t k v = + Vector.push t v (* Dummy insertion to expand *); + for i = Vector.length t - 1 downto k + 1 do + Vector.set t i (Vector.get t (pred i)) + done; + Vector.set t k v + + let remove (type a) (t : a t) k = + for i = k to Vector.length t - 2 do + Vector.set t i (Vector.get t (succ i)) + done; + ignore (Vector.pop t : a) + + let get_exn = get + let get = `shadowed \ No newline at end of file diff --git a/src/progress/engine/renderer.ml b/src/progress/engine/renderer.ml index 218a339..adaba6c 100644 --- a/src/progress/engine/renderer.ml +++ b/src/progress/engine/renderer.ml @@ -143,7 +143,7 @@ end = struct { config : Config.t ; uid : Unique_id.t ; bars : (Bar_id.t, some_bar) Hashtbl.t - ; rows : some_bar option Dynarray.t + ; rows : some_bar option Pvector.t } let config t = t.config @@ -155,11 +155,11 @@ end = struct | None -> None | Some renderer -> Some (E { renderer; latest_width = 0; position = i }) in - Bar_list.mapi bars ~f:{ f } |> Dynarray.of_list + Bar_list.mapi bars ~f:{ f } |> Pvector.of_list ~dummy:None in let bar_count = Bar_list.length bars in let bars = Hashtbl.create bar_count in - Dynarray.iter rows + Pvector.iter rows ~f: (Option.iter (fun (E { renderer; _ } as t) -> Hashtbl.add bars ~key:(Bar_renderer.id renderer) ~data:t)); @@ -190,8 +190,8 @@ end = struct let rerender_all_from_top ~stage ~starting_at ~unconditional ({ config = { ppf; _ }; rows; _ } as t) = - let total_rows = Dynarray.length rows in - Dynarray.iteri_from starting_at rows ~f:(fun idx slot -> + let total_rows = Pvector.length rows in + Pvector.iteri_from starting_at rows ~f:(fun idx slot -> let is_last = idx = total_rows - 1 in let () = match slot with @@ -227,7 +227,7 @@ end = struct match data with | `Clean _ -> () | `Dirty data -> - let distance_from_base = Dynarray.length rows - bar.position - 1 in + let distance_from_base = Pvector.length rows - bar.position - 1 in (* NOTE: we add an initial carriage return to avoid overflowing the line if the user has typed into the terminal between renders. *) @@ -242,13 +242,13 @@ end = struct Hashtbl.remove t.bars uid let add_line ?(above = 0) t renderer = - let position = Dynarray.length t.rows - above in + let position = Pvector.length t.rows - above in let key = Bar_renderer.id renderer in let bar = E { renderer; latest_width = 0; position } in Hashtbl.add t.bars ~key ~data:bar; - Dynarray.insert t.rows position (Some bar); - Dynarray.iteri_from (position + 1) t.rows ~f:(fun i -> function + Pvector.insert t.rows position (Some bar); + Pvector.iteri_from (position + 1) t.rows ~f:(fun i -> function | None -> () | Some (E bar) -> bar.position <- i); @@ -267,7 +267,7 @@ end = struct (* This can either mean that the line has already been finalised, or that this key is unknown. *) match - Dynarray.find_map t.rows ~f:(function + Pvector.find_map t.rows ~f:(function | None -> None | Some (E bar) as some_bar -> if Bar_id.equal key (Bar_renderer.id bar.renderer) then @@ -278,8 +278,8 @@ end = struct | None -> failwith "No such line in display") in if Hashtbl.mem t.bars key then Hashtbl.remove t.bars key; - Dynarray.remove t.rows position; - Dynarray.iteri_from position t.rows ~f:(fun i -> function + Pvector.remove t.rows position; + Pvector.iteri_from position t.rows ~f:(fun i -> function | None -> () | Some (E bar) -> bar.position <- i); @@ -287,7 +287,7 @@ end = struct position for a re-render of the affected suffix of the display. *) Format.pp_print_string t.config.ppf Terminal.Ansi.erase_display_suffix; Terminal.Ansi.move_up t.config.ppf 1; - Terminal.Ansi.move_up t.config.ppf (Dynarray.length t.rows - position - 1); + Terminal.Ansi.move_up t.config.ppf (Pvector.length t.rows - position - 1); rerender_all_from_top ~stage:`update ~starting_at:position ~unconditional:true t @@ -298,10 +298,10 @@ end = struct let handle_width_change ({ config = { ppf; _ }; rows; _ } as display) new_width = - let row_count = Dynarray.length rows in + let row_count = Pvector.length rows in let latest_widths = Array.init row_count ~f:(fun i -> - Dynarray.get_exn rows i + Pvector.get_exn rows i |> Option.fold ~none:0 ~some:(fun (E t) -> t.latest_width)) in let overflows = @@ -319,12 +319,12 @@ end = struct display let tick ({ config = { ppf; _ }; rows; _ } as t) = - Terminal.Ansi.move_up ppf (Dynarray.length rows - 1); + Terminal.Ansi.move_up ppf (Pvector.length rows - 1); rerender_all_from_top ~stage:`tick ~starting_at:0 ~unconditional:false t let pause { config = { ppf; _ }; rows; _ } = Format.fprintf ppf "%s%!" Terminal.Ansi.erase_line; - for _ = 1 to Dynarray.length rows - 1 do + for _ = 1 to Pvector.length rows - 1 do Format.fprintf ppf "%a%s%!" Terminal.Ansi.move_up 1 Terminal.Ansi.erase_line done @@ -342,7 +342,7 @@ end = struct let finalise ({ config = { ppf; hide_cursor; persistent; _ }; rows; _ } as display) = - Terminal.Ansi.move_up ppf (Dynarray.length rows - 1); + Terminal.Ansi.move_up ppf (Pvector.length rows - 1); if persistent then ( rerender_all_from_top ~stage:`finalise ~starting_at:0 ~unconditional:true display; From b62f88266463562cd53cf74511be4b018d86c298 Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Wed, 13 Aug 2025 14:43:35 +0100 Subject: [PATCH 3/8] remove dune-generated warning Signed-off-by: Sacha Ayoun --- progress.opam | 1 - terminal.opam | 1 - 2 files changed, 2 deletions(-) diff --git a/progress.opam b/progress.opam index 25481e6..08419f8 100644 --- a/progress.opam +++ b/progress.opam @@ -1,4 +1,3 @@ -# This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "User-definable progress bars" description: """ diff --git a/terminal.opam b/terminal.opam index 3e90812..5a02bad 100644 --- a/terminal.opam +++ b/terminal.opam @@ -1,4 +1,3 @@ -# This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Basic utilities for interacting with terminals" description: "Basic utilities for interacting with terminals" From ff978641b0d5f1efb5cd46548093d4506d50408f Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Wed, 13 Aug 2025 14:46:12 +0100 Subject: [PATCH 4/8] oops, fmt Signed-off-by: Sacha Ayoun --- src/progress/engine/pvector.dynarray.ml | 4 +- src/progress/engine/pvector.vector.ml | 52 ++++++++++++------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/progress/engine/pvector.dynarray.ml b/src/progress/engine/pvector.dynarray.ml index ae2c28b..38ced08 100644 --- a/src/progress/engine/pvector.dynarray.ml +++ b/src/progress/engine/pvector.dynarray.ml @@ -7,8 +7,8 @@ let iteri_from ~f i t = f i (get t i) done -let of_list ~dummy:_ l = Dynarray.of_list l - +let of_list ~dummy:_ l = Dynarray.of_list l + let rec find_map_from i t ~f = if i >= length t then None else diff --git a/src/progress/engine/pvector.vector.ml b/src/progress/engine/pvector.vector.ml index 8804358..c400a00 100644 --- a/src/progress/engine/pvector.vector.ml +++ b/src/progress/engine/pvector.vector.ml @@ -1,34 +1,32 @@ - include Vector +include Vector - let iter ~f t = iter f t +let iter ~f t = iter f t - let iteri_from ~f i t = - for i = i to length t - 1 do - f i (unsafe_get t i) - done +let iteri_from ~f i t = + for i = i to length t - 1 do + f i (unsafe_get t i) + done - let rec find_map_from i t ~f = - if i >= length t then None - else - let a = unsafe_get t i in - match f a with - | Some _ as some -> some - | None -> find_map_from (i + 1) t ~f +let rec find_map_from i t ~f = + if i >= length t then None + else + let a = unsafe_get t i in + match f a with Some _ as some -> some | None -> find_map_from (i + 1) t ~f - let find_map t ~f = find_map_from 0 t ~f +let find_map t ~f = find_map_from 0 t ~f - let insert t k v = - Vector.push t v (* Dummy insertion to expand *); - for i = Vector.length t - 1 downto k + 1 do - Vector.set t i (Vector.get t (pred i)) - done; - Vector.set t k v +let insert t k v = + Vector.push t v (* Dummy insertion to expand *); + for i = Vector.length t - 1 downto k + 1 do + Vector.set t i (Vector.get t (pred i)) + done; + Vector.set t k v - let remove (type a) (t : a t) k = - for i = k to Vector.length t - 2 do - Vector.set t i (Vector.get t (succ i)) - done; - ignore (Vector.pop t : a) +let remove (type a) (t : a t) k = + for i = k to Vector.length t - 2 do + Vector.set t i (Vector.get t (succ i)) + done; + ignore (Vector.pop t : a) - let get_exn = get - let get = `shadowed \ No newline at end of file +let get_exn = get +let get = `shadowed From 24f6a804bd68aae8f423c9a80b47dae54e641c3f Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Mon, 8 Sep 2025 20:35:35 +0100 Subject: [PATCH 5/8] Apply @kit-ty-kate's comments Signed-off-by: Sacha Ayoun --- progress.opam | 2 +- src/progress/engine/dune | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/progress.opam b/progress.opam index 08419f8..2527a08 100644 --- a/progress.opam +++ b/progress.opam @@ -12,7 +12,7 @@ bug-reports: "https://github.com/CraigFe/progress/issues" depends: [ "dune" {>= "2.7"} "ocaml" {>= "4.08.0"} - ("ocaml" {>= "5.2.0"} | "vector") + ("ocaml" {>= "5.2.0"} | ("ocaml" {< "5.2.0"} & "vector")) "terminal" {= version} "fmt" {>= "0.8.5"} "logs" {>= "0.7.0"} diff --git a/src/progress/engine/dune b/src/progress/engine/dune index a9ccca8..e8af982 100644 --- a/src/progress/engine/dune +++ b/src/progress/engine/dune @@ -1,3 +1,16 @@ +(rule + (target pvector.ml) + (enabled_if + (>= %{ocaml_version} "5.2")) + (action + (copy# pvector.dynarray.ml %{target}))) + +(rule + (enabled_if + (< %{ocaml_version} "5.2")) + (action + (copy# pvector.vector.ml %{target}))) + (library (name progress_engine) (public_name progress.engine) @@ -7,9 +20,4 @@ fmt logs logs.fmt - terminal_ansi - (select - pvector.ml - from - (vector -> pvector.vector.ml) - (!vector -> pvector.dynarray.ml)))) + terminal_ansi)) From bfdc63d5c5bf8608f6150eead87500794df0c31a Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Mon, 8 Sep 2025 20:45:47 +0100 Subject: [PATCH 6/8] oops Signed-off-by: Sacha Ayoun --- src/progress/engine/dune | 1 + 1 file changed, 1 insertion(+) diff --git a/src/progress/engine/dune b/src/progress/engine/dune index e8af982..2373157 100644 --- a/src/progress/engine/dune +++ b/src/progress/engine/dune @@ -6,6 +6,7 @@ (copy# pvector.dynarray.ml %{target}))) (rule + (target pvector.ml) (enabled_if (< %{ocaml_version} "5.2")) (action From 3d8d178fc125dcad65db48b7ae5e8d971f992c9e Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Tue, 9 Sep 2025 14:31:28 +0100 Subject: [PATCH 7/8] use library instead of rules, to be able to specify dependency on vector in only one case Signed-off-by: Sacha Ayoun --- src/progress/engine/dune | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/progress/engine/dune b/src/progress/engine/dune index 2373157..8f6de20 100644 --- a/src/progress/engine/dune +++ b/src/progress/engine/dune @@ -1,24 +1,48 @@ +; We use two different implementations of vectors depending on the availability of Dynarray in the standard library (starting OCaml 5.2). +; This reduces dependencies fo users of the newer OCaml versions, and reduces clashes with the ecosystem (https://github.com/craigfe/progress/pull/50). + +; Rules for OCaml 5.2 and later + (rule - (target pvector.ml) (enabled_if (>= %{ocaml_version} "5.2")) (action - (copy# pvector.dynarray.ml %{target}))) + (copy# pvector.dynarray.ml pvector.ml))) + +(library + (name pvector) + (public_name progress.vector) + (enabled_if + (>= %{ocaml_version} "5.2")) + (modules pvector)) + +; Rules for OCaml versions after 5.2 (rule - (target pvector.ml) (enabled_if (< %{ocaml_version} "5.2")) (action - (copy# pvector.vector.ml %{target}))) + (copy# pvector.vector.ml pvector.ml))) + +(library + (name pvector) + (public_name progress.vector) + (enabled_if + (< %{ocaml_version} "5.2")) + (modules pvector) + (libraries vector)) + +; Main library (library (name progress_engine) (public_name progress.engine) + (modules :standard \ pvector) (libraries (re_export mtime) (re_export optint) fmt logs logs.fmt - terminal_ansi)) + terminal_ansi + progress.vector)) From 5d1f12e2c9b693cc943a946bf6b82365a8940b69 Mon Sep 17 00:00:00 2001 From: Sacha Ayoun Date: Wed, 10 Sep 2025 11:35:43 +0100 Subject: [PATCH 8/8] remove package information from dune-project Signed-off-by: Sacha Ayoun --- dune-project | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/dune-project b/dune-project index 150d7fc..bc48013 100644 --- a/dune-project +++ b/dune-project @@ -2,43 +2,7 @@ (name progress) (implicit_transitive_deps false) -; (generate_opam_files true) (source (github CraigFe/progress)) (license MIT) (maintainers "Craig Ferguson ") (authors "Craig Ferguson ") - -; (package -; (name progress) -; (synopsis "User-definable progress bars") -; (description "\ -; A progress bar library for OCaml, featuring a DSL for declaratively specifying -; progress bar formats. Supports rendering multiple progress bars simultaneously.\ -; ") -; (documentation https://CraigFe.github.io/progress/) -; (depends -; (ocaml (>= 4.08.0)) -; (terminal (= :version)) -; (fmt (>= 0.8.5)) -; (logs (>= 0.7.0)) -; (mtime (>= 2.0.0)) -; (uucp (>= 2.0.0)) -; (uutf (>= 1.0.0)) -; (optint (>= 0.1.0)) -; (alcotest (and :with-test (>= 1.4.0))) -; (astring :with-test))) - -; (package -; (name terminal) -; (synopsis "Basic utilities for interacting with terminals") -; (description "Basic utilities for interacting with terminals") -; (documentation https://CraigFe.github.io/progress/) -; (depends -; (ocaml (>= 4.03.0)) -; (uucp (>= 2.0.0)) -; (uutf (>= 1.0.0)) -; stdlib-shims -; (alcotest (and :with-test (>= 1.4.0))) -; (fmt :with-test) -; (astring :with-test) -; (mtime (and :with-test (>= 2.0.0)))))