Vim

第一部分: VIM的基本使用(第 3 课: VIM)

备注:按键严格区分大小写

vim 的编辑模式

主要操作模式为:

  • 正常模式:在文件中四处移动光标进行修改的模式。进入vim时处于的模式

  • 插入模式:插入文本

  • 替换模式:替换文本

  • 可视化模式:进一步分为一般、行、块模式,主要是移动光标选中一大块文本

  • 命令模式:用于执行命令

以正常模式为“中心模式”,使用 <ESC> 键从任何其他模式返回正常模式。在正常模式下:使用 i 键进入插入模式,使用 R 键进入替换模式,使用 : 键进入命令模式,使用 v 键进入可视化(一般)模式,使用 V 键进入可视化(行)模式,使用 Ctrl+v 进入可视化(块)模式。

vim 界面:缓存(cache),标签页(tab),窗口(window)

Vim 会维护一系列打开的文件,称为“缓存”。一个 Vim 会话包含一系列标签页,每个标签页包含一系列窗口(分隔面板)。每个窗口显示一个缓存。跟网页浏览器等其他你熟悉的程序不一样的是, 缓存和窗口不是一一对应的关系;窗口只是视角。一个缓存可以在多个窗口打开,甚至在同一 个标签页内的多个窗口打开。这个功能其实很好用,比如在查看同一个文件的不同部分的时候。

Vim 默认打开一个标签页,这个标签也包含一个窗口

window

:sp [filename] 表示在下方新建一个窗口,打开 filename 文件

:vsp [filename] 表示在右边新建一个窗口,打开 filename 文件

ctrl+w + h/j/k/l 切换至左/下/上/右的窗口

ctrl+w + +/- 当前窗口增加/减少一行

ctrl+w + 10 + + 当前窗口增加十行

:resize +5:上下方向增加5行

:vertical resize -5:左右方向减少5行

:wq [filename] 表示关闭当前窗口,并将当前窗口的文件更名为 filename

tab

:tabnew [filename] 表示新建一个标签页,打开 filename 文件

切换至左边的标签页::-tabnextgT:tabp(previous)

切换至右边的标签页::+tabnextgt:tabn(next)

vim swap 文件

若出现多个窗口编辑同一个文件,使用 E 表示对原始文件进行编辑,此时会新建一个缓存。以编辑 a.py 为例,第一个缓存的名字为 .a.py.swp,第二个缓存的名字为 .a.py.swo(第三个缓存的名字为 .a.py.swn)。备注:若使用 E 进入,则表示基于 a.py 里的内容新建缓存 .a.py.swo。若使用 R 进入,则表示基于 .a.py.swp 文件新建缓存 .a.py.swo

  • E 表示利用原始文件新建缓存

  • R 表示利用缓存文件新建缓存,若已有多个缓存,则需要按照屏幕提示选择以哪个已有缓存新建缓存

各模式下的基础操作

正常模式

正常模式下,光标的显示方式为块状。

命令作用

u

撤销操作

ctrl+r

重做上一个操作

.

重复上一个操作

第一类操作为移动,也被称为名词

  • 使用 hjkl 分别代表左、下、上、右移动光标,当然也可以使用方向键;

  • 词:w 表示移动到下一个词首,b 表示移动到当前词的词首,e 表示移动到当前词的词尾;

    • 备注(不重要的细节):如果当前光标停在词尾,那么 e 键将会移动到下一个词的词尾;b 键同理。

  • 行:0 (数字零)表示移动到行首,^ 键移动到该行第一个非空格位置,$ 键移动改行的行尾;

  • 屏幕:H 表示屏幕首行,M 表示屏幕中间,L 表示屏幕底部;

  • 翻页:Ctrl+u 表示上翻一页,Ctrl+d 表示下翻一页;

  • 文件:gg 表示移动到文件开头,G 表示移动到文件结尾;

  • 行数:{数字}G或者{数字gg}或者:{数字} 表示移动到某一行,例如:10G 表示移动到文件的第10行

  • Find: f{character}, t{character}, F{character}, T{character}

    • find/to forward/backward {character} on the current line

    • , or ; for navigating matches

    f/F 表示在当前行查找下一个字符/上一个字符 character。t/T表示查找下一个字符character的前一个字符/前一个字符 character 的后一个字符。取消搜索高亮需要在普通模式下输入:nohlsearch:noh

  • Search: /{regex}, n or N for navigating matches。从当前光标位置寻找符合正则表达式 regex 的字符串,n 表示寻找下一个,2n 表示寻找往后第二个,N 表示向前查找

  • Misc: % (corresponding item):匹配左括号或右括号

  • Ctrl+o 回到上一次光标位置,Ctrl+i 回到下一次光标为置。(这里的上一次与下一次是指缓存)

第二类操作为操作,也称为动词

  • 进入到插入模式存在多种方法

    • i 在当前方块的左侧进入插入模式(insert)

    • I 在当前方块行首插入(insert)

    • a 在当前方块的右侧进入插入模式(append)

    • A 在当前方块行尾插入(append)

    • o 在当前行的下一行新增一个新行并进入插入模式

    • O 在当前行的上一行新增一个新行并进入插入模式

  • d{motion}:删除(实际上是剪切)

    • dw:删除单词

    • dd:删除当前行

    • d3w:删除从当前单词开始的3个单词

    • d3l:删除从当前位置开始的3个字符(向右)

    • di":删除双引号内部的全部内容(delete in "

    • da":删除双引号及双引号中的内容(delete around "

  • y{motion}:复制,与d{motion}类似

    • yy:复制当前行

  • x:删除当前字符,等价于dl

  • c{motion}:改变,即删除并进入插入模式

  • u:撤销上一次改变

  • <Ctrl-r>:重做

  • p:粘贴

特殊操作:

  • .:重复上次的操作

  • zz:将当前所在行居于屏幕中央显示

  • <ctrl+a>:将当前数字加1,<ctrl+x>:将当前数字减1。

插入模式

插入模式下,光标的显示方式为块状。键入字符表示在光标停留位置增加一个字符,而原始光标处及该行之后的字符往后移动一位,且新光标位置也向后移动一位。

例子:

abcd

假定当前光标位置在 c 处,键入 f,那么会变为

abfcd

且光标位置依然在 c 处。

替换模式

普通模式下按 R 进入替换模式(此模式比较少用)

替换模式下,光标的显示方式为块状。键入字符表示将光标停留位置做字符替换,新光标位置向后移动一位。

例子:

abcd

假定当前光标位置在 c 处,键入 f,那么会变为

abfd

且光标位置移动至 d 处。

命令模式

备注:保存/退出等都是针对当前窗口(window)的

保存、退出相关的命令

  • :w 表示保存

  • :q 表示退出(前提是所有更改都已经保存了),:q! 表示不保存(不保存从上一次保存之后的更新)退出

  • :wq 表示保存并退出

  • :e! [filename] 表示放弃从上一次保存之后的更新,[并打开 filename 文件进行编辑]。

写完文件时发现没有写入权限:

  • :w !sudo tee %:此处%表示当前文件,一步解决。接下来输入密码确定后,使用:q!退出即可

  • :w ~/x.txt:即先保存到一个有写入权限的位置,再退出vim进行文件copy

分屏

  • :vsplit:左右分屏

  • :split:上下分屏

  • <C-W> {hjkl}:切换屏幕

其他命令:

  • :pwd:显示当前打开文件的目录

  • :Vex:在左侧打开目录树,按方向键选择,按回车键进入,:q退出窗口。:Sex 在上方打开目录树

  • :r !cat x.txt:将x.txt的文件内容读取进来

  • :%TOhtml:将当前代码转换为html页面

可视化模式

增加注释的操作:ctrl+v 后选中若干行,按下 I 进入插入模式,输入 # ,按下 ESC,则选中行将加上注释

取消注释的操作:ctrl+v 后选中若干行的 # 块,输入 dx 即可

操作实例

例1:对所有行进行相同的操作

原始文件

def foo():
    return 1

目标文件

# def foo():
#     return 1
  • 方法一:按shift+v进入可视行模式,选中两行,输入:normal0i#

  • 方法二:按ctrl+v进入可视块模式,选中两行的开头,输入I# ,再输入ESC

VIM Cheatsheet

本部分仅记录原生的VIM快捷键

参考: https://vim.rtorr.com/

重复上次的命令

.用于重复上一条命令

制表符

参考博客

普通模式下: >>插入一个制表符, <<向左侧删除一个制表符 visual模式下(三种块模式均可):

  • 按下>插入一个制表符,继续按.插入第2个制表符

  • 按下<插入一个制表符,继续按.插入第2个制表符

撤销与重做

普通模式下: u撤销上一次操作, ctrl+r重做操作

分屏

:vsp filename <CR>: 左右分屏打开文件 :sp filename <CR>: 上下分屏打开文件

上下移动

ctrl+u上翻半页, ctrl+d下翻半页

abc
defg
h
ijk

现在希望在每行前面加上一个单引号, 结尾加上一个单引号和一个逗号, 可以使用宏来解决

录制宏: 首先回到第一行行首并进入 normal 模式, 按下 qai'<ESC>$',<ESC>q, 其中 qa 代表录制一个名为 a 的宏, 最后的 q 代表宏录制结束 应用宏: 对每行应用刚才录制的操作, 使用 <shift+v> 进入行可式模式, 然后按 G 选中至结尾, 接下来输入 :normal @a 应用宏

第二部分: 自定义VIM

VIMRC、VIMSCRIPT

~/.vimrc 文件

语法

" comment
set number
set syntax on
set laststatus=2
nnoremap S :w<CR>
nnoremap <C-W> :w<CR>
nnoremap R :source $MYVIMRC<CR>
inoremap <Down> <ESC>:echoe "Use j"<CR>
inoremap <Up> <Nop>
nnoremap <C-Right> 5l

set laststatus=2 为VIM命令,即可以在普通模式下按下:再输入laststatus=2,可以起到等同于在~/.vimrc文件中写set laststatus=2一样的效果。此条命令的含义是将当前文件名显示在底部

nnoremapn+nore+map含义分别为normal(普通模式)no recuresive(非递归)map(映射)nnoremap S :w<CR> 指的是在普通模式下,按S建将等同于按下:w与回车键,也就是保存当前文件。类似的语法还有如下:

  • nnoremap、nmap:普通模式非递归/递归映射

  • inoremap、imap:插入模式非递归/递归映射

nnoremap <C-W> :w<CR>表示将ctrl+w键映射为保存文件

nnoremap R :source $MYVIMRC<CR>:中source为VIM命令,此条的含义为普通模式下按下R等同于重新加载~/.vimrc文件(这里假定环境变量MYVIMRC已定义为了~/.vimrc

同理,inoremap <Down> <ESC>:echoe "Use j"<CR> 表示的是将插入模式下的下方向键映射为退出到普通模式,并输出提示:Use jinoremap <Up> <Nop>中的Nop代表无操作,即按上方向键无任何实际效果。

推荐设置

" 设置tab宽度并将tab键替换为若干个空格
set ts=4
set expandtab
set autoindent

" 在底部显示文件名
set laststatus=2

" 当前行底部显示一根下划线
set cursorline

" 在界面右下方显示命令
set showcmd

" 每行的显示内容不会越出窗口的宽度
set wrap

" 语法高亮
set nocompatible
syntax on

" 显示行号/相对行号
set number
set relativenumber

" 搜索结果高亮
set hlsearch

" 搜索时高亮(一边输入一边高亮)
set incsearch

" 忽略大小写搜索与智能大小写搜索
set ignorecase
set smartcase

" 映射取消搜索高亮,默认情况下leader键为反斜杠键。映射后按下leader键,接着再按下回车键即为取消搜索高亮
" let mapleader=" "
noremap <LEADER><CR> :nohlsearch<CR>

VIM 插件

通常而言可以使用一些第三方插件管理器,然后再指定需要的插件进行安装。但其实VIM已经自带了“插件管理器”参考博客。在不使用第三方插件管理器的情况下,可以按如下方法安装插件:

mkdir -p ~/.vim/pack/default/start
# mkdir -p ~/.local/share/nvim/site/pack/default/start  # for neovim
cd ~/.vim/pack/default/start
git clone https://github.com/vim-airline/vim-airline.git  # 在底部显示更多信息

vim-airline

nerdtree

第三部分: Neovim

关于配置插件的一些“原理”:

  • init.lua/init.vim为用户配置的入口

  • .lua/.vim的搜索路径与$VIMRUNTIME变量相关(此变量是nvim中的变量,并非系统环境变量)。关于启动 neovim 时的具体过程可参考:

    • neovim 官方文档:https://neovim.io/doc/user/starting.html#starting

    • 博客:https://thevaluable.dev/vim-runtime-guide-example/

  • 关于自定义配置时 lua 脚本放在哪,可参考官方文档

    • 这几个目录是特殊的 ~/.config/nvim/lua~/.config/nvim/plugin~/.config/nvim/after

本部分以用Neovim配合各种插件替代VSCode为主线介绍Neovim的使用

常用快捷键:

  • 文件自动保存

  • 代码增加/取消注释:

  • 切换标签页:

  • 转到定义:

  • 文件夹导航窗格:

  • 在文件夹中查找关键词:

    • VSCode: ctrl+shift+f

  • 在当前文件中查找关键词:

    • VSCode: ctrl+f

  • 按文件名查找文件:

    • VSCode: ctrl+p

  • 底部终端:

  • 端口转发:

  • git修改显示:

  • git解决冲突时选择use theirs or user ours: VSCode: 高亮+鼠标选择

  • 代码缩进/取消缩进

  • markdown预览

  • 从剪切版复制内容粘贴至命令模式

Last updated