Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions service/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub fn from_event(event: &rdev::Event) -> KeyboardEvent {
.filter(|c| c.is_alphanumeric() || c.is_ascii_punctuation())
.map(|c| Key::Character(c.to_string()));
let (state, key) = match event.event_type {
rdev::EventType::KeyPress(key) => (KeyState::Down, from_key(key)),
rdev::EventType::KeyRelease(key) => (KeyState::Up, from_key(key)),
rdev::EventType::KeyPress(key) => (KeyState::Down, from_key(&key)),
rdev::EventType::KeyRelease(key) => (KeyState::Up, from_key(&key)),
_ => Default::default(),
};

Expand All @@ -28,7 +28,7 @@ pub fn from_event(event: &rdev::Event) -> KeyboardEvent {
}

/// Converts an rdev::Key into a Key.
pub fn from_key(key: rdev::Key) -> Key {
pub fn from_key(key: &rdev::Key) -> Key {
match key {
rdev::Key::Alt => Key::Named(Alt),
rdev::Key::AltGr => Key::Named(AltGraph),
Expand Down
22 changes: 21 additions & 1 deletion service/src/frontend/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct Console {
predicates: Vec<Predicate>,
current_predicate_id: usize,
input: String,
output: String,
idle_state: bool,
tx: Option<Sender<Command>>,
rx: Option<Receiver<Command>>,
Expand All @@ -37,6 +38,7 @@ impl Frontend for Console {
let command = self.rx.as_ref().unwrap().recv()?;
match command {
Command::InputText(input) => self.set_input_text(input.to_owned()),
Command::OutputText(output) => self.set_output_text(output.to_owned()),
Command::PageSize(size) => self.set_max_predicates(size),
Command::State(state) => self.set_state(state),
Command::Predicate(predicate) => self.add_predicate(predicate.to_owned()),
Expand All @@ -61,6 +63,7 @@ impl Frontend for Console {
"_state_" if self.idle_state => {
tx.send(Command::State(false))?;
self.input = String::default();
self.output = String::default();
}
"_exit_" => {
tx.send(Command::End)?;
Expand Down Expand Up @@ -88,6 +91,9 @@ impl Console {
// Input
println!("input: {}", self.input);

// Output
println!("output: {}", self.output);

// Predicates
let page_size = std::cmp::min(self.page_size, self.predicates.len());
println!(
Expand Down Expand Up @@ -120,6 +126,7 @@ impl Console {
self.predicates.clear();
self.current_predicate_id = 0;
self.input = String::default();
self.output = String::default();
}

fn set_max_predicates(&mut self, size: usize) {
Expand All @@ -131,6 +138,10 @@ impl Console {
self.input = text;
}

fn set_output_text(&mut self, text: String) {
self.output = text;
}

fn add_predicate(&mut self, predicate: Predicate) {
predicate
.texts
Expand Down Expand Up @@ -197,7 +208,16 @@ mod tests {
assert_eq!(rx2.recv().unwrap(), Command::NOP);

tx1.send(Command::PageSize(10)).unwrap();

tx1.send(Command::InputText("ngaf3".to_owned())).unwrap();
tx1.send(Command::OutputText("ngɑ̄".to_owned())).unwrap();
tx1.send(Command::Update).unwrap();

tx1.send(Command::Clear).unwrap();
tx1.send(Command::Update).unwrap();

tx1.send(Command::InputText("he".to_owned())).unwrap();
tx1.send(Command::OutputText("he".to_owned())).unwrap();
tx1.send(Command::Predicate(Predicate {
code: "hell".to_owned(),
remaining_code: "llo".to_owned(),
Expand Down Expand Up @@ -226,8 +246,8 @@ mod tests {
can_commit: false,
}))
.unwrap();

tx1.send(Command::Update).unwrap();

tx1.send(Command::SelectPreviousPredicate).unwrap();
tx1.send(Command::SelectedPredicate).unwrap();
assert_eq!(
Expand Down
2 changes: 2 additions & 0 deletions service/src/frontend/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum Command {
Position((f64, f64)),
/// Informs about the current input text.
InputText(String),
/// Informs about the current output text.
OutputText(String),
/// Informs about the max numbers of predicate by page.
PageSize(usize),
/// Whether the backend is in IDLE.
Expand Down
94 changes: 63 additions & 31 deletions service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub use afrim_config::Config;
use afrim_preprocessor::{utils, Command as EventCmd, Preprocessor};
use afrim_translator::Translator;
use anyhow::{Context, Result};
use enigo::{Direction, Enigo, Key, Keyboard};
use enigo::{Enigo, Keyboard};
use frontend::{Command as GUICmd, Frontend};
use rdev::{self, EventType, Key as E_Key};
use std::{rc::Rc, sync::mpsc, thread};
Expand All @@ -17,8 +17,8 @@ pub fn run(
) -> Result<()> {
// State.
let mut is_ctrl_released = true;
let mut is_backspace_pressed = false;
let mut idle = false;
let mut output = String::default();

// Configuration of the afrim.
let memory = utils::build_map(
Expand Down Expand Up @@ -84,6 +84,8 @@ pub fn run(

// We process event.
for event in event_rx.iter() {
let prev_input = preprocessor.get_input();

match event.event_type {
// Handling of idle state.
EventType::KeyPress(E_Key::Pause) => {
Expand All @@ -104,87 +106,117 @@ pub fn run(
EventType::KeyRelease(E_Key::ControlLeft | E_Key::ControlRight) => {
is_ctrl_released = true;
}
EventType::KeyRelease(E_Key::Backspace) => {
is_backspace_pressed = false;
}
_ if idle => (),
// Handling of special functions.
// Select next predicate.
EventType::KeyRelease(E_Key::ShiftRight) if !is_ctrl_released => {
frontend_tx1.send(GUICmd::SelectNextPredicate)?;
}
// Select previous predicate.
EventType::KeyRelease(E_Key::ShiftLeft) if !is_ctrl_released => {
frontend_tx1.send(GUICmd::SelectPreviousPredicate)?;
}
// Commit the selected predicate.
EventType::KeyRelease(E_Key::Space) if !is_ctrl_released => {
rdev::simulate(&EventType::KeyRelease(E_Key::ControlLeft))
.expect("We couldn't cancel the special function key");

frontend_tx1.send(GUICmd::SelectedPredicate)?;
if let GUICmd::Predicate(predicate) = frontend_rx2.recv()? {
preprocessor.commit(
predicate
.texts
.first()
.unwrap_or(&String::default())
.to_owned(),
);
rdev::simulate(&EventType::KeyPress(E_Key::Pause)).unwrap();
keyboard
.text(predicate.texts.first().unwrap_or(&String::default()))
.unwrap();
rdev::simulate(&EventType::KeyRelease(E_Key::Pause)).unwrap();

preprocessor.process(Default::default());
output.clear();
frontend_tx1.send(GUICmd::Clear)?;
}
}
_ if !is_ctrl_released => (),
// Commit the output.
EventType::KeyPress(E_Key::Space) if !prev_input.is_empty() => {
rdev::simulate(&EventType::KeyRelease(E_Key::Space)).unwrap();
rdev::simulate(&EventType::KeyPress(E_Key::Pause)).unwrap();

// Delete the space.
rdev::simulate(&EventType::KeyPress(E_Key::Backspace)).unwrap();
rdev::simulate(&EventType::KeyRelease(E_Key::Backspace)).unwrap();

// Commit
keyboard.text(&output).unwrap();

rdev::simulate(&EventType::KeyRelease(E_Key::Pause)).unwrap();

preprocessor.process(Default::default());
output.clear();
frontend_tx1.send(GUICmd::Clear)?;
}
// GUI events.
EventType::MouseMove { x, y } => {
frontend_tx1.send(GUICmd::Position((x, y)))?;
}
// Process events.
_ => {
if event.event_type == EventType::KeyPress(E_Key::Backspace) {
is_backspace_pressed = true;
}
let (changed, _committed) = preprocessor.process(convert::from_event(&event));
let curr_input = preprocessor.get_input();

if changed {
let input = preprocessor.get_input();
if prev_input.len() < curr_input.len() {
output.push(curr_input.chars().last().unwrap_or_default());

// Cancel the keyboard input.
rdev::simulate(&EventType::KeyPress(E_Key::Pause)).unwrap();
rdev::simulate(&EventType::KeyPress(E_Key::Backspace)).unwrap();
rdev::simulate(&EventType::KeyRelease(E_Key::Backspace)).unwrap();
rdev::simulate(&EventType::KeyRelease(E_Key::Pause)).unwrap();
} else if curr_input.is_empty() {
output.clear();
}

if changed {
frontend_tx1.send(GUICmd::Clear)?;

translator
.translate(&input)
.translate(&curr_input)
.into_iter()
.take(page_size * 2)
.try_for_each(|predicate| -> Result<()> {
if predicate.texts.is_empty() {
} else if auto_commit && predicate.can_commit {
preprocessor.commit(predicate.texts[0].to_owned());

rdev::simulate(&EventType::KeyPress(E_Key::Pause)).unwrap();
keyboard.text(&predicate.texts[0]).unwrap();
rdev::simulate(&EventType::KeyRelease(E_Key::Pause)).unwrap();
} else {
frontend_tx1.send(GUICmd::Predicate(predicate))?;
}

Ok(())
})?;

frontend_tx1.send(GUICmd::InputText(input))?;
frontend_tx1.send(GUICmd::Update)?;
}

// Update frontend.
frontend_tx1.send(GUICmd::InputText(curr_input))?;
frontend_tx1.send(GUICmd::OutputText(output.clone()))?;
frontend_tx1.send(GUICmd::Update)?;
}
}

// Process preprocessor instructions
while let Some(command) = preprocessor.pop_queue() {
match command {
EventCmd::CommitText(text) => {
keyboard.text(&text).unwrap();
output.push_str(&text);
frontend_tx1.send(GUICmd::OutputText(output.clone()))?;
frontend_tx1.send(GUICmd::Update)?;
}
EventCmd::Delete(text) => {
let mut step = text.chars().count();
// Prevent an additional backspace.
if is_backspace_pressed {
keyboard.key(Key::Backspace, Direction::Release).unwrap();
is_backspace_pressed = false;
step -= 1;
}

(0..step).for_each(|_| keyboard.key(Key::Backspace, Direction::Click).unwrap());
let step = text.chars().count();
(0..(if step > 0 { step } else { 1 })).for_each(|_| {
output.pop();
});
}
EventCmd::Pause => {
rdev::simulate(&EventType::KeyPress(E_Key::Pause)).unwrap();
Expand Down
Loading