555 lines
16 KiB
Markdown
555 lines
16 KiB
Markdown
---
|
||
title: Vim 高级功能
|
||
description: 探索 Vim 的高级功能,如正则表达式、多行编辑、宏录制、VimScript 脚本语言及自动化工作流。
|
||
keywords:
|
||
- Vim
|
||
- 高级功能
|
||
- 正则表达式
|
||
- 宏录制
|
||
- VimScript
|
||
- 自动化
|
||
tags:
|
||
- 技术/入门
|
||
- Vim
|
||
author: 仲平
|
||
date: 2024-08-08
|
||
---
|
||
|
||
## 高级技巧
|
||
|
||
### 高级文本操作
|
||
|
||
#### 正则表达式
|
||
|
||
| 功能 | 命令或表达式 | 说明 |
|
||
| ---------- | --------------------------- | ------------ |
|
||
| 向前搜索 | `/pattern` | 向前搜索匹配的模式 |
|
||
| 向后搜索 | `?pattern` | 向后搜索匹配的模式 |
|
||
| 全文替换 | `:%s/pattern/replacement/g` | 全文替换所有匹配的模式 |
|
||
| 当前行替换 | `:s/pattern/replacement/g` | 替换当前行所有匹配的模式 |
|
||
| 删除行首空白 | `:%s/^\s\+//g` | 删除每行开头的空白字符 |
|
||
| 删除行尾空白 | `:%s/\s\+$//g` | 删除每行结尾的空白字符 |
|
||
| 匹配任意字符 | `.` | 匹配任意字符 |
|
||
| 匹配数字字符 | `\d` | 匹配数字字符 |
|
||
| 匹配非数字字符 | `\D` | 匹配非数字字符 |
|
||
| 匹配字母或数字字符 | `\w` | 匹配字母或数字字符 |
|
||
| 匹配非字母或数字字符 | `\W` | 匹配非字母或数字字符 |
|
||
| 匹配行首 | `^` | 匹配行首 |
|
||
| 匹配行尾 | `$` | 匹配行尾 |
|
||
|
||
#### 多行编辑
|
||
|
||
| 功能 | 命令 | 说明 |
|
||
| -------------- | ---------- | -------------------------------- |
|
||
| 行可视模式 | `V` | 进入行可视模式 |
|
||
| 字符可视模式 | `v` | 进入字符可视模式 |
|
||
| 块可视模式 | `Ctrl+v` | 进入块可视模式 |
|
||
| 在每行开头添加 | `:%s/^/#/` | 使用正则表达式在每行开头添加 `#` |
|
||
| 在每行结尾添加 | `:%s/$/;/` | 使用正则表达式在每行结尾添加 `;` |
|
||
|
||
#### 宏录制与播放
|
||
|
||
| 功能 | 命令 | 说明 |
|
||
| ---------- | ---------- | ---------------------------------------------------- |
|
||
| 录制宏 | `qx ... q` | 开始录制宏,`x` 是寄存器名,执行一系列命令后停止录制 |
|
||
| 播放宏 | `@x` | 播放寄存器 `x` 中的宏 |
|
||
| 重复播放宏 | `@@` | 重复播放上一个宏 |
|
||
| 多次播放宏 | `10@x` | 播放寄存器 `x` 中的宏 10 次 |
|
||
|
||
### VimScript
|
||
|
||
#### 基本语法
|
||
|
||
VimScript 是 Vim 的脚本语言,用于扩展和定制 Vim 的功能。以下是一些基本语法:
|
||
|
||
```vim
|
||
" 这是一个注释
|
||
|
||
" 变量
|
||
let myvar = 42 " 整数变量
|
||
let mystr = "Hello" " 字符串变量
|
||
|
||
" 条件语句
|
||
if myvar > 0
|
||
echo "Positive"
|
||
elseif myvar == 0
|
||
echo "Zero"
|
||
else
|
||
echo "Negative"
|
||
endif
|
||
|
||
" 循环语句
|
||
let i = 0
|
||
while i < 5
|
||
echo i
|
||
let i += 1
|
||
endwhile
|
||
|
||
for item in [1, 2, 3, 4, 5]
|
||
echo item
|
||
endfor
|
||
```
|
||
|
||
#### 函数和变量
|
||
|
||
```vim
|
||
" 定义函数
|
||
function! MyFunction(arg)
|
||
echo a:arg
|
||
endfunction
|
||
|
||
" 调用函数
|
||
call MyFunction("Hello")
|
||
|
||
" 局部变量
|
||
function! MyFunction()
|
||
let l:localVar = "I am local"
|
||
echo l:localVar
|
||
endfunction
|
||
|
||
" 全局变量
|
||
let g:globalVar = "I am global"
|
||
echo g:globalVar
|
||
```
|
||
|
||
#### 编写和调试简单的 VimScript 脚本
|
||
|
||
**编写脚本**:
|
||
|
||
将 VimScript 代码写入 `.vim` 文件,例如 `myplugin.vim`:
|
||
|
||
```
|
||
" myplugin.vim
|
||
function! SayHello()
|
||
echo "Hello, Vim!"
|
||
endfunction
|
||
command! SayHello call SayHello()
|
||
```
|
||
|
||
**加载脚本**:
|
||
|
||
将脚本放入 Vim 的 `plugin` 目录,启动 Vim 自动加载:
|
||
|
||
```
|
||
mkdir -p ~/.vim/plugin
|
||
cp myplugin.vim ~/.vim/plugin/
|
||
```
|
||
|
||
**调试脚本**:
|
||
|
||
使用 `echo` 命令输出调试信息:
|
||
|
||
```
|
||
echo "Debug info: " . someVar
|
||
```
|
||
|
||
使用 `:messages` 查看所有输出信息。
|
||
|
||
### 自动化
|
||
|
||
#### 使用自动命令
|
||
|
||
自动命令(autocommand)允许在特定事件发生时自动执行命令,例如文件保存、打开等。
|
||
|
||
```
|
||
augroup MyAutoCmd
|
||
autocmd!
|
||
autocmd BufWritePost *.txt :echo "Text file saved!"
|
||
augroup END
|
||
```
|
||
|
||
| 事件 | 说明 | 权重 |
|
||
| -------------- | ------------ | ---- |
|
||
| `BufReadPost` | 文件读取后 | 5 |
|
||
| `BufWritePost` | 文件写入后 | 5 |
|
||
| `BufNewFile` | 新建文件 | 4 |
|
||
| `FileType` | 文件类型检测 | 5 |
|
||
| `BufEnter` | 缓冲区进入 | 4 |
|
||
| `BufLeave` | 缓冲区离开 | 4 |
|
||
| `VimEnter` | Vim 启动后 | 5 |
|
||
| `VimLeave` | Vim 退出前 | 5 |
|
||
| `WinEnter` | 窗口进入 | 3 |
|
||
| `WinLeave` | 窗口离开 | 3 |
|
||
|
||
#### 配置文件模板
|
||
|
||
在 `~/.vim/templates/` 目录中创建模板文件,例如 `python_template.py`:
|
||
|
||
```python
|
||
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Created on <++>
|
||
|
||
@author: <++>
|
||
"""
|
||
|
||
def main():
|
||
pass
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
```
|
||
|
||
**使用自动命令应用模板:**
|
||
|
||
```
|
||
augroup MyTemplates
|
||
autocmd!
|
||
autocmd BufNewFile *.py 0r ~/.vim/templates/python_template.py
|
||
augroup END
|
||
```
|
||
|
||
## 高效工作流
|
||
|
||
### 版本控制集成
|
||
|
||
#### 使用 Vim-fugitive
|
||
|
||
**安装 vim-fugitive**:
|
||
|
||
在 `vimrc` 文件中添加以下内容(以 vim-plug 为例):
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'tpope/vim-fugitive'
|
||
call plug#end()
|
||
```
|
||
|
||
**基本用法**:
|
||
|
||
| 功能 | 命令 | 说明 |
|
||
| ------------- | ---------- | ------------------------------------------------------------ |
|
||
| 查看 Git 状态 | `:Gstatus` | 打开一个新窗口显示当前 Git 仓库的状态。可以在该窗口中导航和操作。 |
|
||
| Git 添加 | `-` | 在 `:Gstatus` 窗口中,将光标移动到文件名上,按 `-` 号将文件添加到索引。 |
|
||
| Git 提交 | `:Gcommit` | 打开一个新的缓冲区输入提交信息,完成后保存并关闭缓冲区即可提交。 |
|
||
| Git 推送 | `:Gpush` | 将本地提交推送到远程仓库。 |
|
||
| Git 拉取 | `:Gpull` | 从远程仓库拉取最新的代码。 |
|
||
| Git 日志 | `:Glog` | 显示 Git 提交日志,可以在日志中导航和查看每个提交的详细信息。 |
|
||
| Git 分支 | `:Gbranch` | 显示和管理 Git 分支。 |
|
||
|
||
#### 常用 Git 命令
|
||
|
||
在 Vim 中,使用 vim-fugitive 可以执行常见的 Git 命令。同时你也可以在 Vim 外部使用 Git 命令行工具:
|
||
|
||
| 功能 | 命令 | 说明 |
|
||
| -------------- | -------------------------------- | -------------------------------- |
|
||
| 克隆仓库 | `git clone <repository_url>` | 克隆一个远程仓库到本地。 |
|
||
| 查看状态 | `git status` | 查看当前仓库的状态。 |
|
||
| 添加文件 | `git add <file>` | 添加文件到索引。 |
|
||
| 提交更改 | `git commit -m "Commit message"` | 提交已添加的更改。 |
|
||
| 推送到远程仓库 | `git push` | 将本地提交推送到远程仓库。 |
|
||
| 拉取最新代码 | `git pull` | 从远程仓库拉取最新的代码。 |
|
||
| 创建新分支 | `git checkout -b <new_branch>` | 创建一个新的分支并切换到该分支。 |
|
||
| 合并分支 | `git merge <branch>` | 将指定分支合并到当前分支。 |
|
||
|
||
### 项目管理
|
||
|
||
#### NERDTree
|
||
|
||
在 `vimrc` 文件中添加以下内容(以 vim-plug 为例):
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'preservim/nerdtree'
|
||
call plug#end()
|
||
```
|
||
|
||
**打开/关闭 NERDTree**
|
||
|
||
```
|
||
:NERDTreeToggle
|
||
```
|
||
|
||
或者添加快捷键映射:
|
||
|
||
```
|
||
nnoremap <C-n> :NERDTreeToggle<CR>
|
||
```
|
||
|
||
**在 NERDTree 中导航**
|
||
|
||
- 使用 `j` 和 `k` 键上下移动
|
||
- 使用 `o` 键打开文件或目录
|
||
- 使用 `x` 键关闭目录
|
||
|
||
**显示隐藏文件**
|
||
|
||
```
|
||
:NERDTreeShowHidden
|
||
```
|
||
|
||
#### 配置项目相关设置
|
||
|
||
**项目特定的 vimrc**
|
||
|
||
在项目根目录下创建一个 `.vimrc` 文件,包含项目特定的 Vim 配置。然后在主 `vimrc` 中添加以下内容:
|
||
|
||
```
|
||
if filereadable("path/to/project/.vimrc")
|
||
source path/to/project/.vimrc
|
||
endif
|
||
```
|
||
|
||
**自动切换项目配置**
|
||
|
||
可以使用 `vim-rooter` 插件自动切换项目根目录并加载项目特定的配置。在 `vimrc` 中添加以下内容:
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'airblade/vim-rooter'
|
||
call plug#end()
|
||
let g:rooter_patterns = ['.git', '.hg', '.svn', 'Makefile']
|
||
```
|
||
|
||
### 代码补全与调试
|
||
|
||
#### YouCompleteMe 代码补全
|
||
|
||
YouCompleteMe 是一个强大的代码补全插件,需要编译安装。具体步骤如下:
|
||
|
||
1. 安装依赖(以 Ubuntu 为例):
|
||
|
||
```
|
||
sudo apt install build-essential cmake python3-dev
|
||
```
|
||
|
||
2. 安装 YouCompleteMe:
|
||
|
||
```
|
||
git clone https://github.com/ycm-core/YouCompleteMe.git ~/.vim/bundle/YouCompleteMe
|
||
cd ~/.vim/bundle/YouCompleteMe
|
||
git submodule update --init --recursive
|
||
python3 install.py --all
|
||
```
|
||
|
||
3. 在 `vimrc` 中添加以下内容:
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'ycm-core/YouCompleteMe'
|
||
call plug#end()
|
||
```
|
||
|
||
#### Deoplete 代码补全
|
||
|
||
[Deoplete](https://github.com/Shougo/deoplete.nvim) 是另一种流行的代码补全插件,基于 Neovim。
|
||
|
||
1. 安装依赖(以 Neovim 为例):
|
||
|
||
```
|
||
pip install neovim
|
||
```
|
||
|
||
2. 在 `vimrc` 中添加以下内容:
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'Shougo/deoplete.nvim', {'do': ':UpdateRemotePlugins'}
|
||
Plug 'Shougo/neosnippet.vim'
|
||
Plug 'Shougo/neosnippet-snippets'
|
||
call plug#end()
|
||
|
||
let g:deoplete#enable_at_startup = 1
|
||
```
|
||
|
||
#### Vimspector 代码调试
|
||
|
||
在 `vimrc` 文件中添加以下内容(以 vim-plug 为例):
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'puremourning/vimspector'
|
||
call plug#end()
|
||
```
|
||
|
||
**基本配置**:
|
||
|
||
`.vimspector.json` 文件,定义调试配置,例如:
|
||
|
||
```json
|
||
{
|
||
"configurations": {
|
||
"Launch": {
|
||
"adapter": "debugpy",
|
||
"configuration": {
|
||
"request": "launch",
|
||
"program": "${workspaceFolder}/your_script.py",
|
||
"console": "integratedTerminal"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**使用**:
|
||
|
||
1. 启动调试会话:
|
||
|
||
```
|
||
:VimspectorLaunch
|
||
```
|
||
|
||
2. 设置断点: 将光标移动到需要设置断点的行,按 `F9` 键。
|
||
|
||
3. 继续执行、单步执行和停止调试: 使用 `F5`、`F10`、`F11` 和 `F12` 键进行调试控制。
|
||
|
||
## 性能优化
|
||
|
||
### 启动优化
|
||
|
||
#### 延迟加载插件
|
||
|
||
延迟加载插件可以显著提高 Vim 的启动速度,只在需要时加载插件。
|
||
|
||
**使用 vim-plug 进行延迟加载**:
|
||
|
||
1. 在 `vimrc` 中配置延迟加载:
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'tpope/vim-fugitive', { 'on': 'Gstatus' }
|
||
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
|
||
call plug#end()
|
||
```
|
||
|
||
以上配置将 vim-fugitive 插件仅在执行 `:Gstatus` 命令时加载,NERDTree 插件仅在执行 `:NERDTreeToggle` 命令时加载。
|
||
|
||
**使用 lazy.nvim 插件管理器**:
|
||
|
||
lazy.nvim 是一个专门用于延迟加载插件的插件管理器。
|
||
|
||
1. 安装 lazy.nvim:
|
||
|
||
```
|
||
git clone https://github.com/folke/lazy.nvim.git ~/.vim/pack/lazy/start/lazy.nvim
|
||
```
|
||
|
||
2. 配置延迟加载:
|
||
|
||
```
|
||
call lazy#load_plugin('nerdtree', { 'on': 'NERDTreeToggle' })
|
||
```
|
||
|
||
#### 精简配置文件
|
||
|
||
**移除不必要的配置**:
|
||
|
||
定期检查 `vimrc` 文件,移除不再使用的配置和插件,以减少 Vim 的启动时间和运行负担。
|
||
|
||
**分离插件配置**:
|
||
|
||
将插件的配置分离到独立的文件中,以保持 `vimrc` 简洁。例如,将 NERDTree 的配置放在 `~/.vim/plugin/nerdtree.vim` 中:
|
||
|
||
```
|
||
" ~/.vim/plugin/nerdtree.vim
|
||
nnoremap <C-n> :NERDTreeToggle<CR>
|
||
```
|
||
|
||
**使用本地配置**:
|
||
|
||
根据项目需求,在项目根目录下创建 `.vimrc` 或 `.vim/` 目录,存放项目特定的配置文件,以避免在全局配置中添加过多内容。
|
||
|
||
### 系统集成
|
||
|
||
#### 将 Vim 与 Tmux 结合使用
|
||
|
||
tmux 是一个终端复用器,允许你在一个终端窗口中运行多个会话,与 Vim 结合使用可以大大提高工作效率。
|
||
|
||
**安装 tmux**:
|
||
|
||
在 Linux 或 MacOS 中,可以使用包管理器安装 tmux:
|
||
|
||
```shell
|
||
sudo apt install tmux # Debian/Ubuntu
|
||
brew install tmux # macOS
|
||
```
|
||
|
||
| 功能 | 命令 | 说明 |
|
||
| -------------- | ----------------------------------- | ------------------------------------ |
|
||
| 启动 tmux 会话 | `tmux` | 启动一个新的 tmux 会话 |
|
||
| 新建会话 | `tmux new -s session_name` | 创建一个名为 `session_name` 的新会话 |
|
||
| 附加会话 | `tmux attach -t session_name` | 附加到一个名为 `session_name` 的会话 |
|
||
| 列出会话 | `tmux ls` | 列出所有 tmux 会话 |
|
||
| 杀死会话 | `tmux kill-session -t session_name` | 杀死一个名为 `session_name` 的会话 |
|
||
| 分离会话 | `Ctrl-b d` | 分离当前会话 |
|
||
| 新建窗口 | `Ctrl-b c` | 创建一个新窗口 |
|
||
| 切换窗口 | `Ctrl-b n` | 切换到下一个窗口 |
|
||
| 切换窗口 | `Ctrl-b p` | 切换到上一个窗口 |
|
||
| 重命名窗口 | `Ctrl-b ,` | 重命名当前窗口 |
|
||
| 分割窗格 | `Ctrl-b %` | 垂直分割当前窗格 |
|
||
| 分割窗格 | `Ctrl-b "` | 水平分割当前窗格 |
|
||
| 切换窗格 | `Ctrl-b o` | 切换到下一个窗格 |
|
||
| 关闭窗格 | `Ctrl-b x` | 关闭当前窗格 |
|
||
| 同步窗格 | `Ctrl-b :setw synchronize-panes on` | 在所有窗格中同步输入 |
|
||
| 切换会话 | `Ctrl-b s` | 列出所有会话并切换 |
|
||
|
||
**与 Vim 集成**:
|
||
|
||
在 `vimrc` 中添加快捷键映射,方便与 tmux 交互:
|
||
|
||
```
|
||
nnoremap <silent> <Leader>h :TmuxNavigateLeft<CR>
|
||
nnoremap <silent> <Leader>j :TmuxNavigateDown<CR>
|
||
nnoremap <silent> <Leader>k :TmuxNavigateUp<CR>
|
||
nnoremap <silent> <Leader>l :TmuxNavigateRight<CR>
|
||
```
|
||
|
||
需要安装 `christoomey/vim-tmux-navigator` 插件:
|
||
|
||
```
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'christoomey/vim-tmux-navigator'
|
||
call plug#end()
|
||
```
|
||
|
||
#### 在终端中使用 Vim
|
||
|
||
在终端中使用 Vim 可以提高工作效率,特别是当你需要频繁切换编辑器和命令行时。
|
||
|
||
**配置终端**:
|
||
|
||
选择一个支持丰富功能的终端,例如 `iTerm2`(macOS)、`Alacritty`(跨平台)、`GNOME Terminal`(Linux)。
|
||
|
||
**终端快捷键配置**:
|
||
|
||
根据需要配置终端快捷键,方便打开 Vim。例如,在 `iTerm2` 中,可以设置快捷键快速打开新的终端窗口或标签,并启动 Vim。
|
||
|
||
**Shell 集成**:
|
||
|
||
在 `~/.bashrc` 或 `~/.zshrc` 中添加别名和函数,提高使用 Vim 的效率:
|
||
|
||
```shell
|
||
alias vi="vim"
|
||
alias svi="sudo vim"
|
||
alias vrc="vim ~/.vimrc"
|
||
|
||
# 快速打开项目目录中的 Vim
|
||
function vproj() {
|
||
cd ~/projects/$1 && vim
|
||
}
|
||
```
|
||
|
||
**使用 FZF 进行文件搜索**:
|
||
|
||
FZF 是一个命令行模糊查找工具,可以与 Vim 集成,快速搜索和打开文件。
|
||
|
||
1. 安装 FZF:
|
||
|
||
```shell
|
||
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
|
||
~/.fzf/install
|
||
```
|
||
|
||
2. 在 `vimrc` 中配置 FZF:
|
||
|
||
```shell
|
||
call plug#begin('~/.vim/plugged')
|
||
Plug 'junegunn/fzf'
|
||
Plug 'junegunn/fzf.vim'
|
||
call plug#end()
|
||
|
||
" 使用 FZF 查找文件
|
||
nnoremap <Leader>f :Files<CR>
|
||
```
|