diff --git a/Cargo.toml b/Cargo.toml index 03242b7..6adc447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rime_ls" -version = "0.1.2" +version = "0.1.3" edition = "2021" authors = ["ZilcH40 "] rust-version = "1.63" diff --git a/README.md b/README.md index 5aa327c..9365593 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ - 平时关闭, 检测到配置的特殊字符或光标前有非英文字符时触发补全 (写少量汉字) - 可以按配置其他 rime 输入法的方式去配置 (只有能影响候选项的配置是有用的) - 可以同步系统中已有 rime 输入法的词频 +- 可以通过 TCP 远程使用 (无任何加密,谨慎使用) (since v0.1.3) https://user-images.githubusercontent.com/14821247/213079440-f0ab2ddd-5e44-4e41-bd85-81da2bd2957f.mp4 diff --git a/doc/nvim.md b/doc/nvim.md index af10575..cac1774 100644 --- a/doc/nvim.md +++ b/doc/nvim.md @@ -12,8 +12,8 @@ local start_rime = function() init_options = { enabled = false, -- 初始关闭, 手动开启 shared_data_dir = "/usr/share/rime-data", -- rime 公共目录 - user_data_dir = "/home/wlh/.local/share/rime-ls", -- 指定用户目录, 最好新建一个 - log_dir = "/home/wlh/.local/share/rime-ls", -- 日志目录 + user_data_dir = "~/.local/share/rime-ls", -- 指定用户目录, 最好新建一个 + log_dir = "~/.local/share/rime-ls", -- 日志目录 max_candidates = 10, -- 与 rime 的候选数量配置最好保持一致 trigger_characters = {}, -- 为空表示全局开启 }, @@ -100,8 +100,8 @@ function M.setup_rime() init_options = { enabled = false, shared_data_dir = "/usr/share/rime-data", - user_data_dir = "/home/wlh/.local/share/rime-ls", - log_dir = "/home/wlh/.local/share/rime-ls", + user_data_dir = "~/.local/share/rime-ls", + log_dir = "~/.local/share/rime-ls", max_candidates = 9, trigger_characters = {}, }, @@ -215,8 +215,8 @@ A language server for librime init_options = { enabled = vim.g.rime_enabled, shared_data_dir = "/usr/share/rime-data", - user_data_dir = "/home/wlh/.local/share/rime-ls", - log_dir = "/home/wlh/.local/share/rime-ls", + user_data_dir = "~/.local/share/rime-ls", + log_dir = "~/.local/share/rime-ls", max_candidates = 9, trigger_characters = {}, }, @@ -255,3 +255,7 @@ end 为了不影响正常的代码补全,以上代码只在 rime-ls 开启时启用该配置, 配合上一节配置里的 `toggle_rime` 函数使用 +## 通过 TCP 远程使用 + +将运行命令修改为 `cmd = vim.lsp.rpc.connect('', )` + diff --git a/doc/vim.md b/doc/vim.md index 13f57df..453f304 100644 --- a/doc/vim.md +++ b/doc/vim.md @@ -12,14 +12,14 @@ // ...... "rime-ls": { - "command": "/home/wlh/coding/rime-ls/target/release/rime_ls", + "command": "/usr/bin/rime_ls", "filetypes": ["text"], "initializationOptions": { "enabled": true, "shared_data_dir": "/usr/share/rime-data", // rime 公共目录 - "user_data_dir": "/home/wlh/.local/share/rime-ls", // 指定用户目录,最好新建一个 - "log_dir": "/home/wlh/.local/share/rime-ls", // 日志目录 - "max_candidates": 10, // 与 rime 的候选数量配置最好保持一致 + "user_data_dir": "~/.local/share/rime-ls", // 指定用户目录,最好新建一个 + "log_dir": "~/.local/share/rime-ls", // 日志目录 + "max_candidates": 9, // 与 rime 的候选数量配置最好保持一致 "trigger_characters": [], // 为空表示全局开启 } }, diff --git a/src/lsp.rs b/src/lsp.rs index bd781e0..4492f63 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -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, RimeError, RimeResponse, RIME}; +use crate::rime::{Candidate, Rime, RimeError, RimeResponse}; use crate::utils; use dashmap::DashMap; use regex::Regex; @@ -45,11 +45,14 @@ impl Backend { let trigger_characters = &config.trigger_characters; self.compile_regex(trigger_characters).await; // init rime - if RIME.get().is_none() { - let rime = Rime::init(shared_data_dir, user_data_dir, log_dir)?; - RIME.set(rime).ok(); + match Rime::init(shared_data_dir, user_data_dir, log_dir) { + Err(RimeError::AlreadyInitialized) => { + let info = "Use an initialized rime instance."; + self.client.show_message(MessageType::INFO, info).await; + Ok(()) + } + r => r, } - Ok(()) } async fn on_change(&self, params: TextDocumentItem) { @@ -217,10 +220,6 @@ impl Backend { #[tower_lsp::async_trait] impl LanguageServer for Backend { async fn initialize(&self, params: InitializeParams) -> Result { - self.client - .log_message(MessageType::INFO, "Rime-ls Language Server initialized") - .await; - // read user configuration if let Some(init_options) = params.initialization_options { self.init_config(init_options).await; @@ -234,6 +233,10 @@ impl LanguageServer for Backend { self.client.log_message(MessageType::ERROR, e).await; return Err(tower_lsp::jsonrpc::Error::internal_error()); } + // notify client + self.client + .log_message(MessageType::INFO, "Rime-ls Language Server initialized") + .await; // set LSP triggers let triggers = { let mut triggers = [".", ",", "-", "="].map(|x| x.to_string()).to_vec(); // pages @@ -241,7 +244,7 @@ impl LanguageServer for Backend { triggers.extend_from_slice(user_triggers); triggers }; - + // return Ok(InitializeResult { server_info: Some(ServerInfo { name: "rime-ls".to_string(), diff --git a/src/main.rs b/src/main.rs index f67c951..2afa945 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,7 +66,6 @@ async fn main() { tokio::signal::ctrl_c().await.unwrap(); println!("Ctrl-C pressed."); tx.send(()).unwrap(); - Ok::<(), tokio::io::Error>(()) }); // run if let Err(e) = run(rx).await { diff --git a/src/rime.rs b/src/rime.rs index 8062ce5..99f19f4 100644 --- a/src/rime.rs +++ b/src/rime.rs @@ -15,7 +15,7 @@ macro_rules! rime_struct_init { } /// global rime instance -pub static RIME: OnceCell = OnceCell::new(); +static RIME: OnceCell = OnceCell::new(); /// just call unsafe c ffi function simply /// TODO: make a good rust wrapper @@ -34,6 +34,8 @@ pub struct Candidate { pub enum RimeError { #[error("null pointer when talking with librime")] NullPointer(#[from] NulError), + #[error("rime is already initialized")] + AlreadyInitialized, #[error("failed to get candidates")] GetCandidatesFailed, #[error("session {0} not found")] @@ -51,7 +53,7 @@ pub struct RimeResponse { impl Drop for Rime { fn drop(&mut self) { // FIXME: it seems that static once_cell variables will not be dropped? - self.destroy(); + // self.destroy(); } } @@ -69,7 +71,10 @@ impl Rime { shared_data_dir: &str, user_data_dir: &str, log_dir: &str, - ) -> Result { + ) -> Result<(), RimeError> { + if Rime::is_initialized() { + Err(RimeError::AlreadyInitialized)? + } let mut traits = rime_struct_init!(librime::RimeTraits); // set dirs @@ -106,7 +111,8 @@ impl Rime { let _ = CString::from_raw(traits.distribution_version as *mut i8); let _ = CString::from_raw(traits.app_name as *mut i8); } - Ok(Rime) + RIME.set(Rime).unwrap(); + Ok(()) } pub fn destroy(&self) { @@ -298,7 +304,8 @@ fn test_get_candidates() { let log_dir = "/tmp"; // init - let rime = Rime::init(shared_data_dir, user_data_dir, log_dir).unwrap(); + Rime::init(shared_data_dir, user_data_dir, log_dir).unwrap(); + let rime = Rime::global(); // simulate typing let max_candidates = 10; let keys = vec![b'w', b'l', b'h'];