现在是2018年,vim 8已经发布了2年,并且与所有主流Linux发行版和Mac OS X一起发布。但是很多vim教程仍然教授十年前的内容。
您可以使用一些专为Vim 8或NeoVim设计的插件,像Sublime Text或NotePad++一样方便地编译C ++ / Java程序。
例如,AsyncRun插件将允许您在后台运行shell命令并实时从快速修复窗口中读取输出。
查看屏幕截图。
就像在IDE中编译程序一样,编译错误将通过错误格式进行匹配,并进行突出显示并变得可选择。您可以在快速修复窗口中导航错误或继续编辑而不编译。
快速设置
将以下行复制并粘贴到您的vimrc中:
Plug 'skywind3000/asyncrun.vim'
" open quickfix window automatically when AsyncRun is executed
" set the quickfix window 6 lines height.
let g:asyncrun_open = 6
" ring the bell to notify you job finished
let g:asyncrun_bell = 1
" F10 to toggle quickfix window
nnoremap <F10> :call asyncrun#quickfix_toggle(6)<cr>
当您在命令行中输入“:AsyncRun echo hello”时:
请
点击这里查看截图
您将在打开的快速修复窗口中实时查看命令输出。
编译和运行单个文件
使用AsyncRun编译单个文件比Sublime Text的构建系统简单得多。我们可以为此设置F9:
noremap <silent> <F9> :AsyncRun gcc -Wall -O2 "$(VIM_FILEPATH)" -o "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
$(..)
形式中的宏将被展开为实际的文件名或目录,然后我们就可以使用F5运行可执行文件:
noremap <silent> <F5> :AsyncRun -raw -cwd=$(VIM_FILEDIR) "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
双引号用于处理包含空格的路径名。选项
-cwd=$(VIM_FILEDIR)
表示在文件所在目录中运行文件。使用绝对路径名
$(VIM_FILEDIR)/$(VIM_FILENOEXT)
是因为Linux需要一个
./
前缀来运行当前目录下的可执行文件,但Windows不需要。使用二进制文件的绝对路径名可以处理这个跨平台问题。
另一个选项
-raw
表示输出将不会被vim的errorformat匹配,并且将按其本身显示在快速修复窗口中。现在你可以按F9编译你的文件,在快速修复窗口中检查编译错误,按F5运行二进制文件。
构建C/C++项目
无论你使用什么构建工具,make还是cmake,项目构建都意味着对一组文件进行操作。它需要定位项目根目录。AsyncRun使用一种称为根标记的简单方法来识别项目根目录。项目根目录被识别为包含以下任一目录或文件的当前文件的最近祖先目录之一:
let g:asyncrun_rootmarks = ['.svn', '.git', '.root', '_darcs']
如果任何一个父目录中都没有这些根标记,那么当前文件所在的目录将被用作项目根目录。这使我们可以使用<root>
或$(VIM_ROOT)
来表示项目根目录。并且可以设置F7键以构建当前项目:
noremap <silent> <F7> :AsyncRun -cwd=<root> make <cr>
如果您的当前项目没有在任何git或subversion存储库中,该怎么办?如何找到我的项目根目录?解决方案非常简单,只需在项目根目录中放置一个空的.root文件,就可以轻松地定位它。
接下来,设置F8运行当前项目:
noremap <silent> <F8> :AsyncRun -cwd=<root> -raw make run <cr>
该项目将在其根目录中运行。当然,您需要在自己的 makefile 中定义运行规则。然后将 F6 重新映射为测试。
noremap <silent> <F6> :AsyncRun -cwd=<root> -raw make test <cr>
如果您使用cmake,F4可以映射到更新您的Makefile:
nnoremap <silent> <F4> :AsyncRun -cwd=<root> cmake . <cr>
由于c运行时的实现,如果进程正在运行的是非tty环境,则stdout中的所有数据都会被缓冲,直到进程退出。因此,如果您想看到实时输出,必须在
printf
语句之后加上
fflush(stdout)
,或者在开头关闭stdout缓冲区。
setbuf(stdout, NULL);
同时,如果您编写C++代码,可以在std::cout的末尾添加std::endl。这会强制刷新stdout缓冲区。如果您在Windows上开发,则AsyncRun可以为子进程打开一个新的cmd窗口:
nnoremap <silent> <F5> :AsyncRun -cwd=$(VIM_FILEDIR) -mode=4 "$(VIM_FILEDIR)/$(VIM_FILENOEXT)" <cr>
nnoremap <silent> <F8> :AsyncRun -cwd=<root> -mode=4 make run <cr>
在Windows操作系统上使用选项
-mode=4
将打开一个新的提示窗口来运行命令,就像在Visual Studio中运行命令行程序一样。最后,我们有以下按键映射:
- F4:用cmake更新Makefile。
- F5:运行单个文件
- F6:运行项目测试
- F7:构建项目
- F8:运行项目
- F9:编译单个文件
- F10:切换快速修复窗口
这更像是NotePad++和GEdit中的构建系统。如果您经常使用cmake,则可以编写一个简单的shell脚本,位于
~/.vim/script/build.sh
,将F4和F7组合在一起:如果CMakeList.txt已更改,则会更新Makefile,然后执行make。
高级用法
您还可以在dotfiles存储库中定义shell脚本,并使用F3执行该脚本:
nnoremap <F3> :AsyncRun -cwd=<root> sh /path/to/your/dotfiles/script/build_advanced.sh <cr>
以下是AsyncRun定义的shell环境变量:
$VIM_FILEPATH - File name of current buffer with full path
$VIM_FILENAME - File name of current buffer without path
$VIM_FILEDIR - Full path of current buffer without the file name
$VIM_FILEEXT - File extension of current buffer
$VIM_FILENOEXT - File name of current buffer without path and extension
$VIM_CWD - Current directory
$VIM_RELDIR - File path relativize to current directory
$VIM_RELNAME - File name relativize to current directory
$VIM_ROOT - Project root directory
$VIM_CWORD - Current word under cursor
$VIM_CFILE - Current filename under cursor
$VIM_GUI - Is running under gui ?
$VIM_VERSION - Value of v:version
$VIM_COLUMNS - How many columns in vim's screen
$VIM_LINES - How many lines in vim's screen
$VIM_SVRNAME - Value of v:servername for +clientserver usage
所有上述环境变量都可以在您的
build_advanced.sh
中使用。使用外部 shell 脚本文件可以执行比单个命令更复杂的工作。
Grep 符号
有时,如果您的远程 Linux 箱没有良好设置的环境,则 grep 是在源代码中搜索符号定义和引用的最便宜的方法。现在我们将使用 F2 在光标下搜索关键字。
if has('win32') || has('win64')
noremap <F2> :AsyncRun! -cwd=<root> grep -n -s -R <C-R><C-W> --include='*.h' --include='*.c*' '<root>' <cr>
else
noremap <F2> :AsyncRun! -cwd=<root> findstr /n /s /C:"<C-R><C-W>" "\%CD\%\*.h" "\%CD\%\*.c*" <cr>
endif
以上脚本将在你的项目根目录中运行grep或findstr,并仅在.c
、.cpp
和.h
文件中查找符号。现在我们移动光标并按F2键,当前项目中的符号引用将立即显示在快速修复窗口中。
这个简单的按键映射对于大多数情况已经足够了。你可以改进这个脚本以支持更多的文件类型或其他grep工具,在你的vimrc中。
这就是在Vim 8或NeoVim中构建/运行C/C++项目的实用方法。就像Sublime Text的构建系统和NotePad++的NppExec一样。
不再使用过时的vim教程,尝试一些新的东西吧。
:!g++ filename.cpp -o filename
然后输入./filename
很慢,所以我想将其作为键盘快捷方式。 - user1318194Makefile
? - Karoly Horvathmake
命令可能会过度使用。如果您的编译需要在 shell 脚本中编写超过一两行的代码,那么您可能正在做错什么。我认为,一旦您开始运行 make 文件来创建Makefile
,那么您就已经越过了界限。 - SO_fix_the_vote_sorting_bug