about summary refs log tree commit diff stats
path: root/pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-29 10:32:13 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-29 10:32:13 +0200
commit3d507acb42554b2551024ee3ca8490c203a1a9f8 (patch)
treececa79f3696cf9eab522be55c07c32e38de5edaf /pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs
parentflake.lock: Update (diff)
downloadnixos-config-3d507acb42554b2551024ee3ca8490c203a1a9f8.zip
pkgs/river-mk-keymap: Improve with key-chord support and which-key interface
Diffstat (limited to 'pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs')
-rw-r--r--pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs105
1 files changed, 69 insertions, 36 deletions
diff --git a/pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs b/pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs
index 2c82ee05..60ed41b8 100644
--- a/pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs
+++ b/pkgs/by-name/ri/river-mk-keymap/src/key_map/mod.rs
@@ -8,40 +8,91 @@
 // You should have received a copy of the License along with this program.
 // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
 
-use std::{collections::HashMap, fmt::Display, ops::Deref, str::FromStr};
+use std::{fmt::Display, ops::Deref, str::FromStr};
 
-use anyhow::Context;
-use keymaps::{key_repr::Key, map_tree::MapTrie};
+use anyhow::{anyhow, bail, Context, Result};
+use keymaps::{
+    key_repr::{Key, Keys},
+    map_tree::MapTrie,
+};
 use serde::{Deserialize, Serialize};
+use serde_json::{Map, Value};
 
 pub mod commands;
 
-#[derive(Deserialize, Serialize, Debug)]
-#[allow(clippy::module_name_repetitions)]
-pub struct RawKeyMap(HashMap<Key, KeyConfig>);
-
 #[derive(Clone, Deserialize, Serialize, Debug, PartialEq, PartialOrd)]
-/// What values to use for: `riverctl <map_mode> <mode> <mods> <key> <command..>`
+/// What values to use for: `riverctl <command..>`
+#[serde(deny_unknown_fields)]
 pub struct KeyConfig {
     command: Vec<String>,
 
-    #[serde(default = "default_mode")]
-    modes: Vec<String>,
-
-    #[serde(default = "MapMode::default")]
-    map_mode: MapMode,
+    /// Whether to allow this key mapping in the “locked” mode.
+    #[serde(default)]
+    allow_locked: bool,
 }
 
 impl FromStr for KeyMap {
     type Err = anyhow::Error;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
-        let raw: RawKeyMap =
-            serde_json::from_str(s).context("Failed to parse the keymap config file as json.")?;
+        fn decode_value(
+            output: &mut MapTrie<KeyConfig>,
+            current_key: Vec<Key>,
+            value: &Value,
+        ) -> Result<()> {
+            let key_config = if let Some(value) = value.as_array() {
+                KeyConfig {
+                    command: value
+                        .iter()
+                        .map(|v| v.as_str().map(ToOwned::to_owned))
+                        .collect::<Option<_>>()
+                        .ok_or(anyhow!("A array contained a non-string value: {value:#?}"))?,
+                    allow_locked: false,
+                }
+            } else if let Some(object) = value.as_object() {
+                if object.contains_key("command") {
+                    serde_json::from_value(value.to_owned())
+                        .with_context(|| format!("Failed to parse key config: {value:#?}"))?
+                } else {
+                    for (key, value) in object {
+                        let mut local_current_key = current_key.clone();
+                        local_current_key.push(
+                            Key::from_str(key)
+                                .with_context(|| format!("Failed to parse key '{key}'"))?,
+                        );
+
+                        decode_value(output, local_current_key, value)?;
+                    }
+                    return Ok(());
+                }
+            } else {
+                bail!("Value ({}) is invalid (not array or object).", value)
+            };
+
+            output
+                .insert(&current_key, key_config.clone())
+                .with_context(|| {
+                    format!(
+                        "Failed to insert mapping {} -> {key_config}",
+                        Keys::from(current_key)
+                    )
+                })?;
+
+            Ok(())
+        }
+
         let mut out = MapTrie::<KeyConfig>::new();
-        for (key, value) in raw.0 {
-            out.insert(&[key], value.clone())
-                .with_context(|| format!("Failed to insert mapping {key} -> {value}"))?;
+
+        let raw: Map<String, Value> =
+            serde_json::from_str(s).context("Failed to parse the keymap config file as json.")?;
+
+        for (key, value) in raw {
+            decode_value(
+                &mut out,
+                vec![Key::from_str(&key)
+                    .with_context(|| format!("Failed to parse key ('{key}')"))?],
+                &value,
+            )?;
         }
 
         Ok(Self(out))
@@ -53,24 +104,6 @@ impl Display for KeyConfig {
     }
 }
 
-fn default_mode() -> Vec<String> {
-    vec!["normal".to_owned()]
-}
-
-#[derive(Copy, Deserialize, Serialize, Debug, Clone, Default, PartialEq, PartialOrd)]
-enum MapMode {
-    #[default]
-    Map,
-    MapMouse,
-    Unmap,
-}
-
-impl Display for MapMode {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        <Self as std::fmt::Debug>::fmt(self, f)
-    }
-}
-
 #[derive(Debug)]
 pub struct KeyMap(MapTrie<KeyConfig>);