介紹

「编辑器战争」(Editor War)虽说是一场 Vim 与 Emacs 两派无休止的论战。但在我看来,只要完成了编辑器的配置并将其投入了日常生产,不论 Vim 还是 Emacs 的死忠粉,都可以得到十分优秀的体验。产生这一想法的原因是我在 Vim 上做了一次痛苦的尝试。特别是配置 YouCompleteMe 这个名字连听起来都些许暧昧的插件的时候,更是竭尽全力地让我感受到了它的恶意。

本文虽然没有忠实还原掉坑的全过程,我对操作顺序进行了调优,但保留了可能出现问题之处的描述,也对解决方案进行了解释。

Vim 版本 & 配置环境

欲编译安装的 Vim 版本是 Github 官方仓库中目前最新的 8.1

安装的操作系统环境是 Windows 10 17134 版本下 Windows Subsystem for Linux 提供的 Debian GNU/Linux。所以这里的 Debian 是 9/Stretch 的 stable 版本。

Windows Subsystem for Linux(以下简称 WSL)提供的 Debian 9 具有一定的特殊性,主要体现在环境相比大型的发行版更为精简干净,但这并不影响 Vim 的安装流程的体现。

编译安装 Vim 8

为什么编译安装

事实上,除了软件源缺失需要安装的软件包这一情况,一般用软件源下载安装软件应是首选方案。包管理器会好好地处理依赖,也不容易把系统变脏。所以推荐的在 Debian 系的发行版上的做法应该是:

1
sudo apt install vim

但是一些 Vim 插件(如本文的 YouCompleteMe )需要 Vim 对 Python 的支持。而这样默认安装的 Vim 是默认不开启对于 Python / Lua / Ruby 等语言的支持的。

那么如何开启呢?本文采用编译安装加入开启 Python 支持的选项,由此得到符合需求的 Vim 。其他解决方案如 vim-nox 则不再讨论范围之内。

下载 Vim 源码

先安装 Git 。尽管也可以直接前往 Vim 官方仓库获取源码,但考虑到多数的 Vim 插件管理器也都依赖 Git 对插件安装升级,所以 Git 应是我们的第一个安装项目。

1
sudo apt install git

你不需要对 Git 进行复杂的配置,虽然未来你有很大的必要这么做。这里我们只需要使用 Git 的简单操作获取源码。

1
git clone https://github.com/vim/vim

不出意外的话,这将需要几秒钟的等待。

编译 Vim 开启 Python 3 的支持

前面解释编译安装的原因时已经陈述了开启 Python 支持的必要性,那么这里不再重复,先安装 Python 3 与其支持库 libpython3-dev

1
sudo apt install python3 libpython3-dev

理论上主流发行版如 Debian 应已包含 Python3 的支持,但 WSL 并没有涵盖,所以补充安装之。

回到放置 Vim 源码的目录,进入 src 子目录。在编译之前,应确保 build-essential 包含的编译工具成功安装,否则将会因为找不到编译工具而报错。

1
sudo apt-get install build-essential

编译工具准备妥当后便可以开始编译安装。开始「编译三连」。

1
2
3
4
5
6
7
8
./configure --with-features=huge \
            --enable-multibyte \
            --enable-python3interp=yes \
            --with-python3-config-dir=/usr/lib/python3.7/config-3.7m-x86_64-linux-gnu \
            --enable-rubyinterp=yes \
            --enable-perlinterp=yes \
            --enable-luainterp=yes \
            --prefix=/usr/local/vim-8.1

第三条与第四条配置选项中,我选择开启了 Python 3 支持并告知了 config 文件所在目录。如果在上面遗漏了 libpython3-dev 的安装,可能会导致 config 文件的缺失。

当然,以上两个目录也会随着安装 Python 的版本变化(比如此处本机安装的是 3.7 的版本),若报错,可以在 /usr/lib 下目录寻找含有 config 字段的文件夹的 Python 目录填入。

如果需要 Python 2 的支持,比如有些老旧的插件仍然只支持 Python 2 但又没有其它插件可供选择,则应该加入:

1
2
--enable-pythoninterp=yes \
--with-python-config-dir=/usr/lib/python2.7/config \

相应地,你需要提前安装 Python 2libpython2-dev。需要注意的是如果安装了 Python 3 的所需文件,却错误地开启了 enable-pythoninterp 选项,Vim 会因为开启了 Python 2 支持而找不到 Python 2 相关文件而启用 Python 失败。所以,应注意安装相应的版本,开启相应的选项。

你或许也注意到了 Ruby 、Perl 和 Lua 的支持选项的开启,可以相应地进行改动如果确定你不需要这些支持。

--prefix 后的目录指定了 Vim 安装目标目录。

如果在执行 ./configure 时得到了一个这样的错误:

1
2
3
4
no terminal library found
checking for tgetent()… configure: error: NOT FOUND!
You need to install a terminal library; for example ncurses.
Or specify the name of the library with –with-tlib.

解决方案是如错误提示所说,安装 libncurses5-dev 即可。

1
sudo apt install libncurses5-dev

如果 ./configure 一切顺利,接下来你只需要执行:

1
2
sudo make
sudo make install

注册 Vim 为 Editor

Debian 下有以下用法可以将 Vim 注册为 editor:

1
sudo update-alternatives --install /usr/bin/editor editor /usr/local/vim-8.1/bin/vim 1

使用通用的软链接链上 vim

1
sudo ln -s /usr/local/vim-8.1/bin/vim /usr/bin/vim

这样一来,在命令行中输入 vim 即可运行 Vim。

这时为了确保 Vim 的 Python 支持如计划被启用,以下命令可以进行验证:

1
vim --version | grep python

不出意外输出结果其中有两项分别为:

1
2
-python
+python3

项目前存在加号则表明此项启用,存在减号即未启用。所以此处 Python 3 的支持被成功启用了。

安装 YouCompleteMe 插件

YouCompleteMe(以下简称 YCM)是 Vim 上的一款强大而充满恶意的自动补全插件。YCM 官方仓库 的 issues 中,其作者 Valloric 不厌其烦地提醒 issues 作者们好好阅读官方文档,所以跟着官方的 Installation Instructions 并在碰到坑之后先查阅一番 User Guide —— 这也是接下来我们应坚守的流程。

本文中配置 YCM 的目标是让其支持 C/C++ 的自动补全,其它语言不在本文讨论范围内。值得一提的是,对于 C Family 的语义自动补全,官方指定一定要阅读 这份资料

安装 vim-plug 插件管理器

虽然我们的目标仅仅是安装 YCM,但为以后 Vim 的使用做考虑,使用插件管理器的极大帮助是不容忽视的。这里我们选择的是支持异步安装的 Github 上 Star 数目排名第二的 Vim 插件管理器 —— vim-plug

需要下载仓库中的 plug.vim 文件并将其放入 autoload 目录中。

autoload 文件夹存在于 ~/.vim 目录中,两个目录若不存在都可以简单新建得到。

编辑 ~/.vimrc 文件(如果没有请新建),加入对 YCM 的引用。

1
Plug 'Valloric/YouCompleteMe'

vim-plug 的使用方法在官方仓库中的 README 中就已经介绍得十分完备了。简单地说,你可以把上面的那一行配置中单引号间的内容修改为其它插件的地址(按照 「Username/Plugname」 的格式)对插件进行引用。

如果现在对于 Vim 不是很熟悉,可以使用 nano~/.vimrc 进行修改。

安装 Clang

对于 C Family 的语义补全,YCM 采用了 Clang 的语义检索引擎。虽说自带 libclang 但是文档中还是给出了自行编译得到 libclang 的建议。这意味着 Clang 被正确配置在这台计算机上是大前提。

Clang 作为一款基于 LLVM 的编译器,也需要安装 LLVM 框架系统。你可以使用软件源安装(写作本文时最新版本为6.0):

1
sudo apt install clang-6.0

这是最快捷方便的安装 Clang + LLVM 的方式。如果分别下载源码编译安装,其实也并不繁琐。当然,LLVM 在 Download Page 也提供了针对不同系统不同发行版的预编译包。所以,你也可以把下载下来的预编译包移动到 /usr/local 也就是 Vim 安装目录旁边。

以下版本号均使用 xxxxxxx 代替,请以实际下载下来的文件名为准。

1
sudo mv /path/to/package/clang+llvm_xxxxxxx /usr/local

别忘了链接到 clangclang++

1
2
sudo ln -s /usr/local/clang+llvm_xxxxxxx/bin/clang /usr/bin/clang
sudo ln -s /usr/local/clang+llvm_xxxxxxx/bin/clang++ /usr/bin/clang++

至此,Clang 准备完毕。而 libclang 也静静地藏在了 /usr/local/clang+llvm_xxxxxxx/x86_64-linux-gnu/lib 里了。

安装 Cmake

Cmake 是 YCM 默认支持的编译工具,所以使用 Cmake 来编译 YCM 是最安全稳妥的方式。如果这里嫌麻烦不安装 Cmake 去编译 ycm_core,Vim 在启动后会给出错误:

1
The ycmd server SHUT DOWN (restart with ':YcmRestartServer'). Unexpected error while loading the YCM core library.

同时好消息是 Cmake 提供了 Shell 的安装脚本,在 Download Page 中寻找到自己的平台下载即可。下载完成后到达脚本所在目录,移动到 /usr/local ,随后执行安装。

1
2
sudo mv /path/to/cmake-x.xx.x-Linux-x86_64.sh /usr/local
sudo /usr/local/.cmake-x.xx.x-Linux-x86_64.sh

x.xx.x 指版本号,以下载下来的文件为准。

输入 y 选择接受协议并根据提示再次输入 y 安装到所在目录单独子目录。

于是,Cmake 准备好了。

使用 vim-plug 安装 YCM

刚刚仅仅是在 ~/.vimrc 中引用了 YCM ,并没有真正下载安装它,现在才是到了编译安装 YCM 的时候。YCM 安装脚本需要 Cmake 生成一些配置文件并自行编译,所以我们在安装好 Cmake 后执行安装脚本会为我们省不少事情。

打开 Vim,键入 : 进入命令模式,输入 PlugInstall,回车确认。此时 vim-plug 开始通过 Git 获取每一个插件,并妥善处理安装目录。目前只引用了一个插件,所以任务列表中应该只有一项 YouCompleteMe 的安装。

YCM 是较为复杂的 Vim 插件,所以下载下来之后有自己独特的从 Github 获取依赖包的过程,这需要一定的时间。

执行安装脚本并加入 --clang-completer 参数

这一步是向 YCM 添加对于 C-Family 的语义补全支持中的重要一步。所以需要做的是在它的目录下执行 install.sh 加入 --clang-completer 参数:

1
2
cd ~/.vim/plugged/YouCompleteMe
./install.sh --clang-completer

相应的,存在 --js-completer, --java-completer--rust-completer 等参数,可以视需要添加。

如果浏览了一遍 YCM 的目录,你或许会发现有一个名为 install.py 的 Python 脚本。所以如果想使用这个脚本,这也是可行的选择。

1
2
cd ~/.vim/plugged/YouCompleteMe
python3 install.py --clang-completer

如果你使用的是 vundle 插件管理器,YCM 的安装目录应该在 ~/.vim/bundle 下,而非 vim-plug 指定的 ~/.vim/plugged

编译 ycm_core

理论上执行了上一步就已经完成了 YCM 的安装,但是此时启动 Vim 可能仍会得到来自 YCM 的若干错误。其中,它会对寻找 Python 的运行库有不小的困难。

这里 YCM 给出的错误在网络上有多种形式,以 无法加载种种 Python 模块 一类居多。

别忘了还要让 YCM 使用我们刚刚装好的 libclang 。所以编译 ycm_core 加入提供 Python 所在目录的相关参数的同时,顺便加入 -DEXTERNAL_LIBCLANG_PATH

1
2
3
4
5
6
cmake -G "Unix Makefiles" ~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ \
    -DUSE_SYSTEM_BOOST=ON \
    -DEXTERNAL_LIBCLANG_PATH=/usr/local/clang+llvm-xxxxxxx/lib/libclang.so \
    -DPYTHON_LIBRARY=/usr/lib/python3.7 \
    -DPYTHON_INCLUDE_DIR=/usr/include/python3.7 \
    -DUSE_PYTHON2=OFF

LIBCLANG_PATH 指的是 libclang.so 文件所在位置,这取决于前面对 Clang 的安装所选择的目录。

PYTHON_LIBRARYPYTHON_INCLUDE_DIR 则与 Python 版本号(此处是3.7)或安装目录相关。

特别值得注意的是,YCM 此处的 Makefile 默认使用 Python 2 编译,所以如果你没有安装 Python 2 而且设定的 Python 的运行库和头文件目录是 Python 3 的目录,会得到报错:

You set USE_PYTHON2 to make CMake find python2 libs only, but CMake found python3 libs instead. Either don’t set USE_PYTHON2 or install the necessary python2 headers.

解决方案是正如所给的参考参数中最后一行在 Cmake 命令后再添加一行 -DUSE_PYTHON2=OFF 。当然,如果从头你就是用 Python 2 的,就应该把这行去掉,直接执行命令。

指定 .ycmextraconf.py

此时使用 Vim 打开一个 C/C++/ObjC/ObjC++ 文件,有一定的可能还会看到这样的一条错误,同样来自 YCM:

No .ycm_extra_conf.py file detected, so no compile flags are available. Thus no semantic support for C/C++/ObjC/ObjC++. See the docs for details.

深呼吸,这个问题在 YCM 的 仓库 issues 列表以各种描述形式存在。这是 YCM 找不到最为关键的 C-Family 自动补全的配置文件导致的。实际上,这个 ycm_extra_conf.py 文件位置是在这个藏得很深的目录之下的。

1
~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ycm

~/.vimrc 中指定它所在的位置即可。

1
let g:ycm_global_ycm_extra_conf = '~/.vim/plugged/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py'

有人也选择把 ycm_extra_conf.py 文件从深处的目录中拷贝出来,到 YCM 主目录较为浅层的地方,然后再修改 g:ycm_global_ycm_extra_conf 变量。

更进一步

如果不出意外,安装应该是顺利完成。至此,我叙述完毕了安装 Vim 和 YouCompleteMe 插件的流程。除去 issues 中一些奇怪的问题,本文基本覆盖了经典的坑。

关于 Vim 的美化以及进一步的配置不是本文所涉及的内容,所以在这里推荐大家阅读:

  • 官方钦定的 Vim Tips Wiki

  • Github 上 Star 数目较多的 .vimrc

最重要的是,不在调优工具上花费太多的时间,赶紧熟悉 Vim 的键位,尽快地将工具投入生产才是硬道理。

感谢阅读 💗