TODO:
h tips.txt
<2019-01-14, wsxq2>
vim/vim: The official Vim repository
概述
主要配置文件为~/.vimrc
(也就是每次启动vim
都会执行的vim脚本,也是在命令行模式下输入的命令的集合),我的配置文件可在 GitHub: wsxq2/MyProfile 处获得
主要配置目录为~/.vim
(里面有安装的插件,还有自己写的 UltiSnips 代码片段):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/root/.vim
├── autoload/
│ └── plug.vim
├── bundle/
│ ├── dbext.vim/
│ ├── delimitMate/
│ ├── emmet-vim/
│ ├── indentLine/
│ ├── ultisnips/
│ ├── vim-autoformat/
│ ├── vim-markdown-toc/
│ ├── vim-plug/
│ ├── vim-snippets/
│ ├── vim-table-mode/
│ └── YouCompleteMe/
├── UltiSnips/
│ ├── all.snippets
│ ├── javascript.snippets
│ ├── markdown.snippets
│ └── python.snippets
├── .netrwhist
└── .ycm_extra_conf_offical.py*
14 directories, 7 files
我的 Vim 中主要安装了下列插件:
- vim-plug: Vim管理插件的插件Vim-Plug
- delimitMate:
- vim-markdown-toc:
- vim-table-mode:
- emmet-vim: Vim-HTML和CSS插件emmet-vim
- YouCompleteMe: Vim代码补全插件YouCompleteMe
- ultisnips: Vim代码片段插件ultisnips和vim-snippets
- vim-snippets: Vim代码片段插件ultisnips和vim-snippets
- indentLine: Vim插件IndentLine
- dbext.vim:
- vim-autoformat: Vim代码格式化插件vim-autoformat
Vim
五种常用模式:普通模式、插入模式、命令行模式、选择模式(Visual Mode)、搜索模式。下面简述各模式的进入方法:
- 普通模式:在任意模式中按
Esc
或Ctrl+[
进入(可能需要多次)普通模式 - 插入模式:在普通模式中使用插入相关的命令(如
i
)进入插入模式 - 命令行模式:在普通模式中按
:
进入命令行模式 - 选择模式:在普通模式中按
v
进入选择模式 - 搜索模式:在普通模式中按
/
或?
进入搜索模式
普通模式
Bash 的 vi 模式
默认情况下处于插入模式,按Esc
或Ctrl+[
进入普通模式,普通模式下的常用命令如下:
-
i
a
I
A
: 均用于进入插入模式。i
(insert)在当前字符前插入,a
(append)在当前字符后插入,I
在当前行的第一个字符前插入,A
在当前行的最后一个字符后插入 -
j
k
: 回溯历史的命令。如同方向键向上键和向下键。注意,这和VIM中的行为不同,VIM中j
用于移动到下一行,k
用于移动到上一行 h
l
:移动命令。h
向左移动一个字符;l
向右移动一个字符0
^
$
: 移动命令。0
移动到行首;^
和0
类似,只是移动到行首的第一个非空白字符(如空格);$
移动到行尾w
e
b
W
E
B
: 移动命令。w
右移一个单词;e
和w
类似,只是停在末尾处;b
左移一个单词;W
移动到下一个空格后的第一个字符;E
和W
类似,只是停在末尾处;B
移动到上一个空格后的第一个字符f
F
t
T
,
;
: 移动命令。f
向后移动至某个字符,如fa
向后移动至a
字符;F
向前移动至某个字符;t
向后移动至某个字符的前一个字符;T
向前移动至某个字符的后一个字符;,
重复上一个和前述命令相同的移动命令;;
和,
类似,不过方向相反-
,
;
: c
(change): 改变文本并进入插入模式。该命令就配合移动命令使用,如cw
改变一个单词,cb
反向改变一个单词,cl
改变一个字符等等cc
: 改变当前行的所有内容,相当于0c$
C
: 改变当前光标所在位置至行尾的内容,相当于c$
s
(substitute):cl
的简写,用于修改一个字符-
r
(replace): 和s
类似,只是不会进入插入模式 d
(delete): 删除文本。该命令同样配合移动命令使用dd
: 删除当前行的所有内容,相当于0d$
D
: 删除当前光标所在位置至行尾的内容,相当于d$
-
x
:dl
的简写,用于删除一个字符 -
p
P
: 粘贴命令。p
(paste)在当前字符后粘贴,P
在当前字符前粘贴。注意,该命令亦可粘贴已经删除的内容 y
(yank): 复制命令。和移动命令配合使用,如yl
复制一个字符,yw
复制一个单词-
yy
: 复制整行内容。相当于0y$
v
: 进入vim中编辑(编辑多行命令或长命令时非常有用)。注意,这和VIM中的行为不同,VIM中v
用于选择,以进入Visual模式
其它命令
*
#
: 搜索命令。*
搜索当前单词并跳转到下一处;#
搜索当前单词并跳转到上一处K
\K
: 查询帮助命令。K
查询当前单词的man
手册(也可以先选择后再查询,即vWK
);\K
和K
一样,因为我设置的缘故,详见vim内置帮助文档:h :Man
gg
G
: 跳转命令。gg
跳至整个文件的第一行;G
跳到整个文件的最后一行50%
%
: 跳转命令。50%
跳到文件的50%处(即一半的地方,同理,25%
则跳到 1/4 处);%
(即前面不加数字)则完全不同,它用于跳转到当前括号的匹配括号处(如当前是(
,则跳到)
)<Space>
: 折叠命令。本来和l
的作用相同(即向右移动一个字符),但我将其绑定到了za
,即自动折叠或反折叠gd
gD
gf
: 跳转命令。gd
跳到当前光标所指局部变量的定义位置;gD
跳到当前光标所指全局变量的定义位置;gf
跳到当前光标所指路径的文件qa<一堆操作>q
@a
: 宏录制命令。宏是操作的集合,@:
:Ctrl+6
:Ctrl+h
Ctrl+j
Ctrl+k
Ctrl+l
:ma
'a
:.
u
Ctrl+r
:=
:&
:!
:>>
<<
:Ctrl+c
:Ctrl+g
1<C-g>
2<C-g>
插入模式
Ctrl+P
:Ctrl+N
:Ctrl+X Ctrl+L
:Ctrl+X Ctrl+F
:Ctrl+O u
:<C-r>"
:- ``
Bash 的 vi 模式
Ctrl+W
: 向前清除一个单词Ctrl+U
: 向前清除到行首Ctrl+P
: 向上查找命令,注意,因为我在bash默认的启动文件~/.bashrc
(MacOS是~/.bash_profile
)进行了如下设置:1 2 3 4
bind '\C-p: history-search-backward' bind '\C-n: history-search-forward' bind '"\e[A":history-search-backward' bind '"\e[B":history-search-backward'
所以
Ctrl+P
将会向上查找与当前行带有相同前缀的命令,如:1 2 3
vim ~/.vimrc vim<Ctrl+P> #将会得到: vim ~/.vimrc
这个功能使得输入曾经输入过的命令变得异常方便,再也不需要傻乎乎地先用
history
查看一下命令历史,再傻乎乎地用!<history结果前的数字>
来执行输入过的命令了Ctrl+N
: 和Ctrl+P
类似,只是向下查找
命令行模式
Ctrl+D
: 显示所有可能的结果Tab
: 按可能的结果依次补全h<CR>
: 输入h<CR>
(其中<CR>
是回车)可查看帮助。如下述例子:h gd
: 输入h gd
可查看普通模式下gd
命令的帮助h :h
: 输入h :h
可查看命令模式下h
命令的帮助h i_CTRL_N
: 输入h i_CTRL_N
可查看插入模式下Ctrl+N
的帮助h 'nu
: 输入h 'nu
可查看选项nu
的帮助(选项通过命令模式下的set
命令来设置,如set nu
)
选择模式
//
:K
:
搜索模式
使用正则表达式,注意和标准的(Perl)的有点不同:
/abc
:/\<abc\>
/^abc
:
nvim
时代在发展,vim也在进步。nvim 是 vim 的一个重构,现已开始普遍应用。它有许多优点,更多信息参见 neovim/neovim: Vim-fork focused on extensibility and usability (其 star 数量竟然是官方 vim 的 2 倍???)
LSP
- neovim/nvim-lspconfig: Quickstart configurations for the Nvim LSP client
- Language Servers
- Tools supporting the LSP
发行版
vim 有很多发行版,适用于新手:
遇到过的问题
- How to delete lines around a search pattern in vim? - Stack Overflow
- text editor - How to set working/current directory in Vim? - Stack Overflow
- How to store all occurrences of a multiline search in a register? - Vi and Vim Stack Exchange
编码问题?
详情参见 VIM 文件编码识别与乱码处理
在 Vim 中,有四个与编码有关的选项,它们是:fileencodings、fileencoding、encoding 和 termencoding。在实际使用中,任何一个选项出现错误,都会导致出现乱码:
-
encoding
: VIM 内部字符编码建议设置:
1
set encoding=utf-8 "这通常是 VIM 的默认值
-
termencoding
: VIM 用于屏幕显示的编码建议设置:
1 2
set termencoding=utf-8 "for Linux set termencoding=gbk/cp936 "for Windows
-
fileencoding
: VIM 探测到的文件的编码建议设置:
1
set fileencoding? "通常不建议设置该选项,除非你确定你知道文件本身正确的编码
-
fileencodings
: VIM 自动识别编码的顺序建议设置:
1
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
以上的fileencodings
选项的建议设置推荐放到~/.vimrc
,避免 VIM 识别不到 GBK(CP936) 编码(这是使用 VIM 最容易遇到的编码错误的原因)。如果 VIM 确实没有识别正确,你也知道文件本身正确的编码,那么你可以使用如下命令以正确的编码重新打开本文件:
1
:e ++enc=gbk
详情参见:h :e
以encoding
为例,简要说下 VIM 中选项的查看值、设置值的方法和获取 VIM 自带帮助的方法:
1
2
3
:set encoding? "查看 VIM 内部字符编码
:set encoding=utf8 "设置 VIM 内部字符编码
:help 'encoding "查看 VIM encoding 选项的相关帮助
另外还可使用如下命令查看文件的编码:
1
2
$ file quicker.em
quicker.em: ISO-8859 text, with CRLF line terminators
不小心按了Ctrl+S
后卡死?
使用Ctrl+Q
或Ctrl+C
即可
在 Vim 脚本中忽略’Pattern not found’错误信息
- 使用
:silent[!]
前缀::h :silent
- 在
:s
替换命令后添加e
选项::h :s_flags
插入模式中从右往左书写
:set ri
详情参见::h 'ri
对齐文本
:ri
: 右对齐:ce
: 居中对齐:le
: 左对齐
详情参见::h :ri
删除二进制文件末尾的EOF
?
1
:set binary noendofline
详情参见: Vim show and be able to delete 0x0a at end of file - Stack Overflow
实践记录
Markdown文件
- 添加
_post
的头1
:.!head -n 6 $bl/2018-08-08-template.md
或者使用 UltiSnips:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
snippet bl "blog" b --- layout: post tags: [$1] categories: blog --- <!-- vim-markdown-toc GFM --> <!-- vim-markdown-toc --> ## $0 ## 链接 <!-- link start --> <!-- link end --> <!-- abbreviations start --> <!-- abbreviations end --> endsnippet
然后在 .md 文件中(我将 UltiSnips 的快捷键设置为了
<C-J>
):1
bl<C-J>
-
添加
*
使用强大的替换功能:
1
:%s/^\( *\)\([\u4e00-\u9fa5]\)/\1* \2/
或者使用列编辑:
1
<C-V>jjjI* <C-[>
- 为某个单词添加
`
1 2
qe i`ea`
类似地,为某个单词添加
(空格):
1 2
qs i ea
为选定行的中文中的所有英文单词添加空格:
1 2 3
:s/[\u4e00-\u9fa5]\zs[a-zA-Z0-9]\+\ze[\u4e00-\u9fa5]/ & /ge :s/\([\uff0c\u3002\uff08\uff09]\|^\)\zs[a-zA-Z0-9]\+\ze[\u4e00-\u9fa5]/& /ge :s/[\u4e00-\u9fa5]\zs[a-zA-Z0-9]\+\ze\([\uff0c\u3002\uff08\uff09]\|$\)/ &/ge
- 将含有链接的行复制到末尾,将含有链接的行替换为链接本身
-
1 2 3 4 5 6
ql "(Get all Links) :/^<!-- link start -->/+1,/^<!-- link end -->/-1 g!/^$/d :/^<!-- vim-markdown-toc -->/,/^<!-- link start -->/ g/[^!]\[.\+\]([^#].\+)/copy /<!-- link start -->/ :/^<!-- link start -->/,/^<!-- link end -->/ s/.*\(\[.\+\](.\+)\).*/* \1/e :/^<!-- vim-markdown-toc -->/,/^<!-- link start -->/ g/\[[^]]\+\]\[[^]]\+\]/copy /<!-- link start -->/ :/^<!-- link start -->/,/^<!-- link end -->/ s/^.*\(\[[^]]\+\]\[[^]]\+\]\).*$/* \1/e
2.(推荐)
1 2 3 4 5 6 7 8 9 10
ql :/^<!-- link start -->/+1,/^<!-- link end -->/-1 g!/^$/d :let @t='' :1,/^<!-- vim-markdown-toc GFM -->/ s/[^!]\(\[.\{-1,}\](http[^[\]]\{-1,})\)/\=setreg('T','* '.submatch(1),'l')/egn :/^<!-- vim-markdown-toc -->/,/^<!-- link start -->/ s/[^!]\(\[.\{-1,}\](http[^[\]]\{-1,})\)/\=setreg('T','* '.submatch(1),'l')/egn :1,/^<!-- vim-markdown-toc GFM -->/ s/[^!]\?\(\[[^]]\+\]\[[^]]\{-1,}\]\)/\=setreg('T','* '.submatch(1),'l')/egn :/^<!-- vim-markdown-toc -->/,/^<!-- link start -->/ s/[^!]\?\(\[[^]]\+\]\[[^]]\{-1,}\]\)/\=setreg('T','* '.submatch(1),'l')/egn /<!-- link start --> "tp :/^<!-- link start -->/+1,/^<!-- link end -->/-1 sort u
-
-
给一行首尾添加
`
录制宏:
1 2
qq I`<kEnd>`<Esc>
- 缩进所有不是由 1 或 # 开头的行:
1
:.,93 s/^\([^1#]\)/ \1/
- 将
Plug 'junegunn/vim-plug'
变为* [vim-plug](https://github.com/junegunn/vim-plug):
:1
:'<,'>s#^Plug '\([^/]\+\/\([^']\+\)\)'.*$#* [\2](https://github.com/\1):#
- 将
2018-11-25-Vim安装管理插件的插件——Vim-Plug.md
变为[Vim安装管理插件的插件——Vim-Plug](https://wsxq2.55555.io/blog/2018/11/25/Vim安装管理插件的插件——Vim-Plug)
:1 2
qm "(My Blog) :.s/\(\d\+\)-\(\d\+\)-\(\d\+\)-\([^.]\+\)\.md/[\4](https:\/\/wsxq2.55555.io\/blog\/\1\/\2\/\3\/\4)/
录制为宏
m
- 插入图片:
- 使用
Ultisnips
覆盖vim-snippets
默认的snippet
:1 2 3 4
snippet img "Image" b <!--picture $1--> $0 endsnippet
- 然后录制宏将其转换为真正的链接
1 2
qp :%s/<!--picture \([^ ]\+\) -->/![\1](http:\/\/wsxq12.55555.io\/\1)/g
- 控制图片大小和位置
1 2
qo :s/^!\[\([^]]\+\)\](\([^)]\+\))$/<img src="\2" alt="\1" style="width:750px;display:block;margin:auto">/
- 使用
-
收集所有的英文缩写(连续的大写字母)
1.
1 2
qa :/<!-- abbreviations start -->/+1,/<!-- abbreviations end -->/-1 ! sed -nr -e 's/^.*\b([A-Z]{2,})\b.*$/*[\1]: /p' 2018-12-02-16位汇编程序设计.md | sort | uniq
2.
1 2 3 4 5 6 7 8
qa :/^<!-- abbreviations end -->/+1,$ g!/^$/d :let @t='' :/^<!-- vim-markdown-toc -->/,/^<!-- link start -->/ s/\C[^%]\([A-Z]\{2,}\)\>/\=setreg('T',submatch(1),'l')/egn /^<!-- abbreviations end --> "tp :/^<!-- abbreviations end -->/+1,$ sort u :/^<!-- abbreviations end -->/+1,$ !$bl/handle-abbreviations.sh
校正后:
1 2 3 4
qb :/^<!-- abbreviations start -->/+1,/^<!-- abbreviations end -->/-1 d :/^<!-- abbreviations end -->/+1,$ co /^<!-- abbreviations start -->/ :/^<!-- abbreviations start -->/+1,/^<!-- abbreviations end -->/-1 s/\*\[\([^]]\+\)]:\(.\+\)$/* **\1**:\2/
- 在每个标题前面添加新行:
1
%s/^\(##\+\)/\r\1/
- 在
1.3.2 ARP报文数据
前面添加####
:1
%s/^\(\d\.\d\.\d \)/#### \1/
- 给引用的段落加上两个中文空格以缩进:
1 2
qr :%s/^> \([a-zA-Z\u4e00-\u9fa5]\)/> \ \ \1/
- 将如下形式的内容:
1
【转】关于Bootmgfw.efi、Bootx64.efi的详解 - 天南海北 - 萝卜头IT论坛 - Powered by Discuz!: https://bbs.luobotou.org/forum.php?mod=viewthread&tid=11856
转换为如下形式的链接:
1
[【转】关于Bootmgfw.efi、Bootx64.efi的详解 - 天南海北 - 萝卜头IT论坛 - Powered by Discuz!](https://bbs.luobotou.org/forum.php?mod=viewthread&tid=11856)
可使用如下宏:
1 2 3
qk :s/\(^[^[].\+\): \(http.*\)$/[\1](\2)/ :s/\(\[.*[^\\]\)|\(.*\](http.*)\)/\1\\|\2/e
或(推荐):
1 2 3
qk :s/\(^[^[].\+\): \(http.*\)$/[\1](\2)/ :s/|/|/ge
其中的
|
是编码为ff5c
的 Unicode 字符,在 Vim 中可通过<C-V>uff5c
输入 - 将如下内容:
``` <p id="markdown-toc"></p> ```
转换为如下内容:
1 2 3
<pre> <p id="markdown-toc"></p> </pre>
使用
:command
命令自定义一个命令Rh
:1
command! -range Rh <line1>,<line2>s/&/\&/ge | <line1>,<line2>s/</\</ge | <line1>,<line2>s/>/\>/ge | <line1>,<line2>s/^\(\s*\)```\(\_.\{-1,}\)```$/\1<pre>\2<\/pre>/e
参见 HTML转义字符对照表和regex - Substitute the n-th occurrence of a word in vim - Stack Overflow和Passing visual range to a :command as its argument - Vi and Vim Stack Exchange
- 在引用前添加两个中文(Chinese)空格以便阅读:
1 2
qc :s/^\(\s*> \)\([^ >&*#|0-9`]\)/\1\ \ \2/
- 将博客格式转换为 bbs 格式(例如 2019-07-07-科学上网.md):
1 2 3 4 5 6 7 8 9 10 11 12 13
qy :%s/^\s*$\n^|/\r```\r|/ :%s/^\(|.*\)$\n^\s*$/\1\r```\r/ :%s/^\(\s*>\)\s*\n^\(\s*> |\)/\1\r\1 ```\r\2/ :%s/^\(\s*> |.*\)$\n^\(\s*>\)\s*$/\1\r\2 ```\r\2/ :%s/  // 5Gdgg O这是我个人博客上的文章,原文地址为: :/<!-- vim-markdown-toc GFM -->/,/<!-- vim-markdown-toc -->/s/ / /g :g/^<p id=.*$/s//请不要点击下面的目录,因为论坛中的标题默认没有设置`id` :g/^<!-- .* -->/d :g/^\*\[.*\]: /d
vim自带帮助文件
- 复制代码行(Tab开头的行)到”a寄存器
1
qw"ayy:'a,'b g/^\t.\+$/normal "Ayy<Enter>
- 将
|
之间的内容转换为标题1
:522,$s/|\(\d\+\.\d\+\)|/##\1/
asm 文件中
- 写
sing.asm
时需要将曲谱转换为相应的数组(使用了Python)1 2
:/;data start/+1,/;data end/-1 !./convert_music.py :w
Python 文件
- 保存并执行当前文件:
1 2
:w :pyf %
所有文件
- 输出匹配的正则表达式的个数:
1
:s/^#//n " 输出 Python 文件中注释的行数"
二进制(.exe
等)
h hex-editing
1 2 3 4 5 6 7 8 9 10 11
" vim -b : edit binary using xxd-format! augroup Binary au! au BufReadPre *.bin let &bin=1 au BufReadPost *.bin if &bin | %!xxd au BufReadPost *.bin set ft=xxd | endif au BufWritePre *.bin if &bin | %!xxd -r au BufWritePre *.bin endif au BufWritePost *.bin if &bin | %!xxd au BufWritePost *.bin set nomod | endif augroup END
h usr_23.txt
(23.4)