Legend:
Library
Module
Module type
Parameter
Class
Class type
A library for displaying progress bars, including support for rendering multiple bars at once. Start by describing of a sequence of progress bars, then begin rendering them.
(** Description: "⠼️ [###########--------------------] 37/100" *)
let bar ~total =
let open Progress.Line in
list [ spinner (); bar total; count_to total ]
(** Rendering: get access to a function [f] for reporting progress. *)
let run () =
Progress.with_reporter (bar ~total:100) (fun f ->
for i = 1 to 100 do
(* ... do some work ... *)
f 1 (* report some progress *)
done)
See Progress_engine for an equivalent API that is portable to non-Unix platforms.
Preliminaries
Some basic types used throughout the rest of the library:
where each reported value contributes cumulatively towards an eventual total of total. ?style specifies the Bar_style.t to use for rendering the bar, and ?pp is used to pretty-print the <count> segment, if passed. (For example, Units.Bytes.of_int64 can be used for totals measured in bytes.)
with_reporters line f begins rendering line and calls f with the reporting function. Once f returns, the display is finalised. Note: attempting to use the reporting function after f has returned will raise a Finalised exception.
val with_reporters : ?config:Config.t->('a, 'b)Multi.t->'a->'b
with_reporters bars f begins rendering bars and passes the corresponding reporting functions to f. Once f returns, the display is finalised.
Examples
Reading a file into memory and displaying a single progress bar:
let read_file path buffer =
let total = file_size path and in_channel = open_in path in
try
with_reporter (counter ~total ()) @@ fun report ->
let rec aux offset =
let bytes_read = really_read buffer offset in
report bytes_read;
aux (offset + bytes_read)
in
aux 0
with End_of_file -> close_in in_channel
Sending data to multiple clients, with one progress bar each:
let multi_bar_rendering () =
with_reporters
Multi.(line bar_a ++ line bar_b ++ line bar_c)
(fun report_a report_b report_c ->
for i = 1 to 1000 do
report_a (transfer_bytes client_a);
report_b (transfer_bytes client_b);
report_c (transfer_bytes client_c)
done)
Logging during rendering
val interject_with : (unit ->'a)->'a
interject_with f executes the function f while temporarily suspending the rendering of any active progress bar display. This can be useful when printing to stdout / stderr, to avoid any interference from the rendering of progress bars. If using the Logs library, consider using reporter and instrument_reporter instead.
Note: the caller must ensure that the terminal cursor is left in an appropriate position to resume rendering. In practice, this means that any printing to the terminal should be terminated with a newline character and flushed.
Extensions to the Logs library designed to cooperate with progress bar rendering:
reporter is like Logs_fmt.reporter but produces a reporter that suspends any ongoing progress bar rendering while displaying log entries, ensuring that log entries in the terminal are never overwritten by the renderer.
instrument_reporter r wraps the synchronous reporter r to ensure that any progress bar rendering is suspended while messages are being constructed for r.
Note: to ensure that log entries are not overwritten by the Progress renderer, r must flush any log entries to the terminal synchronously: as soon as they are reported. This is true of the Logs reporters built by Logs.format_reporter and reporter. An asynchronous reporter should use interject_with to delimit its flushing action instead.
Manual lifecycle management
Functions for explicitly starting and stopping the process of rendering a bar; useful when the code doing the progress reporting cannot be conveniently delimited inside with_reporter. All Displays must be properly finalised, and it is not possible to interleave rendering of displays.