diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-13 21:51:50 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-13 21:51:50 -0500 |
commit | 726a7a424f7ddec97478490a0f3a25005dde45ac (patch) | |
tree | 499e2fad776e46a7a272806fc2bd10aa98e5610e /src | |
parent | f15674eb5c550423b8b7d02ac05bd36a9dec4040 (diff) |
more work on textfield
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/command_line.rs | 2 | ||||
-rw-r--r-- | src/commands/open_file.rs | 2 | ||||
-rw-r--r-- | src/commands/set_mode.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/run.rs | 148 | ||||
-rw-r--r-- | src/util/menu.rs | 68 | ||||
-rw-r--r-- | src/util/mod.rs | 2 | ||||
-rw-r--r-- | src/util/textfield.rs (renamed from src/textfield.rs) | 8 |
8 files changed, 163 insertions, 70 deletions
diff --git a/src/commands/command_line.rs b/src/commands/command_line.rs index 4d3c820..ff3c694 100644 --- a/src/commands/command_line.rs +++ b/src/commands/command_line.rs @@ -1,7 +1,7 @@ use crate::commands::{self, JoshutoCommand, JoshutoRunnable}; use crate::context::JoshutoContext; use crate::error::JoshutoResult; -use crate::textfield::TextField; +use crate::util::textfield::TextField; use crate::ui::TuiBackend; #[derive(Clone, Debug)] diff --git a/src/commands/open_file.rs b/src/commands/open_file.rs index 5335fcd..b1b46d1 100644 --- a/src/commands/open_file.rs +++ b/src/commands/open_file.rs @@ -5,7 +5,7 @@ use crate::config::mimetype::JoshutoMimetypeEntry; use crate::context::JoshutoContext; use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; use crate::history::DirectoryHistory; -use crate::textfield::TextField; +use crate::util::textfield::TextField; use crate::ui::TuiBackend; use crate::MIMETYPE_T; diff --git a/src/commands/set_mode.rs b/src/commands/set_mode.rs index db42147..a84cc80 100644 --- a/src/commands/set_mode.rs +++ b/src/commands/set_mode.rs @@ -2,7 +2,7 @@ use crate::commands::{CursorMoveDown, JoshutoCommand, JoshutoRunnable}; use crate::context::JoshutoContext; use crate::error::JoshutoResult; use crate::fs::JoshutoDirEntry; -use crate::textfield::TextField; +use crate::util::textfield::TextField; use crate::ui::TuiBackend; use crate::unix; diff --git a/src/main.rs b/src/main.rs index 7b70206..ed60083 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,6 @@ mod preview; mod run; mod sort; mod tab; -mod textfield; mod ui; mod unix; mod util; @@ -8,22 +8,18 @@ use crate::context::JoshutoContext; use crate::tab::JoshutoTab; use crate::ui; use crate::util::event::{Event, Events}; +use crate::util::menu::OptionMenu; use crate::window::JoshutoPanel; use crate::window::JoshutoView; fn recurse_get_keycommand<'a>( events: &Events, keymap: &'a JoshutoCommandMapping, + backend: &'a mut ui::TuiBackend ) -> Option<&'a dyn JoshutoCommand> { - let (term_rows, term_cols) = ui::getmaxyx(); - let event = { + let mut menu = OptionMenu::new(backend, events); let keymap_len = keymap.len(); - let win = JoshutoPanel::new( - keymap_len as i32 + 1, - term_cols, - ((term_rows - keymap_len as i32 - 2) as usize, 0), - ); // TODO: format keys better, rather than debug let mut display_vec: Vec<String> = keymap @@ -31,21 +27,22 @@ fn recurse_get_keycommand<'a>( .map(|(k, v)| format!(" {:?}\t{}", k, v)) .collect(); display_vec.sort(); - - win.move_to_top(); - ui::display_menu(&win, &display_vec); - ncurses::doupdate(); + let display_str: Vec<&str> = display_vec + .iter() + .map(|v| v.as_str()) + .collect(); + let result = menu.get_option(&display_str); + eprintln!("{:?}", result); let event = events.next(); event }; - ncurses::doupdate(); let command = match event { Ok(Event::Input(input)) => match input { Key::Esc => None, key @ Key::Char(_) => match keymap.get(&key) { - Some(CommandKeybind::CompositeKeybind(m)) => recurse_get_keycommand(events, &m), + Some(CommandKeybind::CompositeKeybind(m)) => recurse_get_keycommand(events, &m, backend), Some(CommandKeybind::SimpleKeybind(s)) => Some(s.as_ref()), _ => None, }, @@ -53,7 +50,6 @@ fn recurse_get_keycommand<'a>( }, _ => None, }; - ncurses::doupdate(); command } @@ -84,58 +80,30 @@ pub fn run(config_t: JoshutoConfig, keymap_t: JoshutoCommandMapping) { let mut io_handle = None; while !context.exit { /* checking if there are workers that need to be run */ - match io_handle.as_ref() { - None => { - if !context.worker_queue.is_empty() { - let worker = context.worker_queue.pop_front().unwrap(); - io_handle = { - let event_tx = context.events.event_tx.clone(); - let sync_tx = context.events.sync_tx.clone(); - let thread = thread::spawn(move || { - worker.start(); - while let Ok(evt) = worker.recv() { - let _ = event_tx.send(evt); - let _ = sync_tx.send(()); - } - worker.handle.join(); - let _ = event_tx.send(Event::IOWorkerResult); + if !context.worker_queue.is_empty() { + if let None = io_handle.as_ref() { + let worker = context.worker_queue.pop_front().unwrap(); + io_handle = { + let event_tx = context.events.event_tx.clone(); + let sync_tx = context.events.sync_tx.clone(); + let thread = thread::spawn(move || { + worker.start(); + while let Ok(evt) = worker.recv() { + let _ = event_tx.send(evt); let _ = sync_tx.send(()); - }); - Some(thread) - }; - } + } + worker.handle.join(); + let _ = event_tx.send(Event::IOWorkerResult); + let _ = sync_tx.send(()); + }); + Some(thread) + }; } - _ => {} } match context.events.next() { Ok(event) => { match event { - Event::Input(key) => match keymap_t.get(&key) { - Some(CommandKeybind::CompositeKeybind(m)) => { - match recurse_get_keycommand(&context.events, &m) { - Some(command) => { - if let Err(e) = command.execute(&mut context, &mut backend) { - ui::wprint_err(&view.bot_win, e.cause()); - } - } - None => { - ui::wprint_err( - &view.bot_win, - &format!("Unknown keycode: {:?}", key), - ); - } - } - } - Some(CommandKeybind::SimpleKeybind(command)) => { - if let Err(e) = command.execute(&mut context, &mut backend) { - eprintln!("{}", e.cause()); - } - } - None => { - eprintln!("Unknown keycode: {:?}", key); - } - }, Event::IOWorkerProgress(p) => { ui::wprint_err(&view.bot_win, &format!("bytes copied {}", p)); } @@ -149,6 +117,68 @@ pub fn run(config_t: JoshutoConfig, keymap_t: JoshutoCommandMapping) { } io_handle = None; } + Event::Input(key) => match keymap_t.get(&key) { + None => { + eprintln!("Unknown keycode: {:?}", key); + } + Some(CommandKeybind::SimpleKeybind(command)) => { + if let Err(e) = command.execute(&mut context, &mut backend) { + ui::wprint_err(&view.bot_win, e.cause()); + } + } + Some(CommandKeybind::CompositeKeybind(m)) => { + let mut cmd = None; + let mut map: &JoshutoCommandMapping = &m; + + loop { + eprintln!("run loop"); + let event2 = { + let mut menu = OptionMenu::new(&mut backend, &context.events); + + // TODO: format keys better, rather than debug + let mut display_vec: Vec<String> = map + .iter() + .map(|(k, v)| format!(" {:?}\t{}", k, v)) + .collect(); + display_vec.sort(); + let display_str: Vec<&str> = display_vec + .iter() + .map(|v| v.as_str()) + .collect(); + let result = menu.get_option(&display_str); + eprintln!("{:?}", result); + + result + }; + + match event2 { + Some(key) => { + match key { + Key::Esc => { + break; + } + Key::Char(_) => match map.get(&key) { + Some(CommandKeybind::CompositeKeybind(m)) => map = &m, + Some(CommandKeybind::SimpleKeybind(s)) => { + cmd = Some(s.as_ref()); + break; + } + None => break, + }, + _ => {}, + } + } + _ => {} + } + } + eprintln!("cmd: {:#?}", cmd); + if let Some(command) = cmd { + if let Err(e) = command.execute(&mut context, &mut backend) { + ui::wprint_err(&view.bot_win, e.cause()); + } + } + } + } } backend.render(&context); } diff --git a/src/util/menu.rs b/src/util/menu.rs new file mode 100644 index 0000000..a1be30a --- /dev/null +++ b/src/util/menu.rs @@ -0,0 +1,68 @@ +use std::io::{self, Write}; +use std::iter::Iterator; + +use termion::clear; +use termion::cursor::Goto; +use termion::event::Key; +use termion::input::TermRead; +use termion::raw::IntoRawMode; +use termion::screen::AlternateScreen; +use tui::backend::{Backend, TermionBackend}; +use tui::layout::{Constraint, Direction, Layout, Rect}; +use tui::style::{Color, Style}; +use tui::widgets::{Block, Borders, List, Paragraph, Text, Widget}; +use tui::Terminal; +use unicode_width::UnicodeWidthStr; + +use crate::ui::TuiBackend; +use crate::util::event::{Event, Events}; + +pub struct OptionMenu<'a> { + backend: &'a mut TuiBackend, + events: &'a Events +} + +impl<'a> OptionMenu<'a> { + pub fn new(backend: &'a mut TuiBackend, + events: &'a Events) -> Self { + Self { backend, events } + } + + pub fn get_option(&mut self, options: &[&str]) -> Option<Key> { + let events = self.events; + + // initially, clear the line for textfield and move the cursor there as well + let f_size = { + let frame = self.backend.terminal.get_frame(); + frame.size() + }; + let txt_y = if f_size.height < options.len() as u16 { + 0 + } else { + f_size.height - options.len() as u16 + }; + + let termion_terminal = self.backend.terminal.backend_mut(); + + write!(termion_terminal, "{}", Goto(1, txt_y)); + for (i, option) in options.iter().enumerate() { + write!(termion_terminal, "{}{}{}", + option, Goto(1, txt_y + i as u16), clear::AfterCursor); + } + io::stdout().flush().ok(); + + loop { + eprintln!("menu loop"); + let event = events.next(); + if let Ok(event) = event { + match event { + Event::Input(input) => match input { + Key::Esc => return None, + key => return Some(key), + }, + _ => {}, + } + } + } + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 32992c0..492c42f 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,2 +1,4 @@ pub mod event; pub mod key_mapping; +pub mod menu; +pub mod textfield; diff --git a/src/textfield.rs b/src/util/textfield.rs index 675bdbf..90f58f1 100644 --- a/src/textfield.rs +++ b/src/util/textfield.rs @@ -49,11 +49,6 @@ impl<'a> TextField<'a> { pub fn new(backend: &'a mut TuiBackend, events: &'a Events) -> Self { Self { backend, events } } - /* - Paragraph::new(paragraph_contents.iter()) - .wrap(true) - .render(&mut f, Rect { x: 0, y: 0, height: 2, width: f_size.width}); - */ pub fn readline(&mut self) -> Option<String> { let mut input_string = String::with_capacity(64); @@ -69,8 +64,7 @@ impl<'a> TextField<'a> { let termion_terminal = self.backend.terminal.backend_mut(); - write!(termion_terminal, "{}", Goto(1, txt_y)); - write!(termion_terminal, "{}{}", Goto(1, txt_y), clear::AfterCursor,); + write!(termion_terminal, "{}{}", Goto(1, txt_y), clear::AfterCursor); } loop { |