入坑 Vim,看这一篇就够了

6,658 阅读25分钟

photo © itl.cat

文章的 TOC 太多了,看起来不方便?PC 端可以看看我的 《两个 TamperMonkey 脚本,解决掘金阅读体验的三点不爽》,可以解决一些掘金阅读体验问题。

我写的「入坑」系列文章:

  1. 《入坑 Mac,看这一篇就够了》
  2. 《入坑 iTerm + OMZ,看这一篇就够了》
  3. 《入坑 Firefox Developer Edition 及 Mobile 版,看这一篇就够了》
  4. 《入坑 WebStorm,看这一篇就够了》
  5. 《入坑 VSCode,看这一篇就够了》
  6. 《入坑 Vim,看这一篇就够了》← 本文
  7. 《入坑 Git,看这一篇就够了》
  8. 《入坑 Docusaurus,看这一篇就够了》

🎼 前言

跟随本文进行操作,你将了解 Vim 的基础知识和基础操作,并且知道每一行的设置的目的是什么。 最后,你将得到一个「比较好看」和「比较好用」的 Vim 设置。

入坑 Vim,看这一篇「应该」就够了。

虽然我用 Vim 不多,但必要的设置还是必要的。

学习 Vim,主要就是了解它的模式、键盘指令、配置文件和各种命令,由于指令跟命令实在太多,全部了解完全不可能,但最常用的能够记住,就可以自称 Vim 高手了(Me Not)。

TL;DR

直接跳到文末「完整配置」,有现成完整的 .vimrc,但你会 miss 掉前文逐步详解每个设置步骤背后的原因和设置技巧。

主要内容

适合读者

  • Vim 不熟的同学,想把 Vim 设置得好用一些的

你将获得

  • Vim 设置、使用的基础知识
  • 一个配置得还不错的 .vimrc

编辑历史

日期版本说明
2023/09/06V1

💋 Why Vim

Vim,最古老的编辑器之一,拥有「编辑器之神」之称。它没有 GUI,入门门槛高,却自诞生 50 多年来,一直广受 IT 从业者喜爱。

Vim 简洁高效,纯键盘操作酷极,以至于有人会调侃「不会 Vim 做什么程序员」。

为了避免被调侃,跟随本文一起入坑 Vim 吧。

本文的 Vim 为 Mac 自带的 Vim 在 iTerm 上运行,其他的系统需要按需调整。

🪵 基础知识

安装

Mac 下,Vim 不需要安装,在命令行输入 vivim 即可在终端打开 Vim 编辑器。在 usr/bin 下,我们可以看到,其实 vi 就是 vim

Mac 系统自带了教程,Terminal 中输入 vimtutor 进入学习。

如果你喜欢,可以安装带 GUI 壳的「真」编辑器(如 MacVim);如果不想折腾配置可以试试下面这几个,它们有很棒的预配:

原生的 Vim 就长这样:

别人家设置过的 Vim 可能长这样:

现在,我们已经有了 Vim,先不急着上手设置,先了解一些 Vim 的基础知识很有必要。

模式

对于新手小白来说,第一个问题可能是:「怎么不能输入?」。

这涉及到 Vim 的几个模式(modes),Vim 共有 7 个基础模式 + 7 个辅助模式。

这里仅列举了 6 个模式的特征和用法,其他的可以 :h vim-modes 自行学习。

Normal/Command mode

该模式下,键盘不进行内容输入,而是执行快速导航、快速删除、切换模式等指令。新手进入 Vim 后敲键盘发现「不能输入」就是这个原因。

进入

该模式是默认进入 Vim 的模式,任何其他模式按 ESC 会回到该模式。

Visual mode

该模式下,移动光标会将光标所经过的区域高亮选中,非光标移动的指令则作用于选中区域。

标识

  • -- VISUAL --,普通的 Visual mode
  • -- VISUAL LINE --,以一行为单位进行选择
  • -- VISUAL BLOCK --,纵向选择一块文字,类似 Eclipse 的块编辑

进入

触发说明
v-- VISUAL --,再次按 v 退出
V-- VISUAL LINE --,再次按 V 退出
^v-- VISUAL BLOCK --,再次按 ^v 退出
鼠标圈选-- VISUAL --,需设置 :set mouse=a,鼠标点击会退回至 Normal 模式

Select mode

和 Visual mode 很像,不同的是,在键入第一个可打印字符后,会删除选择区域并进入 Insert mode。

标识

  • -- SELECT --
  • -- SELECT LINE --
  • -- SELECT BLOCK --

进入

触发说明
Normal mode 下 gh-- SELECT --
Normal mode 下 gH-- SELECT LINE --
Normal mode 下 g^H-- SELECT BLOCK --
Visual mode 下 ^G根据原来的模式 -- SELECT ---- SELECT LINE ---- SELECT BLOCK --

Insert mode

让 Vim 跟常规编辑器一样可以接受键盘输入。

标识

  • -- INSERT --

进入

Select mode 下,键入第一个可打印字符即进入 Insert mode,Normal mode 下有多种进入方式。

触发说明
a在光标后开始插入
A在当前行末(算空格)开始插入
cc删除当前行,开始输入
cw删除光标到词尾,开始输入
C删除光标至行尾,开始输入
i在光标前开始插入
I在当前行首(不算空格)开始插入
o在下一行插入空行,开始插入
O在上一行插入空行,开始插入
s删除光标处字符,开始输入
S删除当前行,开始输入

Command-Line 模式

在窗体底部输入命令。

进入

触发说明
:通用命令
/搜索
?搜索

Ex 模式

Command-Line mode 的「不退出」版,输入命令后,不会退出,可继续输入其他命令。

Normal mode 下按 Q 进入 Ex mode,在 Ex mode 下输入 vi / visual 命令退出该模式。

Terminal-Job mode

?不会用。

键盘指令

新手小白可能在键盘一顿乱敲之后,问出第二个问题:「怎么变这样了?」,因此了解常用的键盘指令非常重要。

可以看后面的《使用 Vim》章节。先可以看看 文字版作弊纸,再贴两张作弊纸图:

photo © itl.cat

photo © itl.cat

配置文件

使用命令 :version 可以查看 Vim 的版本详情,里边有配置文件信息。

我们用来做自定义的通常是 ~/.vimrc,可以认为是 User Profile。

如果想换 Profile,怎么办呢?可以在打开 Vim 的时候,附带 -u <vimrc> 参数。

  • vi -u NONE
  • vi -u NORC
  • vi -u DEFAULTS
  • vi -u path/to/custom/vimrc

打命令 :h -u 看详情。

常用命令 :set

.vimrc 用到最多的命令应该是 set,我们可以在 Command-Line 模式下直接打以查看实时效果。

  • set 属性名=值 非开关属性,值根据属性有特定的格式要求,如 set regexpengine=2set tabstop=4
  • set 属性名 开关属性设为 true,如 set numberset cursorline
  • set no属性名 开关属性设为 false,如 set nonumberset nocursorline
  • set 属性名! 开关属性设为 false,如 set number!set cursorline!
  • set 属性名& 将任何属性(包括开关属性)还原为出厂设置
  • set 属性名? 查看当前值,如 set number? 可能显示 numbernonumberset re? 显示 regexpengine=1

属性名有长名和短名(不一定是缩写),为了便于理解,不建议用短名,这里列举一些:

属性名短名类型作用
numbernu开关显示行号
cursorlinecul开关高亮当前行
regexpenginere0 / 1 / 2正则引擎
tabstoptsNumberTab 占据字符数

<leader>

.vimrc 经常可以看到类似 map <leader>... 这样的配置,这个 <leader> 键是 Vim 提供用以创建自定义快捷键的工具,默认为 \,可以用 let mapleader="_" 修改成别的。

map <leader>h :noh<CR>

更多详细内容可以看《How to Use the Vim <leader> Key》

⚙️ 配置 Vim

管理插件的插件

玩 Vim 必须要玩插件,而玩 Vim 插件,需要管理插件的插件。Vim 插件千千万,管理 Vim 插件的插件也不少(数据更新于 2023/09):

插件Github Star上次更新说明
Vundle23.6k3 weeks ago
Pathogen12klast year
VimPlug7k2 weeks ago
Dein3.4klast week官宣停止维护不再积极维护,推荐 Dpp
VAM6597 months ago
apt-vim4775 years ago
Jetpack2913 months ago
VimPackager2412 years ago
Volt2363 years ago
Dpp692 days ago
Vimogen373 years ago
Voom27last year
packer.nvim7k3 weeks ago官宣停止维护,推荐 lazy 和 pckr,但都是 for nvim
lazy.nvim7k2 weeks agofor nvim
pckr.nvim109this weekfor nvim

我选择 Vundle,别的也没用过...

安装 Vundle

参考 Vundle - Quick Start 安装和配置 Vundle。

安装(就是 git clone)

git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

初始 ~/.vimrc

默认应该是没有 ~/.vimrc 的,新建一个,内容如下(根据 Vundle 文档改的):

set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Install plugins, supported formats:
" 
" - Plugin on GitHub repo, e.g. `Plugin 'tpope/vim-fugitive'`
" - Plugin from http://vim-scripts.org/vim/scripts.html, e.g. `Plugin 'L9'`
" - Plugin hosted on other Git repos, e.g. `Plugin 'git://git.wincent.com/command-t.git'`
" - Your local git repos (i.e. your own plugin), e.g. `Plugin 'file:///path/to/plugin'`
" - The sparkup vim script is in a subdirectory of this repo called vim, pass the path to set the runtimepath properly, e.g. `Plugin 'rstacruz/sparkup', {'rtp': 'vim/'}`
" - Install L9 and avoid a Naming conflict if you've already installed a different version somewhere else, e.g. `Plugin 'ascenator/L9', {'name': 'newL9'}`
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" 💥 插件安装

" All of your Plugins must be added before the following line
call vundle#end()            " required
filetype plugin indent on    " required
" To ignore plugin indent changes, instead use: `filetype plugin on`
" 
" Brief help
" :PluginList       - lists configured plugins
" :PluginInstall    - installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo - searches for foo; append `!` to refresh local cache
" :PluginClean      - confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Common Settings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" 💥 通用设置

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Plugin Settings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" 💥 插件设置

注意,Vundle 不会自动安装插件,需要在添加插件记录后,重启 Vim,执行 :PluginInstall 以完成安装。

稍安勿躁

先不急着装插件。

以上,.vimrc 中我留了三大块,用 💥 做了标记。

先 Vim 打开一个 TS 文件,效果是这样的:

来调配一些基本设置,技巧是,先在 Command-Line mode 下执行命令看效果,然后将敲过的命令记录到 .vimrc 的「通用设置」部分。

编辑器标配功能

对于一个「代码编辑器」来说,少了些标配:

  • 显示行号,敲命令 :set number
  • 语法高亮,敲命令 :syntax on:syntax enable 亦可),报错的话先执行 :set regexpengine=2
  • 当前行高亮,敲命令 :set cursorline

效果看起来差不多了,如果你对高亮行的效果不满意(一根线,不明显),这是 colorscheme default 的效果,可以改一个,在命令模式下敲 :colorscheme wildcharm

可用的主题有 bluedarkbluedefaultdelekdesertelflordeveninghabamaxindustrykoehlerlunaperchemorningmurphypablopeachpuffquietretroboxronshineslatesorbettortewildcharmzaibatsuzellner

如果你觉得 colorscheme default 也不错,可以改一下高亮当前行的颜色 :hi CursorLine cterm=NONE ctermbg=black

基本上达到满意的效果了,.vimrc 「通用设置」下添加以下汇总的设置:

" --- Color Scheme
colorscheme wildcharm                       " The default colorscheme shows only a bottom line

" --- Editor Basic
set regexpengine=2                          " Prevent error `redrawtime exceeded` for syntax highlight
syntax on                                   " Syntax highlight, also make NERDTree render properly
set number                                  " Show line number in the gutter
set cursorline                              " Highlight current line
" hi CursorLine cterm=NONE ctermbg=black      " If you realy like default colorscheme
set wrap                                    " Wrap words visually
set linebreak                               " wrap only at the 'breakat' option

空白字符和缩进

自出道以来,我一直是 Tab 党,在阿里期间,被活活转成双 Space,因此现在我是一个双 Space 的内心 Tab 党。

但有一点我从来没变,就是我从来都特别鄙视 Tab 和 Space 混用的人,凡是看到这样的代码,我都会去看一下是谁的杰作,并且非常武断地做出判断:此人「码品」和「码能」不行。

为了避免自己成为被别人嘲讽的对象,我的所有编辑器 / IDE 必须做的设置就是空白字符可见。

比如有这么一段代码,在我的 WebStorm 和仅做了之前的设置的 Vim 下的展示效果:

WebStormVim

Vim 下的 Tab 还有特别的副作用,最左侧的 Tab 处无法向左移动光标。

第一步:真 Tab 宽度

「真」Tab 默认 8 个字符宽,还是 4 个看起来舒服,敲命令 :set tabstop=4

此时,代码「看着」缩进都正确,在没有 Linter 的情况下,完全无法用肉眼看出任何问题。

第二步:显示空白字符

敲命令 :set list

仅展示了 Tab(^I)和回车($),空格看不到,继续敲命令 set listchars=tab:»-⋮,space:·,eol:¶

解释一下:

  • tab 可以两种格式,xyx 永远展示,y 作填充,如 »- 可能展示为 »»-»--»--- 等等;xyzz 永远展示,y 作填充,x 作头,如 »-⋮ 可能展示为 -⋮»-⋮»--⋮»---⋮ 等等
  • space 所有的空格展示,仅允许一个字符,包括行首、中间和行尾
  • eol 行末回车,仅允许一个字符,默认为 $,Eclipse 默认为 ,WebStorm 和 VSCode 下没有

具体可以 :h listchars 查看。

  • tab 推荐 »-⋮»»⋮--⋮▷▷⋮▷-⋮>-»-
  • space 推荐 ·
  • eol 推荐 ↩︎¬

可自行组合以满足自己的特殊癖好。

第三步:Tab 换空格

现在按 Tab 键还是真 Tab,敲命令 :set expandtab,发现按 Tab 变成了 4 个空格(tabstop 的值),但我需要 2 个空格,敲命令 :set softtabstop=2

第四步:自动缩进

敲代码怎么能没有自动缩进呢,敲命令 :set smartindent,会自动缩进了,但空格个数不对,继续 :set shiftwidth=2

set smartindentset autoindent 要好用一些。

.vimrc 「通用设置」下添加以下汇总的设置:

" --- Tab & Space
set list                                    " Make invisible chars visible
set listchars=tab:»-⋮,space:·,eol:¶         " How invisible chars are displayed
set expandtab                               " Press Tab key will generate spaces according to tabstop setting
set tabstop=4                               " Real tab width
set softtabstop=2                           " How many spaces will expand from tab
set smartindent                             " Ease editing code by smart auto indenting
set shiftwidth=2                            " How many spaces for auto indent

至此,编辑器的 Tab、空格、缩进等调校完毕。

光标形状

按照之前的步骤操作过的话,你应该已经在 Normal mode、Command-Line mode、Insert mode 间相互切换过了,你或许发现,Normal mode 和 Insert mode 的光标是一样的。

获取你更希望 Insert mode 的光标是一条竖线,能够更明确地知道插在哪里。

这个没法在命令行预览,在 .vimrc 「通用设置」下添加以下设置(先别急着试):

" --- Cursor shape
let &t_SI.='\e[5 q'               " SI = INSERT mode → blinking vertical bar
let &t_SR.='\e[4 q'               " SR = REPLACE mode → solid underscore
let &t_EI.='\e[1 q'               " EI = NORMAL mode (ELSE) → blinking block

好消息是,这可能奏效,坏消息是,需要 为不同的平台做不同的设置

有人更建议,Normal mode 不高亮,Insert mode 高亮,敲命令 :set cursorline!autocmd InsertEnter,InsertLeave * set cursorline!

个人认为这个形式更舒服,修改「Basic UI」设置:

" --- Basic UI
set regexpengine=2                          " Prevent error `redrawtime exceeded` for syntax highlight
syntax on                                   " Syntax highlight, also make NERDTree render properly
set number                                  " Show line number in the gutter
" set cursorline                              " Highlight current line
colorscheme wildcharm                       " The default colorscheme shows only a bottom line
" hi CursorLine cterm=NONE ctermbg=black    " If you need default colorscheme

autocmd InsertEnter,InsertLeave * set cursorline!

调校搜索

" --- Searching
set smartcase                               " When searching try to be smart about cases
set incsearch                               " Makes search act like search in modern browsers
set lazyredraw                              " Don't redraw while executing macros (good performance config)
set magic                                   " For regular expressions turn magic on
set hlsearch                                " Highlights all search hits

其他必要设置

" --- Window settings
set splitbelow                              " Open split windows below
set splitright                              " Open split windows to the right

" --- Misc
set showcmd                                 " Show current command at the bottom-right for some time
set history=77                              " How many command history vim should remember
set pastetoggle=<F5>                        " Toggle paste mode

安装插件 - Airline

现在,我们来装第一「个」插件,体验一下 Vundle 的操作。

安装

.vimrc 插件部分加入以下代码:

" Plugins for UI
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'

重启 Vim 后,执行 :PluginInstall

安装完成,效果立竿见影,看底部:

启用 Powerline 字体

没有 Powerline 炫酷的三角形,需要在 .vimrc 末尾添加设置代码(如果有乱码,那么很可能就是你系统上还没安 Powerline 字体Nerdfont(推荐)):

let g:airline_powerline_fonts=1

显示顶栏

let g:airline#extensions#tabline#enabled=1

设置主题

我们可以通过 :AirlineTheme xx 动态切换主题,但重启后主题会被还原,可以记住它:

let g:airline_theme='kolor'

这样,Airline 全部设置如下:

" ---- Plugin Settings for vim-airline
let g:airline_powerline_fonts=1                     " Use powerline font when possible
let g:airline#extensions#tabline#enabled=1          " Enable tab line
let g:airline_theme='kolor'                         " Use this theme

我对主题的要求:

  1. 色彩第一眼眼缘(玄学)
  2. Vim 各模式差别明显
  3. 未保存状态明显(最好有颜色区分)
  4. 由于重要信息在两头,所以中间部分颜色不要太突兀

200+ 个主题,除了 base16_xx 之外,几乎每一个我都试了一下,最后刷下来这么些,瑾供参考:

名称优点缺点无编辑待保存
angr配色偏灰
badwolf和 angr 很像,但比 angr 颜色鲜艳一些
behelit色彩鲜明不突兀,底栏的中间部分很舒服
dark默认配色,且 COMMAND 有单独配色
desertink橙色系很抓眼球
kolor蓝紫色系,配色恰到好处

命令行菜单优化

切换主题的时候,已经感觉不爽利了:

  1. 需要的命令是 AirlineTheme,但每次输入 Air 后 Tab,直接变成了 AirlineExtensions(后来我才明白还可以继续用 Tab 切换)
  2. 可选项太多了,不知道下一个 Tab 到的是哪个主题

这个不需要用插件,在「通用设置」处添加几行代码就行:

" --- Use the vim wildmenu for command completion
set wildmenu
set wildmode=longest:full,full
set wildignore+=*/tmp/*,*.so,*.swp,*.zip,.meteor/*      " Ignore files in the wildmenun

效果:

安装插件 - NERDTree

搞个文件树。

安装

.vimrc 插件部分加入以下代码:

" Plugins for tree view
Plugin 'preservim/nerdtree'
Plugin 'Xuyuanp/nerdtree-git-plugin'                " Git status flag
Plugin 'ryanoasis/vim-devicons'                     " File icon
Plugin 'tiagofumo/vim-nerdtree-syntax-highlight'    " File icon color

重启后,敲命令 :NERDTree 即可展示当前目录文件树:

NERDTree 配置

我希望:

  • NERDTree 可以在适当的时候自己开启
  • 焦点在期望的编辑区域
  • 在关闭最末一个编辑区域的时候,不需要再关一次 NERDTree 才能关闭 Vim

.vimrc 末尾添加配置代码:

" ---- Plugin Settings for NERDTree
nnoremap <C-t> :NERDTreeToggle<CR>
autocmd StdinReadPre * let s:std_in=1
" Start NERDTree. If a file is specified, move the cursor to its window.
autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif
" Start NERDTree when Vim starts with a directory argument
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
    \ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif
" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

鼠标交互

剩下一个问题,鼠标怎么办?双击无效果,也无法对 NERDTree 的宽度进行拖拽调整。

这个设置不在 NERDTree 上,但很简单,在「通用设置」处添加一行代码:

set mouse=a                                 " Make mouse interactive, i.e. NERDTree can be clicked

玩转 NERDTree 指令

下面这张表助你玩转 NERDTree,更多内容可以看 NERDTree 文档

命令说明速记
鼠标双击和 o 等效就是很普通的双击操作
鼠标中键单击对文件与 i 等效,对目录是 e
^w + w光标在每个区块之间切换
^w + h/j/k/l光标在相邻区块之间根据方向(h←/j↓/k↑/l→)跳转
o / ⏎展开 / 收起目录,打开文件 / 书签(光标移入工作区)open
O展开所有子目录
go打开文件,光标仍停留在 NERDTree 中(可以看作是文件预览功能)
t在标签页中打开选中节点 / 书签tab
Tt 一样,但光标停留在当前 tab,即在后台标签页中打开
i纵向(向上)分割窗口打开文件
gii 一样,但光标不离开 NERDTree
s横向(向左)分割窗口打开文件
gsi 一样,但光标不离开 NERDTree
x收起当前节点的父节点(其下子节点的展开状态保持)
X收起所有子目录
e编辑目录,会打开一个新的 NERDTreeedit
D删除当前书签
p回到上一级目录parent
P回到根目录BIG Parent
K跳到同目录下第一个节点小 k 向下,大 K 局限在当前目录的最下方
J跳到同目录下最后一个节点小 j 向下,大 J 局限在当前目录的最上方
^J跳到同目录下的下一个节点(有的话)
^K跳到同目录下的上一个节点(有的话)
C将当前选中的目录作为 root
uroot 上跳一级
Uu 一样,不同的是保持老的 root 的展开状态
r刷新光标所在目录refresh
R刷新 rootBIG Refresh
m显示文件系统菜单(添加、删除、移动,不甚好用)menu
cd将 CWD 改为选中目录,或选中文件所在的目录,但只有提示,不会修改树的 root
CD将 CWD 作为 root
I切换是否显示隐藏文件Invisible
fToggle whether the file filters are used不会用
F显示 / 隐藏所有文件(即仅展示目录)
B显示 / 隐藏书签列表
q关闭 NERDTree
A切换全屏状态
?显示 / 隐藏帮助

安装 Git 相关插件

vim-gitguttervim-signify 选一个就行,看效果选后者吧:

vim-gitguttervim-signify

代码:

" Plugins for git
Plugin 'tpope/vim-fugitive'                         " The premier Git plugin for Vim, illegally awesome
Plugin 'mhinz/vim-signify'                          " Add git gutter to note diffs inline

" ------- Plugin Settings for vim-fugitive
nnoremap <leader>gs :Gstatus<return>
nnoremap <leader>gd :Gdiff<return>
nnoremap <leader>gb :Gblame<return>
nnoremap <leader>gr :Gread<return>
nnoremap <leader>gc :Gcommit<return>
nnoremap <leader>gw :Gwrite<return>

安装其他插件

安装代码:

" Plugins for quick editing
Plugin 'mattn/emmet-vim'                            " Emmet-vim for super fast HTML editing
Plugin 'mg979/vim-visual-multi'                     " Multiple cursors
Plugin 'Raimondi/delimitMate'                       " Auto closing of parens, brackets, etc
" Plugin 'Valloric/YouCompleteMe'                     " YouCompleteMe Autocompletion, Works great with Tern
" Plugin 'SirVer/ultisnips'                           " Ultisnips snippet engine
Plugin 'ervandew/supertab'                          " Supertab to get Ultisnips and YCM to play nice
" Plugin 'vim-syntastic/syntastic'                    " Syntax checking

" Plugins misc
Plugin 'ctrlpvim/ctrlp.vim'                         " CtrlP fuzzy finder
Plugin 'embear/vim-localvimrc'                      " Search local vimrc files .lvimrc in the tree and load them

带 💥 的我没有装。

插件推荐指数说明
mattn/emmet-vim★★★★☆触发快捷键是 ^Y,,没有别处的 Tab 键好用
mg979/vim-visual-multi★★★☆多点编辑
Raimondi/delimitMate★★★★★自动闭合括号引号
ycm-core/YouCompleteMe★★★★★💥 不支持 Mac 自带的 Vim
SirVer/ultisnips💥 报错
ervandew/supertab有作用,但缺少 YCM 和 ultisnips 的辅助,不够好用
vim-syntastic/syntastic💥 设置起来比较麻烦,我没有搞出来
ctrlpvim/ctrlp.vim★★★★★^P 找万物
embear/vim-localvimrc★★加载项目本地的 .lvimrc 以支持自定义

localvimrc 设置

" ------- Plugin Settings for localvimrc
let g:localvimrc_ask=0                              " Don't ask to load the .vimrc file
let g:localvimrc_reverse=1                          " load files going from working dir to root
let g:localvimrc_name=['.lvimrc', '.vimrc']

至此,整个 Vim 的配置就基本完成了,你已经得到了一个长的还可以,用起来也挺瞬爽的 Vim 了。

🥑 使用 Vim(TODO)

「命令」和「指令」是两个很容易混淆的概念(我也没有找到很官方的说法),本文中可以认为「命令」是在冒号后面的,比如 :w 等,「指令」是在 Command mode 下通过手指头直接发出的键盘指令,比如切换插入的 i,取消上次编辑用的 u 等。

常用命令

指令说明速记
:s/find/replace查找替换

常用指令

如果你仔细阅读了前文,你应该已经能够感受到 Vim 和常见的编辑器的不同之处了:Vim 是基于指令的,你完全可以脱离鼠标 —— 这既是它能够在命令行工具和服务端得到广泛使用,也是入门门槛偏高的原因。

了解常用的键盘指令非常重要,以下是我整理的一个新手必会的指令列表:

指令说明速记
hjkl移动光标(当然你也可以用「真」方向键)对应 ←↓↑→
i切换为插入模式(光标处)insert
I切换为插入模式(光标移到行首)Insert
a切换为插入模式(光标后)apend
A切换为插入模式(光标移到行末)Apend

🥱 懒人方案

🕋 完整配置

我的 .vimrc,不想折腾的,直接用就行,但记得:

  1. 安装 Vundle
  2. 在 Vim 下执行 :BundleInstall 安装插件
  3. 重启 Vim
set nocompatible              " be iMproved, required
filetype off                  " required

" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

" let Vundle manage Vundle, required
Plugin 'VundleVim/Vundle.vim'

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Install plugins, supported formats:
"
" - Plugin on GitHub repo, e.g. `Plugin 'tpope/vim-fugitive'`
" - Plugin from http://vim-scripts.org/vim/scripts.html, e.g. `Plugin 'L9'`
" - Plugin hosted on other Git repos, e.g. `Plugin 'git://git.wincent.com/command-t.git'`
" - Your local git repos (i.e. your own plugin), e.g. `Plugin 'file:///path/to/plugin'`
" - The sparkup vim script is in a subdirectory of this repo called vim, pass the path to set the runtimepath properly, e.g. `Plugin 'rstacruz/sparkup', {'rtp': 'vim/'}`
" - Install L9 and avoid a Naming conflict if you've already installed a different version somewhere else, e.g. `Plugin 'ascenator/L9', {'name': 'newL9'}`
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" Plugins for UI
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'

" Plugins for tree view
Plugin 'preservim/nerdtree'
Plugin 'Xuyuanp/nerdtree-git-plugin'                " Git status flag
Plugin 'ryanoasis/vim-devicons'                     " File icon
Plugin 'tiagofumo/vim-nerdtree-syntax-highlight'    " File icon color

" Plugins for git
Plugin 'tpope/vim-fugitive'                         " The premier Git plugin for Vim, illegally awesome
Plugin 'mhinz/vim-signify'                          " Add git gutter to note diffs inline

" Plugins for quick editing
Plugin 'mattn/emmet-vim'                            " Emmet-vim for super fast HTML editing
Plugin 'mg979/vim-visual-multi'                     " Multiple cursors
Plugin 'Raimondi/delimitMate'                       " Auto closing of parens, brackets, etc
" Plugin 'Valloric/YouCompleteMe'                     " YouCompleteMe Autocompletion, Works great with Tern
" Plugin 'SirVer/ultisnips'                           " Ultisnips snippet engine
Plugin 'ervandew/supertab'                          " Supertab to get Ultisnips and YCM to play nice
" Plugin 'vim-syntastic/syntastic'                    " Syntax checking

" Install misc
Plugin 'ctrlpvim/ctrlp.vim'                         " CtrlP fuzzy finder
Plugin 'embear/vim-localvimrc'                      " Search local vimrc files .lvimrc in the tree and load them

" All of your Plugins must be added before the following line
call vundle#end()            " required
filetype plugin indent on    " required
" To ignore plugin indent changes, instead use: `filetype plugin on`
" 
" Brief help
" :PluginList         - Lists configured plugins
" :PluginInstall      - Installs plugins; append `!` to update or just :PluginUpdate
" :PluginSearch foo   - Searches for foo; append `!` to refresh local cache
" :PluginClean        - Confirms removal of unused plugins; append `!` to auto-approve removal
"
" see :h vundle for more details or wiki for FAQ
" Put your non-Plugin stuff after this line

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Common Settings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" set fileencodings=ucs-bom,utf-8,gbk,gb2312,cp936,gb18030,big5,latin-1
" set encoding=utf-8                          " encoding used inside Vim, buffers, registers, Strings in expressions, viminfo file, etc
" set termencoding=utf-8                      " encoding used for the terminal
" set fileencoding=utf-8                      " character encoding for the file of this buffer

" --- Window settings
set splitbelow                              " Open split windows below
set splitright                              " Open split windows to the right

" --- Color Scheme
colorscheme wildcharm                       " The default colorscheme shows only a bottom line

" --- Editor Basic
set regexpengine=2                          " Prevent error `redrawtime exceeded` for syntax highlight
syntax on                                   " Syntax highlight, also make NERDTree render properly
set number                                  " Show line number in the gutter
" set cursorline                              " Highlight current line
" hi CursorLine cterm=NONE ctermbg=black      " If you realy like default colorscheme
set wrap                                    " Wrap words visually
set linebreak                               " Wrap only at the 'breakat' option

autocmd InsertEnter,InsertLeave * set cursorline!

" --- Tab & Space
" filetype plugin indent on                   " don't know  what it is for
set list                                    " Make invisible chars visible
set listchars=tab:»-⋮,space:·,eol:¶         " How invisible chars are displayed
set expandtab                               " Press Tab key will generate spaces according to tabstop setting
set tabstop=4                               " Real tab width
set softtabstop=2                           " How many spaces will expand from tab
set smartindent                             " Ease editing code by smart auto indenting
set shiftwidth=2                            " How many spaces for auto indent

" --- Search
set smartcase                               " When searching try to be smart about cases
set incsearch                               " Makes search act like search in modern browsers
set lazyredraw                              " Don't redraw while executing macros (good performance config)
set magic                                   " For regular expressions turn magic on
set hlsearch                                " Highlights all search hits

" --- Use the vim wildmenu for command completion
set wildmenu
set wildmode=longest:full,full
set wildignore+=*/tmp/*,*.so,*.swp,*.zip,.meteor/*      " Ignore files in the wildmenun

" --- Misc
set showcmd                                 " Show current command at the bottom-right for some time
set history=77                              " How many command history vim should remember
set pastetoggle=<F5>                        " Toggle paste mode
set mouse=a                                 " Make mouse interactive, i.e. NERDTree can be clicked

" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" " Plugin Settings
" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" ---- Plugin Settings for vim-airline
let g:airline_powerline_fonts=1                     " Use powerline font when possible
let g:airline#extensions#tabline#enabled=1          " Enable tab line
let g:airline_theme='kolor'                         " Use this theme

" ---- Plugin Settings for NERDTree
nnoremap <C-t> :NERDTreeToggle<CR>
autocmd StdinReadPre * let s:std_in=1
" Start NERDTree. If a file is specified, move the cursor to its window.
autocmd VimEnter * NERDTree | if argc() > 0 || exists("s:std_in") | wincmd p | endif
" Start NERDTree when Vim starts with a directory argument
autocmd VimEnter * if argc() == 1 && isdirectory(argv()[0]) && !exists('s:std_in') |
    \ execute 'NERDTree' argv()[0] | wincmd p | enew | execute 'cd '.argv()[0] | endif
" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

" ------- Plugin Settings for vim-fugitive
nnoremap <leader>gs :Gstatus<return>
nnoremap <leader>gd :Gdiff<return>
nnoremap <leader>gb :Gblame<return>
nnoremap <leader>gr :Gread<return>
nnoremap <leader>gc :Gcommit<return>
nnoremap <leader>gw :Gwrite<return>

" ------- Plugin Settings for vim-localvimrc
let g:localvimrc_ask=0                              " Don't ask to load the .vimrc file
let g:localvimrc_reverse=1                          " load files going from working dir to root
let g:localvimrc_name=['.lvimrc', '.vimrc']

" " -------- Plugin Settings for syntastic
" let g:syntastic_always_populate_loc_list=1
" let g:syntastic_auto_loc_list=1
" let g:syntastic_check_on_open=1
" let g:syntastic_check_on_wq=0

" " ------- Plugin Settings for YCM
" let g:ycm_complete_in_comments=1                            " Completion enabled in comments
" let g:ycm_autoclose_preview_window_after_completion=1       " Close the preview window after we pick an option
" let g:ycm_key_list_select_completion=['<C-n>', '<Down>']    " Make YCM compatible with UltiSnips (using supertab)
" let g:ycm_key_list_previous_completion=['<C-p>', '<Up>']

💎 Even Better

如果不想自己折腾配置,可以试试以下这些更 NB 的:

🙋 FAQ

❓ 如何解决报错「redrawtime exceeded syntax highlighting disabled」,特别是打开 TS 文件的时候?

set regexpengine=2

regexpengine 的可选值有:

  • 0 自动
  • 1 旧的正则引擎 ← 会报错
  • 2 NFA 引擎

参见 Issue

❓ 如何以「出厂设置」打开 Vim?

就像我在写这篇文章一样,有的时候需要去之前的步骤调整截图。我可以把当前的 .vimrc 全注释了再打开 Vim,但这不够聪明。

聪明一些的做法是使用 -u <vimrc> 参数(实际上可以只想任何配置文件):

vi -u DEFAULTS # 出厂设置打开空的 Vim
vi -u DEFAULTS -- path/to/file # 出厂设置打开文件

❓ 如何查看 Vim 自带了哪些色彩主题?

ls /usr/share/vim/vim90/colors/ | grep .vim

❓ 插件安装路径在哪里?

插件全部安装在 ~/.vim/bundle 下:

~/.vim/bundle/
  ├── Vundle.vim
  ├── vim-airline
  └── vim-airline-themes

❓ NERDTree 图标乱码,怎么解决?

Nerd Font 下几个字体,设置成 Terminal 的字体。

参考我的《入坑 iTerm + OMZ,看这一篇就够了》的 配置 Powerline / Nerd 字体 一节。

❓ NERDTree 有中括号和 ^G,怎么解决?

你可能看到 NERDTree 的展示很奇怪,每个文件前面有 ^G,文件图标两边还有一对中括号:

其实是因为语法高亮没有开启的缘故,保证 .vimrc 中有 syntax onsyntax enable 就能解决。

❓ 如何改变行高?

办法是有,但在终端 Vim 中是无效的,仅在 GUI Vim 下有用,比如 MacVim。

set linespace=3

❓ 如何自动重新读取文件,当打开的文件在外部被改动?

set autoread

然而,不建议设置,Vim 会有提示。

❓ 如何让 NERDTree 向右和向下分割窗口?

NERDTree 的 i(纵向切割窗口)和 s(横向切割窗口)默认行为是向上和向左,很不符合人类习惯,在 .vimrc 中添加两行设置:

set splitbelow
set splitright

❓ 如何让帮助文档展示在当前窗口下方?

确保 .vimrc 中有这个设置(跟 NERDTree 的诉求一样):

set splitbelow

❓ 为什么有些单词有红色背景,特别烦人?

像这样:

这个是 SpellCheck 造的,可以关掉 :set spell!

📌 链接

🪭 写在最后

以上介绍了 Vim 的一些基本知识,和一步一步如何将 Vim 配置到「有点好看」、「有点好用」的地步,但如果要把它作为常规的编辑器,甚至开发工具,还是远远不够的,你不仅可能需要按需装更多的插件,更加需要不断地实践和学习。

但「入坑」这个任务,本文算是完成了。