-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: include the ModeChanged event for more flexibility #19
base: master
Are you sure you want to change the base?
Conversation
感谢你的 pr,我有两个点想详细了解一下:
还有一点我需要提前说一下,我觉得这个 pr 里的内容有点过于复杂和精细了,就我之前调研过的用户反馈来看,大部分用户可能完全不会需要这些精细的设置,他们也多半不了解 |
感谢您的回复第一个问题的具体步骤如下(为了方便描述,我们用符号
那么,只要不在命令行模式下保存输入法,就能解决我的问题,于是有了 关于第二个问题我使用 那么, 关于兼容性
set_default_events = { "VimEnter", "FocusGained", ModeChanged = {"i:*", "c:*", "R:*"} }, 也就是说,可以让默认配置与之前保持一致: set_default_events = { "VimEnter", "FocusGained", "InsertLeave", "CmdlineLeave" },
set_previous_events = { "InsertEnter" }, 这样就能确保在默认设置的情况下,现有用户的配置完全不需要改动 然后,需要 save_state_patterns = {}, -- 为空时,与以前的行为一致,还需要修改一下代码
exclude_patterns = {}, (通过注释或其他形式)告知用户 如果需要,我可以更新一下pr,把默认配置改回原来的样子 |
我理解你的意思了,你只是需要在某些事件触发的时候,切换到默认输入法,但是不更新当前输入法的状态。 具体来说就是:在 im-select.nvim/lua/im_select.lua Lines 159 to 161 in 8cf35fa
im-select.nvim/lua/im_select.lua Lines 156 to 157 in 8cf35fa
im_select_saved_state 值改为默认输入法
那我们这样改可以吗? 增加一个参数 config = function()
require("im_select").setup({
set_previous_events = { "InsertEnter" },
set_default_events = { "VimEnter", "InsertLeave", "CmdlineLeave" },
keep_state_when_set_default_events = { "CmdlineLeave" },
})
end, 最终实现的效果就是在 你可以试试这个分支:https://github.com/keaising/im-select.nvim/tree/keep_state_event 我觉得这样简单点,不用引入 |
1. Remove `exclude_patterns` 2. Make the configuration compatible with the previous ones 3. Separate the `save_im_state` from `restore_default_im`
感谢您提供的方案,但在使用过程中发现一个小问题:补全的时候,会出现模式转换,触发 具体复现步骤如下(已禁用除了
在 vim.api.nvim_create_autocmd("ModeChanged", {
pattern = {"*:*"},
callback = function (args)
os.execute("notify-send " .. args.match)
end,
}) 当然,只输入中文几乎不会用到补全,但如果在中文穿插数字或字母,就有可能用到补全 所以,我还是建议引入
您看这样是否满足了兼容性要求? 另外,我目前使用的配置如下: set_default_events = { "VimEnter", ModeChanged = { "[iRc]*:[nvV\x16sS]*" } },
save_state_events = { ModeChanged = { "[iR]*:[nvV\x16sS]*" } },
set_previous_events = { ModeChanged = { "[nvV\x16sS]*:[iR]" } }, -- \x16 means Ctrl-V 在 |
不好意思,前几天新冠了一直没上线 你可以给我一个最小的可复现的配置吗?我试了一下没有复现出来你说的“在补全的时候会触发 InsertLeave”的场景,按理说补全的时候摁 Ctrl+N 是不会脱离 Insert mode 的,也就不会触发 |
抱歉之前没看到消息 不好意思,之前是我测试做得有问题。 最小的复现配置 -- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
"folke/tokyonight.nvim",
-- add any other plugins here
{
"keaising/im-select.nvim",
branch = "keep_state_event",
opts = {
set_previous_events = { "InsertEnter" },
set_default_events = {
"VimEnter",
"InsertLeave",
"CmdlineLeave" -- 注释这行就能防止补全时自动切回默认的英文输入法
},
keep_state_when_set_default_events = { "CmdlineLeave" },
},
},
{
'neoclide/coc.nvim',
branch = 'release',
}
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")
-- add anything else here
vim.api.nvim_create_autocmd("ModeChanged", {
pattern = {"*:*"},
callback = function (args)
os.execute("notify-send " .. args.match)
end,
})
vim.api.nvim_create_autocmd("CmdlineLeave", {
callback = function ()
os.execute("notify-send CmdlineLeave")
end,
})
vim.api.nvim_create_autocmd("InsertLeave", {
callback = function ()
os.execute("notify-send InsertLeave")
end,
}) 通过 不知道怎么配置coc.nvim才能让它不触发CmdlineLeave(看了下coc.nvim的文档,感觉不大可能),目前还不打算放弃使用coc.nvim 非常感谢您的积极维护 |
上面的
|
我这里好像是Linux自带的。 在Ubuntu上可以使用命令安装: apt-get install libnotify-bin 其他平台的安装可以参考这里 |
嗯嗯,我在 macOS 上用的这个 https://formulae.brew.sh/formula/terminal-notifier ,代码改成下面这样 我能复现你说的在 coc 里用 ctrl+p/n 选择补全的时候会触发 CmdlineLeave 的问题,我感觉有点奇怪,我再试试我自己的配置 -- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
{
"keaising/im-select.nvim",
branch = "keep_state_event",
opts = {
set_previous_events = { "InsertEnter" },
set_default_events = {
"VimEnter",
"InsertLeave",
"CmdlineLeave" -- 注释这行就能防止补全时自动切回默认的英文输入法
},
keep_state_when_set_default_events = { "CmdlineLeave" },
},
},
{
'neoclide/coc.nvim',
branch = 'release',
}
}
local cmd_count = 0
local insert_count = 0
require("lazy").setup(plugins, {
root = root .. "/plugins",
})
-- vim.api.nvim_create_autocmd("ModeChanged", {
-- pattern = {"*:*"},
-- callback = function (args)
-- os.execute("terminal-notifier -title ModeChanged -message " .. args.match)
-- end,
-- })
vim.api.nvim_create_autocmd("CmdlineLeave", {
callback = function ()
os.execute("terminal-notifier -title Cmd -message CmdlineLeave" .. cmd_count)
cmd_count = cmd_count + 1
end,
})
vim.api.nvim_create_autocmd("InsertLeave", {
callback = function ()
os.execute("terminal-notifier -title Cmd -message InsertLeave" .. insert_count)
insert_count = insert_count + 1
end,
}) |
好像还真是 Coc 的一个问题,之前也有人提到过类似的问题:neoclide/coc.nvim#3290 (comment) ,在他的注释里提到了一句:
|
嗯嗯,我试过按照他README给的配置,改用
-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
"folke/tokyonight.nvim",
-- add any other plugins here
{
"keaising/im-select.nvim",
branch = "keep_state_event",
opts = {
set_previous_events = { "InsertEnter" },
set_default_events = {
"VimEnter",
"InsertLeave",
"CmdlineLeave" -- 注释这行就能防止补全时自动切回默认的英文输入法
},
keep_state_when_set_default_events = { "CmdlineLeave" },
},
},
{
'neoclide/coc.nvim',
branch = 'release',
config = function ()
-- Some servers have issues with backup files, see #649
vim.opt.backup = false
vim.opt.writebackup = false
-- Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
-- delays and poor user experience
vim.opt.updatetime = 300
-- Always show the signcolumn, otherwise it would shift the text each time
-- diagnostics appeared/became resolved
vim.opt.signcolumn = "yes"
local keyset = vim.keymap.set
-- Autocomplete
function _G.check_back_space()
local col = vim.fn.col('.') - 1
return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') ~= nil
end
-- Use Tab for trigger completion with characters ahead and navigate
-- NOTE: There's always a completion item selected by default, you may want to enable
-- no select by setting `"suggest.noselect": true` in your configuration file
-- NOTE: Use command ':verbose imap <tab>' to make sure Tab is not mapped by
-- other plugins before putting this into your config
local opts = {silent = true, noremap = true, expr = true, replace_keycodes = false}
keyset("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)
keyset("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"]], opts)
-- Make <CR> to accept selected completion item or notify coc.nvim to format
-- <C-g>u breaks current undo, please make your own choice
keyset("i", "<cr>", [[coc#pum#visible() ? coc#pum#confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"]], opts)
end
}
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")
-- add anything else here
vim.api.nvim_create_autocmd("ModeChanged", {
pattern = {"*:*"},
callback = function (args)
os.execute("notify-send " .. args.match)
end,
})
vim.api.nvim_create_autocmd("CmdlineLeave", {
callback = function ()
os.execute("notify-send CmdlineLeave")
end,
})
vim.api.nvim_create_autocmd("InsertLeave", {
callback = function ()
os.execute("notify-send InsertLeave")
end,
}) |
我也去翻了一下 Coc 的文档,好像没有提这个的,具体为什么会在补全的时候触发 CmdlineLeave 就不得而知了,可能得读一下 Coc 的代码才知道能不能改,估计不太好弄 说实话我一直不想引入 ModeChanged 的原因是我觉得这玩意太复杂了,我读了好久才弄明白它是干什么的以及该如何用,至于用起来还是直接抄的你的代码,我想尽量让这个插件简单点,让新来的用户一眼就能看明白里面的逻辑然后在有需求的时候自己修改它(就像你现在做的一样)。所以我不打算合并这个 PR(并不是说你的 PR 有问题,只是单纯我对功能复杂性的偏好导致的) 不过你发现的的确是个兼容性问题,稍后我会把我们的对话和找到的问题翻译一下放在后面,然后在 README 里提示一下如果用 Coc 的话需要把 CmdlineLeave 排除掉 |
嗯嗯,可以。这个插件的代码确实写得不错,我改代码的时候也觉得读起来很舒服,写这个PR的过程中也学到了很多,还是非常感谢您 |
总结结论: Coc 的 bug/feature 导致在 insert mode 里每次用 Coc 补全时切换了候选项,都会导致输入法被切换到默认输入法 通过后面附上的脚本配置可以复现,在使用 Coc 补全的时候(不管快捷键是使用Ctrl+n/p 还是 Tab,应该是更底层的命令触发的),每一次切换补全项都会触发一次 CmdlineEnter 和 CmdlineLeave,这就导致在下列两种情况下会遇到这个问题:
这是一个不兼容的情况,但是目前本插件无法解决,一个可用的解决方案是使用 https://github.com/Zhniing/im-select.nvim ,这个 fork 使用了 https://neovim.io/doc/user/autocmd.html#ModeChanged 来精确匹配切换模式,可以避开 Coc 的这个问题,配置需要修改为 set_default_events = { "VimEnter", ModeChanged = { "[iRc]*:[nvV\x16sS]*" } },
save_state_events = { ModeChanged = { "[iR]*:[nvV\x16sS]*" } },
set_previous_events = { ModeChanged = { "[nvV\x16sS]*:[iR]" } }, -- \x16 means Ctrl-V 复现 Coc 切换问题的 repro.lua Ubuntu: #19 (comment) SummaryConclusion: A bug/feature in Coc causes the input method to be switched to the default input method every time a candidate is switched when using Coc Completion in insert mode. This can be reproduced by the following script configuration, when using Coc complement (regardless of whether the shortcut is Ctrl+n/p or Tab, it should be triggered by a lower level command), every time you switch between the complement items, it triggers
This is an incompatibility, but currently this plugin can't solve it. An available solution is to use https://github.com/Zhniing/im-select.nvim, this fork uses https://neovim.io/doc/user/autocmd.html#ModeChanged to accurately match the switching mode, you can bypass this problem in Coc, the configuration needs to be changed to set_default_events = { "VimEnter", ModeChanged = { "[iRc]*:[nvV\x16sS]*" } },
save_state_events = { ModeChanged = { "[iR]*:[nvV\x16sS]*" } },
set_previous_events = { ModeChanged = { "[nvV\x16sS]*:[iR]" } }, -- \x16 means Ctrl-V You can reproduce this issue by Ubuntu: #19 (comment) |
I have been using this plugin for a while now, and enjoying the convenience of automatically switching IM, thanks for your work.
However, some specific needs cannot be met:
CmdlineLeave
is valuable, because we may search for some text in the command line. But, in most cases, we just want to execute some commands (e.g.:w
), and only the default IM will be used. So, we may not expect the default IM to override the previous IM.CmdlineEnter
(patterni:c
) andCmdlineLeave
(patternc:i
) events will be triggered when I type theEnter
key in the insert mode, which may cause unexpected IM state switching ifCmdlineLeave
is included inset_default_events
.Workaround:
The ModeChanged event supports the pattern match to identify events precisely:
i:n
,R:n
), which could be configured insave_state_patterns
.i:c
,c:i
), which could be configured inexclude_patterns
.这个插件非常棒,非常方便,感谢作者的积极维护。
用一段时间后,发现了一些问题:
CmdlineEnter
(i:c
模式)和CmdlineLeave
(c:i
模式)事件,如果在set_default_events
中配置了CmdlineLeave
就会自动切换为英文输入法。解决方案:
ModeChanged支持使用模式匹配来精确识别事件:
save_state_patterns
里面配置exclude_patterns
里面配置