linux_mint_21 vim配置:剪贴板支持和输入法自动切换
阅读原文时间:2023年07月18日阅读:2

一、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 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 fcitx2en()
33 autocmd InsertChange * call fcitx2back()