《vim实用技巧》小记
=。=最近在看《vim实用技巧》
对一些内容作点简单的记录,方便以后查阅
Vim解决问题的方式
- 多用
.
命令(一个微型宏)来重复一些简单的操作 - 减少无关的移动,形成合理的撤销块
- 善用复合命令减少操作
A
==$a
,插入在行末
C
==c$
,替换行末字符并持续插入
s
==cl
,替换当前字符并持续插入
S
==^c
,替换前一字符并持续插入
I
==^i
,从行首开始编辑
o
==A<CR>
,在下方插入新行
O
==ko
,在上方插入新行
……
- 尽可能使修改、移动变得可重复
- 常用的重复与回退操作
- 一般的修改
{edit}
:
.
重复,u
回退 - 行内的查找
[f|F|t|T]{char}
:
;
重复,,
回退 下 - 文档内的查找
[/|?]{pattern}<CR>
:
n
重复,N
回退 - 执行替换
:s/target/replacement
:
&
重复,u
回退 - 执行一系列修改
qx{changes}q
:
@x
重复,u
回退
- 一般的修改
.
范式
用一个键移动,用另一个键执行的可重复修改操作
普通模式
- 停顿思考时切换到普通模式
- 合理地切分撤销单元(模式间的切换)
- 如果在插入模式中移动的光标,将会产生一个新的撤销单元
- 删除单词
daw
,可以解读为”delete a word”,该命令可重复 - 简单的算术运算
{num}<C-a>
加法,{num}<C-x>
减法
不需要把光标移动到数字上
运算为num加减当前光标或光标以后的数字
注意:默认情况下0开头的数字会被当作八进制,0x开头则为十六进制
可以通过set nrformats=
关闭进制识别(都作为十进制数) - 重复&次数
删除多个单词有两种风格——dw
+.
的重复风格
常用风格,使用灵活,方便回退,无需数单词个数d2w
或2dw
的次数风格
多用于删除一整块词组,如a couple of
;可以提高撤销单元的连贯性
- 操作 = 操作符 + 动作命令{motion}
- 操作符
c
:修改d
:删除y
:复制到寄存器g~
:字母大小写反转gu
:字母转换为小写gU
:字母转换为大写>
:增加缩进<
:减小缩进=
:自动缩进!
:用外部程序过滤{motion}跨越的行
- 动作命令
[h|j|k|l]
:左下上右[-|+]
:上一行(下一行)的非空白字符0
(数字):行首(含空白)^
:行首(不含空白),即本行第一个非空白字符$
:行末gg
:文首G
:文末[f|F|t|T]{char}
:右侧(左侧)的第一个char字符[;|,]
:下一个(上一个)”f|F|t|T”的char字符:{num}
:至第num行[w|b]
:后一个(前一个)或当前单词的头部(尾部)——含符号[W|B]
:后一个(前一个)或当前单词的头部(尾部)——跳过符号(仅字母和数字包括负号)............................
- 动作命令可以待有修饰符前缀
a
:即an,表示一个非空白对象i
:即inner,表示一个内含对象
- 当一个操作符被连续调用两次,就表示作用于当前行
特例:g~~
、guu
、gUU
- 操作符
- 操作符待决模式
键入操作符后vim会进入操作符待决模式,此时vim会等待一个动作命令后执行操作
在该模式下可以按<ESC>
来退回普通模式
因为该模式的存在,使得自定义操作符及动作指令能够存在
插入模式
- 单词输入错误,应删除整个单词再重新输入
可以减少以后输入出错 - 删除
<C-h>
:删除前一个字符,相当于退格键<C-w>
:删除前一个单词<C-u>
:删除至行首- 注意:只能删除本次插入模式下插入的内容
- 这些命令不是插入模式独有,也不是vim独有,在命令行模式、shell中都能使用它们
- 切换到普通模式使用
<C-[>
更加方便 - 插入-普通模式:
<C-o>
执行一个普通模式命令后,马上就可以返回到插入命令
在插入模式下,通过<C-o>zz
迅速把当前行移动到屏幕正中 - 插入模式下的粘贴几个单词
<C-r>{register}
:将register号寄存器的内容粘贴到当前位置
普通模式下复制文本默认保存在0号寄存器中
注意:当文本比较多的时候,应切换到普通模式下操作比较合适 - 运算
<C-r>={expr}<CR>
:执行expr运算并且把结果插入到当前位置 - 用字符编码插入字符
- 十进制ASCII字符:
<C-v>{code}
只能插入三位十进制数的ASCII码,注意高位补0 - 十六进制unicode字符:
<C-v>u{code}
插入四位十六进制数的unicode码,注意高位补0 - 通过二合字母插入字符
<C-k>{char1}{char2}
二合字母集可以通过:digraphs
查看
:digraph-table
可以获得二合字母集更详细的信息
- 十进制ASCII字符:
- 查看当前字符的编码
ga
:屏幕下方会显示当前字符的十进制、十六进制、八进制编码信息 - 虚拟替换模式
R
:替换模式,<Tab>
会作为一个字符被替换
gR
:虚拟替换模式,<Tab>
会作为多个字符(一般为八个)被逐个替换(直到末尾才替换掉<Tab>
)
r
和gr
同理~
应尽量使用虚拟替换模式
可视模式
- 三种可视模式
v
:操作字符文本V
:操作行文本<C-v>
:操作块文本
- 该模式与其他模式不同,是先选择文本后触发命令
- 选择模式
<C-g>
类似与windows的选择模式,输入的可见字符会替换掉选中的文本,之后vim进入插入模式
这个模式只是为了迎合windows用户,应尽量少用 gv
:重选上次的高亮选区- 该模式下的
.
命令有时候会出现异常
所以应尽可能使用操作命令而不是可视命令 - 有时候修改文本的范围很难用动作命令表达出来,这时候才用到可视命令
- 修改多行文本时,只有第一行发生变化,只有当返回普通模式后,其他行才会发生变化
<C-v>
不仅可以选中矩形的区域,还可以选中长短不一的块
当在该模式下选中行末部分,可以实现长短不一的块的选择
命令行模式
- 三种形式的命令行模式
- 按下
:
的Ex命令 - 按下
/
的查找命令 - 用
<C-r>=
访问表达式寄存器
- 按下
- 指定命令作用范围
- 指定行
:{number}....
只包含数字的Ex命令表示跳转
可以使用特殊符号$
表示最后一行,%
表示当前文件的所有行 - 用地址来指定一个范围
:{start},{end}....
,执行命令后光标将跳转到end行 - 用高亮选取指定范围
先用可视模式v
,V
,<C-v>
选取高亮区
再按下:
,此时命令行会自动填充成:'<,'>
,表示作用在高亮区上 - 用模式指定
:/{pattern1},/{pattern2}/....
例如::/<html>/,/<\/html>/
指定了html内的所有内容(包含<html>
和</html>
)
注意:斜杠/
有特殊含义,需要用反斜杠\
转义 - 地址偏移
直接对地址进行+
或-
运算
如::/<html>/+1,/<\/html>/-1
则排除了<html>
和</html>
而只包含了其中间的内容
如果不加数字,默认偏移量为1 - 特殊符号总结
1
:第一行0
:虚拟行,位于第一行上方,常用于插入到首行等功能$
:最后一行.
:当前行%
:整个文件,相当于:1,$
'm
:包含位置标记m的行'<
和'>
:高亮选取的起始和结束行
- 指定行
- 复制命令:
:t
或:co
或:copy
:{range}t {address}
与普通模式下的y
命令不同,该命令不把文本保存到寄存器 - 移动命令:
:move
或:m
:{range}m {address}
- 在指定范围上执行普通模式命令
:{range}normal {commands}
,常用于多行的处理
常用的命令如下::{range}normal .
:对多行重复同一操作:{range}normal A;
:对多行末尾补上分号:{range}normal i//
:将多行内容注释掉
- 重复上一条命令:
@:
- 使用
<C-o>
进入插入-普通模式时,命令记录会跳转到上一条命令,可以借此进行命令记录的跳转 - 自动补全
<Tab>
自动补全命令
多次按<Tab>
会正向遍历补全列表的内容<S-Tab>
反向遍历补全列表,S表示<shift>
按键<C-d>
显示可用的补全列表- 自定义补全行为
- bash shell形式:
set wildmode=longest,list
- zsh形式:
set wildmenu
和set wildmode=full
wildmenu
为补全导航列表
- bash shell形式:
- 将当前单词插入到命令行中
常用于替换命令和查看帮助文档
在命令行模式下,<C-r><C-w>
会复制当前单词到命令行中 - 回溯历史命令
- 回溯所有命令
在:
下保持提示符为空按<up>
(<C-p>
)和<down>
(<C-n>
)<C-p>`
和
的区别 前者方便,但不能过滤命令 解决方法: 在
.vim文件中创建映射项
cnoremapcnoremap
`
- 过滤回溯的命令
如:help<up>
回溯以”help”开头的命令 - 命令历史容量设置
缺省只有20
推荐set history=200
- 除了Ex命令,查找命令也会记录下来并保存在另一个文件中
- 回溯所有命令
- 一次性执行多条命令
用|
隔开命令即可 - 命令行窗口
像一个常规的vim缓冲区,其中每一行是命令历史中的一个条目
可以在该窗口下修改命令历史记录,对之前使用过的命令做调整后方便重复利用
当打开命令行窗口时,它始终拥有焦点,除非关闭它,否则无法切换到其他窗口q:
:打开Ex命令的命令行窗口q/
:打开查找命令的命令行窗口<C-f>
:从命令行模式切换到命令行窗口(起始命令行模式下输入的内容仍然保留下来)
- 运行shell命令
!{command}
%
代表当前文件名:shell
可以打开一个交互式的shell会话(通过exit
退出)
更好的方法是用<C-z>
挂起vim所属进程,用fp
唤醒挂起的作业
shell下的jobs
命令可以查看当前的作业列表
- 大量读取或写入命令输入输出
:read !{cmd}
将命令输出读取到当前缓冲区中
:write !{cmd}
:将当前缓冲区内容作为命令的标准输入 - 借助shell命令过滤指定范围
:{range}!{filter}
如用sort命令,:2,$!sort -t ',' -k 2
表示第2行到最后一行之间,以逗号为分隔符的第二字段排序 - 常见的和操作缓冲区文本的Ex命令
:{range}d {x}
:删除指定内容(并保存到寄存器x中):{range}y {x}
:复制指定内容到寄存器x中:{line}put {x}
:在指定行后粘贴寄存器x中的内容:{range}t {address}
:复制指定内容到address处:{range}m {address}
:移动指定内容到address处:{range}join
:连接指定行内容:{range}normal {commands}
:对指定范围执行普通模式命令:{range}s/{pattern}/{string}/{flag}
:替换:{range}global/{pattern}/{cmd}
:对指定范围内匹配pattern的所有行执行cmd命令(Ex)
管理多个文件
缓冲区列表
文件读取后在内存缓冲区中
:ls
命令可以列出所有被载入到内存中的缓冲区列表- 每个条目开头的数字为系统自动分配而不可改变的缓冲区编号
%
:当前窗口中可见的缓冲区#
:轮换文件
按<C-^>
可以在两个文件之间快速轮换
- 缓冲区切换
- 遍历缓冲区列表:
- 正向移动:
:bn
或:bnext
- 反向移动:
:bp
或:bprevious
- 正向移动:
:buffer {N}
:跳转到指定编号的缓冲区:buffer {bufname}
:跳转到可以被bufname唯一标识的缓冲区(若多个缓冲区具有同一标识,可以通过<Tab>
选择)
- 遍历缓冲区列表:
:bufdo {commands}
:对所有缓冲区执行Ex命令创建快速遍历缓冲区列表的键盘映射
nnoremap <silent> [b :bp<CR> nnoremap <silent> ]b :bn<CR> nnoremap <silent> [B :bfirst<CR> nnoremap <silent> ]B :blast<CR>
删除
:bd
或:bdelect
:bd {N1,N2,N3....}
:删除列出的缓冲区
:{N,M} bd
:删除连续的缓冲区
参数列表
对一批文件进行分组,其文件顺序可调整*
- 初始的参数列表为启动时vim的文件列表
:args
:查看参数列表
其中[]
表明了当前的活动文件:args {arglist}
:填充参数列表
arglist可以是文件名、通配符、shell命令的输出结果等- 用文件名指定文件
:args {file1,file2,....}
- 用Glob模式指定文件
*
:表示0到无穷多个字符,但不包含子目录
**
:表示0到无穷多个字符,包含子目录 - 用反引号结构指定文件
将shell命令用反引号括起来,其输出将填充到相应的位置
如::args \
cat .chapters``
- 用文件名指定文件
- 隐藏缓冲区
缓冲区列表中,+
代表缓冲区被修改过,此时切换缓冲区会弹出错误信息,可以用感叹号强制切换,此时列表中被标记为a
的为活动缓冲区(active),被标记为h
的为隐藏活动区(hidden)- 处理隐藏缓冲区
:w
或:write
:写入磁盘:e
或:edit
:从磁盘中读入到缓冲区(回滚修改操作):qa
或:qall
:关闭所有窗口,放弃所有修改:wa
或:wall
:全部写入磁盘
- 用
:argdo
或:bufdo
修改一组缓冲区
前提:打开hidden
选项
打开后,对已修改的缓冲区执行:next
,:bnext
,cnext
等命令无需再加感叹号
- 处理隐藏缓冲区
窗口
- 分割
<C-w>s
:水平切分(同高度),新窗口仍为当前缓冲区<C-w>v
:垂直切分(同宽度),新窗口仍未当前缓冲区:sp {file}
或:split {file}
:水平切分,新窗口为file内容:vsp {file}
或:vsplit {file}
:垂直切分,新窗口为file内容
- 切换
<C-w>w
:轮换<C-w>{h|j|k|l}
:切换到左(下上右)侧的窗口- 若为GVIM,可以直接点击对用窗口进行切换
- 关闭
:clo
或:close
或<C-w>c
:关闭当前窗口:on
或:only
或<C-w>o
:关闭其他重口
- 改变窗口大小和重排列
<C-w>=
:使所有窗口等宽、等高<C-w>_
:使当前窗口高度最大化<C-w>|
:使当前窗口宽度最大化{N}<C-w>_
:使当前窗口高度调整为N行{N}<C-w>|
:使当前窗口宽度调整为N列- 若为GVIM,可以直接用鼠标拖动窗口的分界线
标签页
对窗口进行分组
:lcd {path}
:设置工作路径
限定标签页的工程范围- 只能改变当前窗口,而不是当前标签页
- 如果要改变标签页的所有窗口,应用
:windo lcd {path}
- 打开和关闭
:tabe {file}
或tabedit {file}
:在新标签页中打开file<C-w>T
:将当前窗口移动到一个新标签页:tabc
或:tabclos
:关闭当前标签页及其所有窗口:tabo
或:tabonly
:关闭其他标签页及其所有窗口
- 切换
- 标签页从1开始编号
:tabn {N}
或:tabnext {N}
或{N}gt
:切换到N号标签页:tabn
或:tabnext
或gt
:切换到下一标签页:tabp
或:tabprevious
或gT
:切换到上一标签页
- 重排列
:tabmove {N}
:将当前标签页移动到N号标签页之后:tabmove 0
:表示移动到开头:tabmove
:表示移动到末尾
- 若为GVIM,可以直接用鼠标拖曳
打开及保存文件
……待施工……