Vim 一款让我相见恨晚的编辑器

发布于 2024-12-11 12:11:13 字数 17443 浏览 0 评论 0

0.1 Vim 简介

Vim is a greatly improved version of the good old UNIX editor Vi. Many new features have been added: multi-level undo, syntax highlighting, command line history, on-line help, spell checking, filename completion, block operations, script language, etc. There is also a Graphical User Interface (GUI) available.

以上关于 Vim 的描述来自 Vim 的官方 GitHub 仓库。 Vim 是一款古老且强大的编辑器,从其诞生之日起到现在已经有二十多年的历史(比我的年 龄都要大 orz)。很多人听说它的大名一般是因爲它与 Emacs 并称编辑器之神与神之编辑器。爲 什麽会有这样的名号?除了它们的功能极其强大之外,还因爲它们极其难以上手。以下图片 爲网友戏称的常用编辑器的学习曲线。

即便如此,Vim 和 Emacs 仍流行到了现在, 以至于后来经常能在各处看到的 Vimer(Vim 党)和 Emacser(Emacs 党)的编辑器之争, 虽然有的时候可能只是类似于 "php 是世界上最好的语言" 之类的梗,但足以看出 Vim 确 实非常强大,并且用上了就再也回不去了。

0.2 安装 Vim

Vim 在所有的 Linux 发行版上都易于获得,只需要使用对应的包管理器进行安装即可, Windows 上也有编译好的二进制包,但实际在安装过程中仍会面临几个选择。

以 Archlinux 爲例,Archlinux 的官方仓库中包含的 Vim 在编译过程中并没有编译进 python、lua 等支持,导致很多插件无法使用,因此爲了能使用上 Vim 的完全体,可以选 择 Gvim。Gvim 是基于 Vim 的一个带有图形界面的版本,并在编译过程中包含进了所有可 用组件。如果选择 Vim 分支,强烈建议使用 Gvim,并且使用 8.0 之后的版本。下载链接 在 此处

另一个可供选择的版本是 Neovim,Neovim 是 Vim 的一个 fork 版本,比 Vim 具有更多的 特性(Neovim 先首先支持的异步架构和内置 terminal,随后 Vim 也提供了支持),目前 开发活跃,推荐进行尝试。下载链接在 此处

以上的所有版本在下文中都将统一称爲 'Vim'(虽然事实上 Vim 与 Neovim 并不是同一个 项目,但在配置和使用方法上是类似的)。无论安装哪个版本,安装完成后从应用啓动菜单 或命令行应该就能成功啓动。恭喜你!此时已经完成了安装 Vim 的第一步,现在你看到的 是一个黑底白字的字符界面。不过彆着急,接下来我们会一步一步将 Vim 配置成称手的编 辑器。

0.3 退出 Vim - 使用 Vim 的第一大难题?

虽然客观上讲,退出 Vim 相较于 Vim 其他功能要容易的多,但是确实是第一次使用 Vim 会遇到的一个问题。相对于其他的编辑器,Vim 没有直观的退出方式,以至于在 Stack Overflow 上有个专门的问题 ( 见 此处 )解答如何退出 Vim。甚至有了如下的梗:

看来确实有必要对 Vim 的退出方式做个总结,之列出平常最常用的几种退出方式

  • :q 正常退出
  • :q! 强制退出不保存
  • :wq 保存并退出
  • :x 保存并退出,与 :wq 不同之处在于如果文件未做修改则不更新时间戳
  • 强制关机

0.4 使用 Vim 前先看帮助文档

安装好 Vim 后,你可能想要马上尝试输入。但我强烈建议先阅读软件自带的帮助文档,一 款优秀的软件都会带有一个详细的用户手册以及一个简要的使用说明,这有助于降低你在接 触新软件时的痛苦感。你可以在 Vim 中随时通过输入 :help<CR> ( 代表回车)来呼出 帮助文档。

0.5 配置 Vim - 从 .vimrc 开始

由于 Vim 的流行,GitHub 上有各种各样现成的 'vimrc'(Vim 的配置文件)可供使用。对 于不想自己折腾配置的用户来说,从 GitHub 上下载安装其他用户已经编辑好的 'vimrc' 是最好的选择。甚至还有像 SpaceVim 这样 的模块化 Vim 配置可以一键安装使用,能大大减少配置所需的时间。

另一些用户可能想要继续对 Vim 进行自定义配置,那麽就需要对 'vimrc' 进行修改。在 Linux 系统中,Gvim 与 Vim 的配置文件默认存放在 $HOME/.vimrc (Neovim 存放在 $HOME/.config/nvim/init.vim ),Windows 下存放在 $VIM/vimrc

你可以选择自己新建一个文件从头开始。不过还是建议拷贝官方自带的配置示例,一方面可 以省去一部分对常规配置的修改时间,另一方面,官方示例中对各配置语句对应有详细的注 释。或者也可以选择从 GitHub 上寻找一个适合你的 'vimrc',或者参考 我的配置

0.5.1 常规配置

在使用 Vim 之前,我们需要对其进行一些常规配置,来使它看起来更像一般的编辑器(以 下步骤默认了你已经学会 Vim 的基本操作,包括移动光标、输入、模式切换等)。

首先,通过输入 :e $HOME/.vimrc<CR> 打开配置文件( $HOME/.vimrc 替换爲你平台 对应的配置文件路径)。这时,如果此前你已经拷贝了 Vim 的示例配置文件,或者是从网 上下载安装了其他人的配置,那麽你打开的文件里应该就有那些内容,如果此前还未做过配 置,那麽打开的就是一个空文件。

接下来可以选择下面的配置中你需要的部分拷贝进你的 'vimrc'

  " about vim setup
  set nocompatible               " disable compatible for vi
  set shell=/bin/bash            " setup default shell
  set shortmess=at               " 啓动时隐去援助提示
  set mouse=a                    " active mouse control
  set clipboard+=unnamed         " support system clipboard
  let mapleader=';'              " remap <leader>
  " display setup
  set relativenumber             " display relative row number
  set ruler                      " 显示标尺,就是在右下角显示光标位置
  set spell spelllang=en_us,cjk  " Spell checking for English, escape Chinese
  set langmenu=zh_CN.UTF-8
  set helplang=cn                " 设置帮助文档爲中文,需要 'yianwillis/vimcdoc'
  syntax enable                  " syntax highlight enable
  syntax on                      " syntax highlight on
  set background=dark            " setup background color
  colorscheme gruvbox            " setup color scheme
  set wildmenu                   " select the candidates in interactive way
  set backspace=indent,eol,start " more powerful backspacing
  set cursorcolumn               " 浅色高亮当前列
  set cursorline                 " 浅色高亮当前行
  set novisualbell               " 关闭视觉响铃
  set laststatus=2               " 啓动显示状态行
  set showcmd                    " show the command executed by shortcuts
  set noshowmode                 " don't show the mode status, avoid override argvs hint
  set hlsearch                   " highlight for searched results
  set incsearch                  " highlight for searching results
  set showmatch                  " show the match of brackets and Quotation mark
  set ignorecase                 " ignore case when searching and command completion
  set gdefault                   " default substitute in the whole line

其中,最重要的一条设置就是 set nocompatible ,它的作用是关闭对 Vi 的兼容性。Vi 是一款更加古老的编辑器,可视作是 Vim 的前身。如果保留对 Vi 的兼容性也就意味着你 放弃了很多 Vim 独有的特性。 set shell=/bin/bash 显式地声明瞭 Vim 在运行脚本时 调用的解释器,如果是 Windows 用户则需要去掉这行。

此时保存配置文件并通过 :so \$HOME/.vimrc<CR> 重载配置后应该就能看到改变了。但 此时你可能会注意到几条错误信息,不要紧张,这是因爲我们在配置中引用了一些插件功能, 但事实上我们现在还未安装插件,安装插件后你会看到错误就消失了。

0.5.2 安装插件管理器 - 管理插件的插件

Vim 有非常多的插件管理器可以使用,除去功能上的细微差异,我们可以将所有插件管理器 分爲异步型和同步型。可以简单地理解爲异步型可以同时下载安装多个插件,而同步型一次 只能处理一个。在 Vim 7.4 版本出来之前,插件管理器都是同步型的,包括大名鼎鼎的 Vundle。

在我刚开始使用 Vim 的时候,Vim 和 Neovim 都已经支持异步架构,但由于当时查的是中 文资料,很多都是非常老的文章。基本上所有文章都推荐使用 Vundle 作爲插件管理器,事 实上在你用过 vim-plug 之类的异步插件管理器后,你会无法再忍受 Vundle 的速度。这告 诉我们技术型的文章还是要去 Google...

不会有人再去使用 Vim 7.4 之前的版本了,所以这里我推荐使用 vim-plug 作爲插件管理器。vim-plug 的优 点是异步下载安装、插件更新方便、支持插件按需加载,并且只包含一个文件。它的 GitHub 仓库 上有详细的安装教程。

0.5.3 安装插件 - 本体不够再打 mod

虽然 Vim 并不是扩展性最好的编辑器,但它仍支持成千上万个插件。寻找插件最好的途径 是 GitHubVim Scripts 。以下是我使用的插件列表:

  let g:python3_host_prog = "/usr/bin/python3"
  call plug#begin('~/.vim/plugged')
  Plug 'tomasr/molokai'                                             " molokai color scheme
  Plug 'morhetz/gruvbox'                                            " gruvbox colorscheme theme
  Plug 'mhinz/vim-startify'                                         " an awesome startup screen
  Plug 'vim-scripts/fcitx.vim'                                      " auto switch fcitx status
  Plug 'manu-mannattil/vim-sdcv'                                    " a simple dictionary for vim
  Plug 'vim-airline/vim-airline'                                    " add status line
  Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }            " directory tree
  Plug 'majutsushi/tagbar', { 'on': 'TagbarToggle' }                " Class structure viewer, need ctags installed
  Plug 'mbbill/undotree', { 'on': 'UndotreeToggle' }                " undo tree manager
  Plug 'tpope/vim-fugitive'                                         " git support
  Plug 'junegunn/gv.vim'                                            " view git commits in Vim
  Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } " fuzzy file searcher
  Plug 'junegunn/fzf.vim'                                           " provide many other search functions
  Plug 'tpope/vim-commentary'                                       " a better comment tool
  Plug 'vim-scripts/EasyMotion'                                     " enhance default motions
  Plug 'Yggdroot/indentLine'                                        " indent line indicator
  Plug 'jiangmiao/auto-pairs'                                       " auto add pairs
  Plug 'junegunn/rainbow_parentheses.vim'                           " a much simpler-using fork of above
  Plug 'junegunn/limelight.vim'                                     " dim others
  Plug 'junegunn/goyo.vim'                                          " provide a dim writing environment
  Plug 'w0rp/ale'                                                   " syntax error check
  Plug 'Valloric/YouCompleteMe',                                    " auto complete
              \{ 'do': './install.py --clang-completer' }
  Plug 'SirVer/ultisnips'                                           " auto complete string
  Plug 'honza/vim-snippets'                                         " complete rules for ultisnips
  Plug 'junegunn/vim-easy-align'                                    " align tool
  Plug 'godlygeek/tabular'                                          " advanced align tool
  Plug 'gabrielelana/vim-markdown', { 'for': 'markdown' }           " markdown plugin
  Plug 'joker1007/vim-markdown-quote-syntax', { 'for': 'markdown' } " syntax highlight for quoted code
  Plug 'iamcco/mathjax-support-for-mkdp', { 'for': 'markdown' }     " mathjax support for markdown preview
  Plug 'iamcco/markdown-preview.vim', { 'for': 'markdown' }         " markdown preview support
  Plug 'vim-scripts/indentpython.vim', { 'for': 'python' }          " auto indent for python
  Plug 'nvie/vim-flake8', { 'for': 'python' }                       " flake8 style code check, need install flake8
  " 这两个插件被 neoformat 替代了
  " Plug 'tell-k/vim-autopep8', { 'for': 'python' }                 " a python code format tool wrapper for autopep8
  " Plug 'fisadev/vim-isort', { 'for': 'python' }                   " imports sorter for python
  Plug 'vim-latex/vim-latex', { 'for': 'tex' }                      " latex edit environment
  Plug 'skywind3000/asyncrun.vim'                                   " AsyncRun plugin
  Plug 'hotoo/pangu.vim'                                            " Chinese text format
  Plug 'vimwiki/vimwiki'                                            " write wiki in vim
  Plug 'yianwillis/vimcdoc'                                         " a Chinese help handbook for Vim
  Plug 'sbdchd/neoformat'                                           " a collection of format tools
  Plug 'ludovicchabant/vim-gutentags'                               " generate tags for project
  Plug 'mhinz/vim-signify'                                          " show file modifying status for git
  Plug 'Shougo/echodoc.vim'                                         " show argvs hint on the command line
  "======================"
  "  text object 全家桶  "
  "======================"
  Plug 'kana/vim-textobj-user'                                            " 用户自定义 text object
  Plug 'kana/vim-textobj-indent'                                          " 缩进对象,关键字 <i>
  Plug 'kana/vim-textobj-syntax'                                          " 语法对象
  Plug 'kana/vim-textobj-function', { 'for':['c', 'cpp', 'vim', 'java'] } " 函数对象,关键字 <f>
  Plug 'sgur/vim-textobj-parameter'                                       " 参数对象,关键字 <,>
  Plug 'coderifous/textobj-word-column.vim'                               " 列对象,关键字 <c>
  Plug 'bps/vim-textobj-python'                                           " python 对象合集,<c> 类,<f> 函数
  Plug 'tpope/vim-surround'                                               " deal with surround for text object
  call plug#end()
  filetype plugin indent on

由于 vim-plug 的强大,我们只需要将上述配置粘贴进 vimrc 中,重载配置文件后运行 :PlugInstall<CR> 就会自动安装所有插件,甚至 vim-plug 会帮我们做好安装后的处理。

0.5.4 必装插件配置 - 大大提高生产力

通过 vim-plug 安装的插件大部分都是即装即用的,但也包括小部分需要在安装完成后进行 一定的配置才能舒适地使用。

0.5.4.1YouCompleteMe - 最强补全神器

YouCompleteMe 是谷歌程序员 Valloric 开发的一款智能补全插件。在 YouCompleteMe 出来之前,大部分补全插件都是基 于 tag 分析,也就是从当前文件以及其他 buffer 中的文件文本中匹配类似字符串进行补 全,说白了就是靠猜。而 YouCompleteMe 是真正支持程序语义分析的补全,能够理解程序 语言进行补全,准确率大大提高,并且体验也提升了很多。

盗用 YouCompleteMe 官方仓库上的一张效果图:

虽然 YouCompleteMe 效果看起来很炫酷,但它也被称爲“最难安装的插件”。它的底层是用 C++ 写成的,爲了能作爲 Vim 的插件,外层又用 Python 做了封装,因此它也是最複杂的 插件。 Plug 'Valloric/YouCompleteMe', { 'do': './install.py --clang-completer' } 命令要求 vim-plug 将 YouCompleteMe 插件下载下来后自动编译,但如果你的终端上缺 少编译的依赖会导致编译失败,此时我们需要手动进行编译。

在 Linux 下进行安装会相对比较容易,在编译之前你需要但不限于以下工具:

  • cmake
  • automake
  • python3-dev(python2 或 python3)

之后运行 cd ~/.vim/plugged/YouCompleteMe/ 进入 YouCompleteMe 的安装目录,运行 ./install.py --clang-completer 进行安装,如果不需要 C 语言补全支持的话无需 --clang-completer 选项。安装程序会自动下载 libclang 依赖,等待安装完成即可。 Windows 的安装过程大部分相似,可参考 YouCompleteMe 的官方仓库文档。

再次使用 Vim 打开一个 Python 或 cpp 文件应该就能自动补全了。但接下来你会发现 YouCompleteMe 弹出的补全菜单里只会包括前面你输入过的关键字,并没有进行语义识别, 那不是和自带的 omni 补全没区别!还浪费我这麽长时间安装!其实之前我也是这麽想的, 直到有一天我看到 这篇文章 ,我才发现原 来我一直用的是半残的 YouCompleteMe,根本没发挥出它真正的实力。通过如下配置就能使 YouCompleteMe 的补全策略更贴近于常见的 IDE。

  set completeopt=longest,menu                                " YCM 的提示方式,previews 会显示具体预览窗口,menu 不提示
  " let g:ycm_add_preview_to_completeopt = 0
  let g:ycm_collect_identifiers_from_tags_files=1             " 使用 ctags 生成的 tags 文件
  let g:ycm_min_num_of_chars_for_completion=2                 " 从第 2 个键入字符就开始罗列匹配项
  let g:ycm_seed_identifiers_with_syntax=1                    " 语法关键字补全
  let g:ycm_cache_omnifunc=1                                  " 禁止缓存匹配项,每次都重新生成匹配项
  let g:ycm_complete_in_comments = 1                          " 在注释输入中也能补全
  let g:ycm_complete_in_strings = 1                           " 在字符串输入中也能补全
  let g:ycm_collect_identifiers_from_comments_and_strings = 1 " 注释和字符串中的文字也会被收入补全
  let g:ycm_python_binary_path = '/usr/bin/python'            " set default python binary
  let g:ycm_global_ycm_extra_conf = '~/.ycm_extra_conf.py'    " set global ycm extra config path
  let g:ycm_confirm_extra_conf = 0                            " confirm for config file
  let g:ycm_use_ultisnips_completer=1                         " 查询 ultisnips 提供的代码模板补全
  let g:ycm_key_invoke_completion = '<c-z>'                   " 手动触发补全的按键
  " 使 YCM 能在输入两个字母的时候自动基于语义补全
  let g:ycm_semantic_triggers =  {
              \ 'c,cpp,python,java,go,erlang,perl': ['re!\w{2}'],
              \ 'cs,lua,javascript': ['re!\w{2}'],
              \ }
  nnoremap <leader>d :YcmCompleter GoToDefinitionElseDeclaration<CR> " goto definition
  autocmd InsertLeave * if pumvisible() == 0|pclose|endif            " 离开插入模式后自动关闭预览窗口
  autocmd VimEnter * EchoDocEnable

0.5.4.2ALE - 第二好的异步语法检查工具

ALE 是一款非常强大的异步语法检查工具。在 Vim 支 持异步之前,最好的语法检查工具是 Syntastic ,但由于它非异步的工作 方式,导致语法检查会阻塞主线程,使用体验比较差。在新版 Vim 中,都会推荐 ALE 或其 他支持异步的语法检查工具。事实上 ALE 并不仅仅是一款语法检查工具,它是包括了语法 检查、代码风格格式化、自动补全功能的工具集。

ALE 安装完成后,随意打开一个代码文件。如果语法存在错误,那麽在窗口的最左侧会显示 一列符号,包括 >>-- 。将光标移至有标记的行,在最下方的 statusline 中会显 示错误的具体信息。

  " let g:ale_set_loclist = 0           " show the lint as a dot on left of a line
  " let g:ale_set_quickfix = 1          " show the lint in quickfix list
  " let g:ale_open_list = 1             " show quickfix window to show error message
  " let g:ale_keep_list_window_open = 1 " keep quickfix window show whether errors exist
  " let g:ale_sign_column_always = 1    " 保持左侧边栏始终可见
  nmap <silent> <C-k> <Plug>(ale_previous_wrap)
  nmap <silent> <C-j> <Plug>(ale_next_wrap)
  " Check Python files with flake8 and pylint.
  " let b:ale_linters = ['flake8', 'pylint']
  " set fixers for different file types
  let b:ale_fixers = {
              \ 'python': ['isort', 'autopep8'],
              \ 'cpp': ['clang-format'],
              \ 'markdown': ['prettier']}
  " let g:ale_linters_explicit = 1
  let g:ale_completion_delay = 500                     " 补全的延迟
  let g:ale_echo_delay = 20                            " 回显的延迟
  let g:ale_lint_delay = 500                           " 停止输入后更新 lint 标记的延迟
  let g:ale_echo_msg_format = '[%linter%] <%code> %%s' " 自定义 lint 输出格式
  let g:ale_lint_on_text_changed = 'normal'            " 当文字在 NORMAL 模式下发生更改的时候更新 lint,防止 YCM 频繁刷新
  let g:ale_lint_on_insert_leave = 1                   " 离开 INSERT 模式时更新 lint

将错误信息表示在左侧只是一种方式,你也可以通过反注释前 4 行,利用 Vim 自带的 quickfix 窗口显示错误信息。虽然通过这种方式你能够更清晰的瞭解各个错误的具体信息, 但需要佔用一部分宝贵的屏幕空间。

11 至 14 行设置了 ALE 的默认格式化工具,ALE 本身并不对代码进行格式化,而是针对不 同文件类型调用合适的格式化工具进行处理(ALE 支持的格式化工具列表可参照 官方仓库 )。其中 isortautopep8prettier 都是 Python 编写的命令行工具, clang-formatclang 编译器带的 C++ 格式化工具。

20、21 行是针对 YCM 做的额外配置,据悉可以解决 YCM 补全菜单频繁刷新的问题。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
24 人气
更多

推荐作者

马化腾

文章 0 评论 0

thousandcents

文章 0 评论 0

辰『辰』

文章 0 评论 0

ailin001

文章 0 评论 0

冷情妓

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文