stitch

Note taking for messy minimalists

git clone git://mccd.space/stitch
commit a76fb32e7c5815e37b5772f15326f00ec58a322d
parent bdd2c807e52e90b340a8b09c41e7353c52080b46
Author: Marc Coquand <marc@mccd.space>
Date:   Tue, 14 May 2024 18:44:58 -0500

Fix offset

Diffstat:
Mlib/grep.ml | 24+++++++++---------------
Mlib/headlines.ml | 13++++++++++---
Mlib/stitched_article.ml | 37+++++++++++++++++++++++++++++++++++--
3 files changed, 54 insertions(+), 20 deletions(-)
diff --git a/lib/grep.ml b/lib/grep.ml
@@ -124,11 +124,14 @@ let get_full_file_content_content file =
 
 
 let parse_full_content files =
-  List.concat_map
-    (fun ((file_name : string), content) ->
-      let content = String.split_on_char '\n' content in
-      List.mapi (fun line_number line -> file_name, line_number, line) content)
-    files
+  List.concat
+  @@ List.mapi
+       (fun file_number ((file_name : string), content) ->
+         let content = String.split_on_char '\n' content in
+         List.mapi
+           (fun line_number line -> file_name, line_number, line, file_number)
+           content)
+       files
 
 
 type display_type =
@@ -138,17 +141,8 @@ type display_type =
 let pretty_print_parsed_content parsed_files =
   let padding = String.make headline_pattern_length ' ' in
   List.concat_map
-    (fun (file_name, line_number, line_content) ->
+    (fun (file_name, line_number, line_content, _) ->
       if line_number == 0
       then [ Bold ("------- " ^ file_name); Normal line_content ]
       else [ Normal (padding ^ line_content) ])
     parsed_files
-
-(* let parse_file_headline collection full = *)
-(*   match full with *)
-(*   | s :: r -> *)
-(*     let split = Str.bounded_split (Str.regexp ":1:") s 1 in *)
-(*     (match split with *)
-(*      (\* file, line, content *\) *)
-(*      | [ file_name; content ] -> file_name, content *)
-(*      | rest ->  *)
diff --git a/lib/headlines.ml b/lib/headlines.ml
@@ -53,11 +53,18 @@ let rec render t ({ pos; scroll; content; content_pretty } as state) =
         content
       |> Array.to_list
     in
-    let content = Grep.parse_full_content content in
-    let content_pretty = Grep.pretty_print_parsed_content content |> Array.of_list in
+    let full_content = Grep.parse_full_content content in
+    let full_content_pretty =
+      Grep.pretty_print_parsed_content full_content |> Array.of_list
+    in
     Stitched_article.render
       t
-      { pos = 0, 0; content = content |> Array.of_list; content_pretty; scroll = 0 }
+      { pos = 0, 0
+      ; content = full_content |> Array.of_list
+      ; content_pretty = full_content_pretty
+      ; scroll = 0
+      ; go_back = (fun () -> render t state)
+      }
   | `Key (`ASCII 's', []) ->
     let (input_state : Input_screen.state) =
       { screen = img
diff --git a/lib/stitched_article.ml b/lib/stitched_article.ml
@@ -6,7 +6,8 @@ module Input_screen = Input_screen
 type state =
   { pos : int * int
   ; scroll : int
-  ; content : (string * int * string) array
+  ; content : (string * int * string * int) array
+  ; go_back : unit -> unit
   ; content_pretty : Grep.display_type array
   }
 
@@ -26,7 +27,7 @@ let render_line size_x y scroll (el : Grep.display_type) i =
     else I.strf "%s" el |> I.pad ~l:0 ~t:i
 
 
-let rec render t ({ pos; scroll; content_pretty; _ } as state) =
+let rec render t ({ pos; scroll; content_pretty; go_back; content } as state) =
   let size_x, size_y = Common.Term.size t in
   let x, y = pos in
   let img =
@@ -56,10 +57,42 @@ let rec render t ({ pos; scroll; content_pretty; _ } as state) =
      | `Down -> scroll_down ()
      | `Up -> scroll_up ())
   | `Resize _ -> render t state
+  | `Key (`ASCII '@', []) -> go_back ()
   | `Mouse ((`Press _ | `Drag), (_, y), _) ->
     render t { state with pos = 0, min y content_length }
   | `Key (`ASCII 'j', []) | `Key (`ASCII 'N', [ `Ctrl ]) -> scroll_down ()
   | `Key (`ASCII 'k', []) | `Key (`ASCII 'P', [ `Ctrl ]) -> scroll_up ()
+  | `Key (`ASCII 'e', []) | `Key (`Enter, []) ->
+    (* Editor might be set with extra args, in that case we need to separate these *)
+    let[@warning "-8"] (editor :: args) =
+      String.split_on_char ' ' (Sys.getenv "EDITOR")
+    in
+    let selected_file, line_number, _, file_number_offset = Array.get content y in
+    let full_path_file = Grep.execution_directory ^ "/" ^ selected_file in
+    let line_number_arg = "+" ^ Int.to_string (line_number - file_number_offset) in
+    let full_args =
+      Array.append (Array.of_list args) [| line_number_arg; full_path_file |]
+    in
+    Common.Term.cursor t (Some (0, 0));
+    let _ =
+      Unix.create_process_env
+        editor
+        full_args
+        (Unix.environment ())
+        Unix.stdin
+        Unix.stdout
+        Unix.stderr
+    in
+    let rec run_editor () =
+      match Unix.wait () with
+      | _, _ ->
+        Common.Term.cursor t None;
+        render t state
+      (* Capture resizing events *)
+      | exception Unix.Unix_error (Unix.EINTR, _, _) -> run_editor ()
+      | exception Unix.Unix_error (_, _, _) -> failwith "ERROR"
+    in
+    run_editor ()
   | `Key (`Arrow d, _) ->
     (match d with
      | `Up -> scroll_up ()