From db4e445ee0f29c1179b5d0746217e5b5525ff3e2 Mon Sep 17 00:00:00 2001 From: Marc Coquand Date: Wed, 15 May 2024 11:17:48 -0500 Subject: State handling done --- lib/compontent.ml | 16 ++++++++++++++++ lib/headlines.ml | 38 ++++++++++++++++++++++++++------------ lib/stitched_article.ml | 41 +++++++++++++++++++++++------------------ lib/todos.ml | 4 ++-- 4 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 lib/compontent.ml diff --git a/lib/compontent.ml b/lib/compontent.ml new file mode 100644 index 0000000..ecdce4b --- /dev/null +++ b/lib/compontent.ml @@ -0,0 +1,16 @@ +open Notty + +let current_line size_x y scroll (el : Grep.display_type) i = + match el with + | Bold el -> + if i == y - scroll + then ( + let fill = String.make (max (size_x - String.length el) 0) ' ' in + I.strf "%s%s" ~attr:A.(st bold ++ st reverse) el fill |> I.pad ~l:0 ~t:i) + else I.strf "%s" ~attr:A.(st bold) el |> I.pad ~l:0 ~t:i + | Normal el -> + if i == y - scroll + then ( + let fill = String.make (max (size_x - String.length el) 0) ' ' in + I.strf "%s%s" ~attr:A.(st reverse) el fill |> I.pad ~l:0 ~t:i) + else I.strf "%s" el |> I.pad ~l:0 ~t:i diff --git a/lib/headlines.ml b/lib/headlines.ml index 954d0e2..4565f5f 100644 --- a/lib/headlines.ml +++ b/lib/headlines.ml @@ -11,10 +11,11 @@ type state = ; scroll : int ; content : (string * string) array ; content_pretty : string array + ; todo_state : Todos.state option } (* TODO: Add page title *) -let rec render t ({ pos; scroll; content; content_pretty } as state) = +let rec render t ({ pos; scroll; content; content_pretty; todo_state } as state) = let x, y = pos in let img = let dot = I.string A.(st bold) ">" |> I.pad ~l:0 ~t:(y - scroll) @@ -51,15 +52,25 @@ let rec render t ({ pos; scroll; content; content_pretty } as state) = render t { state with pos = 0, min y content_length } | `Key (`ASCII '?', []) -> Help_screen.render t { go_back = (fun () -> render t state) } | `Key (`ASCII '2', []) -> - let todo_content = Grep.get_todos () |> Grep.parse_todo_string in - let todo_pretty = Grep.pretty_format_todo todo_content in - let todo_state = - Todos.init - ~goto_headlines:(fun () -> render t state) - ~content:(todo_content |> Array.of_list) - ~content_pretty:(todo_pretty |> Array.of_list) - in - Todos.render t todo_state + (match todo_state with + | Some todo_state -> + Todos.render + t + { todo_state with + goto_headlines = + (fun new_state -> render t { state with todo_state = Some new_state }) + } + | None -> + let todo_content = Grep.get_todos () |> Grep.parse_todo_string in + let todo_pretty = Grep.pretty_format_todo todo_content in + let todo_state = + Todos.init + ~goto_headlines:(fun new_state -> + render t { state with todo_state = Some new_state }) + ~content:(todo_content |> Array.of_list) + ~content_pretty:(todo_pretty |> Array.of_list) + in + Todos.render t todo_state) | `Key (`ASCII 's', []) -> let content = Array.map @@ -78,6 +89,7 @@ let rec render t ({ pos; scroll; content; content_pretty } as state) = ; content_pretty = full_content_pretty ; scroll = 0 ; go_back = (fun () -> render t state) + ; todo_state } | `Key (`ASCII 'r', []) -> let (input_state : Input_screen.state) = @@ -89,7 +101,7 @@ let rec render t ({ pos; scroll; content; content_pretty } as state) = let content = Grep.get_tagged_headlines tag () |> Grep.parse_headlines in let content_pretty = Grep.pretty_format content in Common.Term.cursor t None; - render t { content; content_pretty; pos = 0, 0; scroll = 0 }) + render t { state with content; content_pretty; pos = 0, 0; scroll = 0 }) ; on_cancel = (fun _ -> Common.Term.cursor t None; @@ -148,4 +160,6 @@ let start (tag : string) () = exit 0) else ( let content_pretty = content |> Grep.pretty_format in - render (Common.Term.create ()) { pos = 0, 0; scroll = 0; content; content_pretty }) + render + (Common.Term.create ()) + { pos = 0, 0; scroll = 0; content; content_pretty; todo_state = None }) diff --git a/lib/stitched_article.ml b/lib/stitched_article.ml index ceedc46..c71ca14 100644 --- a/lib/stitched_article.ml +++ b/lib/stitched_article.ml @@ -10,32 +10,17 @@ type state = ; content : (string * int * string * int) array ; go_back : unit -> unit ; content_pretty : Grep.display_type array + ; todo_state : Todos.state option } -let render_line size_x y scroll (el : Grep.display_type) i = - match el with - | Bold el -> - if i == y - scroll - then ( - let fill = String.make (max (size_x - String.length el) 0) ' ' in - I.strf "%s%s" ~attr:A.(st bold ++ st reverse) el fill |> I.pad ~l:0 ~t:i) - else I.strf "%s" ~attr:A.(st bold) el |> I.pad ~l:0 ~t:i - | Normal el -> - if i == y - scroll - then ( - let fill = String.make (max (size_x - String.length el) 0) ' ' in - I.strf "%s%s" ~attr:A.(st reverse) el fill |> I.pad ~l:0 ~t:i) - else I.strf "%s" el |> I.pad ~l:0 ~t:i - - (* TODO: Use grep -l to filter notes by regexp and rerender those files*) -let rec render t ({ pos; scroll; content_pretty; go_back; content } as state) = +let rec render t ({ pos; scroll; content_pretty; go_back; content; todo_state } as state) = let size_x, size_y = Common.Term.size t in let x, y = pos in let img = let elements = Array.mapi - (fun i el -> render_line size_x y scroll el i) + (fun i el -> Compontent.current_line size_x y scroll el i) (* TODO: Fix this ugly slow conversion *) (Array.to_seq content_pretty |> Seq.drop scroll |> Array.of_seq) in @@ -65,6 +50,26 @@ let rec render t ({ pos; scroll; content_pretty; go_back; content } as state) = | `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 '2', []) -> + (match todo_state with + | Some todo_state -> + Todos.render + t + { todo_state with + goto_headlines = + (fun new_state -> render t { state with todo_state = Some new_state }) + } + | None -> + let todo_content = Grep.get_todos () |> Grep.parse_todo_string in + let todo_pretty = Grep.pretty_format_todo todo_content in + let todo_state = + Todos.init + ~goto_headlines:(fun new_state -> + render t { state with todo_state = Some new_state }) + ~content:(todo_content |> Array.of_list) + ~content_pretty:(todo_pretty |> Array.of_list) + in + Todos.render t todo_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) = diff --git a/lib/todos.ml b/lib/todos.ml index 907538c..4e52cd4 100644 --- a/lib/todos.ml +++ b/lib/todos.ml @@ -8,7 +8,7 @@ type state = ; scroll : int ; content : (string * string) array ; content_pretty : string array - ; goto_headlines : unit -> unit + ; goto_headlines : state -> unit } let init ~goto_headlines ~content ~content_pretty = @@ -75,7 +75,7 @@ let rec render t ({ pos; scroll; content; content_pretty; goto_headlines } as st } in Input_screen.render t input_state - | `Key (`ASCII '1', []) -> goto_headlines () + | `Key (`ASCII '1', []) -> goto_headlines state | `Key (`ASCII 'j', []) | `Key (`ASCII 'N', [ `Ctrl ]) -> scroll_down () | `Key (`ASCII 'k', []) | `Key (`ASCII 'P', [ `Ctrl ]) -> scroll_up () | `Key (`ASCII 't', []) -> -- cgit v1.2.3