diff options
author | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-02-09 20:41:07 -0500 |
---|---|---|
committer | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-02-09 20:41:07 -0500 |
commit | 35b15cdea61aa7bc36de1700d66b13a8545b6004 (patch) | |
tree | cb7212b02c698a20dd2b4b45a250159f6212992b /src/ui/widgets | |
parent | 621bd8856f8e8e36ce9ff0351dedeff2a4734def (diff) |
move files around, code clean up
Diffstat (limited to 'src/ui/widgets')
-rw-r--r-- | src/ui/widgets/mod.rs | 4 | ||||
-rw-r--r-- | src/ui/widgets/tui_menu.rs | 100 | ||||
-rw-r--r-- | src/ui/widgets/tui_text.rs | 20 | ||||
-rw-r--r-- | src/ui/widgets/tui_textfield.rs | 244 | ||||
-rw-r--r-- | src/ui/widgets/tui_worker.rs | 2 |
5 files changed, 12 insertions, 358 deletions
diff --git a/src/ui/widgets/mod.rs b/src/ui/widgets/mod.rs index 66ad76f..7591073 100644 --- a/src/ui/widgets/mod.rs +++ b/src/ui/widgets/mod.rs @@ -5,17 +5,15 @@ mod tui_menu; mod tui_prompt; mod tui_tab; mod tui_text; -mod tui_textfield; mod tui_topbar; mod tui_worker; pub use self::tui_dirlist::TuiDirList; pub use self::tui_dirlist_detailed::TuiDirListDetailed; pub use self::tui_footer::TuiFooter; -pub use self::tui_menu::{TuiCommandMenu, TuiMenu}; +pub use self::tui_menu::TuiMenu; pub use self::tui_prompt::TuiPrompt; pub use self::tui_tab::TuiTabBar; pub use self::tui_text::TuiMultilineText; -pub use self::tui_textfield::TuiTextField; pub use self::tui_topbar::TuiTopBar; pub use self::tui_worker::TuiWorker; diff --git a/src/ui/widgets/tui_menu.rs b/src/ui/widgets/tui_menu.rs index 16c2cd9..2634662 100644 --- a/src/ui/widgets/tui_menu.rs +++ b/src/ui/widgets/tui_menu.rs @@ -1,105 +1,7 @@ -use std::iter::Iterator; - -use termion::event::{Event, Key}; use tui::buffer::Buffer; use tui::layout::Rect; use tui::style::{Color, Style}; -use tui::widgets::{Block, Borders, Clear, Widget}; - -use crate::commands::{CommandKeybind, KeyCommand}; -use crate::config::JoshutoCommandMapping; -use crate::context::JoshutoContext; -use crate::ui::views::TuiView; -use crate::ui::TuiBackend; -use crate::util::event::JoshutoEvent; -use crate::util::input; -use crate::util::to_string::ToString; - -const BORDER_HEIGHT: usize = 1; -const BOTTOM_MARGIN: usize = 1; - -pub struct TuiCommandMenu; - -impl TuiCommandMenu { - pub fn new() -> Self { - Self {} - } - - pub fn get_input<'a>( - &mut self, - backend: &mut TuiBackend, - context: &mut JoshutoContext, - m: &'a JoshutoCommandMapping, - ) -> Option<&'a KeyCommand> { - let mut map: &JoshutoCommandMapping = &m; - let terminal = backend.terminal_mut(); - context.flush_event(); - - loop { - let _ = terminal.draw(|frame| { - let f_size: Rect = frame.size(); - - { - let view = TuiView::new(&context); - frame.render_widget(view, f_size); - } - - { - // draw menu - let mut display_vec: Vec<String> = map - .as_ref() - .iter() - .map(|(k, v)| format!(" {} {}", k.to_string(), v)) - .collect(); - display_vec.sort(); - let display_str: Vec<&str> = display_vec.iter().map(|v| v.as_str()).collect(); - let display_str_len = display_str.len(); - - let y = if (f_size.height as usize) - < display_str_len + BORDER_HEIGHT + BOTTOM_MARGIN - { - 0 - } else { - f_size.height - - (BORDER_HEIGHT + BOTTOM_MARGIN) as u16 - - display_str_len as u16 - }; - - let menu_rect = Rect { - x: 0, - y, - width: f_size.width, - height: (display_str_len + BORDER_HEIGHT) as u16, - }; - - frame.render_widget(Clear, menu_rect); - frame.render_widget(TuiMenu::new(&display_str), menu_rect); - } - }); - - if let Ok(event) = context.poll_event() { - match event { - JoshutoEvent::Termion(event) => { - match event { - Event::Key(Key::Esc) => return None, - event => match map.as_ref().get(&event) { - Some(CommandKeybind::SimpleKeybind(s)) => { - return Some(s); - } - Some(CommandKeybind::CompositeKeybind(m)) => { - map = m; - } - None => return None, - }, - } - context.flush_event(); - } - event => input::process_noninteractive(event, context), - } - } - } - } -} +use tui::widgets::{Block, Borders, Widget}; pub struct TuiMenu<'a> { options: &'a [&'a str], diff --git a/src/ui/widgets/tui_text.rs b/src/ui/widgets/tui_text.rs index bd6d5fa..6d726c5 100644 --- a/src/ui/widgets/tui_text.rs +++ b/src/ui/widgets/tui_text.rs @@ -1,14 +1,9 @@ use tui::buffer::Buffer; use tui::layout::Rect; use tui::style::{Color, Modifier, Style}; -use tui::text::{Span, Spans}; -use tui::widgets::{Paragraph, Widget, Wrap}; +use tui::widgets::Widget; use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; -use crate::context::JoshutoContext; -use crate::io::FileOp; -use crate::ui::widgets::TuiTopBar; - #[derive(Clone, Debug)] struct IndexInfo { pub index: usize, @@ -40,6 +35,9 @@ impl<'a> TuiMultilineText<'a> { Some((i, c, w)) }; + // TODO: This is a very hacky way of doing it and I would like + // to clean this up more + let mut lines = Vec::with_capacity(s.len() / area_width + 1); let mut start = 0; let mut end = 0; @@ -47,7 +45,7 @@ impl<'a> TuiMultilineText<'a> { for (i, c, w) in s.char_indices().filter_map(filter) { end = i + c.len_utf8(); - if (line_width + w < area_width) { + if line_width + w < area_width { line_width += w; continue; } @@ -59,7 +57,7 @@ impl<'a> TuiMultilineText<'a> { start = end; line_width = 0; } - if (start < end) { + if start < end { lines.push(LineInfo { start, end: end, @@ -72,13 +70,13 @@ impl<'a> TuiMultilineText<'a> { let (row, line_info) = lines .iter() .enumerate() - .find(|(r, li)| li.start <= idx && li.end > idx) + .find(|(_, li)| li.start <= idx && li.end > idx) .unwrap(); let mut s_width = 0; let substr = &s[line_info.start..line_info.end]; for (i, c, w) in substr.char_indices().filter_map(filter) { - if (line_info.start + i <= idx) { + if line_info.start + i <= idx { s_width += w; continue; } @@ -96,7 +94,7 @@ impl<'a> TuiMultilineText<'a> { index_info = Some(IndexInfo { index: idx, x: s_width % area_width, - y: row + 1, + y: row + s_width / area_width, c: ' ', }); } diff --git a/src/ui/widgets/tui_textfield.rs b/src/ui/widgets/tui_textfield.rs deleted file mode 100644 index 6e24083..0000000 --- a/src/ui/widgets/tui_textfield.rs +++ /dev/null @@ -1,244 +0,0 @@ -use rustyline::completion::{Candidate, Completer, FilenameCompleter, Pair}; -use rustyline::line_buffer; - -use termion::event::{Event, Key}; -use tui::layout::Rect; -use tui::style::{Color, Modifier, Style}; -use tui::text::{Span, Spans}; -use tui::widgets::{Block, Borders, Clear, Paragraph, Wrap}; - -use crate::context::JoshutoContext; -use crate::ui::views::TuiView; -use crate::ui::widgets::{TuiMenu, TuiMultilineText}; -use crate::ui::TuiBackend; -use crate::util::event::JoshutoEvent; -use crate::util::input; - -struct CompletionTracker { - pub index: usize, - pub pos: usize, - pub original: String, - pub candidates: Vec<Pair>, -} - -impl CompletionTracker { - pub fn new(pos: usize, candidates: Vec<Pair>, original: String) -> Self { - CompletionTracker { - index: 0, - pos, - original, - candidates, - } - } -} - -pub struct TuiTextField<'a> { - _prompt: &'a str, - _prefix: &'a str, - _suffix: &'a str, - _menu_items: Vec<&'a str>, -} - -impl<'a> TuiTextField<'a> { - pub fn menu_items<I>(&mut self, items: I) -> &mut Self - where - I: Iterator<Item = &'a str>, - { - self._menu_items = items.collect(); - self - } - - pub fn prompt(&mut self, prompt: &'a str) -> &mut Self { - self._prompt = prompt; - self - } - - pub fn prefix(&mut self, prefix: &'a str) -> &mut Self { - self._prefix = prefix; - self - } - - pub fn suffix(&mut self, suffix: &'a str) -> &mut Self { - self._suffix = suffix; - self - } - - pub fn get_input( - &mut self, - backend: &mut TuiBackend, - context: &mut JoshutoContext, - ) -> Option<String> { - context.flush_event(); - - let mut line_buffer = line_buffer::LineBuffer::with_capacity(255); - let completer = FilenameCompleter::new(); - - let mut completion_tracker: Option<CompletionTracker> = None; - - let char_idx = self._prefix.chars().map(|c| c.len_utf8()).sum(); - - line_buffer.insert_str(0, self._suffix); - line_buffer.insert_str(0, self._prefix); - line_buffer.set_pos(char_idx); - - let terminal = backend.terminal_mut(); - - loop { - terminal - .draw(|frame| { - let area: Rect = frame.size(); - if area.height == 0 { - return; - } - { - let mut view = TuiView::new(&context); - view.show_bottom_status = false; - frame.render_widget(view, area); - } - - let cursor_xpos = line_buffer.pos(); - - let area_width = area.width as usize; - let buffer_str = line_buffer.as_str(); - let line_str = format!("{}{}", self._prompt, buffer_str); - let multiline = - TuiMultilineText::new(line_str.as_str(), area_width, Some(cursor_xpos)); - let multiline_height = multiline.len(); - - { - let menu_widget = TuiMenu::new(self._menu_items.as_slice()); - let menu_len = menu_widget.len(); - let menu_y = if menu_len + 1 > area.height as usize { - 0 - } else { - (area.height as usize - menu_len - 1) as u16 - }; - - let menu_rect = Rect { - x: 0, - y: menu_y - multiline_height as u16, - width: area.width, - height: menu_len as u16 + 1, - }; - frame.render_widget(Clear, menu_rect); - frame.render_widget(menu_widget, menu_rect); - } - - let multiline_rect = Rect { - x: 0, - y: area.height - multiline_height as u16, - width: area.width, - height: multiline_height as u16, - }; - - frame.render_widget(Clear, multiline_rect); - frame.render_widget(multiline, multiline_rect); - }) - .unwrap(); - - if let Ok(event) = context.poll_event() { - match event { - JoshutoEvent::Termion(Event::Key(key)) => { - match key { - Key::Backspace => { - if line_buffer.backspace(1) { - completion_tracker.take(); - } - } - Key::Left => { - if line_buffer.move_backward(1) { - completion_tracker.take(); - } - } - Key::Right => { - if line_buffer.move_forward(1) { - completion_tracker.take(); - } - } - Key::Delete => { - if line_buffer.delete(1).is_some() { - completion_tracker.take(); - } - } - Key::Home => { - line_buffer.move_home(); - completion_tracker.take(); - } - Key::End => { - line_buffer.move_end(); - completion_tracker.take(); - } - Key::Up => {} - Key::Down => {} - Key::Esc => { - return None; - } - Key::Char('\t') => { - if completion_tracker.is_none() { - let res = completer - .complete_path(line_buffer.as_str(), line_buffer.pos()); - if let Ok((pos, mut candidates)) = res { - candidates.sort_by(|x, y| { - x.display() - .partial_cmp(y.display()) - .unwrap_or(std::cmp::Ordering::Less) - }); - let ct = CompletionTracker::new( - pos, - candidates, - String::from(line_buffer.as_str()), - ); - completion_tracker = Some(ct); - } - } - - if let Some(ref mut s) = completion_tracker { - if s.index < s.candidates.len() { - let candidate = &s.candidates[s.index]; - completer.update( - &mut line_buffer, - s.pos, - candidate.display(), - ); - s.index += 1; - } - } - } - Key::Char('\n') => { - break; - } - Key::Char(c) => { - if line_buffer.insert(c, 1).is_some() { - completion_tracker.take(); - } - } - _ => {} - } - context.flush_event(); - } - JoshutoEvent::Termion(_) => { - context.flush_event(); - } - event => input::process_noninteractive(event, context), - }; - } - } - if line_buffer.as_str().is_empty() { - None - } else { - let input_string = line_buffer.to_string(); - Some(input_string) - } - } -} - -impl<'a> std::default::Default for TuiTextField<'a> { - fn default() -> Self { - Self { - _prompt: "", - _prefix: "", - _suffix: "", - _menu_items: vec![], - } - } -} diff --git a/src/ui/widgets/tui_worker.rs b/src/ui/widgets/tui_worker.rs index 24f5fdf..cc76cf6 100644 --- a/src/ui/widgets/tui_worker.rs +++ b/src/ui/widgets/tui_worker.rs @@ -1,7 +1,7 @@ use tui::buffer::Buffer; use tui::layout::Rect; use tui::style::{Color, Modifier, Style}; -use tui::widgets::{Paragraph, Widget, Wrap}; +use tui::widgets::Widget; use crate::context::JoshutoContext; use crate::io::FileOp; |