summaryrefslogtreecommitdiffstats
path: root/src/bindings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings.rs')
-rw-r--r--src/bindings.rs154
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!()
+ }
+ }
+
+}
+