有没有办法在不输入文件名的情况下从VIM编译和运行C程序?
答案 0 :(得分:96)
:!gcc -o somename % && ./somename
使用:!
时,%将替换为当前打开文件的名称。
当你的项目变大时,你也可以编写一个makefile并使用:make
编译当前项目,如果有任何错误,vim会自动跳转到它们。
答案 1 :(得分:40)
在.vimrc文件中使用以下映射代码来编译和运行c编程文件。
map <F8> : !gcc % && ./a.out <CR>
F8键用于运行映射。 “%”是获取当前文件名。
或者,如果要在编译之前保存当前文件,请使用
map <F8> :w <CR> :!gcc % && ./a.out <CR>
或者更理想的情况是,如果要使用文件basename而不是默认的'a.out'作为可执行文件名,请使用以下命令:
map <F8> :w <CR> :!gcc % -o %< && ./%< <CR>
在上面的命令中,“&lt;”在“%”删除扩展名和点(foo.c =&gt; foo)之后,所以“%&lt;”是文件基名。
您可以在cmdline.txt中找到此信息和类似信息。 vim中的命令:help: cmdline.txt
。您还可以在vim中使用:help filename-modifiers
找到有关使用“%”的具体详情。
答案 2 :(得分:6)
因为大部分时间你都会使用Makefile,除了给定的答案之外,我还希望在“清除”屏幕上看到我的结果:
map <F10> :w<CR> :!clear; make<CR> :!./%<<CR>
:w<CR>
保存文件
:!clear; make<CR>
清除屏幕并运行make
:!./%<<CR>
运行的程序(%
)没有扩展程序(<
)
答案 3 :(得分:6)
TL; DR 不需要Makefile,调整&makeprg
也完全没用,但:make %<
足以从Vim编译。
答案很长:
我在一个封闭的“重复问题”中复制了我给出的答案。
考虑到我们使用的是vim,而不是vi,:make
是可行的方法。
在类似Linux的情况下(它也适用于cygwin,但不适用于Windows上 - 在mingw情况下,请参阅更改&makeprg
的其他答案,否则请另外选择)安装gnumake的系统,如果您的项目中没有Makefile,如果您的项目只由一个文件组成,只需键入:make %<
即可。这就足够了(您可以使用$CXXFLAGS
,$CFLAGS
和$LDFLAGS
来调整编译选项。然后,要运行该程序,请键入:!./%<
或使用后一版本的vim,运行:terminal ./%<
。
如果您的项目由多个文件组成,那么您需要一个Makefile来利用:make
。
如果您使用CMake管理项目,并且如果您在源目录树之外的目录(或几个 - > debug,release,...)中编译项目,那么集成将需要一个插件。 AFAIK,我是唯一提出这样一个插件的人:BuildToolsWrapper集成了CMake的管理(构建目录的选择,在调试或发布之间选择的可能性,或者任何构建目录)。它必须与local_vimrc插件中的一个耦合。
在所有情况下,使用:!g++ -o %< %
从Vim内部(或外部)直接调用编译器,或者15年前我们在vi上执行的操作。 Vim有一个很棒的功能:它可以集成(是的,就像在IDE中一样)编译器。见:h quickfix
。直接从编辑器中导航错误要比用我们的眼睛提取一个错误行,在编辑器中键入行号,返回到shell以查看究竟被拒绝的内容要容易得多,......在C中可能已经足够了,但是在C ++中,当我们“试图调用一个不存在的重载”时,我们无法以这种方式工作(在编辑器和shell之间来回切换)。
最后,如果你想在单个按键上编译那些单文件项目,你可以添加.vimrc:
nnoremap <silent> <f7> :make %<<cr>
如果你想根据项目单文件宠物项目的类型或现实世界的多文件项目自动调整编译命令,那么需要更多的布线,这就是BTW does - 它会读取各种选项以了解该做什么。
最后注意:&makeprg
最好不要单独使用,至少不要设置为g ++ / gcc / clang / clang ++ / gfortran / ...因为,每次更改语言时,都必须更改它(除非你使用:setlocal
)。根据我推荐的解决方案,如果我想使用clang ++而不是g ++,我所要做的就是设置::let $CXX='clang++'
(或C中的$CC
),然后调用:make %<
。我甚至可以定义:let $CXXFLAGS='-std=c++11'
在C ++ 11中编译 - 相同的变量将用于打开警告,使用消毒剂等。
答案 4 :(得分:4)
在vimrc
文件中添加此行
nnoremap <silent> <F8> :!clear;gcc % -o % && ./%<CR>
现在您只需按f8键即可编译并运行您的c程序。
答案 5 :(得分:3)
现在是2018年,vim 8发布了2年,并附带了所有Linux发行版和Mac OS X.但是很多vim教程在十年前还在教人们。
你可以在vim中编译你的C ++ / Java程序,就像Sublime Text或NotePad ++一样,带有一些Vim 8或NeoVim的专用插件。
例如,AsyncRun插件允许您在后台运行shell命令并实时读取quickfix窗口的输出。 See the screen capture
就像在IDE中编译程序一样,编译错误将通过errorformat匹配并突出显示并变为可选。您可以在quickfix窗口中导航错误或在编译时继续编辑。
快速设置
复制&amp;将下面的行粘贴到你的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”时:
您将在打开的quickfix窗口中看到实时命令输出。
编译并运行单个文件
使用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的错误格式匹配,并且将在quickfix中显示为原样。现在您可以使用F9编译文件,检查quickfix窗口中的编译错误,然后按F5运行二进制文件。
构建C / C ++项目
无论您使用的是什么构建工具,make或cmake,项目构建都意味着对一组文件起作用。它需要找到项目根目录。 AsyncRun使用一种称为根标记的简单方法来标识项目根。 Project Root被标识为当前文件的最近祖先目录,其中包含以下目录或文件之一:
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中的所有数据都将被缓冲,直到进程退出。因此,如果您想查看实时输出,则在fflush(stdout)
语句后必须有printf
。或者你可以通过
setbuf(stdout, NULL);
同时,如果您正在编写C ++代码,则可以将std :: endl附加到std :: cout的末尾。它可以强制刷新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中运行命令行程序一样。最后,我们在下面有这些关键映射:
它更像是NotePad ++和GEdit中的构建系统。如果您正在大量使用cmake,可以编写一个位于~/.vim/script/build.sh
的简单shell脚本,将F4和F7组合在一起:如果CMakeList.txt已更改,它将更新Makefile,然后执行exectute。
高级用法
您还可以在dotfiles存储库中定义shell脚本,并使用F3执行脚本:
nnoremap <F3> :AsyncRun -cwd=<root> sh /path/to/your/dotfiles/script/build_advanced.sh <cr>
以下shell环境变量由AsyncRun定义:
$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,当前项目中的符号引用将立即显示在quickfix窗口中。
这个简单的键盘映射在大多数时候都足够了。您可以改进此脚本以支持更多文件类型或vimrc中的其他grep工具。
这是在Vim 8或NeoVim中构建/运行C / C ++项目的实用方法。就像Sublime Text的构建系统和NotePad ++的NppExec一样。
再没有过时的vim教程,尝试新的东西。
答案 6 :(得分:2)
我想我会在这里添加这些答案。如前所述,您可以在vim中使用:make
命令。尚未提及的是,:make
可以调用make
以外的其他程序。
:set makeprg=gcc\ %
将导致:make
执行gcc
并将%
符号替换为当前文件名。
然后你可以开玩笑地做
:set makeprg=gcc\ %\ &&\ ./a.out
只需输入:make
即可编译并执行您的程序。当然,您也可以为其他语言执行此操作。
:set makeprg=cabal\ repl
:set makeprg=python\ %
答案 7 :(得分:1)
在做了一些研究(包括这个页面)之后,我决定添加这个快捷方式:
map <F9> :w<CR> :!gcc % -o %<.x -Wall -Wextra 2>errors.err; cat errors.err<CR>
如果愿意,您还可以加入-ansi -pedantic-errors
。
errors.err
文件将为您提供vi quickfix。
答案 8 :(得分:1)
我仔细研究了所有这些解决方案,发现对于在另一个目录中编辑文件而言,它们不起作用(据我所知)-我编写了一些vimscript来完成此任务笨拙的方法,但希望有人能找到这个有用的方法:
let mycommand = ':!gcc % -o %< && echo "%<" && [ $(pwd) == "." ] && %< || ./%< '
nnoremap <silent> <F8> :execute mycommand <CR>
或者如果上面的命令在多个目录中对您有用,请忽略它。
答案 9 :(得分:1)
你可以直接从vim轻松编译和运行你的程序,只需进入普通模式并输入
:!gcc yourProgramName.c
然后只需编写以下内容即可运行程序
:!gcc % | ./a.out
答案 10 :(得分:0)
将这三行添加到.vimrc
文件
au FileType c set makeprg=gcc\ %
au FileType cpp set makeprg=g++\ %
map <F7>:make && ./a.out<CR>
您可以按 F7 按钮编译并运行程序。
答案 11 :(得分:0)
可能值得补充的是,SingleCompile
插件为作者所述的C和其他语言提供了便利设施:
SingleCompile是一个Vim插件,旨在使其更加便捷 编译或运行单个源文件而不离开Vim。考虑一下 情况:你刚刚写了一个小的C源文件 测试,但你必须编写一个Makefile来编译它,或退出Vim 编译它,或使用“!gcc”编译它而不使用quickfix功能 因为Vim的make命令只使用“make”命令?这个插件 会帮助你。
建议的 F9 和 F10 的映射:
nmap <F9> :SCCompile<cr>
nmap <F10> :SCCompileRun<cr>
答案 12 :(得分:0)
我已经创建了运行我的 c 和 cpp 代码的命令
:command Runcpp !clear;g++ % -o %:r && ./%:r<CR>
:command Runc !clear;gcc % -o %:r && ./%:r<CR>
将上面的代码放入 .vimrc 文件中并使用命令 Runcpp & Runc 运行你的代码
答案 13 :(得分:0)
我的 vimrc 中有以下内容:
autocmd filetype c nnoremap <F9> :w<CR> :!clear<CR> :!gcc % -o %< && %<<CR>
这将允许您使用 <F9>
编译/运行 C 并清除控制台
您还可以执行以下操作:
autocmd filetype c nnoremap <F8> :w<CR> :!clear<CR> :!make && ./%<<CR>
这将允许您使用带有 <F8>
的 Makefile 编译/运行 C 并清除控制台