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 => {
for key in seq {
for (i, key) in seq.iter().enumerate() {
if key.modifiers == Modifiers::ALT {
out.push_utfstr(&char_to_symbol('\x1b'));
out.push_utfstr(&char_to_symbol(if key.codepoint == key::Escape {
'\x1b'
} else {
key.codepoint
}));
out.push_utfstr(&char_to_symbol('\x1b', i == 0));
out.push_utfstr(&char_to_symbol(
if key.codepoint == key::Escape {
'\x1b'
} else {
key.codepoint
},
false,
));
} else {
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 {
streams.out.append(L!("# decoded from: "));
for byte in kevt.seq.chars() {
streams.out.append(char_to_symbol(byte));
for (i, byte) in kevt.seq.chars().enumerate() {
streams.out.append(char_to_symbol(byte, i == 0));
}
streams.out.append(L!("\n"));
}

View File

@@ -377,7 +377,7 @@ fn readb(in_fd: RawFd, blocking: bool) -> ReadbResult {
return ReadbResult::Eof;
}
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.
return ReadbResult::Byte(c);
}
@@ -1646,7 +1646,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if i != 0 {
write!(f, " ")?;
}
write!(f, "{}", char_to_symbol(char::from(c)))?;
write!(f, "{}", char_to_symbol(char::from(c), i == 0))?;
}
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 {
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
/// a `bind` command.
fn must_escape(c: char) -> bool {
"~[]()<>{}*\\?$#;&|'\"".contains(c)
fn must_escape(is_first_in_token: bool, c: char) -> bool {
"[]()<>{}*\\$;&|'\"".contains(c) || (is_first_in_token && "~#".contains(c))
}
fn ascii_printable_to_symbol(buf: &mut WString, c: char) {
if must_escape(c) {
fn ascii_printable_to_symbol(buf: &mut WString, is_first_in_token: bool, c: char) {
if must_escape(is_first_in_token, c) {
sprintf!(=> buf, "\\%c", c);
} else {
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.
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 buf = &mut buff;
if c <= ' ' || c == '\x7F' {
ctrl_to_symbol(buf, c);
} else if c < '\u{80}' {
// 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) {
sprintf!(=> buf, "\\x%02x", byte);
} 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 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
bind \cx\cax 'echo foo'
bind \cx\cax