Skip to content

Commit 9d28a92

Browse files
committed
fix(tui): route IME-committed Chinese characters directly to composer instead of paste-burst buffer
1 parent 54151a4 commit 9d28a92

2 files changed

Lines changed: 20 additions & 12 deletions

File tree

crates/tui/src/tui/paste.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,24 @@ pub fn handle_paste_burst_key(app: &mut App, key: &KeyEvent, now: Instant) -> bo
4949
}
5050
KeyCode::Char(c) if !has_ctrl_alt_or_super => {
5151
if !c.is_ascii() {
52+
// IME-committed characters (Chinese, Japanese, Korean)
53+
// arrive as individual KeyCode::Char events, typically with
54+
// tens-of-milliseconds gaps between each committed character.
55+
// Paste-burst buffering would lose characters when the IME
56+
// commits slower than the burst heuristic's timing window.
57+
//
58+
// We still call note_plain_char + extend_window so that:
59+
// 1. The burst timing counter advances for non-IME fast
60+
// typing on terminals without bracketed paste support.
61+
// 2. The Enter-suppression window stays open during a rapid
62+
// non-ASCII sequence, preventing premature submission.
63+
// But the character is inserted directly into the composer
64+
// rather than placed into the paste-burst buffer.
5265
if let Some(pending) = app.paste_burst.flush_before_modified_input() {
5366
app.insert_str(&pending);
5467
}
55-
if app.paste_burst.try_append_char_if_active(c, now) {
56-
return true;
57-
}
58-
if let Some(decision) = app.paste_burst.on_plain_char_no_hold(now) {
59-
return handle_paste_burst_decision(app, decision, c, now);
60-
}
68+
app.paste_burst.note_plain_char(now);
69+
app.paste_burst.extend_window(now);
6170
app.insert_char(c);
6271
return true;
6372
}
@@ -190,10 +199,9 @@ mod tests {
190199
);
191200
}
192201

193-
assert!(app.flush_paste_burst_if_due(
194-
t0 + Duration::from_millis(pasted.chars().count() as u64)
195-
+ crate::tui::paste_burst::PasteBurst::recommended_active_flush_delay()
196-
));
202+
// Non-ASCII characters are now inserted directly into the composer
203+
// rather than buffered by paste burst. The Enter suppression window
204+
// kept the newline from submitting prematurely.
197205
assert_eq!(app.input, pasted);
198206
}
199207

@@ -336,4 +344,4 @@ mod tests {
336344
// contract here).
337345
assert!(app.input.is_empty());
338346
}
339-
}
347+
}

crates/tui/src/tui/paste_burst.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl PasteBurst {
9494
None
9595
}
9696

97-
fn note_plain_char(&mut self, now: Instant) {
97+
pub(crate) fn note_plain_char(&mut self, now: Instant) {
9898
match self.last_plain_char_time {
9999
Some(prev) if now.duration_since(prev) <= PASTE_BURST_CHAR_INTERVAL => {
100100
self.consecutive_plain_char_burst =

0 commit comments

Comments
 (0)