···1313(* this mutex should be global*)
1414let access_lock = Mutex.create ()
15151616+let read_fd_contents fd =
1717+ let buffer_size = 4096 in
1818+ let buffer = Bytes.create buffer_size in
1919+ let output = Buffer.create buffer_size in
2020+ let rec read_loop () =
2121+ match Unix.read fd buffer 0 buffer_size with
2222+ | 0 -> Buffer.contents output (* EOF reached *)
2323+ | n ->
2424+ Buffer.add_subbytes output buffer 0 n;
2525+ read_loop ()
2626+ | exception Unix.Unix_error (Unix.EBADF, _, _) ->
2727+ Buffer.contents output (* Handle EBADF error *)
2828+ | exception Unix.Unix_error (Unix.EAGAIN, _, _) ->
2929+ Unix.sleepf 0.01; (* Short sleep to avoid busy waiting *)
3030+ read_loop ()
3131+ in
3232+ read_loop ()
3333+1634module Make (Vars : Global_vars.Vars) = struct
1735 (** Makes a new process that has acess to all input and output
1836 This should be used for running other tui sub-programs *)
1937 let switch_to_process command =
2038 let stdout = Unix.stdout in
2139 let stdin = Unix.stdin in
2222- let stderr = Unix.stderr in
2323- let pid = Unix.create_process command.(0) command stdin stdout stderr in
2424- let _, status = Unix.waitpid [] pid in
2525- status
4040+ (* Create a pipe for stderr to capture it *)
4141+ let stderr_r, stderr_w = Unix.pipe () in
4242+ let pid = Unix.create_process command.(0) command stdin stdout stderr_w in
4343+ (* Close write end in parent *)
4444+ Unix.close stderr_w;
4545+ let _, status = Unix.waitpid [] pid in
4646+ (* Read stderr contents *)
4747+ let stderr_content = read_fd_contents stderr_r in
4848+ Unix.close stderr_r;
4949+ status, stderr_content
2650 ;;
27512852 (*
+27-20
jj_tui/bin/jj_widgets.ml
···145145 Global_funcs.update_status ();
146146 Lwd.set ui_state.view new_view
147147 in
148148- let exit_status_to_str (y : Unix.process_status) =
148148+ let exit_status_to_str (y : Unix.process_status) stderr_string =
149149 let open Unix in
150150 match match y with WSTOPPED x -> x | WEXITED x -> x | WSIGNALED x -> x with
151151 | 0 ->
152152- "success"
152152+ None
153153 | 1 ->
154154- "failure%s"
154154+ Some (Printf.sprintf "1, Failure\nStderr:\n%s" stderr_string)
155155 | a ->
156156- Printf.sprintf "unknown code %d" a
156156+ Some (Printf.sprintf "unknown code %d\nStderr:\n%s" a stderr_string)
157157 in
158158- let res = switch_to_process (cmd |> Array.of_list) in
159159- let$ ui =
160160- W.vbox
161161- [
162162- W.string (Printf.sprintf "exit code:%s" (res |> exit_status_to_str)) |> Lwd.pure
163163- ; W.button "back to main UI" (fun _ -> post_change `Main) |> Lwd.pure
164164- ]
165165- in
166166- ui
167167- |> Ui.keyboard_area (fun event ->
168168- match event with
169169- | `ASCII ' ', _ ->
170170- post_change `Main;
171171- `Handled
172172- | _ ->
173173- `Unhandled)
158158+ let exit_code, stderr_string = switch_to_process (cmd |> Array.of_list) in
159159+ let error_msg = exit_status_to_str exit_code stderr_string in
160160+ match error_msg with
161161+ | None ->
162162+ post_change `Main;
163163+ Ui.empty |> Lwd.pure
164164+ | Some exit_msg ->
165165+ let$ ui =
166166+ W.vbox
167167+ [
168168+ W.string (Printf.sprintf "exit code: %s" exit_msg) |> Lwd.pure
169169+ ; W.button "Press space to return to main UI" (fun _ -> post_change `Main)
170170+ |> Lwd.pure
171171+ ]
172172+ in
173173+ ui
174174+ |> Ui.keyboard_area (fun event ->
175175+ match event with
176176+ | `Escape, _ | `Enter, _ | `ASCII ' ', _ ->
177177+ post_change `Main;
178178+ `Handled
179179+ | _ ->
180180+ `Unhandled)
174181 ;;
175182end