linux_mint_21 vim配置:剪贴板支持和输入法自动切换
一、vim的剪贴板支持
有的vim版本不支持系统剪切板,也就是说在vim编辑器外面复制的内容,不能够粘贴到vim中;在vim中通过yy、d、c复制剪切的内容也不能粘贴在vim编辑器外面。
这实在是有点奇怪,特别是对windows用户来来说。本来写东西就是复制粘贴,一个文本编辑器复制粘贴都做不到,那搞毛线啊~
我们可以通过在终端输入命令来查看vim是否支持系统剪切板:
vim --version | grep clipboard
终端会输出两行内容:需要关注是“clipboard”和“xterm_clipboard”前面的符号。如下图所示,两个条目前面都是+号(如下图所示),则vim支持系统剪切板,否则不支持。
既然有的vim版本支持剪切板,有的版本不支持,那么是不是自己选择一个版本的源码自己编译安装就行了?折腾了一下,还是不行。
简单说(不一定正确):图形界面的vim,即gvim,一般都支持系统剪切板;而没有图形用户界面的vim,很多不支持系统剪切板。
既然如此,下载一个gvim就行了:
sudo aptitude install vim-gtk
vim-gtk即一个发行版的gui vim。执行这条命令,本质是下载了一个gvim,但是同时也让vim能支持系统系统剪切板。
换一句话说,安装一个gvim,多花了几十M的空间而已,不想用gvim,当它没被安装就好了。这种方式最简单直接。
二、 输入法的切换
(环境:mint21,vim8.2,输入法框架fcitx)
使用vim的时候经常需要在不同的“模式”切换。有的说vim只有两种模式,普通模式和插入模式,这是简单的说法;其实vim的模式有七八种。
其中最经常的就是在普通模式和插入模式间切换。当我们在插入模式切换到普通模式后,想通过按键k移动光标到上一行,如果当前是输入法是中文,我们需要按两次按键,即k+enter(或者shift+k),如果是英文输入状态下我们按下k,光标直接就移动了。所以,能不设置成这样:vim从插入模式切换到普通模式后,输入法同时自动切换到英文。
网上有很多解决办法,大多不管用。不管用的原因是我们的系统有差别,我们的的输入法和vim的版本……也可能不同。
想要达成在vim中自动切换输入法关键在于两点:
(1):识别出vim中模式的转变。
(2)根据(1)识别出来的结果调用软件切换输入法。
vim自己会实时记录自己当前的模式,所以(1)很容易实现。关键在于第二点。
我用的输入法框架是fcitx(不是fcitx5).在fcitx框架中,有一个方法可以查看和改变输入法。
$ fcitx-remote 1 # 执行fcitx-remote,能够获取当前的输入法,当前的输入法是1 $ fcitx-remote -o $ fcitx-remote 2 # fcitx-remote -o ,将输入法改变成2 $ fcitx-remote -c $ fcitx-remote 1 # citx-remote -c ,将输入法改变为1
fcitx-remote是输入法框架fcitx下的一个程序,在目录(/etc/)下可以找到。不带参数调用它,返回当前输入法(1或者2);带参数-c调用,将输入法改为1(英文);带参数-o,将输入法该为2(中文).附带说一句,如果输入法框架是fcitx5,这这个程序名字是fcitx5-remote,也在这个目录。
所以将下面的语句复制到"~ ./.vimrc"中理论上就能实现当:从插入模式切换到普通模式,输入法设置为英文。
1 if exists('s:loaded') 2 finish 3 endif 4 let s:loaded = 1 5 let s:f_status = system("fcitx-remote") 6 let s:cmd = s:f_status == 1 || s:f_status == 2 ? "fcitx-remote" : "fcitx5-remote" 7 8 func! s:fcitx2en() 9 let l:lang = system(s:cmd) 10 if l:lang == 2 11 call system(printf("%s -c", s:cmd)) 12 endif 13 endf 14 15 autocmd InsertLeave * call <SID>fcitx2en()
实际上第一次使用这个脚本的时候,脚本只能在第一次切换到普通模式时自动切换输入法,而且还让我接下来不能通过shift按键切换输入法(输入法处于半卡死的状态)。
许多人在做类似的尝试也碰到过类似的问题。
如果代码很长,我可能会怀疑代码有问题,但是上面的代码很短,很简单,能够看出并没有问题。那问题出在哪里?
我不知道问题出现在哪里,但是最终通过简单的输入法设置,解决了问题。
打开输入法设置,将上面的红色方框中的快捷键设置为自己切换输入法时常用的按键。我习惯用两个shift进行输入法切换,所以就设置成上图这个样子。
至于设置完后,为什么代码能够成功切换输入法,我也不是很明白。
再说一句题外话:方框中的“切换激活/非激活输入法”这句话我倒现在也不明白什么意思~我开始以为是“切换输入法”的意思,现在我认为是“让输入法在激活和非激活两种状态之间切换”,即切换的不是输入法,而是输入法的激活状态。
这种机器翻译的汉语,理解起来是真的费劲。
前面的代码只是实现了从insert模式进入到normal模式后自动切换成英文的功能。类似的功能有一个需求没那么大的,那就是:进入insert模式的时候,将输入法自动切换回到上一次退出insert模式的输入状态。
比如我们:(1)在insert模式中以中文状态进行编辑;(2)然后切换到normal模式移动光标;(3)再切换回到insert模式,希望输入法能自动回到(1)中的输入法状态。前面的代码只是实现了(1)--->(2)的输入法自动切换;但是不能做到(2)--->(3)的自动切换。
查考下面:
1 https://github.com/lilydjwg/fcitx.vim/blob/fcitx5/plugin/fcitx.vim
然后稍微修改一下:
1 if exists('g:fcitx_auto') 2 finish 3 endif 4 let g:fcitx_auto = 1 5 6 let s:r_status = 1 7 let s:f_status = system("fcitx-remote") 8 9 "输入法框架是fcitx启用下句,不确定是fcitx还是fcitx5,启用下下句。 10 let s:cmd = s:f_status 11 "let s:cmd = s:f_status == 1 || s:f_status == 2 ? "fcitx-remote" : "fcitx5-remote" 12 13 14 function s:fcitx2en() "离开插入模式,自动改变输入法为英文,同时记录输入法状态 15 let l:lang = system(s:cmd) 16 if l:lang == 2 17 call system(printf("%s -c", s:cmd)) 18 let s:r_status = 2 19 else 20 let s:r_status = 1 21 endif 22 endfunction 23 24 function s:fcitx2back() "进入插入模式的时候,切换回上一次插入模式时的输入法 25 if s:r_status == 1 26 call system("fcitx-remote -c") 27 else 28 call system("fcitx-remote -o") 29 endif 30 endfunction 31 32 autocmd InsertLeave * call <SID>fcitx2en() 33 autocmd InsertChange * call <SID>fcitx2back()