1. 移动技巧

1.1 在同一行移动

  • 首先是基本的hjkl
  • 使用f<chat>来移动到当前行光标之后的字符上,这里可以选择一些出现频率较低的字符,这样有更高的移动效率。在使用f<char>后,,可以使用;来重复上次的查找移动,如果不小心多移动了一个,可以按,回退
  • 使用w,e,b,ge在单词间跳转,其各自含义为:
    • w 正向移动到下一单词的开头
    • b 反向移动到当前单词/上一单词的开头
    • e 正向移动到当前单词/下一单词的结尾
    • ge 反向移动到上一单词的结尾
  • wb等是在单词间的跳转,但一个逗号或点也算单词,如果是想把一个用空格分隔的串叫做单词,可以使用WBEgE
  • gj, gk按屏幕行进行上下移动

1.2 在当前文件内移动

  • 使用*跳转到当前文件内的当前光标下的单词
  • %跳转到匹配的括号
  • 使用/执行常规搜索,并按n再次执行搜索

1.3 使用位置标记跳转

  • m<a-z>在当前文件中标记当前位置,mA-Z在全局定义一个mark
  • '<a-zA-Z>跳转到刚才的缓冲区
  • vim还预置了一些特殊的标记:
    • ''当前文件中,上次跳转之前的位置;
    • '.上次修改的地方; '^ 上次插入的地方
    • '<, '> 上次高亮选区的起始和结束位置

1.4 在文件之间移动

  • <C-o>, <C-i>后退和前进
  • [count]G 跳转到某个行号, 例如40G跳转至40行
  • (, )跳转到上一句/下一句的开头, {, }跳转到上一段/下一段的开头
  • gf 跳转到光标下的文件名
  • <C-]> 跳转到光标下关键字的定义
  • 改变列表, :changes查看最近的更改,g;g,跳转到下一个和上一个更改

2. 选择技巧

在可视模式下的选择技巧

  • 使用o来切换选区的活动端
  • <CR>+v进入列选择模式
  • 当你在一个具有特定结构的文本中时,例如程序源码,可以使用例如vi}来选择当前大括号中的所有字符,类似的:vi), vi"
  • vi<char>是选择除之外的字符,如果你想选择包括外围大括号}在内的字符,可以使用va}。为了便于记忆,可以把 i 想成"inside",而把 a 想成"around" 或"all"。

形如i}, a)的选区选择的文本在vim中被称为文本对象,Vim 的文本对象由两个字符组成,第一个字符永远是 i 或是a。我们一般说,以 i 开头的文本对象会选择分隔符内部的文本,而以 a 开头的文本对象则会选择包括分隔符在内的整个文本。这里我们使用文本对象进行选取,但也可以借助文本对象进行编辑。

3. 编辑技巧

3.1 使用文本对象进行编辑

  • d{motion}c{motion}y{motion},其中的{motion}都可以被替换为文本对象。例如:ci"修改双引号"之间的文本,yit 命令拷贝标签内的文本,di} 删除大括号}之间的文本

文本对象包含两类,一类是操作分隔符的文本对象,如 i)i"it,它们被称为分隔符文本对象;另一类用于操作文本块,如单词、句子和段落,例如iw 在当前单词内,is当前句子,ip当前段落,iW当前字串,当i被替换为a,这类文本对象将多包含一个空格或空行,这被称为范围文本对象d{motion}aw, as等配合较好,y/c{motion}iw, is等配合较好

3.x 使用surround.vim操作分隔符文本对象

http://github.com/tpope/vim-surround

  • cs"'将双引号"替换为单引号', 其前缀命令为cs,可记为change surround
  • ds"删除双引号", 其前缀命令为ds,可记为delete surround
  • ysiw)在当前单词周围添加括号(,其前缀命令为ys, iw是文本对象,最后的)代表在周围加上小括号且不包含空格
  • yss{在当前行周围加上大括号{},其前缀命令为yss

4. 寄存器操作

  • 在使用y,d进行复制,删除等操作时,默认使用无名寄存器,这就导致一个问题,当你使用yiw复制了一个单词,然后在另一个地方使用diw删除了一个单词之后,再想粘贴刚刚复制的单词,就会发现寄存器被占用了.此时通过一些寄存器操作来获取刚刚复制的单词.
  • 在复制命令之前加上"<a_z>来将复制的内容保存到指定寄存器中,例如"ayiw将当前单词复制到寄存器a中,然后通过"ap将寄存器a中的内容粘贴到当前位置
  • 复制专用寄存器"0, yank操作会将内容保存到寄存器0中,例如["0]yiw将当前单词复制到寄存器0中,然后通过"0p将寄存器0中的内容粘贴到当前位置
  • 黑洞寄存器"_, 通过"_d删除内容,不会保存到任何寄存器中
  • 系统剪贴板"+,可从中读取系统剪贴板的内容
  • :reg命令可以查看所有寄存器的内容
  • 使用R进入替换模式

基本操作

  • %跳转到匹配的括号
  • f<character> 找到当前行中,在光标之后的字符,在找到字符后,使用;跳转到后一个字符,,跳转到前一个字符
  • F<character> 找到当前行中,在光标之前的字符
  • <line_number>G 跳转到某行
  • CTRL-e 向下翻滚页面
  • CTRL-u 向上翻滚半页
  • CTRL-d 向下翻滚半页
  • d$删除至行末,dgg删除从光标到文件开头,ggdG删除整个文件,diw删除当前单词,dip删除当前段,ciw替换当前单词,yiw复制当前单词

vim的抽象层

缓冲区

缓冲区有三种不同状态:

  • active 缓冲区显示在窗口

  • hidden 缓冲区不显示,但存在且文件处于打开状态

  • inactive 缓冲区不显示且为空,没有链接任何文件

  • :buffers 查看所有打开的缓冲区

  • :buffer <ID_or_name> 移动到该缓冲区

  • :bnext:bn 移动到下一个缓冲区

  • :bprevious:bp移动到上一个缓冲区

  • :bfirst:bf移动到第一个

  • :blast:bl移动到最后一个缓冲区

  • CTRL-^切换到备用缓冲区,在列表中用#显示

  • <ID>CTRL-^切换到ID的特定缓冲区,例如75CTRL-^切换到ID为75的缓冲区

  • :bufdo <command> 将命令应用到所有缓冲区

  • 并非所有缓冲区但在列表中,使用:buffers!:ls!列出所有缓冲区

  • :badd <filename> 将某文件添加到缓冲区

  • :bdelete <ID_or_name>:bd 1删除缓冲区,1,10bdelete删除id从1到10的缓冲区

窗口 windows

vim中的窗口是一个用来显示缓冲区内容的空间,当关闭窗口时,缓冲区仍保持打开状态

  • :new创建新的窗口
  • CTRL-W s 水平拆分当前窗口
  • CTRL-W v 垂直拆分当前窗口
  • CTRL-W n 水平拆分当前窗口并编辑新文件
  • CTRL-W ^ 使用备用文件拆分
  • <buffer_ID>CTRL-W ^ 使用某ID的缓冲区拆分窗口
  • CTRL-W 上下左右 将光标移动到另一个窗口
  • CTRL-W r 旋转窗口,CTRL-W x与下一个窗口互换
  • CTRL-W = 调整窗口大小,使其适合相同大小的屏幕
  • CTRL-W - 降低窗口高度,CTRL-W + 增加窗口高度, CTRL-W < 减小窗口宽度, CTRL-W > 增加窗口宽度
  • :q 退出当前窗口

Tabs

:help tab-page

缓冲区是一个打开的文件,窗口是活动缓冲区的容器。可以将选项卡视为一堆窗口的容器。这样一来,它与标准 IDE 中的选项卡概念非常不同

  • :tabnew:tabe 打开新的选项卡
  • :tabclose:tabc 关闭当前选项卡
  • tabonlytabo 关闭除当前选项卡外的所有传其他选项卡
  • gt go 到下一个tab
  • gT go 到上远程tab
  • 1gT go到第一个选项卡

参数列表 arglist

:help arglist

参数列表用于组织打开的文件,可将其视为缓冲区列表的稳定子集。它遵循以下两个原则:

  • arglist 中的每个文件都将位于缓冲区列表中。
  • 缓冲区列表中的某些缓冲区不会出现在 arglist 中。

运行 Vim 时要打开的文件(例如执行 vim file1 file2 file3 )将自动添加到 arglist 中

  • :args 显示arglist
  • :argadd 将文件添加到arglist
  • argdo 对arglist中的每个文件执行命令
  • :next 移动到arglist中的下一个文件
  • :prev 移动到arglist中的上一个文件
  • :first 移动到arglist中的第一个文件

跳跃

:jumps

  • CTRL-o 转到上一个光标位置
  • CTRL-i 转到下一个光标位置

:help jump-motions :help jumplist :help changelist

  • [m 移动到方法的开头
  • ]m 移动到方法的末尾

更改列表

每次插入内容(使用 INSERT 模式)时,光标的位置都会保存在更改列表中。

  • g; 跳转到下一个更改
  • g, 跳转到上一个更改

重复

:help single-repeat

  • . 重复上一次更改
  • @: 重复执行上次的命令

录制宏

  • `q<lowecase_letter>`` - 开始在寄存器中记录击键。您可以将寄存器视为内存中的一个位置,也可以将其视为剪贴板。
  • 您接下来要执行的每次击键都将被保存。
  • q - 停止录制。
  • @<lowercase_letter> - 执行您录制的击键。

命令行窗口

:help cmdline-window

  • q: 打开命令行历史记录
  • q/q? 打开搜索历史记录
  • CTRL+f 在命令行模式下打开命令行历史记录
  • :history : 命令行历史记录
  • :history /:history ?搜索记录

搜索与替换

单个文件搜索

  • 基本搜索,在normal模式下使用/然后键入要搜索的pattern,这将向前搜索,结果将在文件中突出展示;?向后搜索
  • //使用上次的模式搜索
  • :set hlsearch 设置搜索结果高亮
  • * 搜索当前光标下的单词
  • g*搜索部分单词

多个文件搜索

:help :vimgrep

  • :vimgrep <pattern> **/*.php 在*.php文件中搜索。这将使用搜索结果填充quickfix列表,使用:cnext:cn:cprev:cp来查看结果,也可以通过:copen快速打开修复窗口并浏览结果
  • :vimgrep pattern * 在工作目录中的每个文件搜索模式

使用grep搜索

可通过grepprg设置要使用的外部搜索程序

:help :grep

  • :grep <pattern> * 搜索工作目录中出现的每个pattern
  • :grep <pattern> a.txt b.txt 在这两个文件中搜索出现的pattern

替换

:help :substitute

  • s/pattern/replace/g 在当前行上使用“replace”替换“pattern”, 这里的s代表substitute,g表示全局
  • %s/pattern/replace/g 在当前文件中用“replace”替换“pattern”
  • :s/pat\/tern/replace/g 转义以匹配pat/tern
  • :s#pat\tern#replace#g 也可以使用其他分隔符
  • :s/pattern/replace/ 10 将从当前开始的10行中的pattern替换为replace
  • :1,10s/pattern/replace/ 将文件前10行中的pattern替换为replace

一些标志的含意:&使用上一个替换命令中的标志;c要求用户确认每个替换;g替换每行中出现的内容;i不区分大小写;I区分大小写;n只报告匹配次数

逐个替换

  • 使用/执行常规搜索
  • 使用cgn替换当前单词
  • 使用n转到下一个结果
  • 使用.重复上次的替换或使用n跳转到下一个结果

在多个文件中查找和替换

可通过稳定的arglist来作为可以修改的文件的列表

例如,要替换每个html和twig文件中的匹配项,键入如下命令

  • :arg *.html使用当前工作目录中的所有html文件填充arglist,然后编辑第一个文件
  • :argadd *.twig 将twig文件添加到arglist
  • :argdo %s/pattern/replace/ge | update 将arglist中的每个文件中出现的pattern替换为replace
  • :bufdo %s/pattern/replace/ge | update 缓冲区中替换

通过快速修复列表替换

  • :grep pattern **/*.html 查找子目录中的html文件
  • :cdo s/blink/div/g | update替换

g

  • gf编辑位于光标下文件路径中的文件
  • gx打开位于光标下文件路径中的文件
  • gi移动到上次插入并切换到INSERT模式
  • gv启动VISUAL模式并使用在上次VISUAL模式下所做的选择
  • gn选择上次搜索的匹配项
  • gI在行首插入文本,无论第一个字符是什么
  • ga 以十进制、十六进制或八进制打印光标下字符的 a scii 值
  • gu 使用动作的小写(例如, guiw )
  • gU 使用动作的大写(例如, gUiw )

Range 范围

  • .表示当前行
  • $表示当前缓冲区最后一行
  • %表示整个文件
  • * 表示在上一个VISUAL模式下所做的最后选择
  • '<'>分别表示选择的第一行和最后一行

例如,结合range与d

  • :1,40d 删除1-40行
  • :2,$d 删除从第二行到最后
  • .,$d 删除从当前行到最后
  • %d删除每一行

QuickFix 和文件列表

TODO

全局命令

基本形式: :g/pattern/command,其语义为:对全局的pattern执行command命令

例如,删除当前缓冲区中所有包含“useless”单词的行: :g/useless/d

:norm命令,可以在命令模式下执行normal模式中的一些指令,例如::norm daw将删除光标下的单词 :q

将normal模式命令与全局命令结合起来: :g/useless/norm gu$ 这将把每个包含useless的行小写

marks 书签

  • normal模式下,使用m<a-z>当前缓冲区,mA-Z全局缓冲区来定义一个mark
  • normal模式下,使用'<a-z>跳转到刚才的缓冲区
  • :marks 显示标记集
  • :marks <marks>显示一些特定标记
  • :delmarks <mark> or :delm <mark>删除标记
  • :delmarks!delm! 删除a-z范围内所有标记
  • :marks <> 显示两个标记<>

排序

  • :sort:sor根据范围对行进行排序
  • :sort!:sor!倒序

还可以为sort添加一些选项

  • i忽略大小写
  • n根据行中的第一个小数排序
  • f根据行中的第一个浮点数排序
  • /pattern/根据匹配后的情况排序
  • r/pattern/结合,根据匹配模式排序

例如:对csv,根据第二列对每一行进行排序::sort /[^,]*,/