Skip to content

Commit ab3d6d7

Browse files
committed
feat: add pyjj shuangpin scheme
将 flypy 模块抽象为 char_map,支持多种双拼方案切换。 新增拼音加加(pyjj)作为内置方案,通过 setup({ scheme = "pyjj" }) 选择。
1 parent 5848840 commit ab3d6d7

5 files changed

Lines changed: 347 additions & 63 deletions

File tree

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# flash-zh.nvim
22

3-
基于[flash.nvim](https://github.com/folke/flash.nvim)以及小鹤双拼,neovim 中文跳转插件。
3+
基于[flash.nvim](https://github.com/folke/flash.nvim)的 Neovim 中文跳转插件,支持小鹤双拼(默认)与拼音加加双拼
44

55
![iShot_2023-10-05_19 32 53](https://github.com/rainzm/flash-zh.nvim/assets/22927169/4c3ca124-0fee-48a2-b7c6-17391afe8d0e)
66

@@ -44,6 +44,19 @@ return {{
4444

4545
**如果想要跳转的地方没有 label 出现,接着输入即可,和查找一样。**
4646

47+
### 选择双拼方案
48+
49+
插件内置两套方案:
50+
51+
- `flypy`:小鹤双拼(默认)
52+
- `pyjj`:拼音加加双拼
53+
54+
```lua
55+
require("flash-zh").setup({
56+
scheme = "pyjj",
57+
})
58+
```
59+
4760
### 自定义匹配字符
4861

4962
- 你可以覆盖、或是追加字符到默认的匹配字符集。
@@ -73,4 +86,3 @@ return {{
7386
## 感谢
7487

7588
- [hop-zh-by-flypy](https://github.com/zzhirong/hop-zh-by-flypy)
76-

lua/flash-zh/char_map.lua

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
local flypy = require("flash-zh.flypy")
2+
3+
local M = {}
4+
5+
---@class FlashZhCharMap
6+
---@field comma table<string,string>
7+
---@field escape table<string,string>
8+
---@field char1patterns table<string,string>
9+
---@field char2patterns table<string,string>
10+
11+
local current_name = "flypy"
12+
---@type FlashZhCharMap
13+
local current_map = flypy
14+
15+
---@type table<string, FlashZhCharMap>
16+
local cache = {
17+
flypy = flypy,
18+
}
19+
20+
local function build(name)
21+
if cache[name] then
22+
return cache[name]
23+
end
24+
if name == "pyjj" then
25+
local pyjj = require("flash-zh.pyjj")
26+
cache.pyjj = pyjj.from_flypy(flypy)
27+
return cache.pyjj
28+
end
29+
error("unknown scheme: " .. tostring(name))
30+
end
31+
32+
---@return string
33+
function M.name()
34+
return current_name
35+
end
36+
37+
---@return FlashZhCharMap
38+
function M.get()
39+
return current_map
40+
end
41+
42+
---@param name string
43+
function M.set(name)
44+
name = name or "flypy"
45+
current_map = build(name)
46+
current_name = name
47+
end
48+
49+
function M.available()
50+
return { "flypy", "pyjj" }
51+
end
52+
53+
return M
54+

lua/flash-zh/init.lua

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
local flash = require("flash")
2-
local flypy = require("flash-zh.flypy")
2+
local char_map = require("flash-zh.char_map")
33

44
local M = {}
55

66
function M.jump(opts)
77
opts = opts or {}
8-
local mode = M.mix_mode
9-
if opts.chinese_only then
10-
mode = M.zh_mode
8+
9+
-- Allow per-jump override so users can verify schemes quickly,
10+
-- and so it still works even if setup() was not called (common with lazy.nvim misconfig).
11+
if opts.scheme then
12+
require("flash-zh.char_map").set(opts.scheme)
13+
opts.scheme = nil
1114
end
12-
opts = vim.tbl_deep_extend("force", {
13-
labels = "asdfghjklqwertyuiopzxcvbnm",
14-
search = {
15-
mode = mode,
16-
},
17-
labeler = function(_, state)
18-
require("flash-zh.labeler").new(state):update()
19-
end,
20-
}, opts)
21-
flash.jump(opts)
22-
end
2315

24-
function M.remote(opts)
25-
opts = opts or {}
2616
local mode = M.mix_mode
2717
if opts.chinese_only then
2818
mode = M.zh_mode
@@ -36,7 +26,7 @@ function M.remote(opts)
3626
require("flash-zh.labeler").new(state):update()
3727
end,
3828
}, opts)
39-
flash.remote(opts)
29+
flash.jump(opts)
4030
end
4131

4232
function M.mix_mode(str)
@@ -52,38 +42,45 @@ function M.mix_mode(str)
5242
end
5343

5444
function M.zh_mode(str)
45+
local map = char_map.get()
5546
local regexs = {}
5647
while string.len(str) > 1 do
57-
regexs[#regexs + 1] = flypy.char2patterns[string.sub(str, 1, 2)]
48+
local k = string.sub(str, 1, 2)
49+
-- Be defensive: unknown keys should not crash the search.
50+
regexs[#regexs + 1] = map.char2patterns[k] or ("[" .. k .. string.upper(k) .. "]")
5851
str = string.sub(str, 3)
5952
end
6053
if string.len(str) == 1 then
61-
regexs[#regexs + 1] = flypy.char1patterns[str]
54+
regexs[#regexs + 1] = map.char1patterns[str] or ("[" .. str .. string.upper(str) .. "]")
6255
end
6356
local ret = table.concat(regexs)
6457
return ret, ret
6558
end
6659

67-
local nodes = {
68-
alpha = function(str)
69-
return "[" .. str .. string.upper(str) .. "]"
70-
end,
71-
pinyin = function(str)
72-
return flypy.char2patterns[str]
73-
end,
74-
comma = function(str)
75-
return flypy.comma[str]
76-
end,
77-
singlepin = function(str)
78-
return flypy.char1patterns[str]
79-
end,
80-
other = function(str)
81-
str = flypy.escape[str] or str
82-
return str
83-
end,
84-
}
60+
local function get_nodes(map)
61+
return {
62+
alpha = function(str)
63+
return "[" .. str .. string.upper(str) .. "]"
64+
end,
65+
pinyin = function(str)
66+
return map.char2patterns[str]
67+
end,
68+
comma = function(str)
69+
return map.comma[str]
70+
end,
71+
singlepin = function(str)
72+
return map.char1patterns[str]
73+
end,
74+
other = function(str)
75+
str = map.escape[str] or str
76+
return str
77+
end,
78+
}
79+
end
8580

8681
function M.regex(parser)
82+
local map = char_map.get()
83+
local nodes = get_nodes(map)
8784
local regexs = {}
8885
for _, v in ipairs(parser) do
8986
regexs[#regexs + 1] = nodes[v.type](v.str)
@@ -92,10 +89,11 @@ function M.regex(parser)
9289
end
9390

9491
function M.parser(str, prefix)
92+
local map = char_map.get()
9593
prefix = prefix or {}
9694
local firstchar = string.sub(str, 1, 1)
9795
local chars = {}
98-
for k, _ in pairs(flypy.comma) do
96+
for k, _ in pairs(map.comma) do
9997
table.insert(chars, k)
10098
end
10199
if firstchar == "" then
@@ -108,7 +106,7 @@ function M.parser(str, prefix)
108106
prefix2[#prefix2 + 1] = { str = firstchar, type = "singlepin" }
109107
return { prefix, prefix2 }
110108
elseif string.match(secondchar, "%a") then
111-
if flypy.char2patterns[firstchar .. secondchar] then
109+
if map.char2patterns[firstchar .. secondchar] then
112110
local prefix2 = M.copy(prefix)
113111
prefix2[#prefix2 + 1] = { str = firstchar, type = "alpha" }
114112
prefix[#prefix + 1] = { str = firstchar .. secondchar, type = "pinyin" }
@@ -158,24 +156,32 @@ function M.copy(table)
158156
end
159157

160158
-- @param opts table
159+
-- @field[opt] opts.scheme string Choose the built-in shuangpin scheme. One of: "flypy", "pyjj".
161160
-- @field opts.char_map table Char map for flypy.
162161
-- @field[opt] opts.char_map.comma table Override the default comma map.
163162
-- @field[opt] opts.char_map.append_comma table Append to the default comma map.
164163
-- @field[opt] opts.char_map.append_char1 table Append to the default char1patterns map.
165164
-- @field[opt] opts.char_map.append_char2 table Append to the default char2patterns map.
166165
function M.setup(opts)
167166
opts = opts or {}
167+
168+
if opts.scheme then
169+
char_map.set(opts.scheme)
170+
end
171+
168172
if not opts.char_map then
169173
return
170174
end
175+
176+
local map = char_map.get()
171177
local to_escape = "\\^$*+?.%|[]()"
172178
if opts.char_map.comma then
173179
for k, v in pairs(opts.char_map.comma) do
174180
if #k ~= 1 then
175181
error("comma key must be a single character")
176182
else
177183
v = vim.fn.escape(v, to_escape)
178-
flypy.comma[k] = "[" .. v .. "]"
184+
map.comma[k] = "[" .. v .. "]"
179185
end
180186
end
181187
end
@@ -184,9 +190,9 @@ function M.setup(opts)
184190
if #k ~= 1 then
185191
error("append_comma key must be a single character")
186192
else
187-
local chars = flypy.comma[k] or ""
193+
local chars = map.comma[k] or ""
188194
chars = string.sub(chars, 2, -2) .. vim.fn.escape(v, to_escape)
189-
flypy.comma[k] = "[" .. chars .. "]"
195+
map.comma[k] = "[" .. chars .. "]"
190196
end
191197
end
192198
end
@@ -195,9 +201,9 @@ function M.setup(opts)
195201
if #k ~= 1 then
196202
error("append_char1 key must be a single character")
197203
else
198-
local chars = flypy.char1patterns[k] or ""
204+
local chars = map.char1patterns[k] or ""
199205
chars = string.sub(chars, 2, -2) .. vim.fn.escape(v, to_escape)
200-
flypy.char1patterns[k] = "[" .. chars .. "]"
206+
map.char1patterns[k] = "[" .. chars .. "]"
201207
end
202208
end
203209
end
@@ -206,9 +212,9 @@ function M.setup(opts)
206212
if #k ~= 2 then
207213
error("append_char2 key must be two characters")
208214
else
209-
local chars = flypy.char2patterns[k] or ""
215+
local chars = map.char2patterns[k] or ""
210216
chars = string.sub(chars, 2, -2) .. vim.fn.escape(v, to_escape)
211-
flypy.char2patterns[k] = "[" .. chars .. "]"
217+
map.char2patterns[k] = "[" .. chars .. "]"
212218
end
213219
end
214220
end

lua/flash-zh/pinyin.lua

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
local flypy = require("flash-zh.flypy")
1+
local char_map = require("flash-zh.char_map")
22

33
local M = {}
44

5-
local py_table = {}
6-
local mt = {}
7-
setmetatable(py_table, { __index = mt })
5+
local caches = {} ---@type table<string, table>
86

9-
function py_table:insert(char, pinyin)
10-
if not self[char] then
11-
self[char] = {}
7+
local function new_py_table()
8+
local t = {}
9+
local mt = {}
10+
setmetatable(t, { __index = mt })
11+
12+
function t:insert(char, pinyin)
13+
if not self[char] then
14+
self[char] = {}
15+
end
16+
table.insert(self[char], pinyin)
17+
end
18+
19+
function t:find(char)
20+
return self[char]
1221
end
13-
table.insert(self[char], pinyin)
14-
end
1522

16-
function py_table:find(char)
17-
return self[char]
23+
return t
1824
end
1925

2026
local function get_char_size(char) --获取单个字符长度
@@ -62,22 +68,27 @@ local function utf8_sub(str, startChar, numChars) --截取中文字符串
6268
end
6369

6470
local function init_py_table()
65-
for k, v in pairs(flypy.char2patterns) do
71+
local map = char_map.get()
72+
local py_table = new_py_table()
73+
74+
for k, v in pairs(map.char2patterns) do
6675
local start_char, end_char = v:find("%[(.-)%]")
6776
v = v:sub(start_char + 1, end_char - 1)
6877
for i = 1, utf8_len(v) do
6978
local char = utf8_sub(v, i, 1)
7079
py_table:insert(char, k)
7180
end
7281
end
73-
for k, v in pairs(flypy.comma) do
82+
for k, v in pairs(map.comma) do
7483
local start_char, end_char = v:find("%[(.-)%]")
7584
v = v:sub(start_char + 1, end_char - 1)
7685
for i = 1, utf8_len(v) do
7786
local char = utf8_sub(v, i, 1)
7887
py_table:insert(char, k)
7988
end
8089
end
90+
91+
return py_table
8192
end
8293

8394
local function append_to_pinyins(pinyins, suffixes)
@@ -94,6 +105,13 @@ local function append_to_pinyins(pinyins, suffixes)
94105
end
95106

96107
function M.pinyin(chars)
108+
local name = char_map.name()
109+
local py_table = caches[name]
110+
if not py_table then
111+
py_table = init_py_table()
112+
caches[name] = py_table
113+
end
114+
97115
local pinyins = {}
98116
for i = 1, utf8_len(chars) do
99117
local char = utf8_sub(chars, i, 1)
@@ -116,5 +134,4 @@ function M.pinyin(chars)
116134
return result
117135
end
118136

119-
init_py_table()
120137
return M

0 commit comments

Comments
 (0)