Support unbinding a particular key event (#5152)

To remove a default keybinding for a particular edit mode, set the `event: null`:

e.g. to disable screen clearing with Ctrl-L

```
let $config = {keybindings: [{
        modifier: control
        keycode: char_l
        mode: [emacs, vi_normal, vi_insert]
        event: null
      } ]}

```
This commit is contained in:
Stefan Holderbach 2022-04-10 23:54:09 +02:00 committed by GitHub
parent d18f34daa4
commit 625e807a35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 20 deletions

2
Cargo.lock generated
View file

@ -3529,7 +3529,7 @@ dependencies = [
[[package]]
name = "reedline"
version = "0.3.1"
source = "git+https://github.com/nushell/reedline?branch=main#922fab18e0e4dc3320300e30e240b8396a042682"
source = "git+https://github.com/nushell/reedline?branch=main#7ce8b674e060a120c2b110d367aff623c792abcd"
dependencies = [
"chrono",
"crossterm",

View file

@ -698,10 +698,11 @@ fn add_parsed_keybinding(
))
}
};
let event = parse_event(&keybinding.event, config)?;
keybindings.add_binding(modifier, keycode, event);
if let Some(event) = parse_event(&keybinding.event, config)? {
keybindings.add_binding(modifier, keycode, event);
} else {
keybindings.remove_binding(modifier, keycode);
}
Ok(())
}
@ -726,7 +727,7 @@ impl<'config> EventType<'config> {
}
}
fn parse_event(value: &Value, config: &Config) -> Result<ReedlineEvent, ShellError> {
fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>, ShellError> {
match value {
Value::Record { cols, vals, span } => {
match EventType::try_from_columns(cols, vals, span)? {
@ -736,7 +737,8 @@ fn parse_event(value: &Value, config: &Config) -> Result<ReedlineEvent, ShellErr
vals,
config,
span,
),
)
.map(Some),
EventType::Edit(value) => {
let edit = edit_from_record(
value.into_string("", config).to_lowercase().as_str(),
@ -745,16 +747,26 @@ fn parse_event(value: &Value, config: &Config) -> Result<ReedlineEvent, ShellErr
config,
span,
)?;
Ok(ReedlineEvent::Edit(vec![edit]))
Ok(Some(ReedlineEvent::Edit(vec![edit])))
}
EventType::Until(value) => match value {
Value::List { vals, .. } => {
let events = vals
.iter()
.map(|value| parse_event(value, config))
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span()?,
)),
Some(event) => Ok(event),
},
Err(e) => Err(e),
})
.collect::<Result<Vec<ReedlineEvent>, ShellError>>()?;
Ok(ReedlineEvent::UntilFound(events))
Ok(Some(ReedlineEvent::UntilFound(events)))
}
v => Err(ShellError::UnsupportedConfigValue(
"list of events".to_string(),
@ -767,13 +779,24 @@ fn parse_event(value: &Value, config: &Config) -> Result<ReedlineEvent, ShellErr
Value::List { vals, .. } => {
let events = vals
.iter()
.map(|value| parse_event(value, config))
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span()?,
)),
Some(event) => Ok(event),
},
Err(e) => Err(e),
})
.collect::<Result<Vec<ReedlineEvent>, ShellError>>()?;
Ok(ReedlineEvent::Multiple(events))
Ok(Some(ReedlineEvent::Multiple(events)))
}
Value::Nothing { .. } => Ok(None),
v => Err(ShellError::UnsupportedConfigValue(
"record or list of records".to_string(),
"record or list of records, null to unbind key".to_string(),
v.into_abbreviated_string(config),
v.span()?,
)),
@ -965,7 +988,7 @@ mod test {
let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap();
assert_eq!(parsed_event, ReedlineEvent::Enter);
assert_eq!(parsed_event, Some(ReedlineEvent::Enter));
}
#[test]
@ -988,7 +1011,10 @@ mod test {
let config = Config::default();
let parsed_event = parse_event(&event, &config).unwrap();
assert_eq!(parsed_event, ReedlineEvent::Edit(vec![EditCommand::Clear]));
assert_eq!(
parsed_event,
Some(ReedlineEvent::Edit(vec![EditCommand::Clear]))
);
}
#[test]
@ -1019,7 +1045,7 @@ mod test {
let parsed_event = parse_event(&event, &config).unwrap();
assert_eq!(
parsed_event,
ReedlineEvent::Menu("history_menu".to_string())
Some(ReedlineEvent::Menu("history_menu".to_string()))
);
}
@ -1078,10 +1104,10 @@ mod test {
let parsed_event = parse_event(&event, &config).unwrap();
assert_eq!(
parsed_event,
ReedlineEvent::UntilFound(vec![
Some(ReedlineEvent::UntilFound(vec![
ReedlineEvent::Menu("history_menu".to_string()),
ReedlineEvent::Enter,
])
]))
);
}
@ -1129,10 +1155,10 @@ mod test {
let parsed_event = parse_event(&event, &config).unwrap();
assert_eq!(
parsed_event,
ReedlineEvent::Multiple(vec![
Some(ReedlineEvent::Multiple(vec![
ReedlineEvent::Menu("history_menu".to_string()),
ReedlineEvent::Enter,
])
]))
);
}