Skip to content

Commit

Permalink
Phonetic Method: Preserve user's selection if the keypress was a punc…
Browse files Browse the repository at this point in the history
…tuation mark (#40)
  • Loading branch information
mominul authored Dec 23, 2023
1 parent c50f1e2 commit 2039b30
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 32 deletions.
12 changes: 10 additions & 2 deletions include/riti.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -280,9 +280,17 @@ RitiContext *riti_context_new_with_config(const Config *ptr);

void riti_context_free(RitiContext *ptr);

/*
Generates suggestion for `key` press.
`modifier`: state of modifier keys
`selection`: previously selected user selection index if available otherwise `0`.
It is used to preserve user's candidate selection if the key is a punctuation character in Phonetic method.
*/
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.
Expand Down
22 changes: 11 additions & 11 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -111,21 +111,21 @@ 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(), ["হেল্প", "🆘"]);

// Change the layout to Fixed layout
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(), ["হীলপ"]);
}
Expand Down
8 changes: 7 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ pub extern "C" fn riti_context_free(ptr: *mut RitiContext) {
riti_free(ptr)
}

/// Generates suggestion for `key` press.
///
/// `modifier`: state of modifier keys
/// `selection`: previously selected user selection index if available otherwise `0`.
/// It is used to preserve user's candidate selection if the key is a punctuation character in Phonetic method.
#[no_mangle]
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))
}
Expand Down
33 changes: 17 additions & 16 deletions src/fixed/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl Method for FixedMethod {
&mut self,
key: u16,
modifier: u8,
_selection: u8,
data: &Data,
config: &Config,
) -> Suggestion {
Expand Down Expand Up @@ -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, ["()"]);
}

Expand All @@ -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\""]);
}

Expand All @@ -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();

Expand Down Expand Up @@ -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();
Expand Down
34 changes: 32 additions & 2 deletions src/phonetic/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,22 @@ 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
if let Suggestion::Full { selection: ref mut sel, .. } = suggestion {
if matches!(character, '.' | '?' | '!' | ',' | ':' | ';' | '-' | '_' | ')' | '}' | ']' | '\'' | '"') {
*sel = selection.into();
}
}

suggestion
}

fn candidate_committed(&mut self, index: usize, config: &Config) {
Expand Down Expand Up @@ -168,6 +179,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() {
Expand All @@ -188,4 +200,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);
}
}

0 comments on commit 2039b30

Please sign in to comment.