Convert matching system to unicode strings instead of chars. Fix #78

This commit is contained in:
Federico Terzi 2019-10-10 20:53:27 +02:00
parent ebc4cacd27
commit a19b90e50a
5 changed files with 37 additions and 17 deletions

View File

@ -18,12 +18,13 @@
*/ */
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::os::raw::c_void; use std::os::raw::{c_void, c_char};
use crate::event::*; use crate::event::*;
use crate::event::KeyModifier::*; use crate::event::KeyModifier::*;
use crate::bridge::linux::*; use crate::bridge::linux::*;
use std::process::exit; use std::process::exit;
use log::error; use log::error;
use std::ffi::CStr;
#[repr(C)] #[repr(C)]
pub struct LinuxContext { pub struct LinuxContext {
@ -74,14 +75,19 @@ extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const u8, len: i32,
let _self = _self as *mut LinuxContext; let _self = _self as *mut LinuxContext;
if is_modifier == 0 { // Char event if is_modifier == 0 { // Char event
// Convert the received buffer to a character // Convert the received buffer to a string
let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); let c_str = CStr::from_ptr(raw_buffer as (*const c_char));
let r = String::from_utf8_lossy(buffer).chars().nth(0); let char_str = c_str.to_str();
// Send the char through the channel // Send the char through the channel
if let Some(c) = r { match char_str {
let event = Event::Key(KeyEvent::Char(c)); Ok(char_str) => {
let event = Event::Key(KeyEvent::Char(char_str.to_owned()));
(*_self).send_channel.send(event).unwrap(); (*_self).send_channel.send(event).unwrap();
},
Err(e) => {
error!("Unable to receive char: {}",e);
},
} }
}else{ // Modifier event }else{ // Modifier event
let modifier: Option<KeyModifier> = match key_code { let modifier: Option<KeyModifier> = match key_code {

View File

@ -110,7 +110,7 @@ impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIMa
return; return;
} }
self.keyboard_manager.delete_string(m.trigger.len() as i32); self.keyboard_manager.delete_string(m.trigger.chars().count() as i32);
let target_string = if m._has_vars { let target_string = if m._has_vars {
let mut output_map = HashMap::new(); let mut output_map = HashMap::new();

View File

@ -52,7 +52,7 @@ impl From<i32> for ActionType {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum KeyEvent { pub enum KeyEvent {
Char(char), Char(String),
Modifier(KeyModifier) Modifier(KeyModifier)
} }

View File

@ -90,7 +90,7 @@ pub trait MatchReceiver {
} }
pub trait Matcher : KeyEventReceiver { pub trait Matcher : KeyEventReceiver {
fn handle_char(&self, c: char); fn handle_char(&self, c: &str);
fn handle_modifier(&self, m: KeyModifier); fn handle_modifier(&self, m: KeyModifier);
} }
@ -98,7 +98,7 @@ impl <M: Matcher> KeyEventReceiver for M {
fn on_key_event(&self, e: KeyEvent) { fn on_key_event(&self, e: KeyEvent) {
match e { match e {
KeyEvent::Char(c) => { KeyEvent::Char(c) => {
self.handle_char(c); self.handle_char(&c);
}, },
KeyEvent::Modifier(m) => { KeyEvent::Modifier(m) => {
self.handle_modifier(m); self.handle_modifier(m);

View File

@ -35,6 +35,7 @@ pub struct ScrollingMatcher<'a, R: MatchReceiver, M: ConfigManager<'a>> {
struct MatchEntry<'a> { struct MatchEntry<'a> {
start: usize, start: usize,
count: usize,
_match: &'a Match _match: &'a Match
} }
@ -68,7 +69,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> ScrollingMatcher<'a, R, M> {
} }
impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMatcher<'a, R, M> { impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMatcher<'a, R, M> {
fn handle_char(&self, c: char) { fn handle_char(&self, c: &str) {
// if not enabled, avoid any processing // if not enabled, avoid any processing
if !*(self.is_enabled.borrow()) { if !*(self.is_enabled.borrow()) {
return; return;
@ -77,8 +78,12 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa
let mut current_set_queue = self.current_set_queue.borrow_mut(); let mut current_set_queue = self.current_set_queue.borrow_mut();
let new_matches: Vec<MatchEntry> = self.config_manager.matches().iter() let new_matches: Vec<MatchEntry> = self.config_manager.matches().iter()
.filter(|&x| x.trigger.chars().nth(0).unwrap() == c) .filter(|&x| x.trigger.starts_with(c))
.map(|x | MatchEntry{start: 1, _match: &x}) .map(|x | MatchEntry{
start: 1,
count: x.trigger.chars().count(),
_match: &x
})
.collect(); .collect();
// TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup. // TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup.
@ -86,9 +91,18 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa
Some(last_matches) => { Some(last_matches) => {
let mut updated: Vec<MatchEntry> = last_matches.iter() let mut updated: Vec<MatchEntry> = last_matches.iter()
.filter(|&x| { .filter(|&x| {
x._match.trigger[x.start..].chars().nth(0).unwrap() == c let nchar = x._match.trigger.chars().nth(x.start);
if let Some(nchar) = nchar {
c.starts_with(nchar)
}else{
false
}
})
.map(|x | MatchEntry{
start: x.start+1,
count: x.count,
_match: &x._match
}) })
.map(|x | MatchEntry{start: x.start+1, _match: &x._match})
.collect(); .collect();
updated.extend(new_matches); updated.extend(new_matches);
@ -100,7 +114,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa
let mut found_match = None; let mut found_match = None;
for entry in combined_matches.iter() { for entry in combined_matches.iter() {
if entry.start == entry._match.trigger.len() { if entry.start == entry.count {
found_match = Some(entry._match); found_match = Some(entry._match);
break; break;
} }