diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-24 13:45:36 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-24 14:05:16 -0500 |
commit | 72111d986965861fa694f8a111b712fdad76b6bc (patch) | |
tree | e26951aee33dccb5986f8861e4594231cfc9d8a4 /src/ui | |
parent | d38dcdbbee44187bdb605dbf9bbf9c6c6d3e4f35 (diff) |
fix open_file_with
- fix event to not consume the first few inputs on switching to a terminal program
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/tui_backend.rs | 24 | ||||
-rw-r--r-- | src/ui/widgets/tui_menu.rs | 7 | ||||
-rw-r--r-- | src/ui/widgets/tui_prompt.rs | 3 | ||||
-rw-r--r-- | src/ui/widgets/tui_textfield.rs | 49 |
4 files changed, 56 insertions, 27 deletions
diff --git a/src/ui/tui_backend.rs b/src/ui/tui_backend.rs index 446d1c0..498e3f6 100644 --- a/src/ui/tui_backend.rs +++ b/src/ui/tui_backend.rs @@ -1,10 +1,13 @@ +use std::io::Write; +use std::io::stdout; + use termion::raw::{IntoRawMode, RawTerminal}; use termion::screen::AlternateScreen; use tui::backend::TermionBackend; use tui::widgets::Widget; pub struct TuiBackend { - pub terminal: tui::Terminal<TermionBackend<AlternateScreen<RawTerminal<std::io::Stdout>>>>, + pub terminal: Option<tui::Terminal<TermionBackend<AlternateScreen<RawTerminal<std::io::Stdout>>>>>, } impl TuiBackend { @@ -14,16 +17,31 @@ impl TuiBackend { let backend = TermionBackend::new(stdout); let mut terminal = tui::Terminal::new(backend)?; terminal.hide_cursor()?; - Ok(Self { terminal }) + Ok(Self { terminal: Some(terminal) }) } pub fn render<W>(&mut self, widget: &mut W) where W: Widget, { - self.terminal.draw(|mut frame| { + self.terminal_mut().draw(|mut frame| { let rect = frame.size(); widget.render(&mut frame, rect); }); } + + pub fn terminal_mut(&mut self) -> &mut tui::Terminal<TermionBackend<AlternateScreen<RawTerminal<std::io::Stdout>>>> { + self.terminal.as_mut().unwrap() + } + + pub fn terminal_drop(&mut self) { + let _ = self.terminal.take(); + stdout().flush(); + } + + pub fn terminal_restore(&mut self) -> std::io::Result<()> { + let mut new_backend = TuiBackend::new()?; + std::mem::swap(&mut self.terminal, &mut new_backend.terminal); + Ok(()) + } } diff --git a/src/ui/widgets/tui_menu.rs b/src/ui/widgets/tui_menu.rs index 9dde1fe..fdd291e 100644 --- a/src/ui/widgets/tui_menu.rs +++ b/src/ui/widgets/tui_menu.rs @@ -31,9 +31,10 @@ impl TuiCommandMenu { m: &'a JoshutoCommandMapping, ) -> Option<&'a Box<dyn JoshutoCommand>> { let mut map: &JoshutoCommandMapping = &m; + let mut terminal = backend.terminal_mut(); loop { - backend.terminal.draw(|mut frame| { + terminal.draw(|mut frame| { let f_size = frame.size(); { @@ -101,6 +102,10 @@ impl<'a> TuiMenu<'a> { pub fn new(options: &'a Vec<&str>) -> Self { Self { options } } + + pub fn len(&self) -> usize { + self.options.len() + } } const LONG_SPACE: &str = " "; diff --git a/src/ui/widgets/tui_prompt.rs b/src/ui/widgets/tui_prompt.rs index 21526f3..c01965a 100644 --- a/src/ui/widgets/tui_prompt.rs +++ b/src/ui/widgets/tui_prompt.rs @@ -20,8 +20,9 @@ impl<'a> TuiPrompt<'a> { } pub fn get_key(&mut self, backend: &mut TuiBackend, context: &JoshutoContext) -> Key { + let mut terminal = backend.terminal_mut(); loop { - backend.terminal.draw(|mut frame| { + terminal.draw(|mut frame| { let f_size = frame.size(); if f_size.height == 0 { return; diff --git a/src/ui/widgets/tui_textfield.rs b/src/ui/widgets/tui_textfield.rs index 9dbbad3..6d89b14 100644 --- a/src/ui/widgets/tui_textfield.rs +++ b/src/ui/widgets/tui_textfield.rs @@ -9,7 +9,7 @@ use tui::backend::Backend; use tui::layout::Rect; use tui::style::{Color, Style}; use tui::widgets::{Block, Borders, List, Paragraph, Text, Widget}; -use unicode_width::UnicodeWidthStr; +use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use crate::context::JoshutoContext; use crate::ui::TuiBackend; @@ -77,25 +77,25 @@ impl<'a> TuiTextField<'a> { ._prefix .char_indices() .last() - .map(|(i, c)| i) + .map(|(i, c)| i + c.width().unwrap_or(0)) .unwrap_or(0); line_buffer.insert_str(0, self._prefix); - line_buffer.insert_str(line_buffer.len(), self._suffix); + line_buffer.insert_str(char_idx, self._suffix); line_buffer.set_pos(char_idx); - backend.terminal.show_cursor(); - let mut cursor_xpos = line_buffer.pos() + 1; + let mut terminal = backend.terminal_mut();; + terminal.show_cursor(); + let mut cursor_xpos = self._prefix.len() + 1; { - let frame = backend.terminal.get_frame(); + let frame = terminal.get_frame(); let f_size = frame.size(); - backend - .terminal + terminal .set_cursor(cursor_xpos as u16, f_size.height - 1); } loop { - backend.terminal.draw(|mut frame| { + terminal.draw(|mut frame| { let f_size = frame.size(); if f_size.height == 0 { return; @@ -107,15 +107,21 @@ impl<'a> TuiTextField<'a> { view.render(&mut frame, f_size); } - let top_rect = Rect { - x: 0, - y: 0, - width: f_size.width, - height: 1, - }; - if let Some(menu) = self._menu.as_mut() { - menu.render(&mut frame, top_rect); + let menu_len = menu.len(); + let menu_y = if menu_len + 1 > f_size.height as usize { + 0 + } else { + (f_size.height as usize - menu_len - 1) as u16 + }; + + let rect = Rect { + x: 0, + y: menu_y, + width: f_size.width, + height: menu_len as u16, + }; + menu.render(&mut frame, rect); } let cmd_prompt_style = Style::default().fg(Color::LightGreen); @@ -170,7 +176,7 @@ impl<'a> TuiTextField<'a> { Event::Input(Key::Up) => {} Event::Input(Key::Down) => {} Event::Input(Key::Esc) => { - backend.terminal.hide_cursor(); + terminal.hide_cursor(); return None; } Event::Input(Key::Char('\t')) => { @@ -213,14 +219,13 @@ impl<'a> TuiTextField<'a> { } cursor_xpos = line_buffer.pos() + 1; { - let frame = backend.terminal.get_frame(); + let frame = terminal.get_frame(); let f_size = frame.size(); - backend - .terminal + terminal .set_cursor(cursor_xpos as u16, f_size.height - 1); } } - backend.terminal.hide_cursor(); + terminal.hide_cursor(); if line_buffer.as_str().is_empty() { None } else { |