#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "windows")]
mod windows;
use compact_str::ToCompactString;
use super::state::{ImeEvent, ImeMode, ImeState};
use crate::input::event::Event;
pub trait PlatformIme {
fn enable(&mut self) -> bool;
fn disable(&mut self) -> bool;
fn state(&self) -> &ImeState;
fn state_mut(&mut self) -> &mut ImeState;
fn process_event(&mut self, event: &Event) -> Option<ImeEvent>;
fn set_mode(&mut self, mode: ImeMode);
fn is_active(&self) -> bool {
self.state().active
}
}
#[derive(Debug, Default)]
pub struct TerminalIme {
state: ImeState,
}
impl TerminalIme {
pub fn new() -> Self {
Self::default()
}
}
impl PlatformIme for TerminalIme {
fn enable(&mut self) -> bool {
self.state.activate();
true
}
fn disable(&mut self) -> bool {
self.state.deactivate();
true
}
fn state(&self) -> &ImeState {
&self.state
}
fn state_mut(&mut self) -> &mut ImeState {
&mut self.state
}
fn process_event(&mut self, event: &Event) -> Option<ImeEvent> {
match event {
Event::Paste(text) => {
Some(ImeEvent::Commit(text.clone()))
}
Event::Key(key) => {
if !self.state.active {
return None;
}
if self.state.mode.is_japanese()
|| self.state.mode.is_chinese()
|| self.state.mode.is_korean()
{
if key.is_printable()
&& let crate::input::keyboard::Key::Char(c) = key.key
{
return Some(ImeEvent::Commit(c.to_compact_string()));
}
}
None
}
_ => None,
}
}
fn set_mode(&mut self, mode: ImeMode) {
let old_mode = self.state.mode;
self.state.set_mode(mode);
if old_mode != mode {
if self.state.is_composing() {
self.state.end_composition();
}
}
}
}
pub fn create_ime() -> Box<dyn PlatformIme + Send> {
Box::new(TerminalIme::new())
}
#[cfg(test)]
mod tests {
use compact_str::ToCompactString;
use super::{Event, ImeEvent, ImeMode, PlatformIme, TerminalIme};
#[test]
fn test_terminal_ime_new() {
let ime = TerminalIme::new();
assert!(!ime.is_active());
}
#[test]
fn test_terminal_ime_enable_disable() {
let mut ime = TerminalIme::new();
assert!(ime.enable());
assert!(ime.is_active());
assert!(ime.disable());
assert!(!ime.is_active());
}
#[test]
fn test_terminal_ime_paste() {
let mut ime = TerminalIme::new();
ime.enable();
let event = Event::Paste("テスト".to_compact_string());
let result = ime.process_event(&event);
assert!(matches!(result, Some(ImeEvent::Commit(s)) if s == "テスト"));
}
#[test]
fn test_terminal_ime_mode() {
let mut ime = TerminalIme::new();
ime.set_mode(ImeMode::Hiragana);
assert_eq!(ime.state().mode, ImeMode::Hiragana);
}
}