···66open Jj_tui.Key_map
77open Jj_tui.Key
88open Jj_tui
99+910open Log
10111112(** Internal to this module. I'm trying this out as a way to avoid .mli files*)
···4546 (** Allows nesting of commands, shows a popup with command options and waits for the user to press the appropriate key*)
4647 | Fun of (unit -> unit)
4748 (** Execute an arbitrary function. Prefer other command types if possible *)
4949+ | Cmd_async of string * cmd_args
4850 [@@deriving show]
49515052 (** A command that should be run when it's key is pressed*)
···7577 open Nottui
7678 open Log
7779 open! Jj_tui.Util
8080+ module Jj_widgets = Jj_widgets.Make (Vars)
78817982 exception Handled
8083···131134 | Cmd_with_revs _
132135 | Cmd_r _
133136 | Prompt_r _
134134- | Dynamic_r _ )
137137+ | Dynamic_r _
138138+ | Cmd_async _ )
135139 ; sort_key = _
136140 } ->
137141 [ render_command_line ~indent_level (key_to_string key) description ]
···204208 let change_view view = Lwd.set ui_state.view view in
205209 let send_cmd args = change_view (`Cmd_I args) in
206210 match cmd with
211211+ | Cmd_async (loading_msg,args) ->
212212+ jj_async
213213+ args
214214+ ~on_start:(fun () -> show_popup @@ Some (W.hbox [ Jj_widgets.throbber ;(W.string (" "^loading_msg)|>Lwd.pure) ], loading_msg))
215215+ ~on_success:(fun _ ->
216216+ Global_funcs.update_status ~cause_snapshot:true ();
217217+ show_popup None)
218218+ ~on_error:(fun code str ->
219219+ handle_jj_error
220220+ ~cmd:("jj " ^ (args |> String.concat " "))
221221+ ~error:(Printf.sprintf "Exited with code %i; Message:\n%s" code str);
222222+ );
223223+ raise Handled
207224 | Cmd_I args ->
208225 show_popup None;
209226 send_cmd args;
···343360 SubCmd sub_cmd
344361 ;;
345362346346-(**A prompt that allows the user to confirm a command by running it with a dry run and then running the real command if the user confirms*)
363363+ (**A prompt that allows the user to confirm a command by running it with a dry run and then running the real command if the user confirms*)
347364 let confirm_dry_run_prompt ~title ~dry_run_cmd ~real_cmd =
365365+ Fun
366366+ (fun _ ->
367367+ let subcmds =
368368+ [ (let key = key_of_string_exn "y" in
369369+ ( key
370370+ , { key
371371+ ; sort_key = 0.
372372+ ; description = "proceed"
373373+ ; cmd = real_cmd
374374+ } ))
375375+ ; (let key = key_of_string_exn "n" in
376376+ ( key
377377+ , { key
378378+ ; sort_key = 1.
379379+ ; description = "exit"
380380+ ; cmd =
381381+ Fun
382382+ (fun _ ->
383383+ ui_state.input $= `Normal;
384384+ show_popup None)
385385+ } ))
386386+ ]
387387+ |> Key_map.Key_Map.of_list
388388+ in
389389+ (*get the output of the dry run command*)
390390+ let log =
391391+ jj_no_log ~get_stderr:true dry_run_cmd
392392+ |> AnsiReverse.colored_string
393393+ |> Ui.atom
394394+ |> Lwd.pure
395395+ in
396396+ show_popup @@ Some (W.vbox [ log; commands_list_ui subcmds ], title);
397397+ ui_state.input $= `Mode (command_input ~is_sub:true subcmds))
398398+ ;;
399399+400400+ (**A prompt that allows the user to confirm a command by running it with a dry run and then running the real command if the user confirms*)
401401+ let confirm_dry_run_prompt_async ~title ~dry_run_cmd ~real_cmd =
348402 Fun
349403 (fun _ ->
350404 let subcmds =
+49
jj_tui/bin/jj_process.ml
···196196 code, status, stdout, stderr,pid
197197 ;;
198198199199+ let jj_async ?(snapshot = true) ?(color = true) args ~on_start ~on_success ~on_error =
200200+ let run () =
201201+ let locked =
202202+ if snapshot
203203+ then (
204204+ Mutex.lock access_lock;
205205+ true)
206206+ else false
207207+ in
208208+ let res =
209209+ try
210210+ let _, status, out, err, _ =
211211+ picos_process
212212+ "jj"
213213+ (List.concat
214214+ [
215215+ args
216216+ ; [ "--no-pager" ]
217217+ ; (if snapshot then [] else [ "--ignore-working-copy" ])
218218+ ; (if color then [ "--color"; "always" ] else [ "--color"; "never" ])
219219+ ])
220220+ in
221221+ let exit_code =
222222+ match status with
223223+ | Unix.WEXITED code ->
224224+ code
225225+ | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
226226+ -1
227227+ in
228228+ if exit_code = 0 then Ok (out, err) else Error (exit_code, out, err)
229229+ with
230230+ | exn ->
231231+ if locked then Mutex.unlock access_lock;
232232+ raise exn
233233+ in
234234+ if locked then Mutex.unlock access_lock;
235235+ match res with
236236+ | Ok (out, err) ->
237237+ on_success (out, err)
238238+ | Error (code, out, err) ->
239239+ on_error code (err ^ out)
240240+ in
241241+ on_start ();
242242+ Picos_std_structured.Flock.fork(fun _ ->
243243+ run();
244244+245245+ );
246246+ ;;
247247+199248 (* Ui_loop.run (Lwd.pure (W.printf "Hello world"));; *)
200249 let cmdArgs cmd args =
201250 let start_time = Unix.gettimeofday () in
+23
jj_tui/bin/jj_widgets.ml
···208208 | _ ->
209209 `Unhandled)
210210 ;;
211211+212212+ let throbber =
213213+ let frames = [| "⠋"; "⠙"; "⠹"; "⠸"; "⠼"; "⠴"; "⠦"; "⠧"; "⠇"; "⠏" |] in
214214+ let len = Array.length frames in
215215+ let frame_var = Lwd.var 0 in
216216+217217+ (* let update_throb= Lwd.var 0 in *)
218218+ Lwd.bind (Lwd.get frame_var) ~f:(fun frame ->
219219+ Picos_std_structured.Flock.fork(fun _ ->
220220+ Unix.sleepf 0.2;
221221+ Lwd.set frame_var (Lwd.peek frame_var + 1);
222222+ );
223223+ W.string ~attr:A.(fg red) (frames.(frame mod len) )|>Lwd.pure
224224+ )
225225+ ;;
226226+227227+ let main_widget_list =
228228+ let open Lwd_infix in
229229+ let$* loading = Vars.ui_state.loading|>Lwd.get in
230230+ if loading |> Option.is_some
231231+ then W.vbox [ throbber ]
232232+ else W.vbox [ W.string "not loading" |> Lwd.pure]
233233+ ;;
211234end