对于许多经常写代码的朋友来说,终端可能是绝大多数输入操作的载体。而对于熟练使用 VIM 的用户来说,大量便捷的快捷操作,丰富多样的命令模式,深度可定制的 vimrc 使得 VIM 成为了程序员最亲切的编辑器双雄之一(其二是 Emacs)。正是由于 VIM 的深度自定义特点,使得极客们能够将 VIM 改造成随心所欲的地步,正所谓
一千个程序员就有五百零一个 vimrc
你们都很好,但是还不够
每个人的 vimrc 就像是自己的个性宣言,是独一无二的。在普通的文本写作场景中,我们很自然地希望把这种人机合一的美好体验延续到 Markdown 的使用中去。在 macOS 平台上从来就不缺乏优秀的 Markdown 应用,在经历过 Mou / Ulysses / Quiver / Typora / MWeb 之后,总觉得没办法完完全全称心如意:
- 无法使用 VIM 的各种非常便捷的复制、剪切、跳转、删除等等操作。
- 无法自定义种种依据个人习惯的操作命令。
- 无法与 code 撰写形成一致的和谐体验。
我们不禁呼喊:『要是 VIM 就能同时解决 code 和 markdown 写作,那该是何其美哉!』
用 VIM 做 Markdown 编辑器实现英文单词实时联想
对我而言,论文需要英文写作,而如果有类似搜狗输入法的自动联想功能,将使英文输入如虎添翼,大大提高输入效率。在尝试过搜狗输入法的英文助手、TypeFast 输入法之后,发现几个问题:
- 搜狗英文助手需要在搜狗输入法内进行中英文切换操作,与系统英文输入法容易混用
- TypeFast 输入法是个人项目缺少维护,词频不可定制
- TypeFast 输入法的引入相当使得系统内至少需要 3 个输入法,增加了选择难度
因此 macOS 自带的自动补全功能更胜一筹,详见试试 OS X 系统的英文补全:

然而这个功能在系统升级到 Sierra 之后将不能使用 Esc ( ⎋ ) 键触发,现在仅剩下两种触发快捷键:
⌥ + ⎋ 或 Fn + F5
另外系统原生的自动补全在 VIM 中本来也就不支持,而且同样具有不能调整词频的缺点。
Neocomplete 插件的安装与配置
Neocomplete 是 VIM 上的一款知名自动补全插件,代码的自动补全使其常规功能,这里不做展开,这里仅利用了它可以自定义字典的特性。以 macOS 平台举例,注意首先安装 vim with lua:
brew install vim --with-lua
接着按照官网说明安装即可,然后在你的 vimrc 中添加如下内容,用于开启常用功能
let g:neocomplete#enable_at_startup = 1
let g:neocomplete#enable_smart_case = 1
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
英文词库的自定义与维护
英文词库我搜集了常用单词库与托福单词库合计 8000 多个,放在 百度云 上供大家下载。当然也可以把词典里的所有单词都放进词库,但这样做可能会拖慢英文联想的响应速度,可根据个人喜好和硬件配置权衡设置。
甚至可以把任一篇文章里的单词提取出来整理成词库,步骤也很简单
- 把文章全文复制到 VIM 中去
- :%s/\v[^\x00-\xff]+//g 删去所有中文
- :%s/ /\r/g 将所有空格变换行
- :sort 排序
- :g/^\(.*\)$\n\1$/d 删去重复行
当然再做些删除一些不需要的单词,一些特殊字符之类的操作,你的个性化词典就完成了,给它保存个名字,比如 sum.dict,为了让 VIM 能够调用这个词库,新建路径:
mkdir ~/.vim/dict
打开 dict 文件可以一窥成品:

将 sum.dict 放入新建的路径中,并在 vimrc 中添加如下配置,词典就可以正常调用了
let g:neocomplete#sources#dictionary#dictionaries = {
\ 'default' : '',
\ 'markdown' : $HOME.'/.vim/dict/sum.dict',
\ 'vimshell' : $HOME.'/.vimshell_hist',
\ 'scheme' : $HOME.'/.gosh_completions'
效果如下

弹出窗口的选择键与颜色配置
Neocomplete 自动弹窗的选择键也可以在 vimrc 中自定义,这里是我的方案:
inoremap <expr><space> pumvisible() ? neocomplete#close_popup() . "\<SPACE>" : "\<SPACE>"
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <s-tab> <Up>
实现的功能是用 Tab / Shift + Tap 键选择候选单词, 用 Space 键确认并补充空格,选择效果如下,行内单词会随着候选单词的变化而跳变:

弹出窗口的颜色可以在 vimrc 中设置(同理 cursorline 也可以类似设置),这里我定义了灰底白字:
highlight Pmenu ctermfg=250 ctermbg=000
cterm 颜色的定义可在此下载,部分定义截图如下

用 VIM 做 Markdown 编辑器实现中文与 Norm 模式完美兼容
不仅用于英文写作,VIM 自然更可以用于中文写作,然而在使用过程中有一个不可忽视的问题必须要解决:这就是与 Norm 模式的兼容问题。在 Insert 模式中正常输入中文当然没问题,然后想要利用 VIM 诸多的便利操作,必须要回到 Norm 模式。问题的症结在于
- 切换到 Norm 模式后,输入法依然停留在中文输入法
- Norm 操作只支持英文输入法
- 因此必须要进行输入法切换
- Norm 操作完毕之后回到 Insert 模式,输入法依然停留在英文输入法
- 还需要输入法进行二次切换回中文输入法
其实就是这个拦路虎造成了 VIM 中文输入的最大障碍,在 linux 下可以通过 fcitx 命令结合 vimscript 解决。在 macOS 下需要使用 fcitx-remote-for-osx 来辅助:
brew install fcitx-remote-for-osx
brew install fcitx-remote --with-input-method=general
然后在系统设置中将『选择「输入法」菜单中的下一个输入法』快捷键改为 Ctrl-Shift-z

并在 vimrc 中添加如下内容,这部分 vimscript 来自于 lilydjwg/fcitx.vim
function! Fcitx2en()
let input_status = system('fcitx-remote')
if input_status == 2
let b:inputtoggle = 1
call system('fcitx-remote -c')
endif
endfunction
function! Fcitx2zh()
try
if b:inputtoggle == 1
call system('fcitx-remote -o')
let b:inputtoggle = 0
endif
catch /inputtoggle/
let b:inputtoggle = 0
endtry
endfunction
" Autocmds:
au InsertLeave * call Fcitx2en()
au InsertEnter * call Fcitx2zh()
做了上述处理之后,VIM 中进行中文输入切换到 Norm 模式会自动变成英文输入法,重新回到 Insert 模式又会变回成中文,从而实现了完美切换。
用 VIM 做 Markdown 编辑器实现系统剪贴板的全局共享
VIM 在剪切 / 复制 / 删除等等方面的操作非常方便,通过如下设置可以让 VIM 与系统共用剪贴板,从而实现 多终端内容剪切 / 终端到系统内容剪切 / 系统应用直接内容剪切 的功能。而 vimrc 通过如下设置可以令 VIM 支持触摸板滚动,达到更好的阅览效果,而 VIM 的更多与 Markdown 语法的集成还有琳琅满目的插件可供选择。
set clipboard=unnamed
set mouse=nicr
满足个性化定制的方案是没有一定之规的, VIM 与 Markdown 的结合提供了这样一种探索,一种让极客们随心所欲把玩文字,写代码之余还能写文稿的一致体验。
