1
0
wiki/Technology/GettingStarted/命令行工具/Vim/3.Vim 高级功能.md
2024-08-30 12:29:55 +08:00

555 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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>
```