vim+cpp/c(0.01)
我的是OS:Fedora Linux 43 (KDE Plasma Desktop Edition) x86_64,Kernel: Linux 6.18.5-200.fc43.x86_64, 使用vim+clang+lldb作为构建、运行、和调试cpp、c的工具。
下载工具
sudo dnf update
sudo dnf install vim-enhanced #我的系统下vim是这个名字
sudo dnf clang clangd lldb ld.lld make #有时候linux没有提供C++标准库libcxx,此时需要下载
检查
echo "======= 开发工具版本检查 =======" && \
echo "=== Clang 编译器 ===" && clang++ --version && \
echo -e "\n=== LLDB 调试器 ===" && lldb --version && \
echo -e "\n=== LLD 链接器 ===" && ld.lld --version && \
echo -e "\n=== Make 构建工具 ===" && make --version

为了使得vim写起来更舒服点, 我们会在$HOME(即~) 目录下新建(如果没有的话)一个vim的配置文件.vimrc, 下面是我的基本配置
.vimrc
let mapleader = " "
syntax on
set tabstop=4
set shiftwidth=4
set softtabstop=4
set nopaste
set smartindent
set autoindent
set number
set relativenumber
set cursorline
set showcmd
set wildmenu
set hlsearch
set incsearch
set ignorecase
set smartcase
nnoremap <silent> <Space><CR> :nohlsearch<CR>
noremap n nzz
noremap N Nzz
nnoremap sk :set nosplitbelow<CR>:split<CR>
nnoremap sj :set splitbelow<CR>:split<CR>
nnoremap sh :set nosplitright<CR>:vsplit<CR>
nnoremap sl :set splitright<CR>:vsplit<CR>
nnoremap tk :set nosplitbelow<CR>:terminal<CR>
nnoremap tj :set splitbelow<CR>:terminal<CR>
nnoremap th :set nosplitright<CR>:vertical terminal<CR>
nnoremap tl :set splitright<CR>:vertical terminal<CR>
map <LEADER>k <C-w>k
map <LEADER>j <C-w>j
map <LEADER>h <C-w>h
map <LEADER>l <C-w>l
set laststatus=2
set statusline=%n:\ %<%F%m%r\ %{strftime(\"%H:%M\ %a\ %b\%d\ %Y\")}\ %=\ %l/%L:%c\ %p%%
filetype on
filetype plugin on
filetype indent on
filetype plugin indent on
注解:
创建窗口:
按 sj → 在下方创建新窗口
按 sl → 在右侧创建新窗口创建终端:
按 tj → 在下方打开终端
按 tl → 在右侧打开垂直终端切换窗口:
按j → 切换到下方窗口
按l → 切换到右侧窗口
现在我们可以使用vim写cpp(c)代码了,我们首先创建一个main.cpp的文件
$ vim main.cpp
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
然后vim里面使用:wq来保存退出这段代码。
执行下列命令就可以用clang编译运行
$ clang main.cpp -o main
$ ./main
便会输出
Hello, world!
使用lldb调试也容易
$ clang -g -std=c++23 main.cpp -o main
$ lldb ./main
$ b main
$ run
....
上面我们是先在命令行界面进入vim里面,然后写完代码后返回到命令行界面,编译我们刚刚写好的程序并且运行。 但是如果遇到错误,我们得再次进入vim 然后回到命令行界面,如此往复。这仅仅是单个文件, 如果是多个文件呢?我们需要在多个文件中来回穿梭,而依然是那些重复的命令, 非常麻烦。
我们会想, 能不能不退出vim就可以完成这些操作呢?所幸以vim辅佐为编译器, 它支持扩展————vim插件, 而许多热心的开发者贡献了很多实用的vim插件, 这使得编写代码变得更容易。 林佬写的[异步插件asyncrun.vim]就解决了这个问题。但是在说下载异步插件前,我们先介绍一下vim-plug管理器。 以后我们会接触更多的vim插件,而插件多了, 那个需要更新,那个不需要了要卸载, 那个需要下载, 这就需要管理, 这就是vim-plug拿手的事情。
安装vim-plug插件管理器
安装:
下载 plug.vim 会将其放入 “autoload” 目录。
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
此时我们会在~/.vim/autoload/看到plug.vim,这就表示下载成功了,如果没有可以自己新建这些目录, 再尝试下载。

用法
在您的 ~/.vimrc(或 Neovim 的 ~/.config/nvim/init.vim)中添加一个 vim-plug 部分
- 以 call plug#begin() 开头
- 使用 Plug 命令列出插件
- 以 call plug#end() 结束该部分
例如:
call plug#begin('~/.vim/plugged')
" List your plugins here
Plug 'skywind3000/asyncrun.vim'
call plug#end()
注意:
asyncrun.vim的下载路径是https://github.com/skywind3000/asyncrun.vim.git, vim-plug插件可省略前缀‘https://github.com/’和后缀'.git', 简写为skywind3000/asyncrun.vim
重新加载文件或重启Vim后,即可执行:
:PlugInstall 安装插件
:PlugUpdate 安装或更新插件
:PlugDiff 查看上次更新后的变更
:PlugClean 移除列表中已不存在的插件
安装异步运行插件asyncrun.vim和异步任务插件asynctasks.vim
我们想要在不离开vim,在知名就可以编辑,编译,测试,这需要这个asyncrun.vim异步运行插件。
基于异步运行插件,要更方便的调度building, testing 和 deploying 的任务,我们得使用 AsyncRun 的助手——asynctasks.vim异步任务
安装:
使用 vim-plug 进行安装:
Plug 'skywind3000/asynctasks.vim'
Plug 'skywind3000/asyncrun.vim'
重新加载文件或重启Vim后,即可执行:
:PlugInstall 安装插件

使用:
提示:
在安装asynctasks.vim和asyncrun.vim后,在.vimrc里面添加
let g:asyncrun_open = 6
告诉 asyncrun 运行时自动打开高度为 6 的 quickfix 窗口,不然你看不到任何输出,除非你自己手动用 :copen 打开它。
如果输出内容比较多可以使用:clist展开quickfix 窗口内容。
然后在我们给它设置快捷键:
- 按下f6进行多文件调试
- 按下f7进行多文件构建
- 按下f8进行多文件运行
- 按下f9进行单文件调试
- 按下f10进行单文件调试
在.vimrc里面追加如下命令
.vimrc
noremap <silent><f6> :AsyncTask project-debug<cr>
noremap <silent><f7> :AsyncTask project-build<cr>
noremap <silent><f8> :AsyncTask project-run<cr>
noremap <silent><f9> :AsyncTask file-build<cr>
noremap <silent><f10> :AsyncTask file-run<cr>
在~/.vim/下创建tasks.ini文件
.tasks.ini
[project-debug]
command:cpp=clang++ -std=c++23 -g -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fuse-ld=lld *.cpp -o a.out -lm -msse3 && lldb a.out
command:c=clang -std=c17 -g -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fuse-ld=lld *.c -o a.out -lm && lldb a.out
output=terminal
cwd=$(VIM_FILEDIR)
save=2
[project-build]
command:cpp=clang++ -std=c++23 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion *.cpp -o a.out -lm -msse3
command:c=clang -std=c17 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion *.c -o a.out -lm
command:make=make -f "$(VIM_FILEPATH)"
errorformat=%f:%l:%c: %m
output=quickfix
cwd=$(VIM_FILEDIR)
save=2
[project-run]
command=./a.out
output=quickfix
cwd=$(VIM_FILEDIR)
save=2
[file-build]
command:cpp=clang++ -std=c++23 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fsanitize=address "$(VIM_FILEPATH)" -o "$(VIM_PATHNOEXT)" -lm -msse3
command:c=clang -std=c17 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion "$(VIM_FILEPATH)" -o "$(VIM_PATHNOEXT)" -lm
command:make=make -f "$(VIM_FILEPATH)"
output=quickfix
errorformat=
cwd=$(VIM_FILEDIR)
save=2
[file-run]
command="$(VIM_FILEPATH)"
command:c,cpp="$(VIM_PATHNOEXT)"
output=quickfix
errorformat=
cwd=$(VIM_FILEDIR)
save=2
现在我们可以在vim里面直接构建运行了, 比如使用vim打开在~/cpp/main.cpp写的代码
可以使用f9去构建main.cpp源码, f10运行由main.cpp生成的main执行文件。

目录树,翻译和代码补全插件
安装:
使用 vim-plug 进行安装:
"Plug 'preservim/nerdtree'
"Plug 'voldikss/vim-translator'
"Plug 'neoclide/coc.nvim', {'branch': 'release'}
重新加载文件或重启Vim后,即可执行:
:PlugInstall 安装插件
使用
安装完后设置~/.vimrc
" NERDTree
noremap ff :NERDTreeToggle<CR>
" vim-translator
nnoremap <silent> <Leader>t viw:Translate<CR>
" coc full code
inoremap <expr> <cr> coc#pum#visible() ? coc#pum#confirm() : "\<CR>"
inoremap <expr> <space> coc#pum#visible() ? coc#pum#cancel() : "\<space>"
对于目录树的使用我比较简单,按下ff后在左侧打开目录树, 然后移动(jk)到文件, 按下默认的o展开目录或者打开文件。

对于翻译:移动到不认识的词内,按下space+t就会对词翻译。

对于补全代码:coc.nvim 是一个基于 Language Server Protocol (LSP) 的智能代码补全和代码分析插件。需要下载coc-clangd,
使用 Coc 命令(推荐)
:CocInstall coc-clangd 下载扩展
:CocList extensions 查看已安装的扩展
:CocUninstall coc-clangd 卸载扩展
按下enter进行补全,按下space取消, 但取消有个缺点,如果会缩减你打的词,可以搭配ESC使用。

其他插件
Plug 'junegunn/seoul256.vim'
Plug 'junegunn/vim-easy-align'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'vim-scripts/cpp_doxygen'
Plug 'preservim/nerdcommenter'
Plug 'tpope/vim-surround'
总括
~/
├── .vimrc # Vim 主配置文件
├── .vim/ # Vim 配置目录
│ ├── tasks.ini # AsyncTask 任务定义
│ └── autoload/ # Vim管理器的路径
│ └── plug.vim # vim-plug插件
│ └── plugged/ # Vim管理器下载插件的路径
│ ├── asyncrun.vim # 异步运行插件
│ └── asynctasks.vim # 异步任务插件
│ └── coc.nvim # 代码补全
│ ├── #下面fzf和fzf.vim是一起的, 它的作用是:超快的通用命令行模糊查找器
│ ├── fzf # fzf 是引擎,是核心命令行工具
│ └── fzf.vim # 是给 Vim 这个“汽车”装上的专用方向盘、中控台和仪表盘,让你能在 Vim 里方便地使用这个引擎。
│ ├── nerdtree # 目录树
│ ├── seoul256.vim # vim颜色
│ ├── ... # 其他插件
│ └── vim-easy-align # 对齐
├── cpp/ # C++ 项目主目录
│ ├── xxx.h # 分数类头文件
│ ├── xxx.cpp # 分数类实现
│ └── main.cpp # 主程序文件
└── end
tasks.ini
[project-debug]
command:cpp=clang++ -std=c++23 -g -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fuse-ld=lld *.cpp -o a.out -lm -msse3 && lldb a.out
command:c=clang -std=c17 -g -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fuse-ld=lld *.c -o a.out -lm && lldb a.out
output=terminal
cwd=$(VIM_FILEDIR)
save=2
[project-build]
command:cpp=clang++ -std=c++23 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion *.cpp -o a.out -lm -msse3
command:c=clang -std=c17 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion *.c -o a.out -lm
command:make=make -f "$(VIM_FILEPATH)"
errorformat=%f:%l:%c: %m
output=quickfix
cwd=$(VIM_FILEDIR)
save=2
[project-run]
command=./a.out
output=quickfix
cwd=$(VIM_FILEDIR)
save=2
[file-build]
command:cpp=clang++ -std=c++23 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion -fsanitize=address "$(VIM_FILEPATH)" -o "$(VIM_PATHNOEXT)" -lm -msse3
command:c=clang -std=c17 -O2 -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion "$(VIM_FILEPATH)" -o "$(VIM_PATHNOEXT)" -lm
command:make=make -f "$(VIM_FILEPATH)"
output=quickfix
errorformat=
cwd=$(VIM_FILEDIR)
save=2
[file-run]
command="$(VIM_FILEPATH)"
command:c,cpp="$(VIM_PATHNOEXT)"
output=quickfix
errorformat=
cwd=$(VIM_FILEDIR)
save=2
.vimrc
let mapleader = " "
syntax on
set tabstop=4
set shiftwidth=4
set softtabstop=4
set nopaste
set smartindent
set autoindent
set number
set relativenumber
set cursorline
set showcmd
set wildmenu
set hlsearch
set incsearch
set ignorecase
set smartcase
nnoremap <silent> <Space><CR> :nohlsearch<CR>
noremap n nzz
noremap N Nzz
nnoremap sk :set nosplitbelow<CR>:split<CR>
nnoremap sj :set splitbelow<CR>:split<CR>
nnoremap sh :set nosplitright<CR>:vsplit<CR>
nnoremap sl :set splitright<CR>:vsplit<CR>
nnoremap tk :set nosplitbelow<CR>:terminal<CR>
nnoremap tj :set splitbelow<CR>:terminal<CR>
nnoremap th :set nosplitright<CR>:vertical terminal<CR>
nnoremap tl :set splitright<CR>:vertical terminal<CR>
map <LEADER>k <C-w>k
map <LEADER>j <C-w>j
map <LEADER>h <C-w>h
map <LEADER>l <C-w>l
set laststatus=2
set statusline=%n:\ %<%F%m%r\ %{strftime(\"%H:%M\ %a\ %b\%d\ %Y\")}\ %=\ %l/%L:%c\ %p%%
filetype on
filetype plugin on
filetype indent on
filetype plugin indent on
noremap <silent><f6> :AsyncTask project-debug<cr>
noremap <silent><f7> :AsyncTask project-build<cr>
noremap <silent><f8> :AsyncTask project-run<cr>
noremap <silent><f9> :AsyncTask file-build<cr>
noremap <silent><f10> :AsyncTask file-run<cr>
" vim-plug
call plug#begin('~/.vim/plugged')
Plug 'skywind3000/asynctasks.vim'
Plug 'skywind3000/asyncrun.vim'
Plug 'junegunn/seoul256.vim'
Plug 'junegunn/vim-easy-align'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'preservim/nerdtree'
Plug 'vim-scripts/cpp_doxygen'
Plug 'preservim/nerdcommenter'
Plug 'tpope/vim-surround'
Plug 'voldikss/vim-translator'
call plug#end()
" NERDTree
noremap ff :NERDTreeToggle<CR>
" vim-translator
nnoremap <silent> <Leader>t viw:Translate<CR>
" coc full code
" https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.vim
" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count
" utf-8 byte sequence
set encoding=utf-8
" Some servers have issues with backup files, see #649
set nobackup
set nowritebackup
" Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
" delays and poor user experience
set updatetime=300
" Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved
set signcolumn=yes
" Use tab for trigger completion with characters ahead and navigate
" NOTE: There's always complete item selected by default, you may want to enable
" no select by `"suggest.noselect": true` in your configuration file
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config
inoremap <silent><expr> <TAB>
\ coc#pum#visible() ? coc#pum#next(1) :
\ CheckBackspace() ? "\<Tab>" :
\ coc#refresh()
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
" Make <CR> to accept selected completion item or notify coc.nvim to format
" <C-g>u breaks current undo, please make your own choice
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
function! CheckBackspace() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
nmap <silent><nowait> [g <Plug>(coc-diagnostic-prev)
nmap <silent><nowait> ]g <Plug>(coc-diagnostic-next)
" GoTo code navigation
nmap <silent><nowait> gd <Plug>(coc-definition)
nmap <silent><nowait> gy <Plug>(coc-type-definition)
nmap <silent><nowait> gi <Plug>(coc-implementation)
nmap <silent><nowait> gr <Plug>(coc-references)
" Use K to show documentation in preview window
nnoremap <silent> K :call ShowDocumentation()<CR>
function! ShowDocumentation()
if CocAction('hasProvider', 'hover')
call CocActionAsync('doHover')
else
call feedkeys('K', 'in')
endif
endfunction
" Highlight the symbol and its references when holding the cursor
autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming
nmap <leader>rn <Plug>(coc-rename)
" Formatting selected code
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s)
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
augroup end
" Applying code actions to the selected code block
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying code actions at the cursor position
nmap <leader>ac <Plug>(coc-codeaction-cursor)
" Remap keys for apply code actions affect whole buffer
nmap <leader>as <Plug>(coc-codeaction-source)
" Apply the most preferred quickfix action to fix diagnostic on the current line
nmap <leader>qf <Plug>(coc-fix-current)
" Remap keys for applying refactor code actions
nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
" Run the Code Lens action on the current line
nmap <leader>cl <Plug>(coc-codelens-action)
" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Use CTRL-S for selections ranges
" Requires 'textDocument/selectionRange' support of language server
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)
" Add `:Format` command to format current buffer
command! -nargs=0 Format :call CocActionAsync('format')
" Add `:Fold` command to fold current buffer
command! -nargs=? Fold :call CocAction('fold', <f-args>)
" Add `:OR` command for organize imports of the current buffer
command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
" Add (Neo)Vim's native statusline support
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
" Mappings for CoCList
" Show all diagnostics
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
" Show commands
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
" Do default action for previous item
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
" AsyncRun: automatically open quickfix
let g:asyncrun_open = 6

浙公网安备 33010602011771号