diff --git a/lib/nottui-lwt/nottui_lwt.ml b/lib/nottui-lwt/nottui_lwt.ml index b5a5df9..051decd 100644 --- a/lib/nottui-lwt/nottui_lwt.ml +++ b/lib/nottui-lwt/nottui_lwt.ml @@ -70,9 +70,14 @@ let render ?quit ~size events doc = Lwt.async (fun () -> Lwt_stream.iter refresh refresh_stream); result -let run ?quit doc = +let run ?cursor ?quit doc = let term = Term.create () in let images = render ?quit ~size:(Term.size term) (Term.events term) doc in + let cursor () = + let cursor = cursor |> Option.map @@ fun cursor -> + Lwd.quick_sample (Lwd.observe (Lwd.get cursor)) in + Term.cursor term cursor in Lwt.finalize - (fun () -> Lwt_stream.iter_s (Term.image term) images) + (fun () -> + Lwt_stream.iter_s (fun image -> Lwt.join [ Term.image term image; cursor () ]) images) (fun () -> (Term.release term)) diff --git a/lib/nottui-lwt/nottui_lwt.mli b/lib/nottui-lwt/nottui_lwt.mli index f04396b..63802a1 100644 --- a/lib/nottui-lwt/nottui_lwt.mli +++ b/lib/nottui-lwt/nottui_lwt.mli @@ -18,7 +18,7 @@ type event = [ val render : ?quit:unit Lwt.t -> size:int * int -> event Lwt_stream.t -> ui Lwd.t -> image Lwt_stream.t (** Turn a stream of events into a stream of images. *) -val run : (*?term:Term.t ->*) ?quit:unit Lwt.t -> ui Lwd.t -> unit Lwt.t +val run : (*?term:Term.t ->*) ?cursor:(int * int) Lwd.var -> ?quit:unit Lwt.t -> ui Lwd.t -> unit Lwt.t (** Run mainloop in [Lwt], until the [quit] promise is fulfilled. The ui is a normal [Lwd.t] value, but events are free to spawn asynchronous diff --git a/lib/nottui/nottui.ml b/lib/nottui/nottui.ml index 8c67a8e..2beba2a 100644 --- a/lib/nottui/nottui.ml +++ b/lib/nottui/nottui.ml @@ -800,7 +800,7 @@ struct (* FIXME Uses of [quick_sample] and [quick_release] should be replaced by [sample] and [release] with the appropriate release management. *) - let step ?(process_event=true) ?(timeout=(-1.0)) ~renderer term root = + let step ?cursor ?(process_event=true) ?(timeout=(-1.0)) ~renderer term root = let size = Term.size term in let image = let rec stabilize () = @@ -813,7 +813,10 @@ struct in stabilize () in + let cursor = cursor |> Option.map @@ fun cursor -> + Lwd.quick_sample (Lwd.observe (Lwd.get cursor)) in Term.image term image; + Term.cursor term cursor; if process_event then let i, _ = Term.fds term in let has_event = @@ -833,13 +836,13 @@ struct let event = (event : Unescape.event :> Ui.event) in ignore (Renderer.dispatch_event renderer event : [`Handled | `Unhandled]) - let run_with_term term ?tick_period ?(tick=ignore) ~renderer quit t = + let run_with_term term ?cursor ?tick_period ?(tick=ignore) ~renderer quit t = let quit = Lwd.observe (Lwd.get quit) in let root = Lwd.observe t in let rec loop () = let quit = Lwd.quick_sample quit in if not quit then ( - step ~process_event:true ?timeout:tick_period ~renderer term root; + step ?cursor ~process_event:true ?timeout:tick_period ~renderer term root; tick (); loop () ) @@ -848,7 +851,7 @@ struct ignore (Lwd.quick_release root); ignore (Lwd.quick_release quit) - let run ?tick_period ?tick ?term ?(renderer=Renderer.make ()) + let run ?cursor ?tick_period ?tick ?term ?(renderer=Renderer.make ()) ?quit ?(quit_on_escape=true) ?(quit_on_ctrl_q=true) t = let quit = match quit with | Some quit -> quit @@ -863,10 +866,10 @@ struct )) in match term with - | Some term -> run_with_term term ?tick_period ?tick ~renderer quit t + | Some term -> run_with_term term ?cursor ?tick_period ?tick ~renderer quit t | None -> let term = Term.create () in - run_with_term term ?tick_period ?tick ~renderer quit t; + run_with_term term ?cursor ?tick_period ?tick ~renderer quit t; Term.release term end diff --git a/lib/nottui/nottui.mli b/lib/nottui/nottui.mli index a4c72fe..007ac28 100644 --- a/lib/nottui/nottui.mli +++ b/lib/nottui/nottui.mli @@ -342,7 +342,7 @@ module Ui_loop : sig open Notty_unix - val step : ?process_event:bool -> ?timeout:float -> renderer:Renderer.t -> + val step : ?cursor:(int * int) Lwd.var -> ?process_event:bool -> ?timeout:float -> renderer:Renderer.t -> Term.t -> ui Lwd.root -> unit (** Run one step of the main loop. @@ -351,6 +351,7 @@ sig consume and dispatch it. *) val run : + ?cursor:(int * int) Lwd.var -> ?tick_period:float -> ?tick:(unit -> unit) -> ?term:Term.t -> ?renderer:Renderer.t -> ?quit:bool Lwd.var -> ?quit_on_escape:bool ->