diff --git a/bin/forester/main.ml b/bin/forester/main.ml index 6f1d362..f7ade8a 100644 --- a/bin/forester/main.ml +++ b/bin/forester/main.ml @@ -61,20 +61,52 @@ let version = in Format.asprintf "%s" major +let progress_mutex = Eio.Mutex.create () +let locked f = Eio.Mutex.use_rw ~protect:true progress_mutex f +let progress_display : (unit, unit) Progress.Display.t option ref = ref None + +let shared_progress_display () = + locked @@ fun () -> + match !progress_display with + | Some d -> d + | None -> + let config = Progress.Config.v ~persistent:true () in + let d = Progress.Display.start ~config Progress.Multi.blank in + progress_display := Some d; + d + +let finalise_progress_display () = + locked @@ fun () -> + match !progress_display with + | Some d -> + Progress.Display.finalise d; + progress_display := None + | None -> () + let job_progress : Phases.progress = if Unix.isatty (Unix.descr_of_out_channel stderr) then let open Progress in let run ~name ~total f = - let config = Config.v ~persistent:true () in + let d = shared_progress_display () in match total with | Some total -> let line = Line.(spinner () ++ const (" " ^ name ^ " ") ++ count_to total) in - with_reporter ~config line (fun report -> f (fun () -> report 1)) + let reporter = locked @@ fun () -> Display.add_line d line in + Fun.protect + ~finally:(fun () -> + locked @@ fun () -> Display.remove_line d reporter) + (fun () -> + f (fun () -> locked @@ fun () -> Reporter.report reporter 1)) | None -> let line = Line.(spinner () ++ const (" " ^ name)) in - with_reporter ~config line (fun report -> f (fun () -> report ())) + let reporter = locked @@ fun () -> Display.add_line d line in + Fun.protect + ~finally:(fun () -> + locked @@ fun () -> Display.remove_line d reporter) + (fun () -> + f (fun () -> locked @@ fun () -> Reporter.report reporter ())) in {run} else Phases.no_progress @@ -83,11 +115,14 @@ let render_progress : Forester.progress = if Unix.isatty (Unix.descr_of_out_channel stderr) then let open Progress in let run ~total f = - let config = Config.v ~persistent:true () in + let d = shared_progress_display () in let line = Line.(spinner () ++ const " Rendering pages " ++ count_to total) in - with_reporter ~config line (fun report -> f (fun () -> report 1)) + let reporter = locked @@ fun () -> Display.add_line d line in + Fun.protect + ~finally:(fun () -> locked @@ fun () -> Display.remove_line d reporter) + (fun () -> f (fun () -> locked @@ fun () -> Reporter.report reporter 1)) in {run} else Forester.no_progress @@ -122,6 +157,7 @@ let theme_dir_has_changed ~env ~(forest : State.t) theme_dir = else mtime src <= mtime dst in let visible_dir_entries dir = + Link_checker.check_and_report_all ~forest; List.filter (fun name -> not (String.starts_with ~prefix:"." name)) (EP.read_dir dir) @@ -157,7 +193,6 @@ let build ~env ~sw _ config_path dev no_theme emit_legacy_xml = m "Build_forest: %.3fs" (Unix.gettimeofday () -. start)); forest in - Link_checker.check_and_report_all ~forest; if not no_theme then begin let@ theme_dir = Option.iter @~ theme_dir ~config in if theme_dir_has_changed ~env ~forest theme_dir then @@ -167,6 +202,8 @@ let build ~env ~sw _ config_path dev no_theme emit_legacy_xml = end end; Forester.render_forest ~progress:render_progress ~forest ~emit_legacy_xml (); + finalise_progress_display (); + Link_checker.check_and_report_all ~forest; let elapsed = Unix.gettimeofday () -. start_time in let n_trees = List.length (State.get_all_articles ~forest) in let n_other = List.length (State.get_all_evaluated ~forest) - n_trees in