on master help sign in
Improve keymap errors from command typos (#3931)
6e168b5Michael Davis
helix-term/src/keymap.rs+58−2
@@ -144,14 +144,70 @@ impl DerefMut for KeyTrieNode {
144 }
144 }
145}
145}
146
146
147−#[derive(Debug, Clone, PartialEq, Deserialize)]
147+#[derive(Debug, Clone, PartialEq)]
148−#[serde(untagged)]
149pub enum KeyTrie {
148pub enum KeyTrie {
150 Leaf(MappableCommand),
149 Leaf(MappableCommand),
151 Sequence(Vec<MappableCommand>),
150 Sequence(Vec<MappableCommand>),
152 Node(KeyTrieNode),
151 Node(KeyTrieNode),
153}
152}
154
153
154+impl<'de> Deserialize<'de> for KeyTrie {
155+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
156+ where
157+ D: serde::Deserializer<'de>,
158+ {
159+ deserializer.deserialize_any(KeyTrieVisitor)
160+ }
161+}
162+
163+struct KeyTrieVisitor;
164+
165+impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor {
166+ type Value = KeyTrie;
167+
168+ fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
169+ write!(formatter, "a command, list of commands, or sub-keymap")
170+ }
171+
172+ fn visit_str<E>(self, command: &str) -> Result<Self::Value, E>
173+ where
174+ E: serde::de::Error,
175+ {
176+ command
177+ .parse::<MappableCommand>()
178+ .map(KeyTrie::Leaf)
179+ .map_err(E::custom)
180+ }
181+
182+ fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
183+ where
184+ S: serde::de::SeqAccess<'de>,
185+ {
186+ let mut commands = Vec::new();
187+ while let Some(command) = seq.next_element::<&str>()? {
188+ commands.push(
189+ command
190+ .parse::<MappableCommand>()
191+ .map_err(serde::de::Error::custom)?,
192+ )
193+ }
194+ Ok(KeyTrie::Sequence(commands))
195+ }
196+
197+ fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
198+ where
199+ M: serde::de::MapAccess<'de>,
200+ {
201+ let mut mapping = HashMap::new();
202+ let mut order = Vec::new();
203+ while let Some((key, value)) = map.next_entry::<KeyEvent, KeyTrie>()? {
204+ mapping.insert(key, value);
205+ order.push(key);
206+ }
207+ Ok(KeyTrie::Node(KeyTrieNode::new("", mapping, order)))
208+ }
209+}
210+
155impl KeyTrie {
211impl KeyTrie {
156 pub fn node(&self) -> Option<&KeyTrieNode> {
212 pub fn node(&self) -> Option<&KeyTrieNode> {
157 match *self {
213 match *self {