terminal user interface to jujutsu. Focused on speed and clarity
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

improve logging an fix bug displaing status view and improve performance by agressively killing children

+163 -38
+64 -3
forks/nottui/lib/nottui/nottui_main.ml
··· 291 291 | `Paste of Unescape.paste 292 292 ] 293 293 294 + let pp_semantic_key ppf = function 295 + | `Copy -> Format.pp_print_string ppf "Copy" 296 + | `Paste -> Format.pp_print_string ppf "Paste" 297 + | `Focus `Out -> Format.pp_print_string ppf "Focus(Out)" 298 + | `Focus `Next -> Format.pp_print_string ppf "Focus(Next)" 299 + | `Focus `Prev -> Format.pp_print_string ppf "Focus(Prev)" 300 + | `Focus `Left -> Format.pp_print_string ppf "Focus(Left)" 301 + | `Focus `Right -> Format.pp_print_string ppf "Focus(Right)" 302 + | `Focus `Up -> Format.pp_print_string ppf "Focus(Up)" 303 + | `Focus `Down -> Format.pp_print_string ppf "Focus(Down)" 304 + ;; 305 + 306 + let pp_special_key ppf = function 307 + | `Arrow `Up -> Format.pp_print_string ppf "↑" 308 + | `Arrow `Down -> Format.pp_print_string ppf "↓" 309 + | `Arrow `Left -> Format.pp_print_string ppf "←" 310 + | `Arrow `Right -> Format.pp_print_string ppf "→" 311 + | `Enter -> Format.pp_print_string ppf "Enter" 312 + | `Tab -> Format.pp_print_string ppf "Tab" 313 + | `Backspace -> Format.pp_print_string ppf "Backspace" 314 + | `Delete -> Format.pp_print_string ppf "Delete" 315 + | `Escape -> Format.pp_print_string ppf "Escape" 316 + | `Function n -> Format.fprintf ppf "F%d" n 317 + | `Page `Up -> Format.pp_print_string ppf "PgUp" 318 + | `Page `Down -> Format.pp_print_string ppf "PgDn" 319 + | `Home -> Format.pp_print_string ppf "Home" 320 + | `End -> Format.pp_print_string ppf "End" 321 + | `Insert -> Format.pp_print_string ppf "Insert" 322 + ;; 323 + 324 + let pp_main_key ppf = function 325 + | #Unescape.special as special -> pp_special_key ppf special 326 + | `Uchar u -> 327 + if Uchar.is_char u then 328 + Format.fprintf ppf "'%c'" (Uchar.to_char u) 329 + else 330 + Format.fprintf ppf "U+%04X" (Uchar.to_int u) 331 + | `ASCII c -> Format.fprintf ppf "'%c'" c 332 + | #semantic_key as sem -> pp_semantic_key ppf sem 333 + ;; 334 + 335 + let pp_modifier ppf = function 336 + | `Ctrl -> Format.pp_print_string ppf "Ctrl" 337 + | `Alt -> Format.pp_print_string ppf "Alt" 338 + | `Shift -> Format.pp_print_string ppf "Shift" 339 + | `Meta -> Format.pp_print_string ppf "Meta" 340 + ;; 341 + 342 + let pp_key ppf (main_key, mods) = 343 + match mods with 344 + | [] -> pp_main_key ppf main_key 345 + | _ -> 346 + Format.pp_print_list 347 + ~pp_sep:(fun ppf () -> Format.pp_print_string ppf "+") 348 + pp_modifier 349 + ppf 350 + mods; 351 + Format.pp_print_string ppf "+"; 352 + pp_main_key ppf main_key 353 + ;; 354 + 294 355 type layout_spec = 295 356 { w : int 296 357 ; h : int ··· 575 636 | Focus_area (u, _) 576 637 | Shift_area (u, _, _) 577 638 | Event_filter (u, _) -> f u 578 - | X (u1, u2) | Y (u1, u2) | Z (u1, u2) -> 579 - f u1; 580 - f u2 639 + | X (a, b) | Y (a, b) | Z (a, b) -> 640 + f a; 641 + f b 581 642 ;; 582 643 end 583 644
+3
forks/nottui/lib/nottui/nottui_main.mli
··· 199 199 [ Unescape.special | `Uchar of Uchar.t | `ASCII of char | semantic_key ] 200 200 * Unescape.mods 201 201 202 + (** Pretty print a key *) 203 + val pp_key : Format.formatter -> key -> unit 204 + 202 205 (** An event is propagated until it gets handled. 203 206 Handler functions return a value of type [may_handle] to indicate 204 207 whether the event was handled, not handled, or should be remapped to aonother event. *)
+1 -1
jj_tui/bin/jj_commands.ml
··· 263 263 (* Use exceptions so we can break out of the list*) 264 264 let input = Lwd.peek ui_state.input in 265 265 try 266 + [%log debug "command recieved key: %a" Ui.pp_key key]; 266 267 match key with 267 268 | `ASCII k, modifiers -> 268 269 let key = { key = k; modifiers } in 269 - [%log info "key: %s" (key_to_string key)]; 270 270 let cmd = keymap |> Key_Map.find_opt key in 271 271 (match cmd with 272 272 | Some cmd ->
+18 -4
jj_tui/bin/jj_process.ml
··· 162 162 if not !isDone 163 163 then ( 164 164 try 165 - [%log debug "Cleaning up cancelled command %s" (args |> String.concat " ")]; 165 + [%log debug "pid: %i Cleaning up cancelled command %s" pid (args |> String.concat " ")]; 166 166 Unix.kill pid Sys.sigkill; 167 167 Unix.waitpid [ Unix.WUNTRACED ] pid |> ignore 168 168 with ··· 177 177 stdout_i 178 178 stderr_i) 179 179 in 180 + 181 + [%log debug "pid: %i started" pid ]; 180 182 let prom = Flock.fork_as_promise (fun () -> Unix.waitpid [] pid) in 181 183 (* Close unused pipe ends in the parent process *) 182 184 Unix.close stdout_i; ··· 191 193 isDone := true; 192 194 (* let stderr = read_fd_to_end stderr_i in *) 193 195 (* let stdout= ""in *) 194 - code, status, stdout, stderr 196 + code, status, stdout, stderr,pid 195 197 ;; 196 198 197 199 (* Ui_loop.run (Lwd.pure (W.printf "Hello world"));; *) 198 200 let cmdArgs cmd args = 199 201 let start_time = Unix.gettimeofday () in 200 - let code, status, out_content, err_content = picos_process cmd args in 202 + let code, status, out_content, err_content,pid = picos_process cmd args in 201 203 let end_time = Unix.gettimeofday () in 204 + let exit_code_text= 205 + match status with 206 + | Unix.WEXITED code -> 207 + Printf.sprintf "exit: %i" code 208 + | Unix.WSIGNALED x-> 209 + Printf.sprintf "signalled: %i" x 210 + | Unix.WSTOPPED x-> 211 + Printf.sprintf "stopped: %i" x 212 + in 213 + 202 214 [%log 203 215 debug 204 - "Executing '%s %s' took: %fms " 216 + "Executing pid:%i %s '%s %s' took: %fms " 217 + pid 218 + exit_code_text 205 219 cmd 206 220 (args |> String.concat " ") 207 221 ((end_time -. start_time) *. 1000.)];
+24 -2
jj_tui/bin/show_view.ml
··· 1 1 open Picos_std_sync 2 2 open Picos_std_structured 3 3 open Jj_tui.Logging 4 + module Log = (val src_log ~src:(Logs.Src.create "status view")) 4 5 5 6 type detail_state = 6 7 | Loading ··· 78 79 res 79 80 ;; 80 81 82 + let get_latest_message cursor = 83 + 84 + let rec seek_latest last cursor= 85 + let peeked=Stream.peek_opt cursor in 86 + match peeked with 87 + |Some (last,new_cursor)-> 88 + seek_latest last new_cursor 89 + |None-> 90 + [%log debug "skipping to next status because two were queued"]; 91 + (last,cursor) 92 + in 93 + let msg, new_cursor = cursor |> Stream.read in 94 + 95 + (*little 50ms delay to let us move to the next one if it's ready*) 96 + Picos.Fiber.sleep ~seconds:0.05; 97 + (*if the queue isn't empty just skip the current because we really only ever want the newest*) 98 + seek_latest msg new_cursor 99 + 100 + 81 101 (* Wait for messages to come in the stream. 82 102 When a message comes, we try to render it. 83 103 If a new message comes, we cancel the current computation and then start the new rendering ··· 88 108 let current_loading_computation = ref (Promise.of_value ()) in 89 109 let cursor = ref (Stream.tap stream) in 90 110 while true do 91 - let msg, new_cursor = !cursor |> Stream.read in 92 - cursor := new_cursor; 111 + [%log debug "waiting for next status"]; 112 + let msg,new_cursor=get_latest_message !cursor in 113 + cursor:=new_cursor; 114 + [%log debug "cancelling older status because of new message"]; 93 115 Promise.terminate_after ~seconds:0. !current_summary_computation; 94 116 Promise.terminate_after ~seconds:0. !current_detail_computation; 95 117 Promise.terminate_after ~seconds:0. !current_loading_computation;
+51 -28
jj_tui/lib/logging.ml
··· 14 14 ms 15 15 ;; 16 16 17 + module type MYLOG = sig 18 + include Logs.LOG 17 19 20 + val timestamp_tag : float Logs.Tag.def 21 + end 18 22 19 - module Log = struct 20 - let timestamp_tag = 21 - Logs.Tag.def "timestamp" ~doc:"Timestamp" (fun fmt tm -> 22 - time_to_string tm |> Format.pp_print_string fmt) 23 - ;; 23 + let timestamp_tag = 24 + Logs.Tag.def "timestamp" ~doc:"Timestamp" (fun fmt tm -> 25 + time_to_string tm |> Format.pp_print_string fmt) 26 + ;; 24 27 25 - let timestamp_wrap fn : ('a, 'b) Logs.msgf = 26 - fun m -> 27 - fn (fun ?header ?(tags = Logs.Tag.empty) fmt -> 28 - let timestamp = Unix.gettimeofday () in 29 - let tags = Logs.Tag.add timestamp_tag timestamp tags in 30 - m ?header ~tags fmt) 31 - ;; 28 + (** 29 + my own custom version of src log that also includes a timestamp 30 + *) 31 + let src_log ~src = 32 + let open Logs in 33 + let module Log = struct 34 + let timestamp_wrap fn : ('a, 'b) Logs.msgf = 35 + fun m -> 36 + fn (fun ?header ?(tags = Logs.Tag.empty) fmt -> 37 + let timestamp = Unix.gettimeofday () in 38 + let tags = Logs.Tag.add timestamp_tag timestamp tags in 39 + m ?header ~tags fmt) 40 + ;; 41 + 42 + let msg level msgf = msg ~src level (timestamp_wrap msgf) 43 + let kmsg k level msgf = kmsg k ~src level (timestamp_wrap msgf) 44 + let app msgf = msg App msgf 45 + let err msgf = msg Error msgf 46 + let warn msgf = msg Warning msgf 47 + let info msgf = msg Info msgf 48 + let debug msgf = msg Debug msgf 49 + 50 + let on_error ?level ?header ?tags ~pp ~use = 51 + on_error ~src ?level ?header ?tags ~pp ~use 52 + ;; 53 + 54 + let on_error_msg ?level ?header ?tags ~use = 55 + on_error_msg ~src ?level ?header ?tags ~use 56 + ;; 57 + end 58 + in 59 + (module Log : Logs.LOG) 60 + ;; 32 61 33 - let debug ?src fn = Logs.debug ?src (timestamp_wrap fn) 34 - let info ?src fn = Logs.info ?src (timestamp_wrap fn) 35 - let warn ?src fn = Logs.warn ?src (timestamp_wrap fn) 36 - let err ?src fn = Logs.err ?src (timestamp_wrap fn) 37 - let app ?src fn = Logs.app ?src (timestamp_wrap fn) 38 - end 62 + module Log = (val src_log ~src:(Logs.Src.create "app")) 39 63 40 64 module Internal = struct 41 65 let reporter ppf = ··· 50 74 | None -> 51 75 None 52 76 | Some tags -> 53 - Logs.Tag.find Log.timestamp_tag tags 77 + Logs.Tag.find timestamp_tag tags 54 78 in 55 - let dt = Format.pp_print_option (Logs.Tag.printer Log.timestamp_tag) in 79 + let dt = Format.pp_print_option (Logs.Tag.printer timestamp_tag) in 56 80 Format.kfprintf 57 81 k 58 82 ppf 59 - ("%a[%a] @[" ^^ fmt ^^ "@]@.") 83 + ("%a[%a][%s] @[" ^^ fmt ^^ "@]@.") 60 84 Logs.pp_header 61 85 (level, h) 62 86 dt 63 87 stamp 88 + (Logs.Src.name src) 64 89 in 65 90 msgf @@ fun ?header ?tags fmt -> with_stamp header tags k ppf fmt 66 91 in ··· 80 105 then 81 106 List.iteri 82 107 (fun i file -> 83 - if i >= 20 84 - then ( 85 - let file_path = Filename.concat log_path file in 86 - Unix.unlink file_path; 87 - [%log debug "deleted log file:%s" file_path])) 108 + if i >= 20 109 + then ( 110 + let file_path = Filename.concat log_path file in 111 + Unix.unlink file_path; 112 + [%log debug "deleted log file:%s" file_path])) 88 113 log_files 89 114 ;; 90 115 91 116 let normalise_os raw = 92 117 match String.lowercase_ascii raw with "darwin" | "osx" -> "macos" | s -> s 93 118 ;; 94 - 95 - 96 119 97 120 (*tries to get the logging dir for macos and linux*) 98 121 let get_log_dir () =
+2
jj_tui/lib/util.ml
··· 97 97 98 98 ;; 99 99 end 100 + 101 +