aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-04-07 15:48:58 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-04-07 15:48:58 +0300
commited0c051c55e40c1ab3cdc029ba4ca518ee407a1e (patch)
tree3c515192394da2caaca2c63eb93152ed308841b8 /src
parent0276da6f2a44da493d1c198bcc6b5a8b1d2fda44 (diff)
fix: preserve lf in raw terminal input
Diffstat (limited to 'src')
-rw-r--r--src/input/parse.rs5
-rw-r--r--src/input/tests.rs13
-rw-r--r--src/raw_input.rs10
3 files changed, 27 insertions, 1 deletions
diff --git a/src/input/parse.rs b/src/input/parse.rs
index 525119f4..b7b449ae 100644
--- a/src/input/parse.rs
+++ b/src/input/parse.rs
@@ -61,7 +61,10 @@ fn parse_legacy_key_sequence(data: &str) -> Option<TerminalKey> {
}
match data {
- "\r" | "\n" => Some(TerminalKey::new(KeyCode::Enter, KeyModifiers::empty())),
+ // In raw mode, Enter is carriage return. A bare line feed is ambiguous in
+ // terminal input and is commonly used for Ctrl+J or Shift+Enter workarounds.
+ // Preserve LF by letting it fall through to legacy control-byte parsing.
+ "\r" => Some(TerminalKey::new(KeyCode::Enter, KeyModifiers::empty())),
"\t" => Some(TerminalKey::new(KeyCode::Tab, KeyModifiers::empty())),
"\x1b" => Some(TerminalKey::new(KeyCode::Esc, KeyModifiers::empty())),
"\x7f" => Some(TerminalKey::new(KeyCode::Backspace, KeyModifiers::empty())),
diff --git a/src/input/tests.rs b/src/input/tests.rs
index a3c71675..6482b245 100644
--- a/src/input/tests.rs
+++ b/src/input/tests.rs
@@ -462,6 +462,19 @@ fn parse_legacy_ctrl_c_sequence() {
}
#[test]
+fn parse_legacy_lf_sequence_as_ctrl_j() {
+ let key = parse_terminal_key_sequence("\n").unwrap();
+ assert_eq!(key.code, KeyCode::Char('j'));
+ assert_eq!(key.modifiers, KeyModifiers::CONTROL);
+}
+
+#[test]
+fn legacy_lf_roundtrips_as_lf() {
+ let key = parse_terminal_key_sequence("\n").unwrap();
+ assert_eq!(encode_terminal_key(key, KeyboardProtocol::Legacy), b"\n");
+}
+
+#[test]
fn legacy_ctrl_byte_matrix_is_covered() {
for (byte, expected) in [
(b'\x01', 'a'),
diff --git a/src/raw_input.rs b/src/raw_input.rs
index 059791ea..262721c8 100644
--- a/src/raw_input.rs
+++ b/src/raw_input.rs
@@ -530,6 +530,16 @@ mod tests {
assert_eq!(key.modifiers, KeyModifiers::CONTROL);
}
+ #[test]
+ fn parses_raw_lf_as_ctrl_j() {
+ let (RawInputEvent::Key(key), consumed) = extract_one_event(b"\n").unwrap() else {
+ panic!("expected key");
+ };
+ assert_eq!(consumed, 1);
+ assert_eq!(key.code, KeyCode::Char('j'));
+ assert_eq!(key.modifiers, KeyModifiers::CONTROL);
+ }
+
fn assert_fixture_extracts_whole_events(corpus: &str, macos_layout: bool) {
for line in corpus.lines() {
let line = line.trim();