Skip to content

Commit 7bfb8d4

Browse files
committed
vt, input: translate \0 as Ctrl+Space
There exists an ambiguous control character in standard 7-bit ASCII terminals, `\0`, which is the traditional encoding for Ctrl+Space and Ctrl+Shift+2 (or Ctrl+@ on US-104 keyboards). ``` Space 0x20 0b00100000 @ 0x40 0b01000000 ^^^^^ control character bits 0b00000 ``` Anyway, edit didn't support it. We also had a bug in the Windows KEY_EVENT parser where we would disregard otherwise acceptable inputs such as `\0` with a scancode indicating that it came from a keypress (such as, well, Ctrl+Space).
1 parent 885ef2e commit 7bfb8d4

3 files changed

Lines changed: 9 additions & 2 deletions

File tree

crates/edit/src/input.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ impl<'input> Iterator for Stream<'_, '_, 'input> {
340340
let key = ch as u32 | 0x40;
341341
return Some(Input::Keyboard(kbmod::CTRL | InputKey::new(key)));
342342
}
343+
' ' => return Some(Input::Keyboard(kbmod::CTRL | vk::SPACE)),
343344
'\x7f' => return Some(Input::Keyboard(vk::BACK)),
344345
_ => {}
345346
},

crates/edit/src/sys/windows.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ pub fn read_stdin(arena: &Arena, mut timeout: time::Duration) -> Option<BString<
335335
Console::KEY_EVENT => {
336336
let event = unsafe { &inp.Event.KeyEvent };
337337
let ch = unsafe { event.uChar.UnicodeChar };
338-
if event.bKeyDown != 0 && ch != 0 {
338+
let sc = event.wVirtualScanCode;
339+
if event.bKeyDown != 0 && (ch != 0 || sc == 0) {
339340
utf16_buf[utf16_buf_len] = MaybeUninit::new(ch);
340341
utf16_buf_len += 1;
341342
}

crates/edit/src/vt.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,12 @@ impl<'input> Stream<'_, 'input> {
172172
self.parser.state = State::Esc;
173173
self.off += 1;
174174
}
175-
c @ (0x00..0x20 | 0x7f) => {
175+
0x00 => {
176+
// Ctrl+Space and Ctrl+Shift+2 both produce ^@, or \0.
177+
self.off += 1;
178+
return Some(Token::Ctrl(' '));
179+
}
180+
c @ (0x01..0x20 | 0x7f) => {
176181
self.off += 1;
177182
return Some(Token::Ctrl(c as char));
178183
}

0 commit comments

Comments
 (0)