From 1bb93aae00b35fdbfba85dc9fc80233dc2acec3c Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Mon, 1 Jan 2018 02:30:11 -0800 Subject: [PATCH] Got interactive responsiveness to terminal resizing working. --- src/main.rs | 3 +- src/term_ui/mod.rs | 94 +++++++++++++++++++++++++------------------ src/term_ui/screen.rs | 4 +- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/main.rs b/src/main.rs index f0f8276..1bb760b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,6 @@ fn main() { }; // Initialize and start UI - let mut stdin = std::io::stdin(); - let mut ui = TermUI::new_from_editor(&mut stdin, editor); + let mut ui = TermUI::new_from_editor(editor); ui.main_ui_loop(); } diff --git a/src/term_ui/mod.rs b/src/term_ui/mod.rs index 8b071c0..fd6ee29 100644 --- a/src/term_ui/mod.rs +++ b/src/term_ui/mod.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] +use std; use std::cmp::min; -use std::io; use termion; use termion::event::{Event, Key}; @@ -24,26 +24,37 @@ macro_rules! ui_loop { ($term_ui:ident, draw $draw:block, key_press($key:ident) $key_press:block) => { let mut stop = false; + // Draw the editor to screen for the first time + {$draw}; + $term_ui.screen.present(); + + // UI loop loop { - // Draw the editor to screen - {$draw}; - $term_ui.screen.present(); + let mut should_redraw = false; // Handle input - match $term_ui.inp.next() { - Some(Ok(Event::Key($key))) => { - let status = || -> LoopStatus { - $key_press - }(); - if status == LoopStatus::Done { - stop = true; - // break; + loop { + match $term_ui.inp.next() { + Some(Ok(Event::Key($key))) => { + let (status, state_changed) = || -> (LoopStatus, bool) { + $key_press + }(); + should_redraw |= state_changed; + if status == LoopStatus::Done { + stop = true; + break; + } + } + + _ => { + break; } } + } - _ => { - // break; - } + // Check if we're done + if stop || $term_ui.quit { + break; } // Check for screen resize @@ -52,18 +63,26 @@ macro_rules! ui_loop { $term_ui.width = w as usize; $term_ui.height = h as usize; $term_ui.editor.update_dim($term_ui.height - 1, $term_ui.width); + $term_ui.editor.update_view_dim(); + $term_ui.editor.formatter.set_wrap_width($term_ui.editor.view_dim.1); $term_ui.screen.resize(w as usize, h as usize); + should_redraw = true; } - if stop || $term_ui.quit { - break; + // Draw the editor to screen + if should_redraw { + {$draw}; + $term_ui.screen.present(); } + + // Sleep for a small bit so we don't just spin on the CPU + std::thread::sleep(std::time::Duration::from_millis(5)); } }; } -pub struct TermUI<'a> { - inp: termion::input::Events>, +pub struct TermUI { + inp: termion::input::Events, screen: Screen, editor: Editor, width: usize, @@ -77,21 +96,18 @@ enum LoopStatus { Continue, } -impl<'a> TermUI<'a> { - pub fn new<'b>(stdin: &'b mut io::Stdin) -> TermUI<'b> { - TermUI::new_from_editor(stdin, Editor::new(ConsoleLineFormatter::new(4))) +impl TermUI { + pub fn new() -> TermUI { + TermUI::new_from_editor(Editor::new(ConsoleLineFormatter::new(4))) } - pub fn new_from_editor<'b>( - stdin: &'b mut io::Stdin, - ed: Editor, - ) -> TermUI<'b> { + pub fn new_from_editor(ed: Editor) -> TermUI { let (w, h) = termion::terminal_size().unwrap(); let mut editor = ed; editor.update_dim(h as usize - 1, w as usize); TermUI { - inp: stdin.lock().events(), + inp: termion::async_stdin().events(), screen: Screen::new(), editor: editor, width: w as usize, @@ -112,18 +128,17 @@ impl<'a> TermUI<'a> { // Draw draw { - self.editor.update_view_dim(); - self.editor.formatter.set_wrap_width(self.editor.view_dim.1); self.screen.clear(Color::Black); self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1)); }, // Handle input key_press(key) { + let mut state_changed = true; match key { Key::Ctrl('q') => { self.quit = true; - return LoopStatus::Done; + return (LoopStatus::Done, true); } Key::Ctrl('s') => { @@ -192,12 +207,12 @@ impl<'a> TermUI<'a> { self.editor.insert_text_at_cursor(&c.to_string()[..]); } - k => { - println!("{:?}", k); + _ => { + state_changed = false; } } - LoopStatus::Continue + (LoopStatus::Continue, state_changed) } ); } @@ -214,8 +229,6 @@ impl<'a> TermUI<'a> { // Draw draw { - self.editor.update_view_dim(); - self.editor.formatter.set_wrap_width(self.editor.view_dim.1); self.screen.clear(Color::Black); self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1)); for i in 0..self.width { @@ -232,14 +245,15 @@ impl<'a> TermUI<'a> { // Handle input key_press(key) { + let mut state_changed = true; match key { Key::Esc => { cancel = true; - return LoopStatus::Done; + return (LoopStatus::Done, true); } Key::Char('\n') => { - return LoopStatus::Done; + return (LoopStatus::Done, true); } Key::Backspace => { @@ -253,10 +267,12 @@ impl<'a> TermUI<'a> { } } - _ => {} + _ => { + state_changed = false; + } } - return LoopStatus::Continue; + return (LoopStatus::Continue, state_changed); } ); diff --git a/src/term_ui/screen.rs b/src/term_ui/screen.rs index a547124..0477025 100644 --- a/src/term_ui/screen.rs +++ b/src/term_ui/screen.rs @@ -60,6 +60,7 @@ impl Screen { // Double the minimum needed space, because of formatting characters and such. let mut tmp_string = String::with_capacity(self.w * self.h * 2); + tmp_string.push_str(&format!("{}", termion::cursor::Goto(1, 1))); // Write everything to the tmp_string first. for y in 0..self.h { @@ -78,9 +79,10 @@ impl Screen { x += 1; } } + tmp_string.push_str(&format!("{}", termion::cursor::Goto(1, y as u16 + 2))); } - // Then write the tmp_string to screen all at once. + // Write tmp_string to the screen all at once. write!( self.out.borrow_mut(), "{}{}",