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

image

为了使得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,这就表示下载成功了,如果没有可以自己新建这些目录, 再尝试下载。
image

用法

在您的 ~/.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 安装插件

image

使用

提示
在安装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执行文件。

image


目录树,翻译和代码补全插件

安装

使用 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展开目录或者打开文件。
image

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

对于补全代码:coc.nvim 是一个基于 Language Server Protocol (LSP) 的智能代码补全和代码分析插件。需要下载coc-clangd,

使用 Coc 命令(推荐)
:CocInstall coc-clangd 下载扩展
:CocList extensions 查看已安装的扩展
:CocUninstall coc-clangd 卸载扩展

按下enter进行补全,按下space取消, 但取消有个缺点,如果会缩减你打的词,可以搭配ESC使用。
image

其他插件

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

posted @ 2026-01-18 18:11  游翔  阅读(2)  评论(0)    收藏  举报