stitch

Note taking for messy minimalists

git clone git://mccd.space/stitch
commit 8dc118d9bf685d96022a010fb2a20d724c40b5cf
parent a76fb32e7c5815e37b5772f15326f00ec58a322d
Author: Marc Coquand <marc@mccd.space>
Date:   Tue, 14 May 2024 19:11:24 -0500

Add help menu

Diffstat:
Mlib/headlines.ml | 2++
Alib/help_screen.ml | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/stitched_article.ml | 4++++
3 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/lib/headlines.ml b/lib/headlines.ml
@@ -3,6 +3,7 @@ module Common = Common
 open Notty
 module Input_screen = Input_screen
 module Stitched_article = Stitched_article
+module Help_screen = Help_screen
 
 type state =
   { pos : int * int
@@ -46,6 +47,7 @@ let rec render t ({ pos; scroll; content; content_pretty } as state) =
   | `Resize _ -> render t state
   | `Mouse ((`Press _ | `Drag), (_, y), _) ->
     render t { state with pos = 0, min y content_length }
+  | `Key (`ASCII '?', []) -> Help_screen.render t { go_back = (fun () -> render t state) }
   | `Key (`ASCII '@', []) ->
     let content =
       Array.map
diff --git a/lib/help_screen.ml b/lib/help_screen.ml
@@ -0,0 +1,55 @@
+module Common = Common
+open Notty
+
+type state = { go_back : unit -> unit }
+
+let info = [ "STITCH"; "Note composing tool" ]
+
+let render_info =
+  let title = I.strf ~attr:A.(st bold) "%s" "STITCH" |> I.pad ~l:2 ~t:1 in
+  let description =
+    I.strf ~attr:A.(st bold) "%s" "Small Note Composer" |> I.pad ~l:2 ~t:2
+  in
+  let keybindings = I.strf ~attr:A.(st bold) "%s" "Keybindings" |> I.pad ~l:2 ~t:4 in
+  let open I in
+  title </> description </> keybindings
+
+
+let help_menu =
+  [ "Toggle this menu", "?"
+  ; "Exit", "Ctrl-c, q, Esc"
+  ; "Toggle collapsed view", "@"
+  ; "Go down", "Ctrl-n, j"
+  ; "Go up", "Ctrl-p, k"
+  ; "Grep", "s"
+  ]
+
+
+let pad str n =
+  let padding = n - String.length str in
+  String.concat "" [ str; String.make padding ' ' ]
+
+
+let render_help_menu start_y =
+  let elements =
+    List.mapi
+      (fun i (explanation, keybinding) ->
+        let padding = pad explanation 30 in
+        I.strf "%s%s" padding keybinding |> I.pad ~l:2 ~t:(i + start_y))
+      help_menu
+  in
+  let open I in
+  List.fold_left (fun sum el -> el </> sum) I.empty elements
+
+
+let rec render t ({ go_back } as state) =
+  let img =
+    let open I in
+    render_info </> render_help_menu 5
+  in
+  Common.Term.image t img;
+  match Common.Term.event t with
+  | `End | `Key (`Escape, []) | `Key (`ASCII 'q', []) | `Key (`ASCII 'C', [ `Ctrl ]) -> ()
+  | `Resize _ -> render t state
+  | `Key (`ASCII '?', []) -> go_back ()
+  | _ -> render t state
diff --git a/lib/stitched_article.ml b/lib/stitched_article.ml
@@ -2,6 +2,7 @@ module Grep = Grep
 module Common = Common
 open Notty
 module Input_screen = Input_screen
+module Help_screen = Help_screen
 
 type state =
   { pos : int * int
@@ -62,6 +63,7 @@ let rec render t ({ pos; scroll; content_pretty; go_back; content } as state) =
     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 '?', []) -> Help_screen.render t { go_back = (fun () -> render t state) }
   | `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) =
@@ -69,6 +71,8 @@ let rec render t ({ pos; scroll; content_pretty; go_back; content } as state) =
     in
     let selected_file, line_number, _, file_number_offset = Array.get content y in
     let full_path_file = Grep.execution_directory ^ "/" ^ selected_file in
+    (* Because each file title consists of two lines, we need to account for the offset
+       it adds by removing the file_number *)
     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 |]