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/util | |
parent | f15674eb5c550423b8b7d02ac05bd36a9dec4040 (diff) |
more work on textfield
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/menu.rs | 68 | ||||
-rw-r--r-- | src/util/mod.rs | 2 | ||||
-rw-r--r-- | src/util/textfield.rs | 116 |
3 files changed, 186 insertions, 0 deletions
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/util/textfield.rs b/src/util/textfield.rs new file mode 100644 index 0000000..90f58f1 --- /dev/null +++ b/src/util/textfield.rs @@ -0,0 +1,116 @@ +use std::io::{self, Write}; + +use rustyline::completion::{Candidate, Completer, FilenameCompleter, Pair}; +use rustyline::line_buffer; + +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}; +use crate::window; + +use crate::KEYMAP_T; + +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 TextField<'a> { + backend: &'a mut TuiBackend, + events: &'a Events, +} + +impl<'a> TextField<'a> { + pub fn new(backend: &'a mut TuiBackend, events: &'a Events) -> Self { + Self { backend, events } + } + + pub fn readline(&mut self) -> Option<String> { + let mut input_string = String::with_capacity(64); + 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 = f_size.height; + + let termion_terminal = self.backend.terminal.backend_mut(); + + write!(termion_terminal, "{}{}", Goto(1, txt_y), clear::AfterCursor); + } + + loop { + let f_size = { + let frame = self.backend.terminal.get_frame(); + frame.size() + }; + let txt_y = f_size.height; + + let termion_terminal = self.backend.terminal.backend_mut(); + + write!(termion_terminal, "{}", Goto(1, txt_y)); + + write!( + termion_terminal, + "{}{}", + input_string, + Goto(1 + input_string.width() as u16, txt_y) + ); + + io::stdout().flush().ok(); + + // Handle input + if let Ok(event) = events.next() { + match event { + Event::Input(input) => match input { + Key::Char('\n') => { + break; + } + Key::Esc => { + write!(termion_terminal, "{}{}", Goto(1, txt_y), clear::AfterCursor,); + return None; + } + Key::Backspace => { + input_string.pop(); + } + Key::Char(c) => { + input_string.push(c); + } + _ => {} + }, + _ => {} + } + } + } + eprintln!("You typed: {}", input_string); + Some(input_string) + } +} |