Skip to content

Commit

Permalink
feat: 强制4字补全 & 强制触发补全 (#7)
Browse files Browse the repository at this point in the history
* add new config `max_tokens` for force refreshing
* add new config `always_incomplete`
* update doc

---------

Co-authored-by: zilcH40 <wlh233@live.com>
  • Loading branch information
TwIStOy and wlh320 authored Apr 4, 2023
1 parent 4b6528a commit a366a6f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
46 changes: 45 additions & 1 deletion doc/nvim.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ local start_rime = function()
max_candidates = 10, -- [v0.2.0 后不再有用] 与 rime 的候选数量配置最好保持一致
trigger_characters = {}, -- 为空表示全局开启
schema_trigger_character = "&" -- [since v0.2.0] 当输入此字符串时请求补全会触发 “方案选单”
always_incomplete = false -- [since v0.2.3] true 强制补全永远刷新整个列表,而不是使用过滤
max_tokens = 0 -- [since v0.2.3] 大于 0 表示会在删除到这个字符个数的时候,重建所有候选词,而不使用删除字符操作
},
});
vim.lsp.buf_attach_client(0, client_id)
Expand Down Expand Up @@ -237,7 +239,7 @@ return M

## 空格键补全

为了取得与外部输入法更加相似的体验,可以通过配置 cmp 实现用空格键补全,参考配置如下:
为了取得与外部输入法更加相似的体验,可以通过配置 cmp 实现用空格键补全并用回车键直接输入,参考配置如下:

```lua
cmp.setup {
Expand All @@ -248,6 +250,9 @@ cmp.setup {
-- ...
['<Space>'] = cmp.mapping(function(fallback)
local entry = cmp.get_selected_entry()
if entry == nil then
entry = cmp.core.view:get_first_entry()
end
if entry and entry.source.name == "nvim_lsp"
and entry.source.source.client.name == "rime_ls" then
cmp.confirm({
Expand All @@ -258,6 +263,25 @@ cmp.setup {
fallback()
end
end, {'i', 's'}),
['<CR>'] = cmp.mapping(function(fallback)
local entry = cmp.get_selected_entry()
if entry == nil then
entry = cmp.core.view:get_first_entry()
end
if entry and entry.source.name == 'nvim_lsp'
and entry.source.source.client.name == 'rime_ls' then
cmp.abort()
else
if entry ~= nil then
cmp.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true
})
else
fallback()
end
end
end, {'i', 's'}),
-- 其他内容
-- ...
}
Expand All @@ -272,3 +296,23 @@ cmp.setup {

将运行命令修改为 `cmd = vim.lsp.rpc.connect('<ip>', <port>)`

## 五笔或者双形用户

```lua
require('lspconfig').rime_ls.setup {
init_options = {
enabled = vim.g.rime_enabled,
shared_data_dir = "/usr/share/rime-data",
user_data_dir = "~/.local/share/rime-ls",
log_dir = "~/.local/share/rime-ls",
max_candidates = 9,
trigger_characters = {},
schema_trigger_character = "&" -- [since v0.2.0] 当输入此字符串时请求补全会触发 “方案选单”
max_tokens = 4, -- 强制在删除到4字的时候重建一次候选词,避免用退格造成的空列表的问题
always_incomplete = true, -- 将 incomplete 永远设为 true,防止任何时候的过滤代替候选词重建
},
on_attach = rime_on_attach,
capabilities = capabilities,
}
```

18 changes: 18 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ pub struct Config {
/// if set, completion request with this string will trigger「方案選單」
#[serde(default = "default_schema_trigger_character")]
pub schema_trigger_character: String,
/// if set, when a delete action arrives the number of max tokens, emit a force new_typing
#[serde(default = "default_max_tokens")]
pub max_tokens: usize,
/// if CompletionItem is always incomplete
#[serde(default = "default_always_incomplete")]
pub always_incomplete: bool,
}

/// settings that can be tweaked during running
Expand Down Expand Up @@ -66,6 +72,8 @@ impl Default for Config {
max_candidates: default_max_candidates(),
trigger_characters: default_trigger_characters(),
schema_trigger_character: default_schema_trigger_character(),
max_tokens: default_max_tokens(),
always_incomplete: default_always_incomplete(),
}
}
}
Expand All @@ -74,10 +82,18 @@ fn default_enabled() -> bool {
true
}

fn default_always_incomplete() -> bool {
false
}

fn default_max_candidates() -> usize {
10
}

fn default_max_tokens() -> usize {
0
}

fn default_trigger_characters() -> Vec<String> {
Vec::default()
}
Expand Down Expand Up @@ -113,6 +129,8 @@ fn test_default_config() {
config.schema_trigger_character,
default_schema_trigger_character()
);
assert_eq!(config.always_incomplete, default_always_incomplete());
assert_eq!(config.max_tokens, default_max_tokens());
}

#[test]
Expand Down
22 changes: 21 additions & 1 deletion src/input.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::Display;

use ouroboros::self_referencing;
use regex::Regex;

Expand All @@ -15,6 +17,16 @@ pub struct Input {
pub select: &'this str,
}

impl Display for Input {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"pinyin: {}, select: {}",
self.borrow_pinyin(),
self.borrow_select()
))
}
}

impl Input {
/// if matches, take ownership of &str, and self-reference it.
pub fn from_str(re: &Regex, text: &str) -> Option<Self> {
Expand Down Expand Up @@ -101,6 +113,7 @@ impl InputState {
new_offset: usize,
new_input: &Input,
schema_trigger: &str,
max_tokens: usize,
) -> InputResult {
let rime = Rime::global();
let session_id = rime.find_session(self.session_id);
Expand All @@ -118,7 +131,14 @@ impl InputState {
let diff_pinyin = diff(self.input.borrow_pinyin(), new_input.borrow_pinyin());
match diff_pinyin {
DiffResult::Add(suffix) => rime.process_str(session_id, suffix),
DiffResult::Delete(suffix) => rime.delete_keys(session_id, suffix.len()),
DiffResult::Delete(suffix) => {
// if current pinyin len == max_tokens, force new typing
if max_tokens > 0 && max_tokens == new_input.borrow_pinyin().len() {
rime.clear_composition(session_id);
return Self::handle_new_typing(session_id, new_input);
}
rime.delete_keys(session_id, suffix.len())
}
DiffResult::New => {
rime.clear_composition(session_id);
if !schema_trigger.is_empty() && new_input.borrow_pinyin() == &schema_trigger {
Expand Down
9 changes: 7 additions & 2 deletions src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,12 @@ impl Backend {
} = match (*last_state).as_ref() {
Some(state) => {
let schema_trigger = &self.config.read().await.schema_trigger_character;
state.handle_new_input(new_offset, &new_input, schema_trigger)
state.handle_new_input(
new_offset,
&new_input,
schema_trigger,
self.config.read().await.max_tokens,
)
}
None => InputState::handle_first_state(&new_input),
};
Expand Down Expand Up @@ -235,7 +240,7 @@ impl Backend {
.enumerate()
.map(|(i, c)| candidate_to_completion_item(i, c));
Some(CompletionList {
is_incomplete,
is_incomplete: (self.config.read().await.always_incomplete || is_incomplete),
items: item_iter.collect(),
})
}
Expand Down

0 comments on commit a366a6f

Please sign in to comment.