Skip to content

Commit

Permalink
feat: tilde expand && improve error handling
Browse files Browse the repository at this point in the history
- expand tilde to home_dir
- remove unnecessary Box<dyn Error>
- log error in client side
  • Loading branch information
wlh320 committed Feb 7, 2023
1 parent ebfb0bc commit a4f4211
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ serde_json = "1.0.91"
directories = "4.0.1"
lazy_static = "1.4.0"
ouroboros = "0.15.5"
thiserror = "1.0.38"

[features]
default = []
Expand Down
20 changes: 13 additions & 7 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ pub struct InputResult {
pub select: Option<usize>,
}

impl Default for InputResult {
fn default() -> Self {
InputResult {
is_new: true,
select: None,
}
}
}

impl InputState {
/// check if cached input is prefix or suffix of current input
/// return diff result: Add / Delete / New
Expand All @@ -64,14 +73,11 @@ impl InputState {
new_offset: usize,
new_input: &Input,
rime: &Rime,
) -> Result<InputResult, Box<dyn std::error::Error>> {
) -> InputResult {
// new typing
if self.offset != new_offset {
rime.destroy_session(self.session_id);
return Ok(InputResult {
is_new: true,
select: None,
});
return InputResult::default();
}
// continue last typing
// handle pinyin
Expand Down Expand Up @@ -101,9 +107,9 @@ impl InputState {
_ => None,
};

Ok(InputResult {
InputResult {
is_new: matches!(diff_pinyin, DiffResult::New),
select: idx,
})
}
}
}
39 changes: 24 additions & 15 deletions src/lsp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::config::{Config, Settings};
use crate::consts::{trigger_ptn, NT_RE};
use crate::input::{Input, InputResult, InputState};
use crate::rime::{Candidate, Rime, RimeResponse};
use crate::rime::{Candidate, Rime, RimeError, RimeResponse};
use crate::utils;
use dashmap::DashMap;
use regex::Regex;
Expand Down Expand Up @@ -33,13 +33,20 @@ impl Backend {
}
}

async fn init(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
async fn init(&self) -> std::result::Result<(), RimeError> {
let config = self.config.read().await;
let shared_data_dir = config.shared_data_dir.to_str().unwrap();
let user_data_dir = config.user_data_dir.to_str().unwrap();
let log_dir = config.log_dir.to_str().unwrap();
// expand tilde
let shared_data_dir = utils::expand_tilde(&config.shared_data_dir);
let user_data_dir = utils::expand_tilde(&config.user_data_dir);
let log_dir = utils::expand_tilde(&config.log_dir);
// to str
let shared_data_dir = shared_data_dir.to_str().unwrap();
let user_data_dir = user_data_dir.to_str().unwrap();
let log_dir = log_dir.to_str().unwrap();
// compile regex
let trigger_characters = &config.trigger_characters;
self.compile_regex(trigger_characters).await;
// init rime
self.rime.init(shared_data_dir, user_data_dir, log_dir)
}

Expand Down Expand Up @@ -149,13 +156,8 @@ impl Backend {
// handle new input
let mut last_state = self.state.entry(uri.to_string()).or_default();
let InputResult { is_new, select } = match (*last_state).as_ref() {
Some(state) => state
.handle_new_input(new_offset, &new_input, &self.rime)
.ok()?,
None => InputResult {
is_new: true,
select: None,
},
Some(state) => state.handle_new_input(new_offset, &new_input, &self.rime),
None => InputResult::default(),
};

// get rime session_id
Expand All @@ -170,10 +172,16 @@ impl Backend {
let RimeResponse {
preedit,
candidates,
} = self
} = match self
.rime
.get_response_from_session(session_id, max_candidates)
.ok()?;
{
Ok(r) => r,
Err(e) => {
self.client.log_message(MessageType::ERROR, e).await;
None?
}
};
// prevent deleting puncts before real pinyin input
let real_offset = new_offset
+ preedit
Expand Down Expand Up @@ -222,7 +230,8 @@ impl LanguageServer for Backend {
.await;
}
// init rime
if (self.init().await).is_err() {
if let Err(e) = self.init().await {
self.client.log_message(MessageType::ERROR, e).await;
return Err(tower_lsp::jsonrpc::Error::internal_error());
}
// set LSP triggers
Expand Down
32 changes: 24 additions & 8 deletions src/rime.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::consts::{K_PGDN, K_PGUP};
use librime_sys as librime;
use std::error::Error;
use std::ffi::{CStr, CString, NulError};
use std::sync::RwLock;
use thiserror::Error;

macro_rules! rime_struct_init {
($type:ty) => {{
Expand All @@ -27,6 +27,17 @@ pub struct Candidate {
pub order: usize,
}

/// Rime Error Type
#[derive(Error, Debug)]
pub enum RimeError {
#[error("null pointer when talking with librime")]
NullPointer(#[from] NulError),
#[error("fail to get candidates")]
GetCandidatesFailed,
#[error("session {0} not found")]
SessionNotFound(usize),
}

#[derive(Debug)]
pub struct RimeResponse {
/// length of input accepted by rime
Expand Down Expand Up @@ -57,7 +68,7 @@ impl Rime {
shared_data_dir: &str,
user_data_dir: &str,
log_dir: &str,
) -> Result<(), Box<dyn Error>> {
) -> Result<(), RimeError> {
let mut traits = rime_struct_init!(librime::RimeTraits);

// set dirs
Expand Down Expand Up @@ -103,13 +114,18 @@ impl Rime {
session_id: usize,
context: &mut librime::RimeContext,
max_candidates: usize,
) -> Result<Vec<Candidate>, Box<dyn Error>> {
) -> Result<Vec<Candidate>, RimeError> {
let res = RwLock::new(Vec::new());
let mut count_pgdn = 0;
while context.menu.num_candidates != 0 {
for i in 0..context.menu.num_candidates {
let candidate = unsafe { *context.menu.candidates.offset(i as isize) };
let text = unsafe { CStr::from_ptr(candidate.text).to_str()?.to_owned() };
let text = unsafe {
CStr::from_ptr(candidate.text)
.to_str()
.map_err(|_| RimeError::GetCandidatesFailed)?
.to_owned()
};
let comment = unsafe {
(!candidate.comment.is_null())
.then(|| match CStr::from_ptr(candidate.comment).to_str() {
Expand Down Expand Up @@ -150,7 +166,7 @@ impl Rime {
librime::RimeProcessKey(session_id, K_PGUP, 0);
}
}
Ok(res.into_inner()?)
res.into_inner().map_err(|_| RimeError::GetCandidatesFailed)
}

fn get_commit_text(&self, session_id: usize) -> Option<String> {
Expand Down Expand Up @@ -184,10 +200,10 @@ impl Rime {
&self,
session_id: usize,
max_candidates: usize,
) -> Result<RimeResponse, Box<dyn Error>> {
) -> Result<RimeResponse, RimeError> {
unsafe {
if librime::RimeFindSession(session_id) == 0 {
Err("No such session")?
return Err(RimeError::SessionNotFound(session_id));
}
}
// create context
Expand Down Expand Up @@ -224,7 +240,7 @@ impl Rime {
&self,
keys: Vec<u8>,
max_candidates: usize,
) -> Result<Vec<Candidate>, Box<dyn Error>> {
) -> Result<Vec<Candidate>, RimeError> {
let session_id = self.new_session_with_keys(&keys)?;
let res = self.get_response_from_session(session_id, max_candidates)?;
self.destroy_session(session_id);
Expand Down
12 changes: 12 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::{Path, PathBuf};

use crate::consts::AUTO_TRIGGER_RE;
use ropey::Rope;
use tower_lsp::lsp_types::Position;
Expand Down Expand Up @@ -67,3 +69,13 @@ pub fn option_string(s: String) -> Option<String> {
Some(s)
}
}

/// expand tilde in path, panics when home dir does not exist
pub fn expand_tilde(path: impl AsRef<Path>) -> PathBuf {
if !path.as_ref().starts_with("~") {
return path.as_ref().into();
}
let base_dirs = directories::BaseDirs::new().unwrap();
let home_dir = base_dirs.home_dir();
home_dir.join(path.as_ref().strip_prefix("~").unwrap())
}

0 comments on commit a4f4211

Please sign in to comment.