summaryrefslogtreecommitdiffstats
path: root/src/ui/widgets
diff options
context:
space:
mode:
authorJeff Zhao <jeff.no.zhao@gmail.com>2021-02-09 20:41:07 -0500
committerJeff Zhao <jeff.no.zhao@gmail.com>2021-02-09 20:41:07 -0500
commit35b15cdea61aa7bc36de1700d66b13a8545b6004 (patch)
treecb7212b02c698a20dd2b4b45a250159f6212992b /src/ui/widgets
parent621bd8856f8e8e36ce9ff0351dedeff2a4734def (diff)
move files around, code clean up
Diffstat (limited to 'src/ui/widgets')
-rw-r--r--src/ui/widgets/mod.rs4
-rw-r--r--src/ui/widgets/tui_menu.rs100
-rw-r--r--src/ui/widgets/tui_text.rs20
-rw-r--r--src/ui/widgets/tui_textfield.rs244
-rw-r--r--src/ui/widgets/tui_worker.rs2
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;