From 2d27e9950d059c0a55a4960d2500c8f332848a31 Mon Sep 17 00:00:00 2001 From: Nick Dowsett Date: Fri, 29 Nov 2024 07:22:51 +0800 Subject: [PATCH] continue refactor --- youtui/src/config/keybinds.rs | 202 ++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 youtui/src/config/keybinds.rs diff --git a/youtui/src/config/keybinds.rs b/youtui/src/config/keybinds.rs new file mode 100644 index 0000000..0051e25 --- /dev/null +++ b/youtui/src/config/keybinds.rs @@ -0,0 +1,202 @@ +use std::{collections::HashMap, convert::Infallible, str::FromStr}; + +use serde::{Deserialize, Serialize}; + +use crate::app::keycommand::Keybind; + +#[derive(Debug)] +pub struct YoutuiKeymap { + pub global: HashMap>, + pub playlist: HashMap>, + pub browser: HashMap>, + pub browser_artists: HashMap>, + pub browser_search: HashMap>, + pub browser_songs: HashMap>, + pub help: HashMap>, + pub sort: HashMap>, + pub filter: HashMap>, + pub text_entry: HashMap>, + pub list: HashMap>, + pub log: HashMap>, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct YoutuiKeymapIR { + pub global: HashMap, + pub playlist: HashMap, + pub browser: HashMap, + pub browser_artists: HashMap, + pub browser_search: HashMap, + pub browser_songs: HashMap, + pub help: HashMap, + pub sort: HashMap, + pub filter: HashMap, + pub text_entry: HashMap, + pub list: HashMap, + pub log: HashMap, +} + +impl TryFrom for YoutuiKeymap { + type Error = String; + fn try_from(value: YoutuiKeymapIR) -> std::result::Result { + let YoutuiKeymapIR { + global, + playlist, + browser, + browser_artists, + browser_search, + browser_songs, + help, + sort, + filter, + text_entry, + list, + log, + } = value; + Ok(Self { + global: global + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + playlist: playlist + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + browser: browser + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + browser_artists: browser_artists + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + browser_search: browser_search + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + browser_songs: browser_songs + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + help: help + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + sort: sort + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + filter: filter + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + text_entry: text_entry + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + list: list + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + log: log + .into_iter() + .map(|(k, v)| Ok((k, v.try_into()?))) + .collect::, String>>()?, + }) + } +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct YoutuiModeNames { + global: HashMap, + playlist: HashMap, + browser: HashMap, + browser_artists: HashMap, + browser_search: HashMap, + browser_songs: HashMap, + help: HashMap, + sort: HashMap, + filter: HashMap, + text_entry: HashMap, + list: HashMap, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum KeyEnumString { + #[serde(deserialize_with = "super::core::string_or_struct")] + Key(KeyEnumKey), + Mode(HashMap), +} + +#[derive(Debug)] +pub enum KeyEnum { + Key(KeyEnumKey), + Mode(HashMap>), +} + +impl TryFrom for KeyEnum { + type Error = String; + fn try_from(value: KeyEnumString) -> std::result::Result { + let new: KeyEnum = match value { + KeyEnumString::Key(k) => KeyEnum::Key(k.try_map(TryInto::try_into)?), + KeyEnumString::Mode(m) => KeyEnum::Mode( + m.into_iter() + .map(|(k, a)| Ok::<_, String>((k, KeyEnum::::try_from(a)?))) + .collect::>()?, + ), + }; + Ok(new) + } +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct KeyEnumKey { + // Consider - can there be multiple actions? + // Consider - can an action access global commands? Or commands from another component? + // Consider - case where component has list and help keybinds, but some keybinds share a + // mode. What happens here. + pub action: A, + #[serde(default)] + pub value: usize, + #[serde(default)] + pub visibility: CommandVisibility, +} + +impl KeyEnumKey { + fn try_map( + self, + f: impl FnOnce(A) -> std::result::Result, + ) -> std::result::Result, E> { + let Self { + action, + value, + visibility, + } = self; + Ok(KeyEnumKey { + action: f(action)?, + value, + visibility, + }) + } +} + +impl FromStr for KeyEnumKey { + type Err = Infallible; + fn from_str(s: &str) -> std::result::Result { + Ok(KeyEnumKey { + action: s.to_string(), + value: Default::default(), + visibility: Default::default(), + }) + } +} + +#[derive(PartialEq, Debug, Serialize, Deserialize)] +enum ModeNameEnum { + Submode(HashMap), + #[serde(untagged)] + Name(String), +}