From b47bcc4967097535b4b740c2e00c752498c3e39f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 16 Jan 2021 11:40:36 +0100 Subject: Implementation of a vim-like bar with bindings processor --- src/bindings.rs | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/bindings.rs (limited to 'src/bindings.rs') diff --git a/src/bindings.rs b/src/bindings.rs new file mode 100644 index 0000000..3b4587c --- /dev/null +++ b/src/bindings.rs @@ -0,0 +1,153 @@ +use anyhow::Result; +use cursive::Cursive; +use cursive::Printer; +use cursive::Rect; +use cursive::View; +use cursive::XY; +use cursive::direction::Direction; +use cursive::event::Callback; +use cursive::event::Event; +use cursive::event::EventResult; +use cursive::event::Key; +use cursive::view::Nameable; +use cursive::view::Selector; +use cursive::view::SizeConstraint; +use cursive::views::NamedView; +use cursive::views::ResizedView; + +use crate::main_view::MainView; + +pub fn get_bindings() -> Bindings { + Bindings(vec![ + Binding { + chars: vec!['q'], + callback: Callback::from_fn(|siv: &mut Cursive| { + trace!("Callback called: q"); + let continue_running = siv.call_on_name(crate::main_view::MAIN_VIEW_NAME, |mv: &mut MainView| { + if mv.tabs().tab_order().len() == 1 { + false + } else { + if let Some(key) = mv.tabs().active_tab().cloned() { + debug!("Removing tab: {}", key); + if let Err(e) = mv.tabs_mut().remove_tab(&key) { + error!("{:?}", e); // TODO do more than just logging + } + debug!("Remove tab"); + } else { + debug!("No tab to remove found."); + } + true + } + }) + .unwrap_or(true); + + if !continue_running { + debug!("Byebye"); + siv.quit(); + } + }) + }, + + Binding { + chars: vec!['o'], + callback: Callback::from_fn(MainView::add_notmuch_query_layer), + } + ]) +} + +pub const BINDINGS_CALLER: &str = "BINDINGS_CALLER"; + +#[derive(Clone)] +pub struct Bindings(Vec); + +impl Bindings { + pub fn new(bs: Vec) -> Bindings { + Bindings(bs) + } + + pub fn caller(&self) -> BindingCaller { + BindingCaller::new(self.clone()) + } +} + +#[derive(Clone)] +pub struct Binding { + chars: Vec, + callback: Callback, +} + +impl Binding { + pub fn for_events(chars: Vec, callback: Callback) -> Binding { + Binding { chars, callback } + } +} + +pub struct BindingCaller { + configuration: Bindings, + state: Vec +} + +impl BindingCaller { + pub fn new(configuration: Bindings) -> Self { + BindingCaller { configuration, state: Vec::new() } + } + + pub fn process(&mut self, chr: char) { + debug!("Char = {}", chr); + self.state.push(chr); + } + + pub fn finalize(&self) -> Option { + self.configuration + .0 + .iter() + .find(|binding| { + trace!("chars {:?} == state {:?}", binding.chars, self.state); + binding.chars == self.state + }) + .map(|binding| { + trace!("Binding found"); + binding.callback.clone() + }) + } + +} + +impl View for BindingCaller { + fn draw(&self, printer: &Printer) { + trace!("Drawing with offset = {:?}", printer.offset); + trace!("Drawing with output_size = {:?}", printer.output_size); + trace!("Drawing with size = {:?}", printer.size); + + { + let line = "-".repeat(printer.output_size.x); + let position = XY { + x: printer.offset.x, + y: printer.output_size.y - 3, + }; + printer.print(position, &line) + } + + { + let line = format!(":{}", self.state.iter().collect::()); + let position = XY { + x: printer.offset.x, + y: printer.output_size.y - 2, + }; + printer.print(position, &line) + } + } + + fn on_event(&mut self, e: Event) -> EventResult { + match e { + Event::Key(Key::Enter) => EventResult::Consumed(self.finalize()), + Event::Char(chr) => { + self.process(chr); + EventResult::Consumed(None) + }, + _ => unimplemented!() + } + } + +} + -- cgit v1.2.3 From 50c4ab8defaac96174e9d5782b032091c6f37a36 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 17 Jan 2021 17:05:29 +0100 Subject: Make bindings able to handle multiple caller strings Signed-off-by: Matthias Beyer --- src/bindings.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/bindings.rs') diff --git a/src/bindings.rs b/src/bindings.rs index 3b4587c..9907bdc 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -20,7 +20,7 @@ use crate::main_view::MainView; pub fn get_bindings() -> Bindings { Bindings(vec![ Binding { - chars: vec!['q'], + chars: ["quit", "q"].iter().map(ToString::to_string).collect(), callback: Callback::from_fn(|siv: &mut Cursive| { trace!("Callback called: q"); let continue_running = siv.call_on_name(crate::main_view::MAIN_VIEW_NAME, |mv: &mut MainView| { @@ -49,7 +49,7 @@ pub fn get_bindings() -> Bindings { }, Binding { - chars: vec!['o'], + chars: ["open", "o"].iter().map(ToString::to_string).collect(), callback: Callback::from_fn(MainView::add_notmuch_query_layer), } ]) @@ -72,12 +72,12 @@ impl Bindings { #[derive(Clone)] pub struct Binding { - chars: Vec, + chars: Vec, callback: Callback, } impl Binding { - pub fn for_events(chars: Vec, callback: Callback) -> Binding { + pub fn for_events(chars: Vec, callback: Callback) -> Binding { Binding { chars, callback } } } @@ -103,7 +103,8 @@ impl BindingCaller { .iter() .find(|binding| { trace!("chars {:?} == state {:?}", binding.chars, self.state); - binding.chars == self.state + let state_str = self.state.iter().collect::(); + binding.chars.iter().any(|state| *state == state_str) }) .map(|binding| { trace!("Binding found"); -- cgit v1.2.3