From d5583aa9c252bdbd2c2cdcb6e0e1fe3e7fcd5030 Mon Sep 17 00:00:00 2001 From: Leandro Ostera Date: Sat, 30 Mar 2024 03:15:22 +0100 Subject: [PATCH 1/4] feat: upgrade to latest riot --- minttea/io_loop.ml | 2 +- minttea/program.ml | 2 +- minttea/renderer.ml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/minttea/io_loop.ml b/minttea/io_loop.ml index f9091bc..27675b9 100644 --- a/minttea/io_loop.ml +++ b/minttea/io_loop.ml @@ -46,5 +46,5 @@ let run runner = link runner; let termios = Stdin.setup () in let _worker = spawn_link (fun () -> loop runner) in - let _ = receive () in + let _ = receive_any () in Stdin.shutdown termios diff --git a/minttea/program.ml b/minttea/program.ml index dda53b5..7ef818d 100644 --- a/minttea/program.ml +++ b/minttea/program.ml @@ -9,7 +9,7 @@ exception Exit let rec loop renderer (app : 'model App.t) (model : 'model) = let event = - match receive () with + match receive_any () with | Timer ref -> Event.Timer ref | Io_loop.Input event -> event | message -> Event.Custom message diff --git a/minttea/renderer.ml b/minttea/renderer.ml index 7b0cff8..14f37e5 100644 --- a/minttea/renderer.ml +++ b/minttea/renderer.ml @@ -27,7 +27,7 @@ let same_as_last_flush t = t.buffer = t.last_render let lines t = t.buffer |> String.split_on_char '\n' let rec loop t = - match receive () with + match receive_any () with | Shutdown -> flush t; restore t From 204493199b1f9eddf7ca6004039f2de948741477 Mon Sep 17 00:00:00 2001 From: Leandro Ostera Date: Sat, 30 Mar 2024 03:57:53 +0100 Subject: [PATCH 2/4] feat: introduce config and persistent rendering mode --- examples/list/dune | 4 ++-- minttea/config.ml | 1 + minttea/minttea.ml | 10 ++++++---- minttea/minttea.mli | 10 ++++++++-- minttea/program.ml | 8 ++++---- minttea/renderer.ml | 7 +++++-- minttea/renderer.mli | 2 +- 7 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 minttea/config.ml diff --git a/examples/list/dune b/examples/list/dune index 890388a..b00e73b 100644 --- a/examples/list/dune +++ b/examples/list/dune @@ -1,3 +1,3 @@ (executable - (name main) - (libraries minttea spices leaves str)) + (name main) + (libraries minttea spices leaves str)) diff --git a/minttea/config.ml b/minttea/config.ml new file mode 100644 index 0000000..a0dceaf --- /dev/null +++ b/minttea/config.ml @@ -0,0 +1 @@ +type t = { render_mode : [ `clear | `persist ]; fps : int } diff --git a/minttea/minttea.ml b/minttea/minttea.ml index 30e33fd..00f14df 100644 --- a/minttea/minttea.ml +++ b/minttea/minttea.ml @@ -3,21 +3,23 @@ module Event = Event module Command = Command module App = App module Program = Program +module Config = Config +let config ?(render_mode = `clear) ?(fps = 60) () = Config.{ render_mode; fps } let app = App.make -let run ?(fps = 60) ~initial_model app = - let prog = Program.make ~app ~fps in +let run ?(config = config ()) ~initial_model app = + let prog = Program.make ~app ~config in Program.run prog initial_model; Logger.trace (fun f -> f "terminating") -let start app ~initial_model = +let start ?(config = config ()) app ~initial_model = let module App = struct let start () = Logger.set_log_level None; let pid = spawn_link (fun () -> - run app ~initial_model; + run ~config app ~initial_model; Logger.trace (fun f -> f "about to shutdown"); shutdown ~status:0 ()) in diff --git a/minttea/minttea.mli b/minttea/minttea.mli index 2770820..afa6023 100644 --- a/minttea/minttea.mli +++ b/minttea/minttea.mli @@ -1,5 +1,11 @@ open Riot +module Config : sig + type t +end + +val config : ?render_mode:[ `clear | `persist ] -> ?fps:int -> unit -> Config.t + module Event : sig type modifier = No_modifier | Ctrl @@ -46,5 +52,5 @@ val app : unit -> 'model App.t -val run : ?fps:int -> initial_model:'model -> 'model App.t -> unit -val start : 'model App.t -> initial_model:'model -> unit +val run : ?config:Config.t -> initial_model:'model -> 'model App.t -> unit +val start : ?config:Config.t -> 'model App.t -> initial_model:'model -> unit diff --git a/minttea/program.ml b/minttea/program.ml index 7ef818d..1378aef 100644 --- a/minttea/program.ml +++ b/minttea/program.ml @@ -1,9 +1,9 @@ open Riot type Message.t += Timer of unit Ref.t | Shutdown -type 'model t = { app : 'model App.t; fps : int } +type 'model t = { app : 'model App.t; config : Config.t } -let make ~app ~fps = { app; fps } +let make ~app ~config = { app; config } exception Exit @@ -55,14 +55,14 @@ let init { app; _ } initial_model renderer = Renderer.render renderer view; loop renderer app initial_model -let run ({ fps; _ } as t) initial_model = +let run ({ config; _ } as t) initial_model = Printexc.record_backtrace true; let renderer = spawn (fun () -> (* NOTE(@leostera): reintroduce this when riot brings back process-stealing *) (* process_flag (Priority High); *) let runner = Process.await_name "Minttea.runner" in - Renderer.run ~fps ~runner) + Renderer.run ~config ~runner) in let runner = spawn (fun () -> diff --git a/minttea/renderer.ml b/minttea/renderer.ml index 14f37e5..86bb25a 100644 --- a/minttea/renderer.ml +++ b/minttea/renderer.ml @@ -14,6 +14,7 @@ type t = { ticker : Timer.timer; width : int; height : int; + render_mode : [ `clear | `persist ]; mutable buffer : string; mutable last_render : string; mutable lines_rendered : int; @@ -61,7 +62,7 @@ and flush t = let new_lines_this_flush = List.length new_lines in (* clean last rendered lines *) - if t.lines_rendered > 0 then + if t.render_mode = `clear && t.lines_rendered > 0 then for _i = 1 to t.lines_rendered - 1 do Terminal.clear_line (); Terminal.cursor_up 1 @@ -107,7 +108,8 @@ let max_fps = 120 let cap fps = Int.max 1 (Int.min fps max_fps) |> Int.to_float let fps_to_float fps = 1. /. cap fps *. 1_000. |> Int64.of_float -let run ~fps ~runner = +let run ~config ~runner = + let Config.{ render_mode; fps } = config in let ticker = Riot.Timer.send_interval ~every:(fps_to_float fps) (self ()) Tick |> Result.get_ok @@ -123,6 +125,7 @@ let run ~fps ~runner = is_altscreen_active = false; lines_rendered = 0; cursor_visibility = `visible; + render_mode; } let render pid output = send pid (Render output) diff --git a/minttea/renderer.mli b/minttea/renderer.mli index b017ccf..749a7a1 100644 --- a/minttea/renderer.mli +++ b/minttea/renderer.mli @@ -1,6 +1,6 @@ open Riot -val run : fps:int -> runner:Pid.t -> unit +val run : config:Config.t -> runner:Pid.t -> unit val render : Pid.t -> string -> unit val enter_alt_screen : Pid.t -> unit val exit_alt_screen : Pid.t -> unit From 6a6088e1d2bbc128c470e85a3241a396185a4d2e Mon Sep 17 00:00:00 2001 From: jmcavanillas Date: Mon, 15 Apr 2024 22:37:11 +0200 Subject: [PATCH 3/4] Implemented some wrapping examples using shape the term package --- examples/text-wrapping/dune | 3 +++ examples/text-wrapping/main.ml | 44 ++++++++++++++++++++++++++++++++++ examples/word-wrapping/dune | 3 +++ examples/word-wrapping/main.ml | 44 ++++++++++++++++++++++++++++++++++ minttea/minttea.ml | 2 +- 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 examples/text-wrapping/dune create mode 100644 examples/text-wrapping/main.ml create mode 100644 examples/word-wrapping/dune create mode 100644 examples/word-wrapping/main.ml diff --git a/examples/text-wrapping/dune b/examples/text-wrapping/dune new file mode 100644 index 0000000..e23e2a9 --- /dev/null +++ b/examples/text-wrapping/dune @@ -0,0 +1,3 @@ +(executable + (name main) + (libraries minttea shape-the-term spices leaves)) diff --git a/examples/text-wrapping/main.ml b/examples/text-wrapping/main.ml new file mode 100644 index 0000000..2121788 --- /dev/null +++ b/examples/text-wrapping/main.ml @@ -0,0 +1,44 @@ +open Minttea +open Leaves + +type model = { text : Text_input.t; quitting : bool } + +let mint = Spices.color "#77e5b7" +let white = Spices.color "#FFFFFF" + +let cursor = + Cursor.make ~style:Spices.(default |> bg mint |> fg white |> bold true) () + +let initial_model = + { + text = Text_input.make "" ~placeholder:"Type something" ~cursor (); + quitting = false; + } + +let init _ = Command.Hide_cursor + +let update (event : Event.t) model = + let s = + match event with + | e -> + if e = Event.KeyDown (Enter, No_modifier) then + ({ model with quitting = true }, Command.Quit) + else + let text = Text_input.update model.text e in + ({ model with text }, Command.Noop) + in + s + +let view model = + let style = Spices.(default |> fg mint |> build) in + let width = 12 in + let show s = Shape_the_term.wrap width @@ style "%s" s in + if model.quitting then + Format.sprintf "\n🐫 Your text wrapped ✨ (to %s characters width):\n%s\n" (string_of_int width) + @@ show @@ Text_input.current_text model.text + else + Format.sprintf "\n🐫 Text area (%s characters width):\n%s\n" (string_of_int width) + @@ show @@ Text_input.view model.text + +let app = Minttea.app ~init ~update ~view () +let () = Minttea.start ~initial_model app diff --git a/examples/word-wrapping/dune b/examples/word-wrapping/dune new file mode 100644 index 0000000..e23e2a9 --- /dev/null +++ b/examples/word-wrapping/dune @@ -0,0 +1,3 @@ +(executable + (name main) + (libraries minttea shape-the-term spices leaves)) diff --git a/examples/word-wrapping/main.ml b/examples/word-wrapping/main.ml new file mode 100644 index 0000000..6356f8a --- /dev/null +++ b/examples/word-wrapping/main.ml @@ -0,0 +1,44 @@ +open Minttea +open Leaves + +type model = { text : Text_input.t; quitting : bool } + +let mint = Spices.color "#77e5b7" +let white = Spices.color "#FFFFFF" + +let cursor = + Cursor.make ~style:Spices.(default |> bg mint |> fg white |> bold true) () + +let initial_model = + { + text = Text_input.make "" ~placeholder:"Type something" ~cursor (); + quitting = false; + } + +let init _ = Command.Hide_cursor + +let update (event : Event.t) model = + let s = + match event with + | e -> + if e = Event.KeyDown (Enter, No_modifier) then + ({ model with quitting = true }, Command.Quit) + else + let text = Text_input.update model.text e in + ({ model with text }, Command.Noop) + in + s + +let view model = + let style = Spices.(default |> fg mint |> build) in + let show width s = Shape_the_term.wrap_by_word width @@ style "%s" s in + if model.quitting then + Format.sprintf "\n🐫 Your text wrapped by word ✨ (to 12 characters width):\n%s\n" + @@ show 12 @@ Text_input.current_text model.text + else + (Format.sprintf "\n%s\n" @@ show 36 @@ Text_input.view model.text) ^ + Format.sprintf "\n🐫 Wrap by word (to 12 characters width):\n%s\n" + @@ show 12 @@ Text_input.current_text model.text + +let app = Minttea.app ~init ~update ~view () +let () = Minttea.start ~initial_model app diff --git a/minttea/minttea.ml b/minttea/minttea.ml index 30e33fd..2ec92fb 100644 --- a/minttea/minttea.ml +++ b/minttea/minttea.ml @@ -6,7 +6,7 @@ module Program = Program let app = App.make -let run ?(fps = 60) ~initial_model app = +let run ?(fps = 2) ~initial_model app = let prog = Program.make ~app ~fps in Program.run prog initial_model; Logger.trace (fun f -> f "terminating") From 5639d095c22b9e2d785704f8579364ba4819dc7c Mon Sep 17 00:00:00 2001 From: jmcavanillas Date: Wed, 17 Apr 2024 19:56:01 +0200 Subject: [PATCH 4/4] Updated examples to riot 0.0.9 added explicit minttea config --- dune-project | 2 +- examples/text-wrapping/main.ml | 2 +- examples/word-wrapping/main.ml | 2 +- minttea.opam | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dune-project b/dune-project index b33dc49..11e22fd 100644 --- a/dune-project +++ b/dune-project @@ -19,7 +19,7 @@ (description "A longer description") (depends (ocaml (>= "5.1")) - (riot (= "0.0.8")) + (riot (= "0.0.9")) (mdx (and :with-test (>= "2.3.1"))) (tty (>= "0.0.2")) uuseg) diff --git a/examples/text-wrapping/main.ml b/examples/text-wrapping/main.ml index 2121788..88e4c7a 100644 --- a/examples/text-wrapping/main.ml +++ b/examples/text-wrapping/main.ml @@ -41,4 +41,4 @@ let view model = @@ show @@ Text_input.view model.text let app = Minttea.app ~init ~update ~view () -let () = Minttea.start ~initial_model app +let () = Minttea.start ~config:(config ~render_mode: `clear ~fps: 60 ()) ~initial_model app diff --git a/examples/word-wrapping/main.ml b/examples/word-wrapping/main.ml index 6356f8a..0b4fd79 100644 --- a/examples/word-wrapping/main.ml +++ b/examples/word-wrapping/main.ml @@ -41,4 +41,4 @@ let view model = @@ show 12 @@ Text_input.current_text model.text let app = Minttea.app ~init ~update ~view () -let () = Minttea.start ~initial_model app +let () = Minttea.start ~config:(config ~render_mode: `clear ~fps: 60 ()) ~initial_model app diff --git a/minttea.opam b/minttea.opam index 0fea1f1..4bfd49c 100644 --- a/minttea.opam +++ b/minttea.opam @@ -12,7 +12,7 @@ bug-reports: "https://github.com/leostera/minttea/issues" depends: [ "dune" {>= "3.11"} "ocaml" {>= "5.1"} - "riot" {= "0.0.8"} + "riot" {= "0.0.9"} "mdx" {with-test & >= "2.3.1"} "tty" {>= "0.0.2"} "uuseg"