Got interactive responsiveness to terminal resizing working.
This commit is contained in:
parent
c91f1801ad
commit
1bb93aae00
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user