From 1cf28d6a951d555ff84a0780a4d65362c8372f6f Mon Sep 17 00:00:00 2001 From: Mominul Date: Sat, 23 Dec 2023 20:48:52 +0600 Subject: [PATCH] Phonetic Method: Preserve user's selection if the keypress was a punctuation mark --- include/riti.h | 5 +++-- src/context.rs | 22 +++++++++++----------- src/ffi.rs | 3 ++- src/fixed/method.rs | 33 +++++++++++++++++---------------- src/phonetic/method.rs | 38 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 69 insertions(+), 32 deletions(-) diff --git a/include/riti.h b/include/riti.h index 4b6c7b4..a4206ae 100644 --- a/include/riti.h +++ b/include/riti.h @@ -3,7 +3,7 @@ #ifndef RITI_H #define RITI_H -/* Generated with cbindgen:0.23.0 */ +/* Generated with cbindgen:0.26.0 */ /* * Warning, this file is autogenerated by cbindgen. Don't modify this manually. @@ -282,7 +282,8 @@ void riti_context_free(RitiContext *ptr); Suggestion *riti_get_suggestion_for_key(RitiContext *ptr, uint16_t key, - uint8_t modifier); + uint8_t modifier, + uint8_t selection); /* A candidate of the suggestion list was committed. diff --git a/src/context.rs b/src/context.rs index d5d49b2..31dbe33 100644 --- a/src/context.rs +++ b/src/context.rs @@ -21,8 +21,8 @@ impl RitiContext { } /// Get suggestion for key. - pub fn get_suggestion_for_key(&self, key: u16, modifier: u8) -> Suggestion { - self.method.borrow_mut().get_suggestion(key, modifier, &self.data, &self.config) + pub fn get_suggestion_for_key(&self, key: u16, modifier: u8, selection: u8) -> Suggestion { + self.method.borrow_mut().get_suggestion(key, modifier, selection, &self.data, &self.config) } /// A candidate of the suggestion list was committed. @@ -73,7 +73,7 @@ impl RitiContext { } pub(crate) trait Method { - fn get_suggestion(&mut self, key: u16, modifier: u8, data: &Data, config: &Config) -> Suggestion; + fn get_suggestion(&mut self, key: u16, modifier: u8, selection: u8, data: &Data, config: &Config) -> Suggestion; fn candidate_committed(&mut self, index: usize, config: &Config); fn update_engine(&mut self, config: &Config); fn ongoing_input_session(&self) -> bool; @@ -111,10 +111,10 @@ mod tests { let config = get_phonetic_method_defaults(); let mut context = RitiContext::new_with_config(&config); - context.get_suggestion_for_key(VC_H, 0); - context.get_suggestion_for_key(VC_E, 0); - context.get_suggestion_for_key(VC_L, 0); - let suggestion = context.get_suggestion_for_key(VC_P, 0); + context.get_suggestion_for_key(VC_H, 0, 0); + context.get_suggestion_for_key(VC_E, 0, 0); + context.get_suggestion_for_key(VC_L, 0, 0); + let suggestion = context.get_suggestion_for_key(VC_P, 0, 0); context.finish_input_session(); assert_eq!(suggestion.get_suggestions(), ["হেল্প", "🆘"]); @@ -122,10 +122,10 @@ mod tests { let config = get_fixed_method_defaults(); context.update_engine(&config); - context.get_suggestion_for_key(VC_H, 0); - context.get_suggestion_for_key(VC_E, 0); - context.get_suggestion_for_key(VC_L, 0); - let suggestion = context.get_suggestion_for_key(VC_P, 0); + context.get_suggestion_for_key(VC_H, 0, 0); + context.get_suggestion_for_key(VC_E, 0, 0); + context.get_suggestion_for_key(VC_L, 0, 0); + let suggestion = context.get_suggestion_for_key(VC_P, 0, 0); context.finish_input_session(); assert_eq!(suggestion.get_suggestions(), ["হীলপ"]); } diff --git a/src/ffi.rs b/src/ffi.rs index b30667a..512a345 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -37,13 +37,14 @@ pub extern "C" fn riti_get_suggestion_for_key( ptr: *mut RitiContext, key: u16, modifier: u8, + selection: u8, ) -> *mut Suggestion { let context = unsafe { assert!(!ptr.is_null()); &*ptr }; - let suggestion = context.get_suggestion_for_key(key, modifier); + let suggestion = context.get_suggestion_for_key(key, modifier, selection); Box::into_raw(Box::new(suggestion)) } diff --git a/src/fixed/method.rs b/src/fixed/method.rs index 9bf1abb..b8efad7 100644 --- a/src/fixed/method.rs +++ b/src/fixed/method.rs @@ -26,6 +26,7 @@ impl Method for FixedMethod { &mut self, key: u16, modifier: u8, + _selection: u8, data: &Data, config: &Config, ) -> Suggestion { @@ -579,15 +580,15 @@ mod tests { let data = Data::new(&config); config.set_suggestion_include_english(true); - method.get_suggestion(VC_A, 0, &data, &config); - method.get_suggestion(VC_M, 0, &data, &config); - method.get_suggestion(VC_I, 0, &data, &config); + method.get_suggestion(VC_A, 0, 0, &data, &config); + method.get_suggestion(VC_M, 0, 0, &data, &config); + method.get_suggestion(VC_I, 0, 0, &data, &config); assert_eq!(method.typed, "ami"); assert_eq!(method.suggestions, ["আমি", "আমিন", "আমির", "আমিষ", "ami"]); method.finish_input_session(); - method.get_suggestion(VC_PAREN_LEFT, 0, &data, &config); - method.get_suggestion(VC_PAREN_RIGHT, 0, &data, &config); + method.get_suggestion(VC_PAREN_LEFT, 0, 0, &data, &config); + method.get_suggestion(VC_PAREN_RIGHT, 0, 0, &data, &config); assert_eq!(method.suggestions, ["()"]); } @@ -599,16 +600,16 @@ mod tests { config.set_suggestion_include_english(true); config.set_smart_quote(true); - method.get_suggestion(VC_QUOTE, 0, &data, &config); - method.get_suggestion(VC_K, 0, &data, &config); - method.get_suggestion(VC_QUOTE, 0, &data, &config); + method.get_suggestion(VC_QUOTE, 0, 0, &data, &config); + method.get_suggestion(VC_K, 0, 0, &data, &config); + method.get_suggestion(VC_QUOTE, 0, 0, &data, &config); assert_eq!(method.suggestions, ["“ক”", "\"k\""]); method.finish_input_session(); config.set_smart_quote(false); - method.get_suggestion(VC_QUOTE, 0, &data, &config); - method.get_suggestion(VC_K, 0, &data, &config); - method.get_suggestion(VC_QUOTE, 0, &data, &config); + method.get_suggestion(VC_QUOTE, 0, 0, &data, &config); + method.get_suggestion(VC_K, 0, 0, &data, &config); + method.get_suggestion(VC_QUOTE, 0, 0, &data, &config); assert_eq!(method.suggestions, ["\"ক\"", "\"k\""]); } @@ -619,8 +620,8 @@ mod tests { let data = Data::new(&config); config.set_fixed_traditional_kar(false); - method.get_suggestion(VC_SEMICOLON, 0, &data, &config); - method.get_suggestion(VC_PAREN_RIGHT, 0, &data, &config); + method.get_suggestion(VC_SEMICOLON, 0, 0, &data, &config); + method.get_suggestion(VC_PAREN_RIGHT, 0, 0, &data, &config); assert_eq!(method.suggestions, [";)", "😉"]); method.finish_input_session(); @@ -668,9 +669,9 @@ mod tests { config.set_suggestion_include_english(true); config.set_ansi_encoding(true); - method.get_suggestion(VC_A, 0, &data, &config); - method.get_suggestion(VC_M, 0, &data, &config); - method.get_suggestion(VC_I, 0, &data, &config); + method.get_suggestion(VC_A, 0, 0, &data, &config); + method.get_suggestion(VC_M, 0, 0, &data, &config); + method.get_suggestion(VC_I, 0, 0, &data, &config); assert_eq!(method.typed, "ami"); assert_eq!(method.suggestions, ["আমি", "আমিন", "আমির", "আমিষ"]); method.finish_input_session(); diff --git a/src/phonetic/method.rs b/src/phonetic/method.rs index 5e2ff67..0ac698d 100644 --- a/src/phonetic/method.rs +++ b/src/phonetic/method.rs @@ -80,11 +80,26 @@ impl Method for PhoneticMethod { &mut self, key: u16, _modifier: u8, + selection: u8, data: &Data, config: &Config, ) -> Suggestion { - self.buffer.push(keycode_to_char(key)); - self.create_suggestion(data, config) + let character = keycode_to_char(key); + self.buffer.push(character); + let mut suggestion = self.create_suggestion(data, config); + + // Preserve user's selection if the keypress was a punctuation mark + match suggestion { + Suggestion::Full { selection: ref mut sel, .. } => { + if matches!(character, '.' | '?' | '!' | ',' | ':' | ';' | '-' | '_' | ')' | '}' | ']' | '\'' | '"') { + *sel = selection.into(); + } + } + + _ => (), + } + + suggestion } fn candidate_committed(&mut self, index: usize, config: &Config) { @@ -168,6 +183,7 @@ mod tests { use crate::config::get_phonetic_method_defaults; use crate::context::Method; use crate::data::Data; + use crate::keycodes::{VC_COMMA, VC_R}; #[test] fn test_backspace() { @@ -188,4 +204,22 @@ mod tests { }; assert!(method.backspace_event(true, &data, &config).is_empty()); } + + #[test] + fn test_preserve_selection() { + let config = get_phonetic_method_defaults(); + let data = Data::new(&config); + let mut method = PhoneticMethod { + buffer: "coffee".to_string(), + ..Default::default() + }; + + let suggestion = method.get_suggestion(VC_COMMA, 0, 3, &data, &config); + assert_eq!(suggestion.previously_selected_index(), 3); + + method.backspace_event(false, &data, &config); + + let suggestion = method.get_suggestion(VC_R, 0, 3, &data, &config); + assert_eq!(suggestion.previously_selected_index(), 0); + } }