···22[](https://github.com/faldor20/jj_tui/actions/workflows/build-nix.yml)
33A TUI for the new version control system Jujutsu
4455-
55+66+
77+6879Press `h` to show the help.
810Press `Alt+Up`and`Alt+Down` to navigate windows
+13-2
jj_tui/bin/global_funcs.ml
···2020 the start ")
2121 else None)
2222;;
2323-let is_jj_repo() =
2424- jj_no_log ~color:false [ "log";"''" ] |> Base.String.is_substring ~substring:"There is no jj repo"|>not
2323+2424+let check_startup () =
2525+ match jj_no_log_errorable ~color:false [ "log"; "''" ] with
2626+ | Ok _ ->
2727+ `Good
2828+ | Error (`BadExit (i, str)) ->
2929+ if str |> Base.String.is_substring ~substring:"There is no jj repo"
3030+ then `NotInRepo
3131+ else `OtherError str
3232+ | Error (`EioErr a) ->
3333+ `CantStartProcess
3434+;;
3535+2536(**Updates the status windows; Without snapshotting the working copy by default
2637 This should be called after any command that performs a change *)
2738let update_status ?(cause_snapshot = false) () =
+32-9
jj_tui/bin/jj_process.ml
···3030 ~f:(fun x ->
3131 (match x.exit_status with
3232 | `Exited i ->
3333- if i == 0 then x.stdout else x.stdout ^ x.stderr
3434- | `Signaled _ ->
3535- x.stderr)
3333+ if i == 0 then `Ok x.stdout else `BadExit (i, x.stderr)
3434+ | `Signaled i ->
3535+ `BadExit (i, x.stderr))
3636 |> Base.Or_error.return)
3737 ()
3838 in
3939- out |> Result.to_option |> Option.value ~default:"there was an error"
3939+ match out with
4040+ | Error a ->
4141+ Error (`EioErr a)
4242+ | Ok (`Ok a) ->
4343+ Ok a
4444+ | Ok (`BadExit _ as a) ->
4545+ Error a
4046 ;;
41474248 (** Prevents concurrent acess to jj when running commands that cause snapshotting.
···4753 @param ?snapshot=true
4854 When true snapshots the state when running the command and also aquires a lock before running it. Set to false for commands you wish to run concurrently. like those for generating content in the UI
4955 @param ?color=true When true output will have terminal escape codes for color *)
5050- let jj_no_log ?(snapshot = true) ?(color = true) args =
5656+ let jj_no_log_errorable ?(snapshot = true) ?(color = true) args =
5157 let locked =
5258 if snapshot
5359 then (
···6975 res
7076 ;;
71777878+ (** Run a jj command without outputting to the command_log.
7979+ @param ?snapshot=true
8080+ When true snapshots the state when running the command and also aquires a lock before running it. Set to false for commands you wish to run concurrently. like those for generating content in the UI
8181+ @param ?color=true When true output will have terminal escape codes for color *)
8282+ let jj_no_log ?(snapshot = true) ?(color = true) args =
8383+ match jj_no_log_errorable ~snapshot ~color args with
8484+ | Ok a ->
8585+ a
8686+ | Error (`BadExit (code, str)) ->
8787+ failwith (Printf.sprintf "Exited with code %i; Message:\n%s" code str)
8888+ | Error (`EioErr a) ->
8989+ failwith
9090+ (Printf.sprintf
9191+ "Error running jj process:\n%a"
9292+ (fun _ -> Base.Error.to_string_hum)
9393+ a)
9494+ ;;
9595+7296 let jj args =
7397 (*update the command log*)
7498 let current_log = Lwd.peek Vars.ui_state.command_log in
···8010481105 (**gets the description of the current and previous change. Useful when squashing*)
82106 let get_messages () =
107107+ let open Base.Result in
83108 let output =
84109 jj
85110 [
···88113 ; "-T"
89114 ; {|"::"++current_working_copy++"::\n"++description++"\n::end::\n"|}
90115 ]
9191- |> String.trim
116116+ |>String.trim
92117 in
9393- let current, prev =
9494- output |> Jj_tui.OutputParsing.parse_descriptions |> Result.get_ok
9595- in
118118+ let current, prev = output |>Jj_tui.OutputParsing.parse_descriptions|>Result.get_ok in
96119 current |> String.concat "", prev |> String.concat ""
97120 ;;
98121end
+37-24
jj_tui/bin/jj_ui.ml
···5656 `Unhandled
5757 ;;
58585959+ (* shows a pretty box in the middle of the screen with our error in it*)
6060+ let render_startup_error error =
6161+ let message =
6262+ match error with
6363+ | `NotInRepo ->
6464+ "Not in a jj repo."
6565+ | `OtherError str ->
6666+ str
6767+ | `CantStartProcess ->
6868+ "Can't start jj process, maybe it's not installed?"
6969+ in
7070+ W.string message
7171+ |> Lwd.pure
7272+ |> Wd.border_box
7373+ |>$ Ui.resize
7474+ ~sw:1
7575+ ~sh:1
7676+ ~mw:10000
7777+ ~mh:10000
7878+ ~crop:Wd.neutral_grav
7979+ ~pad:Wd.neutral_grav
8080+ |> inputs
8181+ ;;
8282+5983 (** The primary view for the UI with the file_view graph_view and summary*)
6084 let main_view ~sw =
6185 let file_focus = Focus.make () in
···107131108132 let mainUi ~sw env =
109133 (*we want to initialize our states and keep them up to date*)
110110- let is_jj_repo = is_jj_repo () in
111111- if not is_jj_repo
112112- then
113113- W.string "Not in a jj repo."
114114- |> Lwd.pure
115115- |> Wd.border_box
116116- |>$ Ui.resize
117117- ~sw:1
118118- ~sh:1
119119- ~mw:10000
120120- ~mh:10000
121121- ~crop:Wd.neutral_grav
122122- ~pad:Wd.neutral_grav
123123- |> inputs
124124- else (
134134+ match check_startup () with
135135+ | `Good ->
125136 update_status ~cause_snapshot:true ();
126137 Eio.Fiber.fork_daemon ~sw (fun _ ->
127138 let clock = Eio.Stdenv.clock env in
···134145 done;
135146 `Stop_daemon);
136147 let$* running = Lwd.get ui_state.view in
137137- match running with
138138- | `Cmd_I cmd ->
139139- (*We have this extra step to paint the terminal empty for one step*)
140140- Lwd.set ui_state.view @@ `RunCmd cmd;
141141- full_term_sized_background
142142- | `RunCmd cmd ->
143143- Jj_widgets.interactive_process env ("jj" :: cmd)
144144- | `Main ->
145145- main_view ~sw)
148148+ (match running with
149149+ | `Cmd_I cmd ->
150150+ (*We have this extra step to paint the terminal empty for one step*)
151151+ Lwd.set ui_state.view @@ `RunCmd cmd;
152152+ full_term_sized_background
153153+ | `RunCmd cmd ->
154154+ Jj_widgets.interactive_process env ("jj" :: cmd)
155155+ | `Main ->
156156+ main_view ~sw)
157157+ | (`CantStartProcess | `NotInRepo | `OtherError _) as other ->
158158+ render_startup_error other
146159 ;;
147160end