From 9dfd86248d8622e13023c40a80011822f50c2b1b Mon Sep 17 00:00:00 2001 From: Khoa Vo Date: Fri, 26 Jun 2026 15:48:58 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20Telex=20'r'=20(h=E1=BB=8Fi)=20consumed?= =?UTF-8?q?=20as=20tone=20key=20even=20with=20no=20vowel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tone keys (f,s,r,x,j) now only apply when composition has a vowel - Without a vowel, they fall through to normal character append - Fixes 'r' disappearing in words like 'trời', 'trâm', 'trảm' - Added test_telex_r_as_normal_char covering 4 scenarios - Also: 15ms delay between clipboard paste and trailing uinput chars --- engine/src/bamboo.rs | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/engine/src/bamboo.rs b/engine/src/bamboo.rs index b96fbb0..dcb02be 100644 --- a/engine/src/bamboo.rs +++ b/engine/src/bamboo.rs @@ -89,12 +89,18 @@ impl BambooEngine { self.macro_buf.clear(); } - // Check tone keys + // Check tone keys — only apply if composition has a vowel, else treat as normal char if let Some(&(tone_char, _tone_name)) = self.rules.tone_keys.get(&lower) { - return self.apply_tone(tone_char); + let has_vowel = self.composition.iter().any(|t| { + is_vowel(t.mark_applied.unwrap_or(t.base_char)) + }); + if has_vowel { + return self.apply_tone(tone_char); + } + // Fall through: append as normal character } - // Smart "uo" → "ươ" shortcut with flexible backtrack: + // Smart "uo" → "ươ" shortcut with flexible backtrack": // Scan backward through consonants to find the "uo" pair if self.rules.method == InputMethod::Telex && lower == 'w' || self.rules.method == InputMethod::Vni && lower == '7' @@ -123,7 +129,7 @@ impl BambooEngine { } } - // Try mark rules with flexible backtrack (scan up to 3 chars backward) + // Try mark rules with flexible backtrack" (scan up to 3 chars backward) let mark_match = self.find_mark_backtrack(lower); if let Some((idx, pattern, result)) = mark_match { @@ -560,4 +566,31 @@ fn test_telex_gios() { } + + #[test] + fn test_telex_r_as_normal_char() { + let mut e = BambooEngine::new(InputMethod::Telex); + let mut out = String::new(); + for ch in "tr".chars() { + if let Some(o) = e.process_key(ch) { out = o; } + } + assert_eq!(out, "tr"); + out.clear(); e.reset(); + for ch in "traf".chars() { + if let Some(o) = e.process_key(ch) { out = o; } + } + assert_eq!(out, "trà"); + out.clear(); e.reset(); + for ch in "tar".chars() { + if let Some(o) = e.process_key(ch) { out = o; } + } + assert_eq!(out, "tả"); + out.clear(); e.reset(); + for ch in "tramr".chars() { + if let Some(o) = e.process_key(ch) { out = o; } + } + assert_eq!(out, "trảm"); + } + + }