helix
helix copied to clipboard
Improve keymap errors from command typos
Currently, opening helix with a config containing a bad command mapping fails with a cryptic error. For example, say we have a config (bad.toml) with a command name that doesn't exist:
[keys.normal]
b = "buffer_close" # should be ":buffer-close"
When we hx -c bad.toml, we get...
Bad config: data did not match any variant of untagged enum KeyTrie for key
keys.normalat line 1 column 1 Press <ENTER> to continue with default config
This is because of the way that Serde tries to deserialize untagged enums such as helix_term::keymap::KeyTrie. From the Serde docs^1:
Serde will try to match the data against each variant in order and the first one that deserializes successfully is the one returned.
MappableCommand::deserialize fails (returns an Err variant) when a command does not exist. Serde interprets this as the KeyTrie::Leaf variant failing to match and declares that the input data doesn't "match any variant of untagged enum KeyTrie."
Luckily the variants of KeyTrie are orthogonal in structure: we can tell them apart by the type hints from a serde::de::Visitor. This change uses a custom Deserialize implementation along with a Visitor that discerns which variant of the KeyTrie applies. With this change, the above failure becomes:
Bad config: No command named 'buffer_close' for key
keys.normal.bat line 2 column 5 Press <ENTER> to continue with default config
We also provide more explicit information about the expectations on the field. A config with an unexpected type produces a message with that information and the expectation:
[keys.normal]
b = 1
Bad config: invalid type: integer
1, expected a command, list of commands, or sub-keymap for keykeys.normal.bat line 2 column 5 Press <ENTER> to continue with default config