use termion::event::Key;
use ini::Ini;
use strum::IntoEnumIterator;
use std::collections::HashMap;
use std::default::Default;
use std::str::FromStr;
use std::fmt::{Display, Debug};
use crate::fail::{HError, HResult, KeyBindError, ErrorLog};
use crate::widget::Widget;
pub type KbResult<T> = Result<T, KeyBindError>;
#[derive(Clone, Debug)]
pub struct Bindings<T>(HashMap<AnyKey, T>);
impl<T> Bindings<T> {
pub fn get(&self,
key: impl Into<AnyKey>) -> Option<&T> {
self.0.get(&key.into())
}
pub fn insert(&mut self,
key: impl Into<AnyKey>,
value: T) -> Option<T> {
self.0.insert(key.into(), value)
}
pub fn new() -> Self {
Bindings(HashMap::new())
}
}
pub trait Acting
where
Self: Widget,
Self::Action: BindingSection + Debug,
Bindings<Self::Action>: Default,
{
type Action;
fn search_in(&self) -> Bindings<Self::Action>;
fn do_action(&mut self, action: &Self::Action) -> HResult<()>;
fn movement(&mut self, _movement: &Movement) -> HResult<()> {
Err(KeyBindError::MovementUndefined)?
}
fn do_key(&mut self, key: Key) -> HResult<()> {
dbg!("\n");
dbg!("Looking in map: ", self.search_in());
dbg!("for key: ", &key);
let gkey = AnyKey::from(key);
dbg!("as anykey: ", &gkey);
// Moving takes priority
if let Some(movement) = self.get_core()?
.config()
.keybinds
.movement
.get(gkey) {
dbg!("found bind: ", movement);
match self.movement(movement) {
Ok(()) => return Ok(()),
Err(HError::KeyBind(KeyBindError::MovementUndefined)) => {}
Err(e) => Err(e)?
}
}
self.search_in();
let bindings = self.search_in();
if let Some(action) = bindings.get(key) {
dbg!("found bind: ", action);
return self.do_action(action)
} else if let Some(any_key) = gkey.any() {
if let Some(action) = bindings.get(any_key) {
dbg!("found bind: ", action);
let action = action.insert_key_param(key);
dbg!("turned into: ", action);
return self.do_action(dbg!(&action));
}
}
HError::undefined_key(key)
}
}
#[derive(Clone, Debug)]
pub struct KeyBinds {
pub movement: Bindings<Movement>,
pub filebrowser: Bindings<FileBrowserAction>,
pub filelist: Bindings<FileListAction>,
pub tab: Bindings<TabAction>,
pub media: Bindings<MediaAction>,
pub bookmark: Bindings<BookmarkAction>,
pub process: Bindings<ProcessAction>,
pub minibuffer: Bindings<MiniBufferAction>,
pub fold: Bindings<FoldAction