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
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();
}

View File

@ -1,7 +1,7 @@
#![allow(dead_code)]
use std;
use std::cmp::min;
use std::io;
use termion;
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) => {
let mut stop = false;
loop {
// Draw the editor to screen
// Draw the editor to screen for the first time
{$draw};
$term_ui.screen.present();
// UI loop
loop {
let mut should_redraw = false;
// Handle input
loop {
match $term_ui.inp.next() {
Some(Ok(Event::Key($key))) => {
let status = || -> LoopStatus {
let (status, state_changed) = || -> (LoopStatus, bool) {
$key_press
}();
should_redraw |= state_changed;
if status == LoopStatus::Done {
stop = true;
// break;
break;
}
}
_ => {
// break;
break;
}
}
}
// Check if we're done
if stop || $term_ui.quit {
break;
}
// Check for screen resize
let (w, h) = termion::terminal_size().unwrap();
@ -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<io::StdinLock<'a>>,
pub struct TermUI {
inp: termion::input::Events<termion::AsyncReader>,
screen: Screen,
editor: Editor<ConsoleLineFormatter>,
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<ConsoleLineFormatter>,
) -> TermUI<'b> {
pub fn new_from_editor(ed: Editor<ConsoleLineFormatter>) -> 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);
}
);

View File

@ -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(),
"{}{}",