Remove unnecessary escaping for # and ~ inside key name tokens

While at it, don't escape "?", I don't know why 68e167d576 (f-k-r should
use the user's locale, 2016-06-29) did that. Question mark is only special
in combination with redirections.
This commit is contained in:
Johannes Altmanninger
2025-04-01 22:59:36 +02:00
parent 892c970bfa
commit daa692a20b
5 changed files with 32 additions and 19 deletions

View File

@@ -127,17 +127,20 @@ fn list_one(
} }
} }
KeyNameStyle::RawEscapeSequence => { KeyNameStyle::RawEscapeSequence => {
for key in seq { for (i, key) in seq.iter().enumerate() {
if key.modifiers == Modifiers::ALT { if key.modifiers == Modifiers::ALT {
out.push_utfstr(&char_to_symbol('\x1b')); out.push_utfstr(&char_to_symbol('\x1b', i == 0));
out.push_utfstr(&char_to_symbol(if key.codepoint == key::Escape { out.push_utfstr(&char_to_symbol(
'\x1b' if key.codepoint == key::Escape {
} else { '\x1b'
key.codepoint } else {
})); key.codepoint
},
false,
));
} else { } else {
assert!(key.modifiers.is_none()); assert!(key.modifiers.is_none());
out.push_utfstr(&char_to_symbol(key.codepoint)); out.push_utfstr(&char_to_symbol(key.codepoint, i == 0));
} }
} }
} }

View File

@@ -92,8 +92,8 @@ fn process_input(streams: &mut IoStreams, continuous_mode: bool, verbose: bool)
}; };
if verbose { if verbose {
streams.out.append(L!("# decoded from: ")); streams.out.append(L!("# decoded from: "));
for byte in kevt.seq.chars() { for (i, byte) in kevt.seq.chars().enumerate() {
streams.out.append(char_to_symbol(byte)); streams.out.append(char_to_symbol(byte, i == 0));
} }
streams.out.append(L!("\n")); streams.out.append(L!("\n"));
} }

View File

@@ -377,7 +377,7 @@ fn readb(in_fd: RawFd, blocking: bool) -> ReadbResult {
return ReadbResult::Eof; return ReadbResult::Eof;
} }
let c = arr[0]; let c = arr[0];
FLOG!(reader, "Read byte", char_to_symbol(char::from(c))); FLOG!(reader, "Read byte", char_to_symbol(char::from(c), true));
// The common path is to return a u8. // The common path is to return a u8.
return ReadbResult::Byte(c); return ReadbResult::Byte(c);
} }
@@ -1646,7 +1646,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if i != 0 { if i != 0 {
write!(f, " ")?; write!(f, " ")?;
} }
write!(f, "{}", char_to_symbol(char::from(c)))?; write!(f, "{}", char_to_symbol(char::from(c), i == 0))?;
} }
Ok(()) Ok(())
} }

View File

@@ -416,7 +416,8 @@ fn from(key: Key) -> Self {
) )
}) })
}); });
let mut res = name.unwrap_or_else(|| char_to_symbol(key.codepoint)); let mut res =
name.unwrap_or_else(|| char_to_symbol(key.codepoint, key.modifiers.is_none()));
if key.modifiers.shift { if key.modifiers.shift {
res.insert_utfstr(0, L!("shift-")); res.insert_utfstr(0, L!("shift-"));
@@ -453,12 +454,12 @@ fn ctrl_to_symbol(buf: &mut WString, c: char) {
/// Return true if the character must be escaped when used in the sequence of chars to be bound in /// Return true if the character must be escaped when used in the sequence of chars to be bound in
/// a `bind` command. /// a `bind` command.
fn must_escape(c: char) -> bool { fn must_escape(is_first_in_token: bool, c: char) -> bool {
"~[]()<>{}*\\?$#;&|'\"".contains(c) "[]()<>{}*\\$;&|'\"".contains(c) || (is_first_in_token && "~#".contains(c))
} }
fn ascii_printable_to_symbol(buf: &mut WString, c: char) { fn ascii_printable_to_symbol(buf: &mut WString, is_first_in_token: bool, c: char) {
if must_escape(c) { if must_escape(is_first_in_token, c) {
sprintf!(=> buf, "\\%c", c); sprintf!(=> buf, "\\%c", c);
} else { } else {
sprintf!(=> buf, "%c", c); sprintf!(=> buf, "%c", c);
@@ -466,14 +467,14 @@ fn ascii_printable_to_symbol(buf: &mut WString, c: char) {
} }
/// Convert a wide-char to a symbol that can be used in our output. /// Convert a wide-char to a symbol that can be used in our output.
pub fn char_to_symbol(c: char) -> WString { pub fn char_to_symbol(c: char, is_first_in_token: bool) -> WString {
let mut buff = WString::new(); let mut buff = WString::new();
let buf = &mut buff; let buf = &mut buff;
if c <= ' ' || c == '\x7F' { if c <= ' ' || c == '\x7F' {
ctrl_to_symbol(buf, c); ctrl_to_symbol(buf, c);
} else if c < '\u{80}' { } else if c < '\u{80}' {
// ASCII characters that are not control characters // ASCII characters that are not control characters
ascii_printable_to_symbol(buf, c); ascii_printable_to_symbol(buf, is_first_in_token, c);
} else if let Some(byte) = decode_byte_from_char(c) { } else if let Some(byte) = decode_byte_from_char(c) {
sprintf!(=> buf, "\\x%02x", byte); sprintf!(=> buf, "\\x%02x", byte);
} else if ('\u{e000}'..='\u{f8ff}').contains(&c) { } else if ('\u{e000}'..='\u{f8ff}').contains(&c) {

View File

@@ -120,6 +120,15 @@ bind | string match -v '*\e\\[*'
# CHECK: bind -M bind_mode ctrl-x true # CHECK: bind -M bind_mode ctrl-x true
# CHECK: bind tab 'echo banana' # CHECK: bind tab 'echo banana'
bind ctrl-#
bind alt-\#
bind super-ctrl-~
bind super-alt-\~
# CHECKERR: bind: No binding found for key 'ctrl-#'
# CHECKERR: bind: No binding found for key 'alt-#'
# CHECKERR: bind: No binding found for key 'super-ctrl-~'
# CHECKERR: bind: No binding found for key 'super-alt-~'
# Legacy # Legacy
bind \cx\cax 'echo foo' bind \cx\cax 'echo foo'
bind \cx\cax bind \cx\cax