Vim使用教程

Kevin2li大约 14 分钟Tutorial

简介

Vim是一款文本编辑器,它可以在终端或命令行界面下使用。Vim最初是由Bram Moolenaar在1991年发布的,并基于另一款文本编辑器Vi开发而来。

Vim具有强大的编辑功能,可以帮助用户快速编辑和处理文本文件。它支持多种编辑模式,包括命令模式、插入模式和可视模式,可以通过快捷键在不同的模式之间切换。Vim还支持多种自定义配置选项,可以让用户根据自己的需求进行定制。

由于Vim可以在终端下运行,因此它特别适合在远程服务器上进行编辑操作。Vim也有广泛的使用者社群和丰富的插件生态系统,可以通过插件扩展其功能。由于Vim的学习曲线较陡峭,因此需要一定的学习成本。但是一旦掌握了Vim的基本用法,就能够大幅提高文本编辑效率。

官网:https://www.vim.org/open in new window

教程

模式

命令模式

窗口管理
功能按键
关闭当前窗口:q
保存并关闭当前窗口:wq
关闭当前窗口(不保存):q!
水平分割窗口Ctrl-W s
垂直分割窗口Ctrl-W v
tab页管理
功能按键
在新tab页打开文件:tabnew {file}
切换到下一个tab:tabn
切换到上一个tab:tabp
关闭其他tab:tabo
文本内容处理
功能按键
复制第49到51行的内容:49,51y
删除第30到第34行的内容:30,34d
删除当前行及下面两行:.,+2d
删除整个文档:%d
其他
  1. 保存需要用sudo权限保存的文件: :w !sudo tee %
  2. 取消搜索高亮: :nohl
光标移动
功能按键
光标向上移动10行:-10
光标向下移动10行:+10
移动到第123行:123
移动到首行:0
移动到末行:$

输入模式

功能按键
在光标前输入i
在光标后输入a
在行首输入I
在行尾输入A
在下一行开头输入o
在上一行开头输入O
修改当前chars
删除前一个charCtrl-H
删除前一个wordCtrl-W
删除当前行光标前内容Ctrl-U
回到上次修改位置gi
粘贴寄存器x的内容Ctrl-R x

替换模式

  • r: 进入char替换模式

可视模式

功能按键
进入char-level可视模式v
进入line-level可视模式V
进入block-level可视模式Ctrl-V

语法

# 格式1:
[count] [operator] [motion | text objects]

# 格式2:
[operator]  [count] [motion | text objects]

说明:

  • count: 命令执行次数
  • operator: 命令类型,包括ydcx
  • motion: 指明光标移动范围
  • text objects: 文本块对象

例如:

  • caw: 修改当前word
  • yaw: 复制当前word
  • dl: 删除当前字符
  • ct.: 修改直到.前面的内容
  • 3dd: 删除3行
  • d2w: 向后删除2个word

文本对象(text object)

在Vim中,text objects(文本对象)是一种用于快速选择和操作文本块的功能。它可以让用户在编辑时快速选择一段文本,而不需要使用鼠标进行拖拽或者键盘进行移动光标来选择。text objects可以让用户通过一些命令快速选择文本对象,然后进行复制、剪切、粘贴或其他操作。

在Vim中,text objects有多种类型,例如:

typecommand
wordawiw
sentenceasis
paragraphapip
stringa"i", a'i'
codea`i`
parenthesesa(i(
bracketsa[i[
bracesa{i{
tagsatit

其中, a表示around,包含定界符; i表示inside,不包括定界符

术语解释:

来源: :help word

术语解释
wordA word consists of a sequence of letters, digits and underscores, or a sequence of other non-blank characters, separated with white space (spaces, tabs, EOL).
WORDA WORD consists of a sequence of non-blank characters, separated with white space. An empty line is also considered to be a WORD
sentenceA sentence is defined as ending at a '.', '!' or '?' followed by either the end of a line, or by a space or tab. Any number of closing ')', ']', '"' and ''' characters may appear after the '.', '!' or '?' before the spaces, tabs or end of line. A paragraph and section boundary is also a sentence boundary.
paragraphA paragraph begins after each empty line, and also at each of a set of paragraph macros, specified by the pairs of characters in the 'paragraphs' option.

动作(motion)

在vim中,motion表示移动光标的操作。具体来说,motion是指通过键盘输入一系列命令来使光标在文本中向前或向后移动的操作,这些命令通常与方向键(如上、下、左、右)无关,而是使用vim的特殊命令,例如单词、行、段落等。

motion是vim中的重要概念之一,熟练掌握各种motion的使用可以提高vim的操作效率。

下面介绍vim中常见的motion:

行内移动
移动到行首/行尾
功能按键
移动到行首0
移动到行尾$
移动到行首(非空白)^
移动到行尾(非空白)g_
按单词移动

word和Word的区别

功能按键
移动到下一个word开头w
移动到上一个word开头b
移动到下一个word结尾e
移动到上一个word结尾ge
移动到下一个WORD开头W
移动到上一个WORD开头B
移动到下一个WORD结尾E
移动到上一个WORD结尾gE
按括号移动
功能按键
移动到对应括号匹配位置(支持{[()]})%
按指定字符移动
功能按键
移到到下一个charf{char}
移到到上一个charF{char}
移到直到下一个chart{char}
移到直到上一个charT{char}

查找匹配

查找下一个: ;
查找上一个: ,

跨行移动
功能按键
移动到首行gg
移动到尾行G
移动到{line-number}{line-number}gg{line-number}G
移动到屏幕顶端H
移动到屏幕中端M
移动到屏幕底端L
向下翻页半个屏幕Ctrl+d
向上翻页半个屏幕Ctrl+u
向下翻页整个屏幕Ctrl+f
向上翻页整个屏幕Ctrl+b
向下滚动Ctrl+e
向上滚动Ctrl+y

文本操作

复制/剪切/修改/粘贴

复制
功能按键
复制一个letteryl
复制当前行yy or Y
复制text object内容y{text object}
复制motion内容y{motion}
粘贴
功能按键
在当前光标后粘贴 (结束后光标置于粘贴内容前)p
在当前光标前粘贴 (结束后光标置于粘贴内容前)P
在当前光标后粘贴 (结束后光标置于粘贴内容后)gp
在当前光标前粘贴 (结束后光标置于粘贴内容后)gP
拷贝当前行到下一行yyp
交换上下两行ddp
剪切
功能按键
剪切当前字符x
剪切当前行dd
剪切至行尾D
交换左右字母顺序dlpxp
剪切text object内容d{text object}
剪切motion内容d{motion}
修改
功能按键
修改当前行cc
修改至行尾C
修改text object内容c{text object}
修改motion内容c{motion}

查找

格式:

  • /pattern: 向后查找{pattern}
  • ?pattern: 向后查找{pattern}
  • *: 向后查找光标下所在单词, 相当于/pattern
  • #: 向前查找光标下所在单词, 相当于?pattern

查找匹配

  • n: 查找下一个
  • N: 查找上一个

==.配合使用,可以实现对匹配项的批量修改或删除==

例如:

测试文本: cucumber carrot lettuce cabbage carrot lettuce cucumber cucumber cucumber carrot kale cucumber kale

操作序列:

/cucumber<Enter>    # 查找匹配项
cgnfoo<ESC>         # 执行对匹配项的修改: 将匹配项修改为foo
.                   # 重复执行修改

`gn`的作用

在Vim中,"gn"是一种高级文本对象的选择方式,可以选中下一个匹配项。"gn"命令的作用是在当前光标位置查找下一个与当前选中文本相同的文本,然后选中该文本。如果没有选中文本,"gn"会选中当前光标所在单词。

结果: foo carrot lettuce cabbage carrot lettuce foo foo foo carrot kale foo kale

替换

格式:

:[range]s/{pattern}/{substitute}/[flags]

说明:

  • range: 作用范围,如:
    • %表示整个文档
    • 3,5表示第3行至第5行
    • 1,$表示第1行至最后一行
    • .,+2表示当前行及后面两行
  • pattern: 表示匹配的模式
  • substitute: 表示替换的内容
  • flags: 替换标志位,如:
    • g: 表示全部匹配项替换
    • i: 表示忽略大小写
    • c: 表示替换前提示要求确认

例如:

# 将第296行至299行中的所有cucumber替换为foo
:296,299s/cucumber/foo/g

# 将整个文档中所有cucumber替换为foo
:%s/cucumber/foo/g

# 将当前行所有cucumber替换为foo
:s/cucumber/foo/g

环绕

功能按键说明
删除环绕ds
添加环绕ys
添加环绕S{word}需要先选中再使用
修改环绕cs'"将'修改为"
将指定单词环绕符号ysiw<li>将指定单词用<li>包裹

其他

功能按键
交换大小写~
交换整行大小写g~~
增加缩进>>
减少缩进<<
自增1Ctrl-A
自减1Ctrl-X

寄存器(register)

参考:https://www.iteye.com/blog/liuzhijun-1830931open in new window

类型名称作用
未命名寄存器(unamed register)"复制/剪切默认的寄存器存储位置
命名寄存器(named register)a-z由用户自定义存储内容
复制寄存器(yank register)0存储最近复制的内容
剪切寄存器(cut register)1-9存储最近9次剪切的内容(以行为单位),其中1表示最近1次剪切的内容,2表示倒数第二次剪切的内容,以此类推
小删除寄存器(small delete register)-相比1-9寄存器以行为单位,这个粒度更细, 可以存储char、word等
系统寄存器(system register)*系统寄存器,可以与vim共享内容

查看寄存器内容::reg

语法

  • 通过"x语法来指定使用命名寄存器x,向其中覆盖写入内容
  • 通过"X语法来指定使用命名寄存器x,向其中追加写入内容
功能按键
存储内容到命名寄存器a"ay{motion}"ad{motion}"ac{motion}
粘贴命名寄存器a的内容"ap
粘贴系统剪贴板内容"*p

宏(macro)

  • q{register}<Command>q: 录制宏, 以q为界开始录制,以q为界结束录制
  • @{register}: 调用宏
# 自增序号宏录制
qa
"xyiwjdiw"xp<Ctrl>-a
q

# 调用
@a  # 调用1次
5@a # 调用5次
@@  # 重复上次调用

标记(mark)

  • m{register}: 添加标记到register中,register可以为a-zA-Z
  • `{register}: 跳转到register存储的标记处
  • '{register}: 跳转到register存储的标记处行首
  • `` : 在当前光标处与标记处来回切换
  • '' : 当前光标所在行处与标记处来回切换,光标定位在行首

重复执行

  • .: 重复执行上次修改

撤销和恢复

  • u: 撤销上次更改
  • Ctrl+R: 恢复上次更改

配置

常用基础配置

配置选项说明
set number显示行号
set autoindent自动缩进
set smartindent智能缩进,根据上一行的缩进方式来缩进
set tabstop=4tab 为 4 个空格
set shiftwidth=4设置每次缩进的空格数为 4
set autoread当文件被改动时自动载入
syntax on语法高亮
set ignorecase搜索时忽略大小写
set smartcase搜索时区分大小写,但如果搜索词全小写则忽略大小写
set mouse=a鼠标支持
set clipboard=unnamedplus允许使用鼠标复制和粘贴
set backupdir=~/.vim/backup备份文件目录
set expandtab将 tab 转为空格
set hlsearch高亮显示搜索结果
set incsearch在搜索时逐步显示结果
set showmatch在插入括号时高亮显示匹配的括号
set nowrap不折行显示内容
set wrap折行显示内容
set noswapfile禁止创建 swap 文件
set path=.,**设置 Vim 的寻找文件路径,在当前目录和所有子目录下查找文件
set ruler显示当前光标所在行和列的位置
set spell开启拼写检查功能
set spelllang=en_us设置拼写检查语言为英语
set foldmethod=indent按照缩进级别进行折叠
set foldcolumn=2设置折叠列的宽度为 2
set scrolloff=3设置距离屏幕顶端和底端的距离,以保证光标始终在屏幕中央
set textwidth=80设置每行最大字符数为 80
set undofile开启撤销文件功能,每次编辑时都会自动生成一个撤销文件
set undolevels=1000设置撤销文件保存的最大历史记录数为 1000
set undoreload=10000设置 Vim 自动重新加载撤销文件的时间间隔为 10000 次编辑操作
set nofoldenable禁用折叠功能
set foldenable启用折叠功能
set cursorline高亮显示当前行
set cursorcolumn高亮显示当前列
set list显示行尾空格等不可打印字符
set clipboard=unnamed允许与系统剪贴板交互
export VISUAL=vim将 Vim 设置为默认编辑器
let mapleader = ","自定义键映射中的前缀键为,
nnoremap <Leader>x dd<Leader>x 映射为某个功能,如dd删除当前行

插件管理

插件管理器:vim-plugopen in new window

  • 安装
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  • 使用

添加插件示例(支持多种格式):

call plug#begin()
" The default plugin directory will be as follows:
"   - Vim (Linux/macOS): '~/.vim/plugged'
"   - Vim (Windows): '~/vimfiles/plugged'
"   - Neovim (Linux/macOS/Windows): stdpath('data') . '/plugged'
" You can specify a custom plugin directory by passing it as the argument
"   - e.g. `call plug#begin('~/.vim/plugged')`
"   - Avoid using standard Vim directory names like 'plugin'

" Make sure you use single quotes

" Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
Plug 'junegunn/vim-easy-align'

" Any valid git URL is allowed
Plug 'https://github.com/junegunn/vim-github-dashboard.git'

" Multiple Plug commands can be written in a single line using | separators
Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'

" On-demand loading
Plug 'preservim/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }

" Using a non-default branch
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }

" Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
Plug 'fatih/vim-go', { 'tag': '*' }

" Plugin options
Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }

" Plugin outside ~/.vim/plugged with post-update hook
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }

" Unmanaged plugin (manually installed and updated)
Plug '~/my-prototype-plugin'

" Initialize plugin system
" - Automatically executes `filetype plugin indent on` and `syntax enable`.
call plug#end()
" You can revert the settings after the call like so:
"   filetype indent off   " Disable file-type-specific indentation
"   syntax off            " Disable syntax highlighting

" 键位映射
nmap <Leader>k yyP
nmap <Leader>j yyp
nmap <Leader>h ^
nmap <Leader>h ^
nmap <Leader>l g_

命令说明:

CommandDescription
PlugInstall [name ...] [#threads]Install plugins
PlugUpdate [name ...] [#threads]Install or update plugins
PlugClean[!]Remove unlisted plugins (bang version will clean without prompt)
PlugUpgradeUpgrade vim-plug itself
PlugStatusCheck the status of plugins
PlugDiffExamine changes from the previous update and the pending changes
PlugSnapshot[!] [output path]Generate script for restoring the current snapshot of the plugins

推荐配置

参考: https://github.com/amix/vimrcopen in new window

安装:

git clone --depth=1 https://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh

此时,会生成一个默认的~/.vimrc文件,包含了该项目为我们指定的推荐配置。 我们可以将自己补充的配置添加在~/.vim_runtime/my_configs.vim中。

set number
set mouse=a

" 解决tmux中粘贴缩进混乱
if &term =~ "screen"                                                   
    let &t_BE = "\e[?2004h"                                              
    let &t_BD = "\e[?2004l"                                              
    exec "set t_PS=\e[200~"                                              
    exec "set t_PE=\e[201~"                                              
endif

call plug#begin()

Plug 'https://github.com/tpope/vim-surround'
Plug 'jiangmiao/auto-pairs'
Plug 'easymotion/vim-easymotion'
Plug 'tpope/vim-commentary' 

call plug#end()

let mapleader = ","

"""""""""""""""""""""""""""
" easymotion插件配置
"""""""""""""""""""""""""""
" <Leader>f{char} to move to {char}
map  <Leader>f <Plug>(easymotion-bd-f)
nmap <Leader>f <Plug>(easymotion-overwin-f)

" s{char}{char} to move to {char}{char}
nmap s <Plug>(easymotion-overwin-f2)

" Move to line
map <Leader>L <Plug>(easymotion-bd-jk)
nmap <Leader>L <Plug>(easymotion-overwin-line)

" Move to word
map  <Leader>w <Plug>(easymotion-bd-w)
nmap <Leader>w <Plug>(easymotion-overwin-w)

在其他编辑器中使用vim

VSCode

可以安装vimopen in new window插件,来获得类似原生vim的编辑体验。

启用与关闭vim: Ctrl-Shift-P: Vim: Toggle Vim Mode

自用配置:

"vim.smartRelativeLine": true,
"vim.camelCaseMotion.enable": true,
"vim.cursorStylePerMode.normal": "block",
"vim.cursorStylePerMode.insert": "line",
"vim.handleKeys": {
    "<C-a>": false,
    "<C-b>": false,
    "<C-c>": false,
    "<C-d>": false,
    "<C-e>": false,
    "<C-f>": false,
    "<C-g>": false,
    "<C-h>": false,
    "<C-i>": false,
    "<C-j>": false,
    "<C-k>": false,
    "<C-l>": false,
    "<C-m>": false,
    "<C-n>": false,
    "<C-o>": false,
    "<C-p>": false,
    "<C-q>": false,
    "<C-r>": false,
    "<C-s>": false,
    "<C-t>": false,
    "<C-u>": false,
    "<C-v>": false,
    "<C-w>": false,
    "<C-x>": false,
    "<C-y>": false,
    "<C-z>": false,
},
"vim.leader": ",",
"vim.matchpairs": "(:),{:},[:],<:>",
"vim.useSystemClipboard": true

JetBrains

同样可以安装vim插件

Cheatsheet

参考

  1. https://vim.rtorr.com/open in new window
  2. https://www.lesswrong.com/posts/ioGf4LHid42mCK3SK/vimopen in new window
  3. Learn Vim | vscode插件open in new window