summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-02-24 13:45:36 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-02-24 14:05:16 -0500
commit72111d986965861fa694f8a111b712fdad76b6bc (patch)
treee26951aee33dccb5986f8861e4594231cfc9d8a4 /src/ui
parentd38dcdbbee44187bdb605dbf9bbf9c6c6d3e4f35 (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.rs24
-rw-r--r--src/ui/widgets/tui_menu.rs7
-rw-r--r--src/ui/widgets/tui_prompt.rs3
-rw-r--r--src/ui/widgets/tui_textfield.rs49
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 {