aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Coquand <marc@mccd.space>2024-05-18 13:13:29 -0500
committerMarc Coquand <marc@mccd.space>2024-05-18 13:13:29 -0500
commitfbbbdca67c79145d43d6fdd59202a36fddfc8cd0 (patch)
tree12409c608ddd653e14ef42963a15aae144ce3cf3
parent256397061fe5ae5649b4569c45bb53c8e45e0cbe (diff)
downloadstitch-fbbbdca67c79145d43d6fdd59202a36fddfc8cd0.tar.gz
stitch-fbbbdca67c79145d43d6fdd59202a36fddfc8cd0.tar.bz2
stitch-fbbbdca67c79145d43d6fdd59202a36fddfc8cd0.zip
Add command execution to TODO
-rw-r--r--lib/todos.ml64
1 files changed, 59 insertions, 5 deletions
diff --git a/lib/todos.ml b/lib/todos.ml
index 51b878f..bdbf877 100644
--- a/lib/todos.ml
+++ b/lib/todos.ml
@@ -10,6 +10,8 @@ type state =
; content_pretty : string array
; goto_headlines : (unit -> unit) -> unit
; goto_done : (unit -> unit) -> unit
+ ; output : string option
+ ; tag : string
}
let title = I.strf ~attr:A.(st bold) "%s" "Todo View" |> I.pad ~l:0 ~t:0
@@ -24,6 +26,8 @@ let init ~goto_done ~goto_headlines =
; content_pretty = content_pretty |> Array.of_list
; goto_headlines
; goto_done
+ ; output = None
+ ; tag = ""
}
@@ -35,11 +39,19 @@ let load_todos () =
let rec render
t
- ({ pos; scroll; content; content_pretty; goto_headlines; goto_done } as state)
+ ({ pos; scroll; content; content_pretty; goto_headlines; goto_done; output; _ } as state)
=
let x, y = pos in
+ let size_x, size_y = Common.Term.size t in
let content_position = y - content_start in
let img =
+ let output_info =
+ match output with
+ | Some line ->
+ I.strf "%s%s" (String.escaped line) (String.make size_x ' ')
+ |> I.pad ~t:(size_y - 1)
+ | None -> I.empty
+ in
let dot =
if Array.length content_pretty = 0
then I.empty
@@ -53,18 +65,17 @@ let rec render
(Array.to_seq content_pretty |> Seq.drop scroll |> Array.of_seq)
in
let open I in
- Array.fold_left (fun sum el -> el </> sum) (title </> dot) elements
+ Array.fold_left (fun sum el -> el </> sum) (title </> dot </> output_info) elements
in
- let _, size_y = Common.Term.size t in
Common.Term.image t img;
let content_end = Array.length content_pretty + (content_start - 1) in
let scroll_up () =
let scroll = if y - content_start - scroll = 0 then max (scroll - 1) 0 else scroll in
- render t { state with pos = x, max (y - 1) content_start; scroll }
+ render t { state with pos = x, max (y - 1) content_start; scroll; output = None }
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_end; scroll }
+ render t { state with pos = x, min (y + 1) content_end; scroll; output = None }
in
match Common.Term.event t with
| `End | `Key (`Escape, []) | `Key (`ASCII 'q', []) | `Key (`ASCII 'C', [ `Ctrl ]) -> ()
@@ -103,6 +114,7 @@ let rec render
{ state with
content = content |> Array.of_list
; content_pretty = content_pretty |> Array.of_list
+ ; tag
})
; on_cancel =
(fun _ ->
@@ -113,6 +125,48 @@ let rec render
Input_prompt.render t input_state
| `Key (`ASCII 'j', []) | `Key (`ASCII 'N', [ `Ctrl ]) -> scroll_down ()
| `Key (`ASCII 'k', []) | `Key (`ASCII 'P', [ `Ctrl ]) -> scroll_up ()
+ | `Key (`ASCII '!', []) ->
+ let selected_file, _ = Array.get content content_position in
+ let selected_file = Grep.execution_directory ^ "/" ^ selected_file in
+ let content =
+ Array.map (fun (_, c) -> c) content |> Array.to_list |> String.concat "\n"
+ in
+ let (input_state : Input_prompt.state) =
+ { screen = img
+ ; user_input = ""
+ ; prompt = "COMMAND"
+ ; on_enter =
+ (fun command ->
+ if String.equal (String.trim command) String.empty
+ then (
+ Common.Term.cursor t None;
+ render t state)
+ else
+ Arbitrary_command.run
+ t
+ ~command:(Scanf.unescaped command)
+ ~content
+ ~selected_file
+ ~on_return:(fun result ->
+ let content, content_pretty = load_todos () in
+ let y = min (List.length content_pretty + content_start) y in
+ Common.Term.cursor t None;
+ render
+ t
+ { state with
+ content = Array.of_list content
+ ; content_pretty = Array.of_list content_pretty
+ ; pos = 0, y
+ ; scroll = 0
+ ; output = Some result
+ }))
+ ; on_cancel =
+ (fun _ ->
+ Common.Term.cursor t None;
+ render t state)
+ }
+ in
+ Input_prompt.render t input_state
| `Key (`ASCII 'T', [ `Ctrl ]) ->
let selected_file, _ = Array.get content (y - content_start) in
let _ = Grep.toggle_done selected_file in