Got interactive responsiveness to terminal resizing working.

This commit is contained in:
Nathan Vegdahl 2018-01-01 02:30:11 -08:00
parent c91f1801ad
commit 1bb93aae00
3 changed files with 59 additions and 42 deletions

View File

@ -51,7 +51,6 @@ fn main() {
}; };
// Initialize and start UI // Initialize and start UI
let mut stdin = std::io::stdin(); let mut ui = TermUI::new_from_editor(editor);
let mut ui = TermUI::new_from_editor(&mut stdin, editor);
ui.main_ui_loop(); ui.main_ui_loop();
} }

View File

@ -1,7 +1,7 @@
#![allow(dead_code)] #![allow(dead_code)]
use std;
use std::cmp::min; use std::cmp::min;
use std::io;
use termion; use termion;
use termion::event::{Event, Key}; use termion::event::{Event, Key};
@ -24,27 +24,38 @@ macro_rules! ui_loop {
($term_ui:ident, draw $draw:block, key_press($key:ident) $key_press:block) => { ($term_ui:ident, draw $draw:block, key_press($key:ident) $key_press:block) => {
let mut stop = false; let mut stop = false;
loop { // Draw the editor to screen for the first time
// Draw the editor to screen
{$draw}; {$draw};
$term_ui.screen.present(); $term_ui.screen.present();
// UI loop
loop {
let mut should_redraw = false;
// Handle input // Handle input
loop {
match $term_ui.inp.next() { match $term_ui.inp.next() {
Some(Ok(Event::Key($key))) => { Some(Ok(Event::Key($key))) => {
let status = || -> LoopStatus { let (status, state_changed) = || -> (LoopStatus, bool) {
$key_press $key_press
}(); }();
should_redraw |= state_changed;
if status == LoopStatus::Done { if status == LoopStatus::Done {
stop = true; stop = true;
// break; break;
} }
} }
_ => { _ => {
// break; break;
} }
} }
}
// Check if we're done
if stop || $term_ui.quit {
break;
}
// Check for screen resize // Check for screen resize
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
@ -52,18 +63,26 @@ macro_rules! ui_loop {
$term_ui.width = w as usize; $term_ui.width = w as usize;
$term_ui.height = h as usize; $term_ui.height = h as usize;
$term_ui.editor.update_dim($term_ui.height - 1, $term_ui.width); $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); $term_ui.screen.resize(w as usize, h as usize);
should_redraw = true;
} }
if stop || $term_ui.quit { // Draw the editor to screen
break; 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> { pub struct TermUI {
inp: termion::input::Events<io::StdinLock<'a>>, inp: termion::input::Events<termion::AsyncReader>,
screen: Screen, screen: Screen,
editor: Editor<ConsoleLineFormatter>, editor: Editor<ConsoleLineFormatter>,
width: usize, width: usize,
@ -77,21 +96,18 @@ enum LoopStatus {
Continue, Continue,
} }
impl<'a> TermUI<'a> { impl TermUI {
pub fn new<'b>(stdin: &'b mut io::Stdin) -> TermUI<'b> { pub fn new() -> TermUI {
TermUI::new_from_editor(stdin, Editor::new(ConsoleLineFormatter::new(4))) TermUI::new_from_editor(Editor::new(ConsoleLineFormatter::new(4)))
} }
pub fn new_from_editor<'b>( pub fn new_from_editor(ed: Editor<ConsoleLineFormatter>) -> TermUI {
stdin: &'b mut io::Stdin,
ed: Editor<ConsoleLineFormatter>,
) -> TermUI<'b> {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
let mut editor = ed; let mut editor = ed;
editor.update_dim(h as usize - 1, w as usize); editor.update_dim(h as usize - 1, w as usize);
TermUI { TermUI {
inp: stdin.lock().events(), inp: termion::async_stdin().events(),
screen: Screen::new(), screen: Screen::new(),
editor: editor, editor: editor,
width: w as usize, width: w as usize,
@ -112,18 +128,17 @@ impl<'a> TermUI<'a> {
// Draw // Draw
draw { draw {
self.editor.update_view_dim();
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
self.screen.clear(Color::Black); self.screen.clear(Color::Black);
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1)); self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
}, },
// Handle input // Handle input
key_press(key) { key_press(key) {
let mut state_changed = true;
match key { match key {
Key::Ctrl('q') => { Key::Ctrl('q') => {
self.quit = true; self.quit = true;
return LoopStatus::Done; return (LoopStatus::Done, true);
} }
Key::Ctrl('s') => { Key::Ctrl('s') => {
@ -192,12 +207,12 @@ impl<'a> TermUI<'a> {
self.editor.insert_text_at_cursor(&c.to_string()[..]); 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
draw { draw {
self.editor.update_view_dim();
self.editor.formatter.set_wrap_width(self.editor.view_dim.1);
self.screen.clear(Color::Black); self.screen.clear(Color::Black);
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1)); self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
for i in 0..self.width { for i in 0..self.width {
@ -232,14 +245,15 @@ impl<'a> TermUI<'a> {
// Handle input // Handle input
key_press(key) { key_press(key) {
let mut state_changed = true;
match key { match key {
Key::Esc => { Key::Esc => {
cancel = true; cancel = true;
return LoopStatus::Done; return (LoopStatus::Done, true);
} }
Key::Char('\n') => { Key::Char('\n') => {
return LoopStatus::Done; return (LoopStatus::Done, true);
} }
Key::Backspace => { Key::Backspace => {
@ -253,10 +267,12 @@ impl<'a> TermUI<'a> {
} }
} }
_ => {} _ => {
state_changed = false;
}
} }
return LoopStatus::Continue; return (LoopStatus::Continue, state_changed);
} }
); );

View File

@ -60,6 +60,7 @@ impl Screen {
// Double the minimum needed space, because of formatting characters and such. // Double the minimum needed space, because of formatting characters and such.
let mut tmp_string = String::with_capacity(self.w * self.h * 2); 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. // Write everything to the tmp_string first.
for y in 0..self.h { for y in 0..self.h {
@ -78,9 +79,10 @@ impl Screen {
x += 1; 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!( write!(
self.out.borrow_mut(), self.out.borrow_mut(),
"{}{}", "{}{}",