Skip to content

Commit

Permalink
refactor(keyboard): refine keyboard layout modules
Browse files Browse the repository at this point in the history
  • Loading branch information
kanru committed Jul 23, 2023
1 parent 6c1e756 commit bfdc35b
Show file tree
Hide file tree
Showing 16 changed files with 362 additions and 371 deletions.
45 changes: 20 additions & 25 deletions capi/chewing-internal/src/bopomofo.rs
@@ -1,11 +1,8 @@
use std::{ffi::CString, slice};

use chewing::editor::{
keymap::{
IdentityKeymap, KeyCode, KeyCodeFromQwerty, Keymap, RemappingKeymap, CARPALX, DVORAK,
QWERTY,
},
layout::{
keyboard::{Dvorak, KeyCode, KeyboardLayout, Modifiers, Qgmlwy, Qwerty},
syllable::{
DaiChien26, Et, Et26, GinYieh, Hsu, Ibm, KeyBehavior, KeyboardLayoutCompat, Pinyin,
Standard,
},
Expand All @@ -21,7 +18,7 @@ use super::{
#[repr(C)]
pub struct SyllableEditorWithKeymap {
kb_type: KeyboardLayoutCompat,
keymap: Box<dyn Keymap>,
keyboard: Box<dyn KeyboardLayout>,
editor: Box<dyn SyllableEditor>,
}

Expand All @@ -33,67 +30,67 @@ pub extern "C" fn NewPhoneticEditor(
match kb_type {
KB::Default => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Standard::new()),
}),
KB::Hsu => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Hsu::new()),
}),
KB::Ibm => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Ibm::new()),
}),
KB::GinYieh => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(GinYieh::new()),
}),
KB::Et => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Et::new()),
}),
KB::Et26 => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Et26::new()),
}),
KB::Dvorak => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(RemappingKeymap::new(DVORAK, QWERTY)),
keyboard: Box::new(Dvorak),
editor: Box::new(Standard::new()),
}),
KB::DvorakHsu => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(RemappingKeymap::new(DVORAK, QWERTY)),
keyboard: Box::new(Dvorak),
editor: Box::new(Hsu::new()),
}),
KB::DachenCp26 => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(DaiChien26::new()),
}),
KB::HanyuPinyin => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Pinyin::hanyu()),
}),
KB::ThlPinyin => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Pinyin::thl()),
}),
KB::Mps2Pinyin => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(IdentityKeymap::new(QWERTY)),
keyboard: Box::new(Qwerty),
editor: Box::new(Pinyin::mps2()),
}),
KB::Carpalx => Box::new(SyllableEditorWithKeymap {
kb_type,
keymap: Box::new(RemappingKeymap::new(CARPALX, QWERTY)),
keyboard: Box::new(Qgmlwy),
editor: Box::new(Standard::new()),
}),
}
Expand All @@ -114,17 +111,15 @@ pub extern "C" fn BopomofoPhoInput(pgdata: &mut ChewingData, key: i32) -> KeyBeh
}

let editor_keymap = pgdata.bopomofo_data.editor_with_keymap.as_mut();
let key_code = match (key as u8).as_key_code() {
Some(key_code) => key_code,
None => return KeyBehavior::KeyError,
};
let key_event = editor_keymap.keymap.map_key(key_code);
let key_event = editor_keymap
.keyboard
.map_ascii(key as u8, Modifiers::default());
let result = editor_keymap.editor.key_press(key_event);
let key_buf = editor_keymap.editor.read();

if result == KeyBehavior::Commit {
if key_buf.is_empty() {
return if key_code == KeyCode::Space {
return if key_event.code == KeyCode::Space {
KeyBehavior::KeyError
} else {
KeyBehavior::NoWord
Expand Down
117 changes: 42 additions & 75 deletions src/editor.rs
Expand Up @@ -2,13 +2,13 @@

pub mod composition_editor;
mod estimate;
pub mod keymap;
pub mod layout;
pub mod keyboard;
pub mod syllable;

use std::{fmt::Debug, rc::Rc};

pub use estimate::{EstimateError, SqliteUserFreqEstimate, UserFreqEstimate};
pub use layout::SyllableEditor;
pub use syllable::SyllableEditor;
use tracing::warn;

use crate::{
Expand All @@ -19,8 +19,8 @@ use crate::{

use self::{
composition_editor::CompositionEditor,
keymap::KeyEvent,
layout::{KeyBehavior, Standard},
keyboard::KeyEvent,
syllable::{KeyBehavior, Standard},
};

/// Indicates the state change of the editor.
Expand Down Expand Up @@ -210,11 +210,12 @@ impl<C, D> ChewingEditorState<C, D> for Entering {
_ => (EditorKeyBehavior::Bell, &EnteringSyllable),
},
LanguageMode::English => {
let char_ = evt.code.to_char();
match editor.character_form {
CharacterForm::Halfwidth => editor.composition.push(Symbol::Char(char_)),
CharacterForm::Halfwidth => {
editor.composition.push(Symbol::Char(evt.unicode))
}
CharacterForm::Fullwidth => {
let char_ = full_width_symbol_input(char_).unwrap();
let char_ = full_width_symbol_input(evt.unicode).unwrap();
editor.composition.push(Symbol::Char(char_));
}
}
Expand Down Expand Up @@ -404,40 +405,41 @@ mod tests {
use std::{collections::HashMap, rc::Rc};

use crate::{
conversion::ChewingConversionEngine, dictionary::Dictionary, editor::EditorKeyBehavior,
syl, zhuyin::Bopomofo,
conversion::ChewingConversionEngine,
dictionary::Dictionary,
editor::{keyboard::Modifiers, EditorKeyBehavior},
syl,
zhuyin::Bopomofo,
};

use super::{
keymap::{KeyCode, KeyEvent, KeyIndex},
keyboard::{KeyCode, KeyboardLayout, Qwerty},
BasicEditor, Editor, EditorKeyEvent,
};

#[test]
fn editing_mode_input_bopomofo() {
let keyboard = Qwerty;
let dict: Rc<dyn Dictionary> = Rc::new(HashMap::new());
let conversion_engine = ChewingConversionEngine::new(dict.clone());
let mut editor = Editor::new(conversion_engine, dict);

let key_behavior = editor.key_press(EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K32,
code: KeyCode::H,
}));
let ev = keyboard.map_keycode(KeyCode::H, Modifiers::default());
let key_behavior = editor.key_press(EditorKeyEvent::Default(ev));

assert_eq!(EditorKeyBehavior::Absorb, key_behavior);
assert_eq!(syl![Bopomofo::C], editor.syllable_buffer());

let key_behavior = editor.key_press(EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K34,
code: KeyCode::K,
}));
let ev = keyboard.map_keycode(KeyCode::K, Modifiers::default());
let key_behavior = editor.key_press(EditorKeyEvent::Default(ev));

assert_eq!(EditorKeyBehavior::Absorb, key_behavior);
assert_eq!(syl![Bopomofo::C, Bopomofo::E], editor.syllable_buffer());
}

#[test]
fn editing_mode_input_bopomofo_commit() {
let keyboard = Qwerty;
let dict: Rc<dyn Dictionary> = Rc::new(HashMap::from([(
vec![crate::syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]],
vec![("冊", 100).into()],
Expand All @@ -446,22 +448,13 @@ mod tests {
let conversion_engine = ChewingConversionEngine::new(dict.clone());
let mut editor = Editor::new(conversion_engine, dict);

let keys = [
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K32,
code: KeyCode::H,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K34,
code: KeyCode::K,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K4,
code: KeyCode::N4,
}),
];

let key_behaviors: Vec<_> = keys.iter().map(|&key| editor.key_press(key)).collect();
let keys = [KeyCode::H, KeyCode::K, KeyCode::N4];
let key_behaviors: Vec<_> = keys
.into_iter()
.map(|key| keyboard.map_keycode(key, Modifiers::default()))
.map(|ev| EditorKeyEvent::Default(ev))
.map(|key| editor.key_press(key))
.collect();

assert_eq!(
vec![
Expand All @@ -477,6 +470,7 @@ mod tests {

#[test]
fn editing_mode_input_chinese_to_english_mode() {
let keyboard = Qwerty;
let dict: Rc<dyn Dictionary> = Rc::new(HashMap::from([(
vec![crate::syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]],
vec![("冊", 100).into()],
Expand All @@ -486,23 +480,11 @@ mod tests {
let mut editor = Editor::new(conversion_engine, dict);

let keys = [
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K32,
code: KeyCode::H,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K34,
code: KeyCode::K,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K4,
code: KeyCode::N4,
}),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::H, Default::default())),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::K, Default::default())),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::N4, Default::default())),
EditorKeyEvent::CapsLock,
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K39,
code: KeyCode::Z,
}),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::Z, Default::default())),
];

let key_behaviors: Vec<_> = keys.iter().map(|&key| editor.key_press(key)).collect();
Expand All @@ -523,6 +505,7 @@ mod tests {

#[test]
fn editing_mode_input_english_to_chinese_mode() {
let keyboard = Qwerty;
let dict: Rc<dyn Dictionary> = Rc::new(HashMap::from([(
vec![crate::syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]],
vec![("冊", 100).into()],
Expand All @@ -533,23 +516,11 @@ mod tests {

let keys = [
EditorKeyEvent::CapsLock,
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K39,
code: KeyCode::X,
}),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::X, Default::default())),
EditorKeyEvent::CapsLock,
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K32,
code: KeyCode::H,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K34,
code: KeyCode::K,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K4,
code: KeyCode::N4,
}),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::H, Default::default())),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::K, Default::default())),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::N4, Default::default())),
];

let key_behaviors: Vec<_> = keys.iter().map(|&key| editor.key_press(key)).collect();
Expand All @@ -574,20 +545,16 @@ mod tests {

#[test]
fn editing_mode_input_full_shape_symbol() {
let keyboard = Qwerty;
let dictionary = Rc::new(HashMap::new());
let conversion_engine = ChewingConversionEngine::new(dictionary.clone());
let mut editor = Editor::new(conversion_engine, dictionary);
editor.switch_character_form();

let keys = [
EditorKeyEvent::CapsLock,
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K10,
code: KeyCode::N0,
}),
EditorKeyEvent::Default(KeyEvent {
index: KeyIndex::K11,
code: KeyCode::Minus,
}),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::N0, Default::default())),
EditorKeyEvent::Default(keyboard.map_keycode(KeyCode::Minus, Default::default())),
];

let key_behaviors: Vec<_> = keys.iter().map(|&key| editor.key_press(key)).collect();
Expand Down

0 comments on commit bfdc35b

Please sign in to comment.