1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// nixos-config - My current NixOS configuration
//
// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of my nixos-config.
//
// 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::{fmt::Display, ops::Deref, str::FromStr};
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(Clone, Deserialize, Serialize, Debug, PartialEq, PartialOrd)]
/// What values to use for: `riverctl <command..>`
#[serde(deny_unknown_fields)]
pub struct KeyConfig {
command: Vec<String>,
/// 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> {
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(¤t_key, key_config.clone())
.with_context(|| {
format!(
"Failed to insert mapping {} -> {key_config}",
Keys::from(current_key)
)
})?;
Ok(())
}
let mut out = MapTrie::<KeyConfig>::new();
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))
}
}
impl Display for KeyConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.command.join(" ").as_str())
}
}
#[derive(Debug)]
pub struct KeyMap(MapTrie<KeyConfig>);
impl Display for KeyMap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Deref for KeyMap {
type Target = MapTrie<KeyConfig>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
|