chiark / gitweb /
Move terminal output into a sub-struct.
authorSimon Tatham <anakin@pobox.com>
Sun, 4 Feb 2024 14:09:41 +0000 (14:09 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 4 Feb 2024 14:55:15 +0000 (14:55 +0000)
The sub-struct is held in an Rc<RefCell> by Tui, which will allow me
to make other copies of the Rc and use them to give preliminary
display updates.

src/tui.rs

index 2ad2545e1bea10fd54e659bf229b26feaf36e44c..e427d4ed97d60bce8b214f013b669bc5e8c39875 100644 (file)
@@ -178,7 +178,7 @@ pub enum PhysicalAction {
 }
 
 pub struct Tui {
-    terminal: Terminal<CrosstermBackend<Stdout>>,
+    output: Rc<RefCell<TuiOutput>>,
     subthread_sender: std::sync::mpsc::SyncSender<SubthreadEvent>,
     subthread_receiver: std::sync::mpsc::Receiver<SubthreadEvent>,
     state: TuiLogicalState,
@@ -333,8 +333,10 @@ impl Tui {
         let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
         terminal.clear()?;
 
+        let output = Rc::new(RefCell::new(TuiOutput::new(terminal)));
+
         let mut tui = Tui {
-            terminal,
+            output,
             subthread_sender: sender,
             subthread_receiver: receiver,
             state,
@@ -478,19 +480,7 @@ impl Tui {
 
     fn main_loop(&mut self) -> Result<(), TuiError> {
         'outer: loop {
-            {
-                let state = &mut self.state;
-
-                self.terminal.draw(|frame| {
-                    let area = frame.size();
-                    let buf = frame.buffer_mut();
-                    if let Some((x, y)) = state.draw_frame(area, buf) {
-                        if let (Ok(x), Ok(y)) = (x.try_into(), y.try_into()) {
-                            frame.set_cursor(x, y);
-                        }
-                    }
-                })?;
-            }
+            self.output.borrow_mut().draw(&mut self.state)?;
 
             // One physical keypress can break down into multiple
             // things we treat as logical keypresses. So we must do an
@@ -556,7 +546,9 @@ impl Tui {
                 match physact {
                     PhysicalAction::Beep => Self::beep()?,
                     PhysicalAction::Exit => break 'outer Ok(()),
-                    PhysicalAction::Refresh => self.terminal.clear()?,
+                    PhysicalAction::Refresh => {
+                        self.output.borrow_mut().clear()?
+                    }
                     PhysicalAction::Error(err) => break 'outer Err(err),
                     PhysicalAction::MainSessionSetup => {
                         self.main_session_setup()?
@@ -575,6 +567,39 @@ impl Tui {
     }
 }
 
+struct TuiOutput {
+    terminal: Terminal<CrosstermBackend<Stdout>>,
+}
+
+impl TuiOutput {
+    fn new(terminal: Terminal<CrosstermBackend<Stdout>>) -> Self {
+        TuiOutput {
+            terminal,
+        }
+    }
+
+    fn draw(
+        &mut self,
+        state: &mut TuiLogicalState,
+    ) -> Result<(), std::io::Error> {
+        self.terminal.draw(|frame| {
+            let area = frame.size();
+            let buf = frame.buffer_mut();
+            if let Some((x, y)) = state.draw_frame(area, buf) {
+                if let (Ok(x), Ok(y)) = (x.try_into(), y.try_into()) {
+                    frame.set_cursor(x, y);
+                }
+            }
+        })?;
+
+        Ok(())
+    }
+
+    fn clear(&mut self) -> Result<(), std::io::Error> {
+        self.terminal.clear()
+    }
+}
+
 #[derive(Debug)]
 pub enum CursorPosition {
     None,             // cursor is hidden