Iawen's Blog

我喜欢这样自由的随手涂鸦, 因为我喜欢风......

Vim是从 vi 发展出来的一个文本编辑器。代码补完、编译及错误跳转等方便编程的功能特别丰富, 在程序员中被广泛使用。
简单的来说, vi 是老式的字处理器, 不过功能已经很齐全了, 但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。
连 vim 的官方网站 自己也说 vim 是一个程序开发工具而不是文字处理软件。
0

1. 基本操作

2

1.1 基本编辑命令

命令 作用
u 撤销你刚才做的动作
ctrl+r 恢复你刚才撤销的动作
n
L 移到屏幕的最后一行
M 移到屏幕的中间一行
H 移到屏幕的第一行
$ 移动光标到行尾
n$ 移动到第n行的行尾
0 移动光标到行首
^ 移动光标到行首第一个非空字符上去
gg 移动文件首
{ / } 移到段落的开头 / 结尾
[[ / ]] 回到段落的开头处 / 向前移到下一个段落的开头处
Shift+G 移动到文件尾
d1G 删除光标所在到第一行的所有数据
dG 删除光标所在到最后一行的所有数据
d$ 删除光标所在处, 到该行的最后一个字符
d0 (数字0)删除光标所在到该行的最前面的一个字符
x,X x向后删除一个字符(相当于[del]按键),X向前删除一个字符(相当于[backspace]即退格键)
nx n为数字, 连续向后删除n个字符
dd 剪切一行
n+dd 剪切n行
yy 复制一行
n+yy 复制n行
p 对复制的行进行粘贴
: 32,65d 32-65行就被删除了
~ 将光标下的字母改变大小写
3~ 将光标位置开始的3个字母改变其大小写
g~~ 改变当前行字母的大小写
U 将可视模式下选择的字母全改成大写字母
u 将可视模式下选择的字母全改成小写
gUU 将当前行的字母改成大写
guu 将当前行的字母全改成小写
3gUU 将从光标开始到下面3行字母改成大写
guw 将光标下的单词改成小写
gUw 将光标下的单词改成大写

1.2 基本的替换

查找与替换, 语法如下: :{作用范围}s/{目标}/{替换}/{替换标志}
作用范围: . 表示当前行, $表示结尾, 或者行数如n,m, 如无则表示当前行
替换标志: g 替换当前行所有, i表示大小写不敏感, I表示大小写敏感, c表示需要确认
可以使用 # 作为分隔符, 此时中间出现的 / 不会作为分隔符

命令 作用
:s/vivian/sky/ 替换当前行第一个 vivian 为 sky
:s/vivian/sky/g 替换当前行所有 vivian 为 sky
:n,$s/vivian/sky/ 替换第 n 行开始到最后一行中每一行的第一个 vivian 为 sky
:n,$s/vivian/sky/g 替换第 n 行开始到最后一行中每一行所有 vivian 为 sky
:%s/vivian/sky/ (等同于 :g/vivian/s//sky/) 替换每一行的第一个 vivian 为 sky
:%s/vivian/sky/g (等同于 :g/vivian/s//sky/g) 替换每一行中所有 vivian 为 sky
:s#vivian/#sky/# 替换当前行第一个 vivian/ 为 sky/
:%s+/oradata/apras/+/user01/apras1+ (使用+ 来 替换 / ): /oradata/apras/替换成/user01/apras1/
:%s/foo/bar/gic 按下y表示替换, n表示不替换, a表示替换所有, q表示退出查找模式, l表示替换当前位置并退出。^E与^Y是光标移动快捷键
:%s/%x00/ /g 替换不可见字符

1.3 复制/移动 多行

任务: 将第9行至第15行的数据, 复制到第16行 : 9, 15 copy 16 或 : 9, 15 co 16
由此可有: 9, 15 move 16:9,15 m 16 将第9行到第15行的文本内容移动到第16行的后面

假设编辑文件nginx.conf , 把该文件的51至91行拷贝到新文件./vhost/res.help.com.conf中, 详细实现, 请参阅下面示例:

:51,91w!./vhost/res.help.com.conf

再拓展下, 如何把nginx.conf 中的31到34行追加到文件./vhost/res.help.com.conf中, 请参阅下面示例:

:31,34 w! >>./vhost/res.help.com.conf

1.4 符串查找功能

◈ 命令 / 代表正向搜索模板
◈ 命令 ? 代表正向搜索模板

输入 / 或者 ?  加 需要查找的字符串来进行搜索, 比如想搜索 super 这个单词,  可以输入  /super  或者  ?super,   两者的区别是前者是从上往下搜索, 后者是从下往上搜索, 通过 n  或  N 进行上一个或下一个的匹配。
1. 最快的方式是让光标停留在想要查找的单词的任意一个字母上面,  然后输入Shift + *  , 即可快速选中该单词。
2. 让光标停留在单词的第一个字母上,  然后输入yw拷贝该单词,  然后输入 / (Ctrl + R) 0 (即 /”0), 回车,  就查找到了第一个匹配的单词。

1.5 使用 VI/VIM 编辑器打开多个文件

要打开多个文件, 命令将与打开单个文件相同。我们只要添加第二个文件的名称。

vi file1 file2 file3

vim已经启动, 输入 :e file 可以再打开一个文件, 并且此时vim里会显示出file文件的内容。

窗口分割命令:

命令 作用
:sp 水平切分窗口
:vsplit 垂直切分窗口
Ctrl+w+方向键 切换到前/下/上/后一个窗
Ctrl+w+h/j/k/l 同上
Ctrl+ww 依次向后切换到下一个窗格中
ctrl+w++/- 增大或缩小窗口
q当前 qall全部 only除当前之外的窗口 关闭窗口
:bdelete 或者:bd 关闭其中一个文件

要浏览到下一个文件, 我们可以(在 vim 命令模式中)使用:

命令 作用
Ctrl+6 两文件间的切换
:n 切换到下一个文件, :wn保存再切换
:N 到上一个文件, :wN保存再切换
:bn 下一个文件
:bp 上一个文件
:ls 列出打开的文件, 带编号
:b1~n 切换至第n个文件
:.= 看当前行
:e filename
:bd 关闭当前文件

1.6 在编辑器中运行外部命令

运行命令的语法是:
:! command
这是一个例子:
:! df -H

1.7 使用 set 命

我们也可以使用 set 命令自定义 vi/vim 编辑器的行为和外观。下面是一些可以使用 set 命令修改 vi/vim 编辑器行为的选项列表:

:set nu| nonu	在每行开始显示/取消行号
:set hlsearch|nohlsearch	高亮显示匹配的单词
:set autoindent|noautoindent	是否自动缩排
:set backup	
:set ruler	
:set showmode	
:set backspace=(012)	
:set all	显示目前所有的环境参数设置值
:set	
:syntax on|off	依据程序相关语法显示不同颜色
:set bg=dark|light	 

:set ic ' 在搜索时忽略大小写
:set smartcase ' 搜索强制区分大小写
:set ro ' 将文件类型更改为只读
:set term ' 打印终端类型
:set ai ' 设置自动缩进
:set noai ' 取消自动缩进
其他一些修改 vi 编辑器的命令是: 
:colorscheme ' 用来改变编辑器的配色方案 。(仅适用于 VIM 编辑器)

1.8 区块选择

v	字符选择, 会将光标经过的地方反白选择
V	列选择
Ctrl + v	区块选择, 可以用长方形的方式选择数据
y	复制
d	删除
p	粘贴

1.9 vim中大小写转化的命令是: gu或者gU

1.9.1 整篇文章大写转化为小写: ggguG

  • gg=光标到文件第一个字符
  • gu=把选定范围全部小写
  • G=到文件结束

1.9.2 只转化某个单词

guw 、gue
gUw、gUe
这样, 光标后面的单词便会进行大小写转换
想转换5个单词的命令如下:
gu5w、gu5e
gU5w、gU5e

1.9.3 转换几行的大小写

将光标定位到想转换的行上, 键入: 1gU 从光标所在行 往下一行都进行小写到大写的转换
10gU, 则进行11行小写到大写的转换
以此类推, 就出现其他的大小写转换命令

  • gU0: 从光标所在位置到行首, 都变为大写
  • gU$: 从光标所在位置到行尾, 都变为大写
  • gUG: 从光标所在位置到文章最后一个字符, 都变为大写
  • gU1G: 从光标所在位置到文章第一个字符, 都变为大写

2. 正则替换

2.1 使用正则表达式的命令

使用正则表达式的命令最常见的就是 / (搜索)命令。其格式如下:
/正则表达式
另一个很有用的命令就是 :s(替换)命令, 将第一个//之间的正则表达式替换成第二个//之间的字符串。
:s/正则表达式/替换字符串/选项
在学习正则表达式时可以利用 / 命令来练习。

2.2 元字符

元字符是具有特殊意义的字符。使用元字符可以表达任意字符、行首、行 尾、某几个字符等意义。

元字符 说明
. 匹配任意一个字符
[abc] 匹配方括号中的任意一个字符。可以使用-表示字符范围, 如[a-z0-9]匹 配小写字母和阿拉伯数字
[^abc] 在方括号内开头使用^符号, 表示匹配除方括号中字符之外的任意字符
\d 匹配阿拉伯数字, 等同于[0-9]
\D 匹配阿拉伯数字之外的任意字符, 等同于[^0-9]
\x 匹配十六进制数字, 等同于[0-9A-Fa-f]
\X 匹配十六进制数字之外的任意字符, 等同于[^0-9A-Fa-f]
\w 匹配单词字母, 等同于[0-9A-Za-z_]
\W 匹配单词字母之外的任意字符, 等同于[^0-9A-Za-z_]
\t 匹配字符
\s 匹配空白字符, 等同于[ \t]
\S 匹配非空白字符, 等同于[^ \t]

另外, 如果要查找字符 *、.、/等, 则需要在前面用 \ 符号, 表示这不是元字符, 而只是普通字符而已。

\*	匹配 * 字符。
\.	匹配 . 字符。
\/	匹配 / 字符。
\\	匹配 \ 字符。
\[	匹配 [ 字符。

表示数量的元字符

*	    匹配0-任意个
\+	    匹配1-任意个
\?	    匹配0-1个
\{n,m}	匹配n-m个
\{n}	匹配n个
\{n,}	匹配n-任意个
\{,m}	匹配0-m个

表示位置的符号

$	匹配行尾
^	匹配行首
\<	匹配单词词首
\>	匹配单词词尾

使用例:

/char\s\+[A-Za-z_]\w*   查找所有以char开头, 之后是一个以上的空白, 最后是一个标识符和分号
/\d\d:\d\d:\d\d         查找如 17:37:01 格式的时间字符串
:g/^\s*$/d              删除只有空白的行
:s/\<four\>/4/g         将所有的four替换成4, 但是fourteen中的four不替换

2.3 替换变量

在正规表达式中使用 ( 和 ) 符号括起正规表达式, 即可在后面使用\1、\2 等变量来访问 ( 和 ) 中的内容。
使用例

/\(a\+\)[^a]\+\1 " 查找开头和结尾处a的个数相同的字符串, 
" 如 aabbbaa, aaacccaaa, 但是不匹配 abbbaa
:s/\(http:\/\/[-a-z\._~\+%\/]\+\)/<a href="\1">\1<\/a>/ " 将URL替换为<a href="http://url">http://url</a>的格式
:s/\(\w\+\)\s\+\(\w\+\)/\2\t\1 " 将 data1 data2 修改为 data2 data1

2.4 函数式

在替换命令 s/// 中可以使用函数表达式来书写替换内容, 格式为

:s/替换字符串/\=函数式

在函数式中可以使用 submatch(1)、submatch(2) 等来引用 \1、\2 等的内容, 而submatch(0)可以引用匹配的整个内容。
使用例

:%s/\<id\>/\=line(".") " 将各行的 id 字符串替换为行号
:%s/^\<\w\+\>/\=(line(".")-10) .".". submatch(1) " 将每行开头的单词替换为 (行号-10).单词 的格式, " 如第11行的 word 替换成 1. word

2.5 与Perl正则表达式的区别

Vim语法 Perl语法 含义
+ + 1-任意个
? ? 0-1个
{n,m} {n,m} n-m个
\(和\) (和) 分组

3. 利用 Vim 进行程序设计

3.1 执行代码

在 VimScript 中创建函数的语法非常简单。它以关键字 func 开头, 然后是函数名(在 VimScript 中函数名必须以大写字母开头, 否则 Vim 将提示错误)。在函数的结尾用关键词 endfunc。
以执行CXX程序为例, 在.vimrc 配置文件里创建的一个名为 CPP() 函数的片段。
在函数的主体中, 可以看到 exec 语句, 无论您在 exec 关键字之后写什么, 都会在 Vim 的命令模式上执行(记住, 就是在 Vim 窗口的底部以 : 开始的命令)。现在, 传递给 exec 的字符串是(LCTT 译注: :!clear && g++ % && ./a.out) -

func CPP()
    exec "!clear && g++ % && ./a.out && rm -rf ./a.out" 
endfunc
map <silent> <C-r> :call CPP()<CR>

将语句 call CPP() 映射到键组合 Ctrl+r, 以便我现在可以按 Ctrl+r 来执行我的 C++ 代码, 无需手动输入 :call CPP(), 然后按 Enter 键。

3.2 用 Vim 中的自动命令 autocmd

autocmd 的优点是这些命令无需用户调用, 它们在用户所提供的任何特定条件下自动执行。
需要先开启: filetype plugin indent on
我想用 autocmd 实现这个, 而不是对每种语言使用不同的映射, 执行不同程序设计语言编译出的代码。
1

func CPP()
    exec "!clear && g++ % && ./a.out" 
endfunc
autocmd FileType cpp map<C-r> :call CPP()<CR>

会发生什么?当我打开任何上述提到的文件类型的缓冲区, Vim 会自动将 Ctrl + r 映射到函数调用, 而 表示回车键, 这样就不需要每完成一个独立的任务就按一次回车键了。
为了实现这个功能, 您只需将函数片段添加到 .vimrc 文件中, 然后将所有这些 autocmd也一并添加进去。这样, 当您下一次打开 Vim 时, Vim 将拥有所有相应的功能来执行所有具有相同绑定键的代码。

3.3 vim多行注释和取消注释

多行注释:

  1. 进入命令行模式, 按ctrl + v进入 visual block模式, 然后按j, 或者k选中多行, 把需要注释的行标记起来
  2. 按大写字母I, 再插入注释符, 例如//
  3. 按esc键就会全部注释了
    取消多行注释:
  4. 进入命令行模式, 按ctrl + v进入 visual block模式, 按字母l横向选中列的个数, 例如 // 需要选中2列
  5. 按字母j, 或者k选中注释符号
  6. 按d键就可全部取消注释

3.4 vim多行缩进技巧

  1. 按v进入visual状态, 选择多行, 用>或<缩进或缩出
  2. 通常根据语言特征使用自动缩进排版: 在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的下面n行。你可以试试把代码缩进任意打乱再用n==排版, 相当于一般IDE里的code format。
  3. 用gg=Shift+G可对整篇代码进行排版。(gg代表首, Shift+G代表尾)

4. 配置

4.1 vim的几种模式和按键映射

Map是Vim强大的一个重要原因, 可以自定义各种快捷键, 用起来自然得心应手。
vim里最基本的map用法也就是
:map c a

这里把c映射成了a, 在map生效的情况下, 按下c就等同于按下了a
当然, 常用的Ctrl,Shift,Alt自然也是支持的。

令Ctrl+a对应到a  :map <C-a> a
令Alt+a对应到a   :map <A-a> a
令Ctrl+Alt+a对应到a    :map <C-A-a> a

到此, 我们已经可以做很多事情了。
但是map命令远不只这一种, 在不同的模式下, 同一组按键可以被映射到不同的组合上。

Vim的模式众多, 但是一般被提及的也就是这么几种:

  • Normal Mode 也就是最一般的普通模式, 默认进入vim之后, 处于这种模式。
  • Visual Mode 一般译作可视模式, 在这种模式下选定一些字符、行、多列。

在普通模式下, 可以按v进入。

  • Insert Mode 插入模式, 其实就是指处在编辑输入的状态。普通模式下, 可以按i进入。
  • Select Mode 在gvim下常用的模式, 可以叫作选择模式吧。用鼠标拖选区域的时候, 就进入了选择模式。

和可视模式不同的是, 在这个模式下, 选择完了高亮区域后, 敲任何按键就直接输入并替换选择的文本了。
和windows下的编辑器选定编辑的效果一致。普通模式下, 可以按gh进入。

  • Command-Line/Ex Mode
    就叫命令行模式和Ex模式吧。两者略有不同, 普通模式下按冒号(:)进入Command-Line模式, 可以输入各种命令,
    使用vim的各种强大功能。普通模式下按Q进入Ex模式, 其实就是多行的Command-Line模式。

对于Map, 有几个基本的概念
命令的组合
同Vim下的其他命令一样, 命令的名字往往由好几段组成。前缀作为命令本身的修饰符, 微调命令的效果。
对于map而言, 可能有这么几种前缀

nore    表示非递归, 见下面的介绍
n    表示在普通模式下生效
v    表示在可视模式下生效
i    表示在插入模式下生效
c    表示在命令行模式下生效

Recursive Mapping
递归的映射。其实很好理解, 也就是如果键a被映射成了b, c又被映射成了a, 如果映射是递归的, 那么c就被映射成了b。

:map a b
:map c a

对于c效果等同于 :map c b
默认的map就是递归的。如果遇到[nore]这种前缀, 比如:noremap, 就表示这种map是非递归的。
unmap
unmap后面跟着一个按键组合, 表示删除这个映射。
:unmap c
那么在map生效模式下, c不再被映射到a上。
同样, unmap可以加各种前缀, 表示影响到的模式。
mapclear
mapclear直接清除相关模式下的所有映射。
同样, mapclear可以加各种前缀, 表示影响到的模式。
这里列出常用的一些map命令, 默认map命令影响到普通模式和可视模式。

:map :noremap :unmap :mapclear
:nmap :nnoremap :nunmap :nmapclear
:vmap :vnoremap :vunmap :vmapclear
:imap :inoremap :iunmap :imapclear
:cmap :cnoremap :cunmap :cmapclear

可以试试这些命令
命令行模式下建一个mapping
nmap b a
现在普通模式下, 按b, 可以进入插入模式, 随便输入一些字符
命令行模式下建一个mapping
vmap b d
现在普通模式下, 按V, 进入了可视模式, 并且选定了一整行, 按下b, 可以删除整行
命令行模式下建一个mapping
imap b a
现在试着给正在编辑的这个文件输入一个字符”b”吧 :p
命令行模式下建一个mapping
cmap b c
命令行模式下, 按下b, 会出来一个a
好了, 到此vim的按键已经被你弄得乱七八糟了, 试着用unmap和mapclear清除这些mapping吧。:]

Reference
vim的几种模式和按键映射

键表

<k0> - <k9> 小键盘 0 到 9
<Fn> - 功能键盘 F1 到 F12 
<S-...> Shift+键 
<C-...> Control+键 
<M-...> Alt+键 或 meta+键 
<A-...> 同 <M-...> 
<Esc> Escape 键 
<Up> 光标上移键 
<Space> 插入空格 
<Tab> 插入Tab 
<CR> 等于<Enter>

4.2 键盘映射时的作用是什么?

The key is mapped to \ by default. So if you have a map of t, you can execute it by default with \t【1】.
For more detail or re-assigning it using the mapleader variable, see
:help leader
To define a mapping which uses the “mapleader” variable, the special string
” can be used. It is replaced with the string value of “mapleader”.
If “mapleader” is not set or empty, a backslash is used instead.
Example:
:map A oanother line
Works like:
:map \A oanother line
But after:
:let mapleader = “,”
It works like:
:map ,A oanother line
Note that the value of “mapleader” is used at the moment the mapping is
defined. Changing “mapleader” after that has no effect for already defined
mappings.

Reference
What is the in a .vimrc file?

4.3 vim与Tab相关的几个参数

normal 模式下:

>>  当前行增加缩进
<<  当前行减少缩进

insert模式下:

CTRL+SHIFT+T:   当前行增加缩进(Ubuntu下试过, 不对)
CTRL+SHIFT+D:   当前行减少缩进 

与Tab相关的参数有shiftwidth、tabstop、softtabstop、expandtab。

shiftwidth      缩进操作(<<和>>)时缩进的列数(这里的一列相当于一个空格)
tabstop         一个tab键所占的列数, linux 内核代码建议每个tab占用8列
softtabstop     敲入tab键时实际占有的列数。
expandtab       输入tab时自动将其转化为空格

softtabstop大于tabstop时, 且没有设置expandtab时, 例如: softtabstop=12, tabstop=8, 那么当输入一个tab时(softtabstop: 实际占用的是12列), 最后会变成一个tab(tabstop)加4个空格(8+4), 输入两个tab(2个softtabstop: 24列)会变成3个tab(tabstop), 也就是说vim或用tabstop+空格来表示, 最终你能看到的缩进的列数一定是softtabstop*按的tab键次数。(ps: :set list 可以查看tab符号)
softtabstop小于tabstop且没有设置expandtab时, 如果softtabstop=4, tabstop=8, 输入一个tab(softtabstop), 会变成4个空格(因为不够用一个tabstop表示), 输入两个tab会变成一个tab(8列)。
如果softtabstop等于tabstop, 而且expandtab没有设置, softtabstop与tabstop就没什么区别了。
如果设置的expandtab, 输入一个tab, 将被展开成softtabstop值个空格, 如果softtabstop=4, 那么一个tab就会被替换成4个空格。
常用的tab设置为:
" 设置tab缩进为空格
set expandtab “set et
" 设置换行自动缩进为4个空格
set shiftwidth=4
" 设置tab键缩进为4个空格的距离, vim默认是8
set tabstop=4 “set ts=4
" 敲入tab键时,一个实际占有的列数
set softtabstop=4

Reference
每日一Vim(9)—-缩进

4.4 vim检测文件类型

执行:filetype可以查看Vim的文件类型检测功能是否已打开, 默认你会看到: detection:ON plugin:OFF indent:OFF。
下面详细介绍这三个参数的具体含义

  • detection: 默认情况vim会对文件自动检测文件类型, 也就是你看到的’detection:ON’, 同样你可以手动关闭:filetype off。 可以用:set filetype查看当前文件是什么类型了。 类似file.txt文件的filetype设置为python, 那么就和普通的python文件一样的显示效果了: set filetype=python。
  • 另一种方式就是在文件内容中指定, Vim会从文件的头几行自动扫描文件是否有声明文件的类型的代码, 如在文件的行首加入# vim: filetype=python, Java文件变通的做法/* vim: filetype=java */, 总之就是把这行当作注释, 以致于不影响文件的编译, 这样Vim不通过文件名也能检测出文件是什么类型了。
  • plugin: 如果plugin状态时ON, 那么就会在Vim的运行时环境目录下加载该类型相关的插件。比如为了让Vim更好的支持Python编程, 你就需要下载一些Python相关的插件, 此时就必须设置plugin为ON插件才会生效, 具体设置方法就是:filetype plugin on
    indent: 不同类型文件有不同的方式, 比如Python就要求使用4个空格作为缩进, 而c使用两个tab作为缩进, 那么indent就可以为不同文件类型选择合适的缩进方式了。你可以在Vim的安装目录的indent目录下看到定义了很多缩进相关的脚本。具体设置方法: filetype indent on。
    以上三个参数, 可以写成一行filetype plugin indent on设置在_vimrc文件中。

Reference
每日一Vim(25)filetype—- 文件类型检测

4.5 vim自动缩进的几种方式

There are a number of methods enabling automatic indentation in Vim, ranging from fairly “stupid” and unintrusive ones, like ‘autoindent’ and ‘smartindent’, to complex ones such as ‘cindent’ and custom indentation based on filetype using ‘indentexpr’. The amount of indentation used for one level is controlled by the ‘shiftwidth’ option(缩进的个数是由’shiftwidth’设置来控制的).[1]
‘autoindent’
‘autoindent’ does nothing more than copy the indentation from the previous line, when starting a new line. It can be useful for structured text files, or when you want to control most of the indentation manually, without Vim interfering.
‘autoindent’ does not interfere with other indentation settings, and some file type based indentation scripts even enable it automatically.(一些基于filetype来缩进的脚本会自动enable它, 所以set autoindent 加上filetype plugin indent on是一个比较好的选择)
‘smartindent’ and ‘cindent’
‘smartindent’ automatically inserts one extra level of indentation in some cases, and works for C-like files. ‘cindent’ is more customizable, but also more strict when it comes to syntax.
‘smartindent’ and ‘cindent’ might interfere with file type based indentation, and should never be used in conjunction with it.
When it comes to C and C++, file type based indentations automatically sets ‘cindent’, and for that reason, there is no need to set ‘cindent’ manually for such files. In these cases, the ‘cinwords’, ‘cinkeys’ and ‘cinoptions’ options still apply.
Generally, ‘smartindent’ or ‘cindent’ should only be set manually if you’re not satisfied with how file type based indentation works.(仅当你对基于文件类型的缩进不满意时, 才需要设置’smartindent’ or ‘cindent’)
参照[2]的介绍,
smartindent is an old script that was meant, when it was written, to be a “smart” complement to autoindent. Since then, most languages have either specific indentation functions or use cindent with specific options.
Generally, smartindent shouldn’t be used at all.
The following lines are usually enough to deal with indentation(通常, 如下设置便足够了):
set autoindent
filetype plugin indent on

Reference
[1] Methods for automatic indentation
[1] autoindent is subset of smartindent in vim?

4.6 vim粘贴代码格式变乱

有时候从编辑器里面复制粘贴代码到vim中, 代码格式会完全乱套。其原因是vim开启了smartindent(智能缩减)或autoindent(自动对齐)模式。为了保持代码的格式, 在粘贴前可以先停止上面的两种模式, 在Normal模式下的命令为【1】:

:set nosmartindent
:set noautoindent

为了一个粘贴搞出这么多事来, 确实是麻烦。不过还有一个更加简单的方法, 用命令开始粘贴模式, 即:
(1)开启
:set paste

(2)按i进入插入模式, 然后执行粘贴操作
为什么要先进入插入模式再粘贴呢?因为你所要粘贴的内容如果含有字符i的话, 在Normal模式下, 字符i会被Vim看做是插入命令, i字符前面的内容会被丢失(比如复制 #include <stdio.h>,复制的结果为 nclude <stdio.h>)。

(3)关闭
:set nopaste 或 :set paste!
由于粘贴模式和上面的smartindent、autoindent模式是互斥的, 而smartindent、autoindent是不可少的, 所以粘贴完后使用上面的两条命令之一来关闭粘贴模式。

另外还可以通过绑定自定义快捷键的方式来快速切换, 例如将下属配置加入到.vimrc中
方式1:
set pastetoggle=
方式2:
:map :set paste
:map :set nopaste
注意: 方式1在阅读和编辑模式下都可以使用, 对粘贴模式开启和关闭进行切换; 方式2是在阅读模式下使用, 按下相应的快捷键就相当于执行后面定义的命令。

Reference
[1]vim粘贴代码格式变乱

4.7 vim折叠设置

4.7.1 折叠方式

可用选项 ‘foldmethod’ 来设定折叠方式: set fdm=*****。
有 6 种方法来选定折叠:
manual 手工定义折叠
indent 更多的缩进表示更高级别的折叠
expr 用表达式来定义折叠
syntax 用语法高亮来定义折叠
diff 对没有更改的文本进行折叠
marker 对文中的标志折叠
注意, 每一种折叠方式不兼容, 如不能即用expr又用marker方式, 我主要轮流使用indent和marker方式进行折叠。
使用时, 用: set fdm=marker 命令来设置成marker折叠方式(fdm是foldmethod的缩写)。
要使每次打开vim时折叠都生效, 则在.vimrc文件中添加设置, 如添加: set fdm=syntax, 就像添加其它的初始化设置一样。

4.7.2 折叠命令

zi/za 打开关闭折叠
zv 查看此行
zm 关闭折叠
zM 关闭所有
zr 打开
zR 开所有
zc/zo 折叠/ 打开当前行
zd 删除折叠
zD 删除所有折叠

4.7.3 如何在打开文件时默认不折叠?

set foldlevel=99

4.8 其他设置

set nocompatible            " 关闭 vi 兼容模式 
syntax on                   " 自动语法高亮 
colorscheme evening         " 设定配色方案 
set number                  " 显示行号 
set cursorline              " 突出显示当前行 
set ruler                   " 打开状态栏标尺 
set shiftwidth=4            " 设定 << 和 >> 命令移动时的宽度为 4 
set softtabstop=4           " 使得按退格键时可以一次删掉 4 个空格 
set tabstop=4               " 设定 tab 长度为 4 
set nobackup                " 覆盖文件时不备份 
set autochdir               " 自动切换当前目录为当前文件所在的目录 
filetype plugin indent on   " 开启插件 
set backupcopy=yes          " 设置备份时的行为为覆盖 
set ignorecase smartcase    " 搜索时忽略大小写, 但在有一个或以上大写字母时仍保持对大小写敏感 
set nowrapscan              " 禁止在搜索到文件两端时重新搜索 
set incsearch               " 输入搜索内容时就显示搜索结果 
set hlsearch                " 搜索时高亮显示被找到的文本 
set noerrorbells            " 关闭错误信息响铃 
set novisualbell            " 关闭使用可视响铃代替呼叫 
set t_vb=                   " 置空错误铃声的终端代码 
" set showmatch               " 插入括号时, 短暂地跳转到匹配的对应括号 
" set matchtime=2             " 短暂跳转到匹配括号的时间 
set magic                   " 设置魔术 
set hidden                  " 允许在有未保存的修改时切换缓冲区, 此时的修改由 vim 负责保存 
set guioptions-=T           " 隐藏工具栏 
set guioptions-=m           " 隐藏菜单栏 
set smartindent             " 开启新行时使用智能自动缩进 
set backspace=indent,eol,start 
                            " 不设定在插入状态无法用退格键和 Delete 键删除回车符 
set cmdheight=1             " 设定命令行的行数为 1 
set laststatus=2            " 显示状态栏 (默认值为 1, 无法显示状态栏) 
set statusline=\ %<%F[%1*%M%*%n%R%H]%=\ %y\ %0(%{&fileformat}\ %{&encoding}\ %c:%l/%L%)\  
                            " 设置在状态行显示的信息 
set foldenable              " 开始折叠 
set foldmethod=syntax       " 设置语法折叠 
set foldcolumn=0            " 设置折叠区域的宽度 
setlocal foldlevel=1        " 设置折叠层数为 
" set foldclose=all           " 设置为自动关闭折叠                             
" nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR> 
                            " 用空格键来开关折叠 
 
" return OS type, eg: windows, or linux, mac, et.st.. 
function! MySys() 
    if has("win16") || has("win32") || has("win64") || has("win95") 
        return "windows" 
    elseif has("unix") 
        return "linux" 
    endif 
endfunction 
 
" 用户目录变量$VIMFILES 
if MySys() == "windows" 
    let $VIMFILES = $VIM.'/vimfiles' 
elseif MySys() == "linux" 
    let $VIMFILES = $HOME.'/.vim' 
endif 
 
" 设定doc文档目录 
let helptags=$VIMFILES.'/doc' 
 
" 设置字体 以及中文支持 
if has("win32") 
    set guifont=Inconsolata:h12:cANSI 
endif 
 
" 配置多语言环境 
if has("multi_byte") 
    " UTF-8 编码 
    set encoding=utf-8 
    set termencoding=utf-8 
    set formatoptions+=mM 
    set fencs=utf-8,gbk "here can add argment to spurt the chinese 
 
    if v:lang =~? '^zh\|ja\|ko' 
        set ambiwidth=double 
    endif 
 
    if has("win32") 
        source $VIMRUNTIME/delmenu.vim 
        source $VIMRUNTIME/menu.vim 
        language messages zh_CN.utf-8 
    endif 
else 
    echoerr "Sorry, this version of (g)vim was not compiled with +multi_byte" 
endif 
 
" Buffers操作快捷方式! 
nnoremap <C-RETURN> :bnext<CR> 
nnoremap <C-S-RETURN> :bprevious<CR> 
 
" Tab操作快捷方式! 
nnoremap <C-TAB> :tabnext<CR> 
nnoremap <C-S-TAB> :tabprev<CR> 
 
"关于tab的快捷键 
" map tn :tabnext<cr> 
" map tp :tabprevious<cr> 
" map td :tabnew .<cr> 
" map te :tabedit 
" map tc :tabclose<cr> 
 
"窗口分割时,进行切换的按键热键需要连接两次,比如从下方窗口移动 
"光标到上方窗口,需要<c-w><c-w>k,非常麻烦,现在重映射为<c-k>,切换的 
"时候会变得非常方便. 
nnoremap <C-h> <C-w>h 
nnoremap <C-j> <C-w>j 
nnoremap <C-k> <C-w>k 
nnoremap <C-l> <C-w>l 
 
"一些不错的映射转换语法(如果在一个文件中混合了不同语言时有用) 
nnoremap <leader>1 :set filetype=xhtml<CR> 
nnoremap <leader>2 :set filetype=css<CR> 
nnoremap <leader>3 :set filetype=javascript<CR> 
nnoremap <leader>4 :set filetype=php<CR> 
 
" set fileformats=unix,dos,mac 
" nmap <leader>fd :se fileformat=dos<CR> 
" nmap <leader>fu :se fileformat=unix<CR> 
 
" use Ctrl+[l|n|p|cc] to list|next|previous|jump to count the result 
" map <C-x>l <ESC>:cl<CR> 
" map <C-x>n <ESC>:cn<CR> 
" map <C-x>p <ESC>:cp<CR> 
" map <C-x>c <ESC>:cc<CR> 
 
 
" 让 Tohtml 产生有 CSS 语法的 html 
" syntax/2html.vim, 可以用:runtime! syntax/2html.vim 
let html_use_css=1 
 
" Python 文件的一般设置, 比如不要 tab 等 
autocmd FileType python set tabstop=4 shiftwidth=4 expandtab 
autocmd FileType python map <F12> :!python %<CR> 
 
" 选中状态下 Ctrl+c 复制 
vmap <C-c> "+y 
 
" 打开javascript折叠 
let b:javascript_fold=1 
" 打开javascript对dom、html和css的支持 
let javascript_enable_domhtmlcss=1 
" 设置字典 ~/.vim/dict/文件的路径 
autocmd filetype javascript set dictionary=$VIMFILES/dict/javascript.dict 
autocmd filetype css set dictionary=$VIMFILES/dict/css.dict 
autocmd filetype php set dictionary=$VIMFILES/dict/php.dict 
 
"----------------------------------------------------------------- 
" plugin - bufexplorer.vim Buffers切换 
" \be 全屏方式查看全部打开的文件列表 
" \bv 左右方式查看   \bs 上下方式查看 
"----------------------------------------------------------------- 
 
 
"----------------------------------------------------------------- 
" plugin - taglist.vim  查看函数列表, 需要ctags程序 
" F4 打开隐藏taglist窗口 
"----------------------------------------------------------------- 
if MySys() == "windows"                " 设定windows系统中ctags程序的位置 
    let Tlist_Ctags_Cmd = '"'.$VIMRUNTIME.'/ctags.exe"' 
elseif MySys() == "linux"              " 设定windows系统中ctags程序的位置 
    let Tlist_Ctags_Cmd = '/usr/bin/ctags' 
endif 
nnoremap <silent><F4> :TlistToggle<CR> 
let Tlist_Show_One_File = 1            " 不同时显示多个文件的tag, 只显示当前文件的 
let Tlist_Exit_OnlyWindow = 1          " 如果taglist窗口是最后一个窗口, 则退出vim 
let Tlist_Use_Right_Window = 1         " 在右侧窗口中显示taglist窗口 
let Tlist_File_Fold_Auto_Close=1       " 自动折叠当前非编辑文件的方法列表 
let Tlist_Auto_Open = 0 
let Tlist_Auto_Update = 1 
let Tlist_Hightlight_Tag_On_BufEnter = 1 
let Tlist_Enable_Fold_Column = 0 
let Tlist_Process_File_Always = 1 
let Tlist_Display_Prototype = 0 
let Tlist_Compact_Format = 1 
 
 
"----------------------------------------------------------------- 
" plugin - mark.vim 给各种tags标记不同的颜色, 便于观看调式的插件。 
" \m  mark or unmark the word under (or before) the cursor 
" \r  manually input a regular expression. 用于搜索. 
" \n  clear this mark (i.e. the mark under the cursor), or clear all highlighted marks . 
" \*  当前MarkWord的下一个     \#  当前MarkWord的上一个 
" \/  所有MarkWords的下一个    \?  所有MarkWords的上一个 
"----------------------------------------------------------------- 
 
 
"----------------------------------------------------------------- 
" plugin - NERD_tree.vim 以树状方式浏览系统中的文件和目录 
" :ERDtree 打开NERD_tree         :NERDtreeClose    关闭NERD_tree 
" o 打开关闭文件或者目录         t 在标签页中打开 
" T 在后台标签页中打开           ! 执行此文件 
" p 到上层目录                   P 到根目录 
" K 到第一个节点                 J 到最后一个节点 
" u 打开上层目录                 m 显示文件系统菜单(添加、删除、移动操作) 
" r 递归刷新当前目录             R 递归刷新当前根目录 
"----------------------------------------------------------------- 
" F3 NERDTree 切换 
map <F3> :NERDTreeToggle<CR> 
imap <F3> <ESC>:NERDTreeToggle<CR> 
 
 
"----------------------------------------------------------------- 
" plugin - NERD_commenter.vim   注释代码用的,  
" [count],cc 光标以下count行逐行添加注释(7,cc) 
" [count],cu 光标以下count行逐行取消注释(7,cu) 
" [count],cm 光标以下count行尝试添加块注释(7,cm) 
" ,cA 在行尾插入 /* */,并且进入插入模式。 这个命令方便写注释。 
" 注: count参数可选, 无则默认为选中行或当前行 
"----------------------------------------------------------------- 
let NERDSpaceDelims=1       " 让注释符与语句之间留一个空格 
let NERDCompactSexyComs=1   " 多行注释时样子更好看 
 
 
"----------------------------------------------------------------- 
" plugin - DoxygenToolkit.vim  由注释生成文档, 并且能够快速生成函数标准注释 
"----------------------------------------------------------------- 
let g:DoxygenToolkit_authorName="Asins - asinsimple AT gmail DOT com" 
let g:DoxygenToolkit_briefTag_funcName="yes" 
map <leader>da :DoxAuthor<CR> 
map <leader>df :Dox<CR> 
map <leader>db :DoxBlock<CR> 
map <leader>dc a /*  */<LEFT><LEFT><LEFT> 
 
 
"----------------------------------------------------------------- 
" plugin – ZenCoding.vim 很酷的插件, HTML代码生成 
" 插件最新版: http://github.com/mattn/zencoding-vim 
" 常用命令可看: http://nootn.com/blog/Tool/23/ 
"----------------------------------------------------------------- 
 
 
"----------------------------------------------------------------- 
" plugin – checksyntax.vim    JavaScript常见语法错误检查 
" 默认快捷方式为 F5 
"----------------------------------------------------------------- 
let g:checksyntax_auto = 0 " 不自动检查 
 
 
"----------------------------------------------------------------- 
" plugin - NeoComplCache.vim    自动补全插件 
"----------------------------------------------------------------- 
let g:AutoComplPop_NotEnableAtStartup = 1 
let g:NeoComplCache_EnableAtStartup = 1 
let g:NeoComplCache_SmartCase = 1 
let g:NeoComplCache_TagsAutoUpdate = 1 
let g:NeoComplCache_EnableInfo = 1 
let g:NeoComplCache_EnableCamelCaseCompletion = 1 
let g:NeoComplCache_MinSyntaxLength = 3 
let g:NeoComplCache_EnableSkipCompletion = 1 
let g:NeoComplCache_SkipInputTime = '0.5' 
let g:NeoComplCache_SnippetsDir = $VIMFILES.'/snippets' 
" <TAB> completion. 
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>" 
" snippets expand key 
imap <silent> <C-e> <Plug>(neocomplcache_snippets_expand) 
smap <silent> <C-e> <Plug>(neocomplcache_snippets_expand) 
  
"----------------------------------------------------------------- 
" plugin - matchit.vim   对%命令进行扩展使得能在嵌套标签和语句之间跳转 
" % 正向匹配      g% 反向匹配 
" [% 定位块首     ]% 定位块尾 
"----------------------------------------------------------------- 
 
"----------------------------------------------------------------- 
" plugin - vcscommand.vim   对%命令进行扩展使得能在嵌套标签和语句之间跳转 
" SVN/git管理工具 
"----------------------------------------------------------------- 
  
"----------------------------------------------------------------- 
" plugin – a.vim 

5. 其他

5.1 vim e518: unknown option

原因在于系统默认的vi编辑器是“Vi IMproved 7.4.160”, 此版本不支持语法高亮。
第一种方法:

:set nomodeline

第二种方法:

vim ~/.bashrc   # 仅对当前用户有效 
# 加入下面的内容 
export EDITOR=vim 
alias vi="vim" # 设置vi是vim编辑器的别名 

source ~/.bashrc​