> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/di-41-zhang-kai-fa-gong-ju/di-41.2-jie-vim-kai-fa-huan-jing.md).

# 41.2 Vim 开发环境

Vim 是一款高度可配置的文本编辑器，旨在实现高效的文本编辑。它是 vi 编辑器的改进版本，包含在大多数 UNIX 系统中。

Vim 常被称为“程序员的编辑器”，在编程实践中实用性极强，因此许多开发者将其视为完整的 IDE。实际上，Vim 的用途不限于编程，而是适用于各类文本编辑工作，从撰写电子邮件到编辑配置文件均可胜任。

> **思考题**
>
> 从工具哲学视角审视，过度投入编辑器的美化和配置而忽视实际编程效率的提升，是一种值得反思的工具使用倾向。
>
> 工具的选择应区分探索性使用与生产性使用：前者源于技术好奇心，后者则服务于特定工程目标。专业主义不仅体现在正式场合，同样适用于业余爱好者的探索活动。
>
> 如何看待工具优化与实际生产力之间的平衡？

## 安装 Vim 及插件管理器

> **注意**
>
> 本节中 `clangd20`、`clang20`、`clang-format19` 等 LLVM 版本号为撰写时的 Ports 版本。请根据当前 FreeBSD Ports 中可用的最新 LLVM 版本调整，可通过 `pkg search llvm` 查询可用版本。

在开始配置之前，需要先安装 Vim 及其插件管理器。

### 安装 Vim

使用 pkg 安装：

```sh
# pkg install vim
```

或者使用 Ports 安装：

```sh
# cd /usr/ports/editors/vim/
# make install clean
```

### 安装 Vim 插件管理器

Vim 的功能可通过插件扩展，需先安装插件管理器以统一管理。本节采用 Vim 插件管理器 vim-plug。如使用其他插件管理器，请自行调整：

```sh
$ mkdir -p ~/.vim/autoload   # 创建 Vim 自动加载目录
$ fetch -o ~/.vim/autoload/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim   # 下载 vim-plug 插件管理器到指定目录
```

配置文件结构：

```sh
~/.vim/
├── autoload/
│   └── plug.vim    # vim-plug 插件管理器文件
├── plugged/        # 插件安装目录
├── coc-settings.json  # coc.nvim 配置文件
└── tasks.ini      # asynctasks.vim 全局任务配置
```

## coc.nvim 添加 clangd 补全

coc.nvim 是一款基于 Node.js 的代码补全插件，适用于 Vim 和 Neovim，支持完整的 LSP（Language Server Protocol，语言服务器协议）。LSP 是一种用于编辑器与语言服务之间通信的开放协议，它将代码分析、补全、跳转定义等功能从编辑器中分离出来，由独立的语言服务提供。其配置方式及插件系统的整体风格与 VS Code 相似。clangd 用于为 C/C++ 提供 LSP 支持。

安装 coc.nvim 的依赖时，请参照本书 Node.js 相关章节安装 npm，Node.js 会作为依赖自动安装。

在 **\~/.vimrc** 文件中写入：

```ini
call plug#begin('~/.vim/plugged')           " 初始化 vim-plug 并指定插件安装目录
Plug 'neoclide/coc.nvim', {'branch':'release'}  " 安装 coc.nvim 插件的 release 分支
call plug#end()                             " 结束插件安装块
```

进入 `vim`，输入以下命令，使用 vim-plug 安装配置的所有插件：

```sh
:PlugInstall
```

插件安装完成后，继续在 Vim 中安装 JSON、clangd、CMake 补全插件：

```sh
:CocInstall coc-json coc-clangd coc-cmake
```

配置 clangd 补全：

```sh
:CocConfig
```

打开配置文件后，输入以下内容并保存（也可以手动编辑 **\~/.vim/coc-settings.json** 文件写入以下内容）：

```json
{
	"clangd.path":"clangd20"
}
```

此时可通过 coc.nvim 使用代码补全功能。

***

对于简单的小程序，在源文件目录下新建 `compile_flags.txt` 文件，输入：

```sh
-I/usr/local/include
```

这样即可在 coc 中对 **/usr/local/include** 下的头文件补全（指定编译程序搜索头文件的路径为 **/usr/local/include**）。

对于复杂项目，应使用 `compile_commands.json` 文件来配置补全。clangd 会在文件所在目录的父目录及子目录 `build/` 中查找。例如，正在编辑 `$SRC/gui/window.cpp` 时，clangd 会依次查找 `$SRC/gui/`、`$SRC/gui/build/`、`$SRC/`、`$SRC/build/` 等目录。

以 CMake 项目为例，在项目文件夹下，项目结构如下：

![CMake 项目](/files/bC52t2VOyikeIpAuWDt5)

```sh
$ mkdir build                    # 创建构建目录 build
$ cd build                        # 进入构建目录
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..   # 生成构建系统，并导出编译命令到 compile_commands.json
```

或者在 `CMakeLists.txt` 中添加：

```cmake
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
```

这样即可自动生成 `compile_commands.json` 文件，生成该文件后，编辑源文件时即可使用补全功能。

CMake 默认使用系统自带的 Clang 编译程序，可以通过以下方式指定使用 clang20：

```sh
$ export CC=clang20       # 设置 C 编译程序为 clang20
$ export CXX=clang++20    # 设置 C++ 编译程序为 clang++20
```

再执行 `cmake` 以使用 clang20。

可以在 `.xprofile` 等文件中写入：

```ini
export CC=clang20       # 设置 C 编译程序为 clang20
export CXX=clang++20    # 设置 C++ 编译程序为 clang++20
```

这样可使 clang20 和 clang++20 成为默认编译程序，但具体是否设置应根据项目要求决定。

![Neovim](/files/QcLoqNMeJGaJqIce4dmo)

此时已生成 `compile_commands.json` 文件，可在 Vim 中进行补全。

![Neovim](/files/BM5YjeTbvBz8ibxCfqfx)

> **注意**
>
> 以下操作在 sh/bash/zsh 中使用，csh/tcsh 请做相应改动。请确保已正确配置 shell 环境。

## 代码格式化

代码格式化可统一代码风格，提升代码可读性。vim-clang-format 插件不兼容新版 clang-format 的命令行接口变更，且多年未更新，对新版 clang-format 支持存在问题（clang-format15 可正常运行，而 clang-format17 和 clang-format19 可能存在异常），因此推荐使用 vim-codefmt。

### vim-codefmt 代码格式化

vim-codefmt 是 Google 开发的代码格式化插件。在 **\~/.vimrc** 文件中加入：

```ini
Plug 'google/vim-maktaba'   " 安装 Google 的 vim-maktaba 插件
Plug 'google/vim-codefmt'   " 安装 Google 的 vim-codefmt 插件，用于代码格式化
Plug 'google/vim-glaive'    " 安装 Google 的 vim-glaive 插件
```

同时在 **\~/.vimrc** 文件中设置如下：

```sh
call glaive#Install()

Glaive codefmt clang_format_executable="/usr/local/bin/clang-format19"
Glaive codefmt clang_format_style="{BasedOnStyle: LLVM, IndentWidth: 4}"

augroup autoformat_settings
  autocmd FileType c,cpp AutoFormatBuffer clang-format
  autocmd InsertLeave *.h,*.hpp,*.c,*.cpp :FormatCode
augroup END
```

| 配置项                                                    | 说明                                                                                                                                                                                                       |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Glaive codefmt clang_format_executable`               | 设置 clang-format 执行文件路径                                                                                                                                                                                   |
| `Glaive codefmt clang_format_style`                    | 设置格式化风格，也可设为 `"file"` 或 `"file:<format_file_path>"`。参考 ClangFormatStyleOptions\[EB/OL]. \[2026-03-25]. <https://clang.llvm.org/docs/ClangFormatStyleOptions.html>. 该文档列举了 clang-format 所有可配置的格式化选项及其取值说明 |
| `autocmd FileType c,cpp AutoFormatBuffer clang-format` | 在文件类型为 c/cpp 时启用 AutoFormatBuffer clang-format                                                                                                                                                           |
| `autocmd InsertLeave *.h,*.hpp,*.c,*.cpp :FormatCode`  | 在文件后缀为 `.h`、`.hpp`、`.c`、`.cpp` 时，退出插入模式后执行 `:FormatCode` 命令                                                                                                                                              |

***

保存 **\~/.vimrc** 文件后，使用 vim-plug 安装配置的所有 Google 插件：

```sh
:PlugInstall
```

此时可以在退出插入模式后自动格式化代码，也可以在 Vim 中手动执行 `:FormatCode` 命令格式化。

### vim-clang-format 代码格式化

除了 vim-codefmt 外，vim-clang-format 也是一款代码格式化插件，可参照以下配置：

在 **\~/.vimrc** 文件中加入以下行，以安装 vim-clang-format 插件，用于自动格式化代码：

```sh
Plug 'rhysd/vim-clang-format'
```

并在 **\~/.vimrc** 文件中设置：

```ini
let g:clang_format#code_style = "google"                     " 设置 clang-format 使用 Google 风格
let g:clang_format#command = "clang-format15"                " 指定 clang-format 命令版本
let g:clang_format#auto_format = 1                            " 启用自动格式化功能
let g:clang_format#auto_format_on_insert_leave = 1           " 在离开插入模式时自动格式化代码
```

保存 **\~/.vimrc** 文件后，使用 vim-plug 安装 vim-clang-format 插件：

```sh
:PlugInstall
```

安装插件后即可使用，例如：

![Vim 插件](/files/0YHuluVvh8DG4WD72cxA)

退出插入模式

![vim 退出插入模式](/files/h4fCZXkkDMMOuY01FWPa)

## asynctasks.vim 构建任务系统

构建任务管理可简化编译、运行和测试等工作流程。插件 asynctasks.vim 为 Vim 引入类似 VSCode 的 tasks 任务系统，以统一方式系统化管理各类编译、运行、测试和部署任务。

安装插件：

```ini
Plug 'skywind3000/asynctasks.vim'   " 安装 asynctasks.vim 插件，用于异步任务管理
Plug 'skywind3000/asyncrun.vim'     " 安装 asyncrun.vim 插件，用于异步运行外部命令
```

在 **\~/.vimrc** 文件中设置：

```ini
let g:asyncrun_open = 6                                  " 设置 asyncrun 输出窗口行为（6 表示自动打开在底部）
let g:asyncrun_rootmarks = ['.git', '.svn', '.root', '.project']  " 指定项目根目录标识文件
```

其中 `asyncrun_rootmarks` 用于指定标记项目根目录的文件/文件夹。

`asynctasks.vim` 在每个项目根目录下放置 `.tasks` 文件以描述该项目的局部任务，同时维护一份 **\~/.vim/tasks.ini** 的全局任务配置，适用于通用性较强的项目，避免每个项目重复编写 `.tasks` 配置。

Vim 可使用 `:AsyncTaskEdit` 编辑本地任务，使用 `:AsyncTaskEdit!` 编辑全局任务。

例如：

```ini
[project-build]
command=cd build && cmake .. && make     # 在当前项目的根目录运行 make
cwd=$(VIM_ROOT)

[project-run]
command=src/test                         # <root> 是 $(VIM_ROOT) 的别名，更便于书写
cwd=<root>
```

参考文献：

* skywind3000. asynctasks.vim: 现代化的构建任务系统\[EB/OL]. \[2026-03-25]. <https://github.com/skywind3000/asynctasks.vim/blob/master/README-cn.md>. 该插件为 Vim 提供了类似 VSCode 的任务系统，统一管理编译、运行等工作流程。

## 以最简单的 C++ Hello World 项目为例

以下以最简单的 C++ 项目为例，展示整个开发环境的使用流程。项目文件结构如下：

```sh
/home/j/
└── project/
    ├── CMakeLists.txt  # 主项目 CMake 配置文件
    ├── src/
    │   ├── CMakeLists.txt  # 子项目 CMake 配置文件
    │   └── main.cpp       # 源文件
    └── build/              # 构建目录
```

* **/home/j/project/CMakeLists.txt** 文件

```cmake
cmake_minimum_required(VERSION 3.10)      # 指定 CMake 最低版本要求为 3.10
project(test)                              # 定义项目名称为 test

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)       # 启用生成 compile_commands.json 文件

include_directories(/usr/local/include)    # 添加头文件搜索路径 /usr/local/include
add_subdirectory(src)                       # 添加 src 子目录作为构建子目录
```

* **/home/j/project/src/CMakeLists.txt** 文件

```sh
add_executable(test main.cpp)   # 将 main.cpp 编译为可执行文件 test
```

* **/home/j/project/src/main.cpp** 文件

```cpp
#include <iostream>   // 引入标准输入输出库

int main() {
    std::cout << "Hello World" << std::endl;   // 输出“Hello World”并换行
    return 0;                                  // 返回 0 值表示程序正常结束
}
```

编译运行：

```sh
$ cd /home/j/project/build   # 进入构建目录
$ cmake ..                   # 运行 CMake 配置上级目录的项目
```

生成程序文件 **/home/j/project/build/src/test**，此后即可正常运行。

![生成程序文件](/files/IsznYDNzYLkFjxj0b2CZ)

或者在 Vim 中运行 `:AsyncTask project-build` 和 `:AsyncTask project-run`：

![在 Vim 中运行程序](/files/qXzy6e9fexFEmnuym1GK)

![在 Vim 中运行程序](/files/VPhea9P373MPD64sjzEw)

## 未竟事宜

### 后续工作方向

本节聚焦 Vim 作为开发环境的基础配置，以下方向值得进一步探索：

* **扩展功能范围**：当前配置主要涵盖代码补全和格式化，未来可纳入运行、调试、自动化构建、GUI 集成以及 AI 辅助编程等功能模块。

如果希望补充上述内容，可通过 Pull Request 方式提交。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/di-41-zhang-kai-fa-gong-ju/di-41.2-jie-vim-kai-fa-huan-jing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
