From be2bf751536850e7bdfbd876ef908c5d6cf00087 Mon Sep 17 00:00:00 2001 From: Marc Coquand Date: Tue, 14 May 2024 10:46:28 -0500 Subject: Add search and tag search --- lib/headlines.ml | 92 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 16 deletions(-) (limited to 'lib/headlines.ml') diff --git a/lib/headlines.ml b/lib/headlines.ml index 8fab7f6..f32b6ef 100644 --- a/lib/headlines.ml +++ b/lib/headlines.ml @@ -1,16 +1,27 @@ module Grep = Grep module Common = Common open Notty +module Input_screen = Input_screen -let content = Grep.get_headlines () |> Grep.parse_headlines -let content_pretty = content |> Grep.pretty_format +type state = + { tag : string option + ; pos : int * int + ; scroll : int + ; content : (string * string) array + ; content_pretty : string array + } -let rec headline_screen t (((x, y) as pos), scroll) = +let rec headline_screen t ({ tag; pos; scroll; content; content_pretty } as state) = + print_endline (Option.value ~default:"No tag" tag); + let x, y = pos in let img = - let dot = I.string A.(fg black) ">" |> I.pad ~l:0 ~t:(y - scroll) + let dot = I.string A.(st bold) ">" |> I.pad ~l:0 ~t:(y - scroll) and elements = Array.mapi - (fun i el -> I.strf ~attr:A.(fg black) "%s" el |> I.pad ~l:2 ~t:i) + (fun i el -> + if i == y - scroll + then I.strf ~attr:A.(st underline) "%s" el |> I.pad ~l:2 ~t:i + else I.strf "%s" el |> I.pad ~l:2 ~t:i) (Array.to_seq content_pretty |> Seq.drop scroll |> Array.of_seq) in let open I in @@ -21,11 +32,11 @@ let rec headline_screen t (((x, y) as pos), scroll) = let content_length = Array.length content_pretty in let scroll_up () = let scroll = if y - scroll = 0 then max (scroll - 1) 0 else scroll in - headline_screen t @@ ((x, max (y - 1) 0), scroll) + headline_screen t @@ { state with pos = x, max (y - 1) 0; scroll } in let scroll_down () = let scroll = if y - scroll >= size_y - 1 then scroll + 1 else scroll in - headline_screen t @@ ((x, min (y + 1) content_length), scroll) + headline_screen t @@ { state with pos = x, min (y + 1) content_length; scroll } in match Common.Term.event t with | `End | `Key (`Escape, []) | `Key (`ASCII 'q', []) | `Key (`ASCII 'C', [ `Ctrl ]) -> () @@ -33,18 +44,52 @@ let rec headline_screen t (((x, y) as pos), scroll) = (match s with | `Down -> scroll_down () | `Up -> scroll_up ()) - | `Resize _ -> headline_screen t (pos, scroll) + | `Resize _ -> headline_screen t state | `Mouse ((`Press _ | `Drag), (_, y), _) -> - headline_screen t ((0, min y content_length), scroll) + headline_screen t { state with pos = 0, min y content_length } + | `Key (`ASCII 't', []) -> + let (input_state : Input_screen.state) = + { screen = img + ; user_input = "" + ; prompt = "TAG: " + ; on_enter = + (fun tag -> + let content = Grep.get_tagged_headlines tag () |> Grep.parse_headlines in + let content_pretty = Grep.pretty_format content in + Common.Term.cursor t None; + headline_screen + t + { state with content; content_pretty; pos = 0, 0; scroll = 0 }) + ; on_cancel = + (fun _ -> + Common.Term.cursor t None; + headline_screen t state) + } + in + Input_screen.render t input_state + | `Key (`ASCII 's', []) -> + let (input_state : Input_screen.state) = + { screen = img + ; user_input = "" + ; prompt = "SEARCH: " + ; on_enter = + (fun _ -> + Common.Term.cursor t None; + headline_screen t { state with pos = 0, 0; scroll = 0 }) + ; on_cancel = + (fun _ -> + Common.Term.cursor t None; + headline_screen t state) + } + in + Input_screen.render t input_state | `Key (`ASCII 'j', []) | `Key (`ASCII 'N', [ `Ctrl ]) -> scroll_down () - | `Key (`ASCII 'k', []) | `Key (`ASCII 'P', [ `Ctrl ]) -> - let scroll = if y - scroll = 0 then max (scroll - 1) 0 else scroll in - headline_screen t @@ ((x, max (y - 1) 0), scroll) + | `Key (`ASCII 'k', []) | `Key (`ASCII 'P', [ `Ctrl ]) -> scroll_up () | `Key (`Arrow d, _) -> (match d with | `Up -> scroll_up () | `Down -> scroll_down () - | _ -> headline_screen t ((x, y), scroll)) + | _ -> headline_screen 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) = @@ -67,13 +112,28 @@ let rec headline_screen t (((x, y) as pos), scroll) = match Unix.wait () with | _, _ -> Common.Term.cursor t None; - headline_screen t ((x, y), scroll) + headline_screen t state (* Capture resizing events *) | exception Unix.Unix_error (Unix.EINTR, _, _) -> run_editor () | exception Unix.Unix_error (_, _, _) -> failwith "ERROR" in run_editor () - | _ -> headline_screen t (pos, scroll) + | _ -> headline_screen t state -let start () = headline_screen (Common.Term.create ()) ((0, 0), 0) +let start (tag : string) () = + let tag = if String.equal tag "" then None else Some tag in + let content = + match tag with + | None -> Grep.get_headlines () |> Grep.parse_headlines + | Some tag -> Grep.get_tagged_headlines tag () |> Grep.parse_headlines + in + if Array.length content == 0 + then ( + print_endline "No entry for tag"; + exit 0) + else ( + let content_pretty = content |> Grep.pretty_format in + headline_screen + (Common.Term.create ()) + { tag; pos = 0, 0; scroll = 0; content; content_pretty }) -- cgit v1.2.3