Space-vim documentation

Table of Contents

1 前言

1.1 什么是 layer

layer, 名词有 "层次", 动词有 "分层" 的意思, 其实很简单, layer 这个概念不过是为了井然有序, 便于进一步的处理而已。就像计算机网络有应用层, 传输层等等, 每个 layer 有自己的职能。space-vim 中一个 layer 不过是针对某方面的 vim 配置与插件的集合.

space-vim 中, 像如下的 c-c++, graphviz, html 等等都为一个 layer. layer 的上一级目录, 比如 python layer 的上一级目录 +lang, 可称之为 topic. topic 下的内容均可认为是一个 layer.

layers
├── +lang
│   ├── c-c++
│   ├── graphviz
│   ├── html
│   ├── markdown
│   └── python
├── +themes
│   ├── airline
│   └── lightline
├── +tools
│   ├── fzf
│   └── ycmd
├── +version-control
│   ├── git
│   └── github
├── +vim
│   ├── better-defaults
│   ├── programming
│   └── text-align
└── LAYERS.md

一个 layer 通常由 3 个部分组成, README.md 为其简要介绍, config.vim 为针对该 layer 的配置信息, packages.vim 为支持该 layer 所需安装的一些插件.

python
├── README.md
├── config.vim
└── packages.vim
Layer Component Description
README.md layer 的简要介绍
config.vim 针对 layer 的配置信息
packages.vim 支持该 layer 所需的一些插件

1.2 为什么使用空格键作为前缀建

space-vim 的前缀键 (Leader key) 设置为空格键,取自 spacemacs. 当然了,在 spacemacs 之前就已经有很多人这么设置了, 它不是第一个,但是它的流行影响了很多人对 Leader key 的设置。

spacemacs 除了外观漂亮,社区驱动等等优点,主打 evil 并用空格键作为其前缀键可能也是其中一个成功的卖点,因为真的可以减轻手指负担,毕竟 "触手可及".

let g:mapleader="\<Space>"

从现代键盘设计的角度看,空格键理应受到优待, 毕竟一个人在 “VIP” 区占了好几个位. 即使 HHKB 这样的神器,也有空格键的一席之地.

hhkb.jpg

Figure 1: HHKB keyboard

1.3 为什么使用 hjkl 作为方向键

关于 vim 自身的键位设定,刚开始时可能会觉得很奇怪, 为什么要用这几个键作为方向键呢? 这是因为以前的键盘长这样:

ancient_keyboard.png

Figure 2: Lear Siegler's ADM-3A computer terminal's full keyboard

ADM-3A.png

看到这个,也就应该能够理解为什么 vim 使用 hjkl 作为方向键,因为物理条件就是这样, 没得选. 参见 why-vim-uses-hjkl-as-arrow-keys .

2 运行截图

screenshot.png

Figure 4: python

以上截图可能并非最新版本,仅供参考。

3 适用人群

  • vim 初学者. 如果是老司机, 选择感兴趣的部分看看就好.
  • 同时使用 vim 与 spacemacs, 并且希望 vim 不那么 “寒碜”。
  • 惯用 Terminal vim, 而不是 GUI vim.

虽然大部分设置 terminal 与 GUI 通用, 但因为我基本不使用 GUI vim, 所以仍然会有些设置可能对 GUI vim 不那么友好. 不过非常欢迎您帮助改进 GUI vim 下的一些潜在问题.

4 开始使用

4.1 安装工作

又想马儿跑,又要马儿不吃草,那是不太现实的,所以要想要 space-vim 的体验好一些,一些准备工作必不可少.

4.1.1 满足 “要求” 的 vim

所谓要求,是指有些插件需要 vim 在编译时必须包含某项特性 (feature),比如 ycmd layer 中使用的 YouCompleteMe 要求 vim 得有 python 支持。如果使用 NeoVim 可以直接跳过这一节, 因为 NeoVim 默认编译时包含全部特性.

terminal 中输入 vim --version, 可以看到一串信息,下面显示的是我使用 brew 安装的 vim, 带 "+" 说明该 feature 有了, 带 "-" 说明没有,比如下面的 +python3 说明支持 python3. 安装时还是保险一点,什么 lua, python , clipboard都装上, 以免后患。

$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Nov 21 2016 17:35:16)
MacOS X (unix) version
Included patches: 1-94
Compiled by Homebrew
Huge version without GUI.  Features included (+) or not (-):
+acl             +file_in_path    +mouse_sgr       +tag_old_static
+arabic          +find_in_path    -mouse_sysmouse  -tag_any_white
+autocmd         +float           +mouse_urxvt     -tcl
-balloon_eval    +folding         +mouse_xterm     +termguicolors
-browse          -footer          +multi_byte      +terminfo
++builtin_terms  +fork()          +multi_lang      +termresponse
+byte_offset     -gettext         -mzscheme        +textobjects
+channel         -hangul_input    +netbeans_intg   +timers
+cindent         +iconv           +num64           +title
-clientserver    +insert_expand   +packages        -toolbar
+clipboard       +job             +path_extra      +user_commands
+cmdline_compl   +jumplist        +perl            +vertsplit
+cmdline_hist    +keymap          +persistent_undo +virtualedit
+cmdline_info    +lambda          +postscript      +visual
+comments        +langmap         +printer         +visualextra
+conceal         +libcall         +profile         +viminfo
+cryptv          +linebreak       -python          +vreplace
+cscope          +lispindent      +python3         +wildignore
+cursorbind      +listcmds        +quickfix        +wildmenu
+cursorshape     +localmap        +reltime         +windows
+dialog_con      +lua             +rightleft       +writebackup
+diff            +menu            +ruby            -X11
+digraphs        +mksession       +scrollbind      -xfontset
-dnd             +modify_fname    +signs           -xim
-ebcdic          +mouse           +smartindent     -xpm
+emacs_tags      -mouseshape      +startuptime     -xsmp
+eval            +mouse_dec       +statusline      -xterm_clipboard
+ex_extra        -mouse_gpm       -sun_workshop    -xterm_save
+extra_search    -mouse_jsbterm   +syntax
+farsi           +mouse_netterm   +tag_binary
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/local/share/vim"
Compilation: clang -c -I. -Iproto -DHAVE_CONFIG_H   -DMACOS_X_UNIX  -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: clang   -L. -L/usr/local/lib  -L/usr/local/lib -o vim        -lm  -lncurses -liconv -framework Cocoa  -L/usr/local/lib -llua -fstack-protector  -L/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE -lperl  -L/usr/local/opt/python3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/config-3.5m -lpython3.5m -framework CoreFoundation  -lruby.2.0.0 -lobjc

macOS 下使用 brew 安装 vim 非常方便, 其他平台下可以自行搜索更多内容, 网络上有很多指引.

4.1.2 第三方工具

比如语法检查时用到的各种 linter, python 代码格式化时用到的 yapf。具体这些工具如何安装,在需要时自行安装即可。

4.1.3 安装字体

要想界面漂亮,字体可能也是不可或缺, 况且安装也不是很复杂。

对于 airline layer 中使用的 vim-airline 最好搭配 powerline fonts 字体, space-vim 默认不使用. 推荐安装:

$ git clone https://github.com/powerline/fonts.git ~/.fonts
$ sh ~/.fonts/install.sh

powerline font 安装完成后,在 .spacevim 中启用字体:

let g:airline_powerline_fonts=1

4.1.4 字体设置

GUI 环境下, 可直接在 vim 的配置文件进行设置.

终端环境下 vim 的字体服从于 terminal 的字体设置,因此安装完成后, 需要在 terminal 的字体设置中启用带有 for powerline 样式的字体,否则在启用 airline 时可能会出现状态栏乱码. 下图为 iterm2 中的字体设置:

iterm2_powerline_setting.png

Figure 5: iterm2 font setting

4.2 启用已有 layer / 禁用部分插件

启用 layer 非常简单,使用一键安装脚本安装 space-vim 时会自动在当前用户目录下生成一个 .spacevim ,可在其中的 Layers() 部分进行启用已有的 layer, 也可以在里面放置 space-vim 没有的插件:

每个 layer 下,通常附有一个 README 以简要说明,请在启用该 layer 时进行查阅

使用 Layer 命令可以加载 layer, 但是如果不想加载 layer 中的所有插件, 可以使用 exclude 选项进行部分禁用, 比如不想要 'itchyny/vim-cursorword' (这是给当前单词相匹配的所有单词加上下划线的插件):

function! Layers()

    Layer 'fzf'
    Layer 'unite'
    Layer 'better-defaults', { 'exclude': 'itchyny/vim-cursorword' }

endfunction

注意,如果是首次启用一个 layer,需要执行 SPC f R, 或者 :so $MYVIMRC, 重新加载 .vimrc 并执行 :PlugInstall 安装所需的相关插件 。或者退出重新打开 vim, vim-plug 将会检测并自动安装缺失的插件。

4.3 添加个性化插件

UserInit() 可以放置个人私有的一些插件。

function! UserInit()

   Plug 'extr0py/oni'

endfunction

4.4 覆盖已有配置信息

.spacevim 中有个 UserConfig() ,可以将一些个性化配置放在这里, 对已有的一些配置信息进行覆盖。比如想换个主题, 自定义一些快捷键等:

function! UserConfig()

    color molokai
    nnoremap Q :qa!<CR>

endfunction

如果个性化配置比较多,也可以放在 private 目录下。private 可看做是一个 layer, 里面可以有 config.vim 与 packages.vim 这两个文件。如果这两个文件存在,space-vim 也会在启动时进行加载。

5 更新

对于 vim 插件的更新,自然是通过插件管理器 vim-plug 提供的相关命令 :PlugUpdate

对于 space-vim , 可以进入 path/to/.space-vim 执行 git pull origin master

$ git pull origin master

6 默认安装

.spacevim 默认启用了 3 个 layer:

Layer 'fzf'
Layer 'unite'
Layer 'better-defaults'

一个尽快上手最重要的快捷键: SPC ? , 使用空格键加问号查看现有的键位绑定, 打开后可使用 Ctrl j, Ctrl k 进行上下选择, Ctrl c 退出, 也可直接输入进行模糊查找:

maps.png

Figure 6: SPC ? key maps

从图中可以看到键位映射,比如挑一个 <Space> b p, 后面跟着该快捷键对应的命令 :bprevious<CR>, 意为 buffer previous, 即跳转前一个 buffer. 后面还跟着定义该快捷键的文件, 来自 vim-better-default/plugin/default.vim 。不熟悉时,可以将快捷键都看一下。

SPC ? 实际映射的命令是 fzf.vim:Maps, 因此 fzf layer 实际是为了支持 unite layer. 不过其中安装的 fzf 除了可在 vim 中,也可在 terminal 中使用, 非常值得了解。

更多内容请直接查看各 layer 下的 README. 如果 README 有问题,还是直接查看其中的 config.vim 与 packages.vim, 不要害怕,这些内容都很简单,跟平常的 vimrc 并没有什么两样。

6.1 better-defaults

一些 “人性化” 设置和基本的键位映射,包括 buffer, window, esay-motion 快速移动等操作。了解 better-defaults 下面的键位设置非常重要,因为这些是所有快捷键设定的重要组成部分.

6.2 unite

unite layer 主要希望提供一个界面来选择一些不太常用或稍复杂的命令.

7 基础键位

7.1 Basic

insert mode 与 command mode 的快捷键大都由 rsi.vim 支持, :h rsi 查看其完整文档。 它是一种类似 Emacs 的键位绑定,这种设定在很多地方都是默认配置,比如 bash.

Key Binding Mode Description
SPC q Normal q uit, 退出
SPC Q Normal quit without saving, 不保存强制退出
SPC d Normal go d own half page, 向下移动半屏
SPC u Normal go u p half page, 向上移动半屏
SPC s c Normal s earch result highlight c ountermand, 取消搜索结果高亮
SPC t p Normal t oggle p astemode, 粘贴模式开关
U Normal redo, 重做(对应 u 为撤销,undo)
H Normal beginning of line, 光标跳转到行首
L Normal end of line, 光标跳转到行尾
Y Normal yank from cursor to end of line, 从光标处复制到行尾
; Normal :, 快速进入 command mode
SPC f s Normal f ile s ave, 保存文件
SPC f [1-9] Normal f old level, 设置折叠层次,f 0 相当于全部折叠, f 9 相当于取消折叠全部展开
Ctrl j Insert j, 向下移动
Ctrl k Insert k, 向上移动
Ctrl h Insert h, 向左移动
Ctrl l Insert l, 向右移动
jj Insert \<Esc>
jk Insert \<Esc>
kk Insert \<Esc>
Ctrl h Command <left>
Ctrl j Command <down>, next command, 下一条历史命令
Ctrl k Command <up>, previous command, 上一条历史命令
Ctrl l Command <right>
Ctrl a Insert, Command <home>, 行首
Ctrl e Insert, Command <end>, 行尾
Ctrl d Insert, Command <delete>, 删除
Ctrl g Command <esc>, return to nomral mode from command mode
Ctrl f Insert, Command f orward, move forward one character
Ctrl b Insert, Command b ackward, move backward one character
v Visual <Esc>

7.2 Tab

Key Binding Mode Description
<Ctrl-Tab> Normal, Insert next tab
<Alt-Tab> Normal, Insert previous tab

tabline 显示的信息示例: T-2:1/3W, T-当前 tab 编号:当前光标所在 Window 的编号/该 tab 所有的 window 总数.

7.3 Buffer

Key Binding Mode Description
SPC b [1-9] Normal switch to buffer with number [1-9], 切换至对应编号[1-9]对应缓冲区
SPC b p Normal p revious b uffer, 上一个缓冲区
SPC b n Normal n ext b uffer, 下一个缓冲区
<Tab> Normal next buffer, equal to SPC b n, 等同于 SPC b n
<Shift-Tab> Normal previous buffer, equal to SPC b p, 等同于 SPC b p
SPC b d Normal d elete current buffer, 删除当前缓冲区
SPC b k Normal k ill current buffer, 杀掉当前缓冲区

7.4 Window

Key Binding Mode Description
SPC w j Normal window-down, 移动至下方窗口
SPC w k Normal window-up, 移动至上方窗口
SPC w h Normal window-left, 移动至左侧窗口
SPC w l Normal window-right, 移动至右侧窗口
SPC w J Normal 向下扩大当前窗口
SPC w K Normal 向上扩大当前窗口
SPC w H Normal 向右扩大当前窗口
SPC w L Normal 向左扩大当前窗口
SPC w v Normal split-window-right, 竖直分割窗口
SPC w 2 Normal layout-double-columns, 将窗口分割为两列,等同于 SPC w v
SPC w s Normal split-window-below, 水平分割窗口, 等同于 SPC w -
SPC w d Normal delete-window, 关闭 (cancel, 记 d elete) 当前窗口
SPC w q Normal quit-window, 退出 (q uit) 当前窗口,若是最后一个窗口则退出vim
SPC w w Normal other-window, 在所有窗口中循环移动
SPC w r Normal window-replace, 向右或向下方交换 (r eplace) 窗口
SPC w m Normal GUI 环境下 vim 窗口最大化 (m aximum) 开关

7.5 easy-motion

Key Binding Mode Description
SPC j w Nomral 单词跳转 (jump to word)
SPC j l Nomral 行间跳转 (jump to line)
SPC j j Nomral goto-char, 单个字符搜索, 等同于 SPC SPC s
SPC j J Nomral goto-char-2, 两个字符搜索
SPC SPC w Normal 快速词间移动(向前)
SPC SPC b Normal 快速词间移动 (向后)
SPC SPC s Normal 快速字符搜索 (双向)
SPC SPC f Normal 快速字符搜索 (向前)
SPC SPC j Normal 快速行间移动 (向下)
SPC SPC k Normal 快速行间移动 (向上)

7.6 Others

Key Binding Mode Description
SPC b h Normal b uffer h ome, 主 buffer
SPC f f Normal f ile s earch, 使用 fzf 搜索当前用户目录下的文件 (terminal vim)
SPC f ? Normal f ile search, 使用 fzf 搜索当前工作目录下的文件 (terminal vim)
SPC f R Normal reload .vimrc, 重新加载 .vimrc (f ile R esource)
SPC f r Normal f ile used r ecently, 最近使用的文件
SPC f t Normal f ilet/ oggle, NERDTree toggle, 打开 NERDTree
SPC x d Normal delete trailing whitespace, 去掉行尾多余空格 (te x t d elete)

8 使用建议

8.1 启动时间

当启用很多 layer 时, 意味着加载了很多插件与配置信息, 很可能会导致 vim 启动时变慢, 这是我们不愿意看到的.

vim-startuptime-benchmark 可以看出, 即使使用很多插件仍然可以保持很快的启动 ( 200 ms 以内). 尽管加载的插件不尽相同, 但仍具有借鉴意义. 这里 也有一篇关于 vim 启动优化非常好的文章。

虽然有些使用插件延迟加载, 但有一段时间 space-vim 启用很多 layer 时, 启动时间普遍超过 500 ms, 有时甚至会超过 900 ms. 测试环境:

  • Retina 13-inch mid 2014
  • VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Nov 21 2016 17:35:16).

    vim --startuptime vim.log 会将启动时的一些时间, 加载的文件等情况写入到 vim.log 中, 大家可以自行测试一下.

虽然比起 spacemacs 几秒钟的启动时间, 几百毫秒已经很快. 但对于 vim, 启动迅速是硬性要求, 而且当超过 900 ms 时, 就会有明显的 lag. 后来在这里找到了暂时的解决方案: load-plugins-manually , 主要是 YouCompleteMe 与 ultisnips 两个插件.

下面是我一般会启用的 layer, 其中 airline 我已经默认不启用了, 因为可能会它可能会导致 100 ms 的启动延迟, 默认的 statusline 已经够用了, 我会在接下来介绍它。

function! Layers()

    Layer 'emoji'
    Layer 'goyo'

    Layer 'html'
    Layer 'c-c++'
    Layer 'python'
    Layer 'markdown'
    Layer 'graphviz'

    Layer 'airline'

    Layer 'chinese'

    Layer 'text-align'
    Layer 'programming'

    Layer 'ycmd'
    Layer 'syntax-checking'

endfunction

8.2 space-vim statusline

statusline.png Terminal vim 默认的 statuline 显示的信息依次为:

buffer 编号 ❖ window 编号 [TOT: buffer 总数] 文件大小 文件名 fugitive/ale 信息  [文件类型] 文件编码 | 编码类型 | 行号:列号-虚拟列号 位置信息

GUI vim 由于渲染的原因,有些 unicode 字符无法正常显示, 因此去掉了 unicode 字符。

[buffer-编号] [window-编号] [TOT: buffer 总数] 文件大小 文件名 fugitive/ale 信息  [文件类型] 文件编码 | 编码类型 | 行号:列号-虚拟列号 位置信息

通过 statuline 的 window-编号, 可以使用 SPC 编号 切换到对应的 window. 通过 [TOT: buffer 总数], 可以知道当前共有几个 buffer, 使用 TabShift-Tab 进行前后的 buffer 切换.

如果启用 airline Layer, 默认的 SPC [1-9] 快捷键可能不是那么人性化, 可以参考 这里 重新进行覆盖设置.

9 后记

space-vim 仅仅是一个起点,在不断使用 vim 的过程中,每个人都会不断总结出适合自己的套路。开始不仅仅 "手中有剑", 而是 "心中有剑", 到这时你便完全可以打造一个独属于自己的配置。 为什么要有一个自己的配置? Because you can and you love it.

学习从模仿开始, 而且要从模仿最好的开始. 我在学习与使用 vim 的过程中也向别人偷师了很多内容, 同样, 如果在此过程中,space-vim 能够发挥些许作用,也算功德圆满。

在使用 space-vim 的过程中,如果您能分享一些更好的解决方案,或是改进一些不合理之处,欢迎之至。

vim 只不过是工具, 你用记事本写程序都可以, 我们最终要做的是解决问题, 切莫舍本逐末, 一味地追求工具的打磨.

10 感谢

感谢 spacemacs, vim-plug 以及众多开源项目等杰出的工作,也感谢所有关注 space-vim 并帮助其不断进步的人们!

Author: Liu-Cheng Xu

Created: 2017-03-14 Tue 20:41

Validate