mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-03 01:00:48 +00:00
keymap: refuse scope names with outer whitespace, which binding text trims
This commit is contained in:
1 parent
0da8ea8a9f
commit
056a709d0f
2 files changed
+17
-4
No files matched your search
@@ -9,17 +9,21 @@ pub const MAX_SCOPE_NAME: usize = 64;
|
||||
|
||||
const APP: &str = "Application";
|
||||
|
||||
/// The name of a scope. Never empty, at most [`MAX_SCOPE_NAME`] bytes, without `:`.
|
||||
/// The name of a scope. Never empty, at most [`MAX_SCOPE_NAME`] bytes, without `:` or outer
|
||||
/// whitespace.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Scope(String);
|
||||
|
||||
impl Scope {
|
||||
/// `None` for an empty name, one over [`MAX_SCOPE_NAME`] bytes, or one with `:` or a control
|
||||
/// character.
|
||||
/// `None` for an empty name, one over [`MAX_SCOPE_NAME`] bytes, one with `:` or a control
|
||||
/// character, or one with whitespace at either end, which binding text would lose.
|
||||
pub fn new(name: impl Into<String>) -> Option<Scope> {
|
||||
let name = name.into();
|
||||
let ok = !name.is_empty() && name.len() <= MAX_SCOPE_NAME && !name.chars().any(|c| c == ':' || c.is_control());
|
||||
let ok = !name.is_empty()
|
||||
&& name.len() <= MAX_SCOPE_NAME
|
||||
&& name.trim() == name
|
||||
&& !name.chars().any(|c| c == ':' || c.is_control());
|
||||
ok.then_some(Scope(name))
|
||||
}
|
||||
|
||||
|
||||
@@ -375,6 +375,15 @@ fn binding_text_round_trips_for_every_key() {
|
||||
assert_eq!(Binding::parse(": :"), Ok(Binding::new(Trigger::double(Chord::plain(Key::Colon)))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scope_names_with_outer_whitespace_are_refused() {
|
||||
for name in [" Timeline", "Timeline ", "\u{a0}Timeline", ""] {
|
||||
assert_eq!(Scope::new(name), None, "{name:?}");
|
||||
}
|
||||
assert_eq!(Scope::new("Time line").map(|s| s.to_string()).as_deref(), Some("Time line"));
|
||||
assert_eq!(Binding::parse(" Timeline : K").map(|b| b.scope), Ok(Some(scope("Timeline"))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edits_are_refused_when_the_overrides_are_full() {
|
||||
let catalog = vec![app("edit.copy", &["Cmd+C"]), app("edit.duplicate", &["Cmd+D"]), app("edit.cut", &[])];
|
||||
|
||||
Reference in new issue
Block a user