mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
## Why Deserializing keybindings through an untagged enum hides the specific validation error, making invalid `tui.keymap` settings harder to diagnose. ## What changed Deserialize single keybinding strings and lists by value type so validation errors reach the user. Errors now retain the reason a binding is invalid and the affected configuration key, including when loading configuration for `codex mcp list`. ## Testing Add TOML regression tests for unknown keys, invalid chord strokes, and overly long chords in both string and list forms. Add a CLI snapshot test verifying that `codex mcp list` reports the invalid keybinding reason and configuration key. GitOrigin-RevId: 26e3dea93fc43db21e993ea5cf93df53ce93a43e
94 lines
2.7 KiB
Rust
94 lines
2.7 KiB
Rust
use super::KeybindingSpec;
|
|
use super::KeybindingsSpec;
|
|
use super::TuiKeymap;
|
|
use super::normalize_keybinding_spec;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn normalizes_each_stroke_in_a_key_chord() {
|
|
assert_eq!(
|
|
normalize_keybinding_spec(" CONTROL-X Option-Return "),
|
|
Ok("ctrl-x alt-enter".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn deserializes_a_two_stroke_global_key_chord() {
|
|
let actual = toml::from_str::<TuiKeymap>(
|
|
r#"
|
|
[global]
|
|
open_transcript = "ctrl-x ctrl-t"
|
|
"#,
|
|
)
|
|
.expect("two-stroke key chords should deserialize");
|
|
|
|
let expected = TuiKeymap {
|
|
global: super::TuiGlobalKeymap {
|
|
open_transcript: Some(KeybindingsSpec::One(KeybindingSpec(
|
|
"ctrl-x ctrl-t".to_string(),
|
|
))),
|
|
..Default::default()
|
|
},
|
|
..Default::default()
|
|
};
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn keeps_single_keys_and_chords_as_alternative_bindings() {
|
|
let actual = toml::from_str::<TuiKeymap>(
|
|
r#"
|
|
[global]
|
|
open_transcript = ["ctrl-t", "ctrl-x ctrl-t"]
|
|
"#,
|
|
)
|
|
.expect("single keys and key chords should coexist");
|
|
|
|
let expected = TuiKeymap {
|
|
global: super::TuiGlobalKeymap {
|
|
open_transcript: Some(KeybindingsSpec::Many(vec![
|
|
KeybindingSpec("ctrl-t".to_string()),
|
|
KeybindingSpec("ctrl-x ctrl-t".to_string()),
|
|
])),
|
|
..Default::default()
|
|
},
|
|
..Default::default()
|
|
};
|
|
|
|
assert_eq!(actual, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_chords_longer_than_two_strokes() {
|
|
let error = normalize_keybinding_spec("ctrl-x ctrl-s ctrl-t")
|
|
.expect_err("key chords should have a bounded length");
|
|
|
|
assert!(error.contains("at most 2 strokes"), "{error}");
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_an_invalid_second_chord_stroke() {
|
|
let error = normalize_keybinding_spec("ctrl-x ctrl-unknown")
|
|
.expect_err("every key chord stroke should be valid");
|
|
|
|
assert!(error.contains("unknown key"), "{error}");
|
|
}
|
|
|
|
#[test]
|
|
fn preserves_keybinding_validation_errors_when_deserializing_toml() {
|
|
for invalid in ["backslash", "ctrl-x ctrl-unknown", "ctrl-x ctrl-s ctrl-t"] {
|
|
for bindings in [format!("'{invalid}'"), format!("['ctrl-j', '{invalid}']")] {
|
|
let error =
|
|
toml::from_str::<TuiKeymap>(&format!("[editor]\ninsert_newline = {bindings}\n"))
|
|
.expect_err("invalid bindings should retain the validation error");
|
|
|
|
assert_eq!(
|
|
error.message(),
|
|
normalize_keybinding_spec(invalid).unwrap_err()
|
|
);
|
|
assert!(error.to_string().contains("insert_newline"), "{error}");
|
|
}
|
|
}
|
|
}
|