基本上我想要的是vim中的键盘快捷键,它允许我[编译]运行当前正在编辑的C,C ++或Python程序。在伪代码中:
when a shortcut key is pressed:
if current_extension == 'c' then
shell: gcc this_filename.c -o this_filename_without_extension
if retcode == 0 then shell: ./this_filename_without_extension
else if current_extension == 'cpp' then
shell: g++ this_filename.cpp -o this_filename_without_extension
if retcode == 0 then shell: ./this_filename_without_extension
else if current_extension == 'py' then
shell: python this_filename.py
end if
end key
我意识到我可能会问多一点但是如果可能的话就会喜欢它!
答案 0 :(得分:27)
这样的事情会起作用。只需创建映射<F4>
或任何您想要保存的文件类型autocmd,然后编译并运行该程序。它使用exec构建字符串并使用shellescape来转义文件名。
autocmd filetype python nnoremap <F4> :w <bar> exec '!python '.shellescape('%')<CR>
autocmd filetype c nnoremap <F4> :w <bar> exec '!gcc '.shellescape('%').' -o '.shellescape('%:r').' && ./'.shellescape('%:r')<CR>
autocmd filetype cpp nnoremap <F4> :w <bar> exec '!g++ '.shellescape('%').' -o '.shellescape('%:r').' && ./'.shellescape('%:r')<CR>
%
是当前的缓冲区文件名。 %:r
是没有扩展名的缓冲区文件名
答案 1 :(得分:8)
http://singlecompile.topbug.net似乎比你想要的更多。对于更简单的解决方案,您还可以将以下内容添加到vimrc
au BufEnter *.cpp set makeprg=g++\ -g\ %\ -o\ %<
au BufEnter *.c set makeprg=gcc\ -g\ %\ -o\ %<
au BufEnter *.py set makeprg=python\ %
au BufEnter *.[rR] set makeprg=Rscript\ %
map <F5> :call CompileGcc()<CR>
func! CompileGcc()
exec "w"
silent make
endfunc
HTH
答案 2 :(得分:2)
现在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教程,尝试新的东西。
答案 3 :(得分:0)
我知道7年后我来到这里。我尝试了其他答案的代码,但结果令我不满意,所以我尝试了以下方法:
autocmd filetype cpp nnoremap <F9> :w<bar>term ++shell g++ %:p -o %:p:r && %:p:r<CR>
按F9时,它将(与上面的所有答案一样)编译并执行当前文件。输出显示在:terminal部分拆分屏幕中。 您可以更改g ++命令以运行其他语言代码。
将其保存在gist中,并带有另一个映射以显示输出,该显示也显示在分割的部分中,但是保存在新文件中,因此您可以保存输出。
希望它能对某人有所帮助。
答案 4 :(得分:0)
我也想找到一条捷径。但是由于某些原因,我不想使用autocmd
。我使用了bash脚本。我已经在使用bash脚本来编译和运行C / C ++代码。因此,我想,为什么不使用bash脚本并将其用于C和C ++的fltplugin文件中。我制作了两个单独的bash脚本。一种用于C,另一种用于C ++。这是C的脚本(对于C ++,它也类似,只是将编译器更改为clang++
/ g++
,
std=c2x
至std=c++20
和$filename.c
至$filename.cpp
),
filename=$1
compiler=clang-10
if [ $2 ]; then
if [ $2 == "-v" ]; then
FLAGS="-g -Wall -Wextra -pedantic -std=c2x"
fi
else
FLAGS="-Wall -Wextra -pedantic -std=c2x"
fi
$compiler $FLAGS $filename.c -o $filename -lm
return_value=$?
if [ $return_value -eq 0]; then
if [ $2 ]; then
if [ $2 == "-v" ]; then
valgrind ./$filename
rm $filename
fi
else
./$filename
echo
echo "[process exited $return_value]"
rm $filename
fi
fi
将其另存为run
。我使它对所有用户都可执行,
$ chmod 777 run
我将其移至用户bin
目录。
$ mv run ~/bin
如果您没有用户bin
目录,请继续。转到您的主目录,并创建一个名为bin
的目录。
$ cd ~
$ mkdir bin
然后将run
(或您给脚本指定的任何名称)文件移动到bin目录。
$ mv run ~/bin
继续前进。
然后,我在c.vim
目录中创建了一个~/.vim/after/ftplugin
文件。并将两个新的键重映射添加到c.vim
文件中。
nnoremap <F9> :vertical bo term run %:r<CR>
# This will run my code with valgrind
nnoremap <F2> :vertical bo term run %:r -v<CR>
以下是一些屏幕截图,
Clicking F9 shows me the output screen in a vim buffer,
Clicking F2 shows me the output using valgrind in a vim buffer
您可以使用C ++进行相同的操作,只需在cpp.vim
目录中创建一个~/.vim/after/ftplugin
文件。并制作另一个run
文件(如run_cpp
),并将其保存在用户bin
(~/bin
)文件中。进行一些自定义的键绑定,就可以了。
答案 5 :(得分:-1)
这是我的地图,它确实可以将其更新为任何语言:
" <!----------------------------" gcc compile C files----------------------------------------!>
autocmd filetype c nnoremap <Leader>c :w <CR>:!gcc % -o %:r && ./%:r<CR>
" <!----------------------------" java compile files----------------------------------------!>
autocmd filetype java nnoremap <Leader>c :w <CR>:!javac % :r&& java %:r<CR>
" <!----------------------------" php compile files----------------------------------------!>
autocmd filetype php nnoremap <Leader>c :w <CR>:!clear && php %<CR>
现在如果你是vim中的那个文件中的一个只是在正常模式下执行:
<leader>c