aboutsummaryrefslogtreecommitdiff
path: root/lib/stitched_article.ml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stitched_article.ml')
-rw-r--r--lib/stitched_article.ml68
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/stitched_article.ml b/lib/stitched_article.ml
new file mode 100644
index 0000000..41efa75
--- /dev/null
+++ b/lib/stitched_article.ml
@@ -0,0 +1,68 @@
+module Grep = Grep
+module Common = Common
+open Notty
+module Input_screen = Input_screen
+
+type state =
+ { pos : int * int
+ ; scroll : int
+ ; content : (string * int * string) array
+ ; content_pretty : Grep.display_type array
+ }
+
+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
+
+
+let rec render t ({ pos; scroll; content_pretty; _ } 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)
+ (* TODO: Fix this ugly slow conversion *)
+ (Array.to_seq content_pretty |> Seq.drop scroll |> Array.of_seq)
+ in
+ let open I in
+ Array.fold_left (fun sum el -> el </> sum) I.empty elements
+ in
+ Common.Term.image t img;
+ 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
+ render 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
+ render t @@ { state with pos = x, min (y + 1) (content_length - 1); scroll }
+ in
+ match Common.Term.event t with
+ | `End | `Key (`Escape, []) | `Key (`ASCII 'q', []) | `Key (`ASCII 'C', [ `Ctrl ]) -> ()
+ | `Mouse (`Press (`Scroll s), _, _) ->
+ (match s with
+ | `Down -> scroll_down ()
+ | `Up -> scroll_up ())
+ | `Resize _ -> render t state
+ | `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 (`Arrow d, _) ->
+ (match d with
+ | `Up -> scroll_up ()
+ | `Down -> scroll_down ()
+ | _ -> render t state)
+ | _ -> render t state