liubianshi / cmp-lsp-rimels

让 Neovim 下的中英文混合输入无比丝滑
MIT License
14 stars 0 forks source link

能否通过快捷键/命令修改 cmp 空格行为? #6

Open inkfin opened 4 months ago

inkfin commented 4 months ago

在输入文本的时候,中文输入使用空格上屏非常符合直觉,但是在默认英文模式下,会出现很多意想不到的事情。我在本地开启了两个 cmp 补全:copilot 和 dictionary,在空格上屏的时候,前者会在意料不到的时候突然插入随机的长文本,后者会把短词语给补全成另一个有相同前缀的词语。

我的方案目前是通过一些启动项来初始化空格或者回车上屏,以及一个命令指定关闭这两个补全源,问题在于:写的时候无法切换空格上屏行为;不知道有没有办法进行动态修改 cmp 补全 keymap?

liubianshi commented 3 months ago

我安装 uga-rosa/cmp-dictionary 测试了一下,下面这种情况(开启了 rime_ls),按空格时并不会自动上屏候选词 autopsy,而是插入空格,即 autop。按理应该不会出现补全成有相同前缀词语的问题。

flameshot_20240716102700

另外,如果默认在英文模式下,感觉还是使用后及时关闭 rime_ls 为好。

至于你说的动态修改 keymap,应该是可行的。我这里设置了几个 keymap,

https://github.com/liubianshi/cmp-lsp-rimels/blob/3bc9d700e4601bf04d7dc275de4ffa3c72b1ee7a/lua/rimels/init.lua#L146

可以选择性关闭,然后参考我这部分的配置,设置符合你要求的 keymap。

inkfin commented 3 months ago

抱歉一直没空实验,这两天试了下,发现uga-rosa/cmp-dictionary确实不会影响,影响空格行为的似乎是buffer补全和copilot,后者是通过插件段插入cmp的补全,不清楚做了些什么还需要调查;

我目前的解决方案仍然是用快捷键暂时关闭补全列表,放在下面供参考。这周再调查下动态修改 keymap


更新

试了一下,找到了个较为简便的方案可以做到实时切换输入法,放在下面供大家参考

local cmp_cache = { keymaps = {}, cmp_sources = {} }

... -- your configs

keys = {
    {
        "<leader>rt",
        function()
            vim.cmd("ToggleRime")
            local cmp = require("cmp")
            local sources = assert(cmp.get_config().sources, "[toggle_rime] can't get cmp_config.sources!")
            local mapping = assert(cmp.get_config().mapping, "[toggle_rime] can't get cmp_config.mapping!")

            -- remove conflict sources
            local bIsChineseInputOn = false
            local conflict_sources = { "dictionary", "buffer", "copilot" }
            for i = #sources, 1, -1 do
                for _, v in ipairs(conflict_sources) do
                    if sources[i].name == v then
                        table.insert(cmp_cache.cmp_sources, sources[i])
                        table.remove(sources, i)
                        bIsChineseInputOn = true
                        break
                    end
                end
            end
            if bIsChineseInputOn then
                print("Rime Input On 🚀")

                -- restore cmp <Space> keymap in insert mode
                if mapping[" "] ~= nil then
                    mapping[" "].i = cmp_cache.keymaps["<Space>i"]
                end
            else
                print("Rime Input Off 💤")

                -- refill conflict sources
                for _, v in ipairs(cmp_cache.cmp_sources) do
                    table.insert(sources, v)
                end
                cmp_cache.cmp_sources = {}

                -- disable cmp <Space> keymap in insert mode
                if mapping[" "] ~= nil then
                    cmp_cache.keymaps["<Space>i"] = mapping[" "].i
                    mapping[" "].i = function()
                        vim.fn.feedkeys(" ", "n")
                    end
                end
            end
            cmp.setup.buffer({ sources = sources })
            cmp.setup.buffer({ mapping = mapping })
        end,
        desc = "toggle rime",
    },
},

这段代码会动态修改cmp 空格 keymap 在输入 (i) 模式下的行为,用一个全局变量缓存和恢复起来。这样可以避免大部分键位冲突的情况

inkfin commented 3 months ago

一些其他补充:

目前的 rime_ls 似乎会导致一些 vim 的卡顿。如果不想每次都运行 rime_ls ,可以使用给 vim 传参的方式

nvim --cmd "let g:use_rime='on'" hello.md

注意:-c 会在加载完.vimrc以后执行,所以需要使用 --cmd

然后在 lua 中就可以读取了

if vim.g.rime and vim.g.rime == "on" then
    -- do something
end