From 57cb1ee3ffca4ecede0345c0d9af0e94a74d58a3 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Tue, 28 Nov 2023 17:16:51 +0100
Subject: [PATCH] add TTYApplication

---
 lib-nested-core/src/reprTree/context.rs |  2 +-
 lib-nested-tty/src/lib.rs               |  2 +
 lib-nested-tty/src/terminal.rs          |  2 +-
 lib-nested-tty/src/tty_application.rs   | 71 +++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 lib-nested-tty/src/tty_application.rs

diff --git a/lib-nested-core/src/reprTree/context.rs b/lib-nested-core/src/reprTree/context.rs
index 06af8c3..9bfc9f9 100644
--- a/lib-nested-core/src/reprTree/context.rs
+++ b/lib-nested-core/src/reprTree/context.rs
@@ -1,4 +1,4 @@
-use {
+ use {
     r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
     laddertypes::{TypeDict, TypeTerm, TypeID},
     crate::{
diff --git a/lib-nested-tty/src/lib.rs b/lib-nested-tty/src/lib.rs
index 85ded4d..4c1c7f6 100644
--- a/lib-nested-tty/src/lib.rs
+++ b/lib-nested-tty/src/lib.rs
@@ -10,6 +10,7 @@ pub mod compositor;
 pub mod ansi_parser;
 
 pub mod terminal;
+pub mod tty_application;
 
 //pub mod list_editor;
 //pub mod widgets;
@@ -21,6 +22,7 @@ pub use {
     compositor::TerminalCompositor,
     style::TerminalStyle,
     terminal::{Terminal, TerminalEvent},
+    tty_application::TTYApplication
 };
 
 use r3vi::view::grid::*;
diff --git a/lib-nested-tty/src/terminal.rs b/lib-nested-tty/src/terminal.rs
index c03e588..a7169c4 100644
--- a/lib-nested-tty/src/terminal.rs
+++ b/lib-nested-tty/src/terminal.rs
@@ -24,7 +24,7 @@ use {
     },
 };
 
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Debug)]
 pub enum TerminalEvent {
     Resize(Vector2<i16>),
     Input(termion::event::Event),
diff --git a/lib-nested-tty/src/tty_application.rs b/lib-nested-tty/src/tty_application.rs
new file mode 100644
index 0000000..aeb3fbb
--- /dev/null
+++ b/lib-nested-tty/src/tty_application.rs
@@ -0,0 +1,71 @@
+use {
+    cgmath::Vector2,
+    nested::{
+        editTree::NestedNode,
+        reprTree::{Context, ReprTree},
+    },
+    crate::{
+        terminal::TermOutWriter, DisplaySegment, Terminal, TerminalAtom, TerminalCompositor,
+        TerminalEvent, TerminalStyle, TerminalView,
+    },
+    r3vi::{
+        buffer::singleton::*,
+        view::{port::UpdateTask, singleton::*, ViewPort},
+    },
+    std::sync::{Arc, Mutex, RwLock},
+    termion::event::{Event, Key},
+};
+
+pub struct TTYApplication {
+    pub port: ViewPort<dyn TerminalView>,
+    term_writer: Arc<TermOutWriter>,
+}
+
+impl TTYApplication {
+    pub fn new(event_handler: impl Fn(TerminalEvent) + Send + Sync + 'static) -> Self {
+        let port = ViewPort::new();
+        let portmutex = Mutex::new(());
+        let term = Terminal::new(port.outer());
+        let term_writer = term.get_writer();
+
+        async_std::task::spawn(TTYApplication::event_loop(term, port.clone(), Arc::new(event_handler)));
+        async_std::task::spawn(TTYApplication::update_loop(port.clone()));
+
+        TTYApplication {
+            port,
+            term_writer,
+        }
+    }
+
+    /* this task handles all terminal events (e.g. key press, resize)
+     */
+    async fn event_loop(mut term: Terminal, port: ViewPort<dyn TerminalView>, event_handler: Arc<dyn Fn(TerminalEvent) + Send + Sync>) {
+        loop {
+            let ev = term.next_event().await;
+            if ev == TerminalEvent::Input(Event::Key(Key::Ctrl('d'))) {
+                break;
+            }
+
+            event_handler( ev );
+            port.update();
+        }
+    }
+
+    /* this task will continuously pull forward
+     * all notifications which are influencing
+     * the view in `term_port`
+     */
+    async fn update_loop(port: ViewPort<dyn TerminalView>) {
+        loop {
+            port.update();
+            async_std::task::sleep(std::time::Duration::from_millis(500)).await;
+        }
+    }
+
+    /* write the changes in the view of `term_port` to the terminal
+     */
+    pub async fn show(&self) -> Result<(), std::io::Error> {
+        self.term_writer.show().await
+    }
+}
+