diff options
Diffstat (limited to 'src/bindings.rs')
-rw-r--r-- | src/bindings.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/bindings.rs b/src/bindings.rs new file mode 100644 index 0000000..9907bdc --- /dev/null +++ b/src/bindings.rs @@ -0,0 +1,154 @@ +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: ["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| { + 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: ["open", "o"].iter().map(ToString::to_string).collect(), + callback: Callback::from_fn(MainView::add_notmuch_query_layer), + } + ]) +} + +pub const BINDINGS_CALLER: &str = "BINDINGS_CALLER"; + +#[derive(Clone)] +pub struct Bindings(Vec<Binding>); + +impl Bindings { + pub fn new(bs: Vec<Binding>) -> Bindings { + Bindings(bs) + } + + pub fn caller(&self) -> BindingCaller { + BindingCaller::new(self.clone()) + } +} + +#[derive(Clone)] +pub struct Binding { + chars: Vec<String>, + callback: Callback, +} + +impl Binding { + pub fn for_events(chars: Vec<String>, callback: Callback) -> Binding { + Binding { chars, callback } + } +} + +pub struct BindingCaller { + configuration: Bindings, + state: Vec<char> +} + +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<Callback> { + self.configuration + .0 + .iter() + .find(|binding| { + trace!("chars {:?} == state {:?}", binding.chars, self.state); + let state_str = self.state.iter().collect::<String>(); + binding.chars.iter().any(|state| *state == state_str) + }) + .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::<String>()); + 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!() + } + } + +} + |