diff --git a/src/key.rs b/src/key.rs index 1e94ab9cf..50aafe91d 100644 --- a/src/key.rs +++ b/src/key.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use libc::VERASE; use crate::{ + common::{escape_string, EscapeFlags, EscapeStringStyle}, fallback::fish_wcwidth, reader::TERMINAL_MODE_ON_STARTUP, wchar::prelude::*, @@ -224,6 +225,13 @@ pub(crate) fn canonicalize_key(mut key: Key) -> Result { pub const KEY_SEPARATOR: char = ','; +fn escape_nonprintables(key_name: &wstr) -> WString { + escape_string( + key_name, + EscapeStringStyle::Script(EscapeFlags::NO_PRINTABLES | EscapeFlags::NO_QUOTED), + ) +} + pub(crate) fn parse_keys(value: &wstr) -> Result, WString> { let mut res = vec![]; if value.is_empty() { @@ -267,7 +275,7 @@ pub(crate) fn parse_keys(value: &wstr) -> Result, WString> { return Err(wgettext_fmt!( "unknown modifier '%s' in '%s'", modifier, - full_key_name + escape_nonprintables(full_key_name) )) } } @@ -298,7 +306,10 @@ pub(crate) fn parse_keys(value: &wstr) -> Result, WString> { codepoint, } } else { - return Err(wgettext_fmt!("cannot parse key '%s'", full_key_name)); + return Err(wgettext_fmt!( + "cannot parse key '%s'", + escape_nonprintables(full_key_name) + )); }; res.push(key); } diff --git a/tests/checks/bind.fish b/tests/checks/bind.fish index 14d56da7d..baf7dc683 100644 --- a/tests/checks/bind.fish +++ b/tests/checks/bind.fish @@ -148,4 +148,7 @@ bind \r bind \n 2>&1 # CHECK: bind: No binding found for key 'ctrl-j' +bind _\cx_\ci_\ei_\\_\'_ 'echo foo' +# CHECKERR: bind: cannot parse key '_\cx_\t_\ei_\\_'_' + exit 0