Vim [编译]运行快捷方式

时间:2013-08-18 06:00:25

标签: c++ python c shell vim

基本上我想要的是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

我意识到我可能会问多一点但是如果可能的话就会喜欢它!

6 个答案:

答案 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”时:

see the capture here

您将在打开的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。或者你可以通过

关闭stdout缓冲区
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中运行命令行程序一样。最后,我们在下面有这些关键映射:

  • F4:使用cmake更新Makefile。
  • F5:运行单个文件
  • F6:运行项目测试
  • F7:构建项目
  • F8:运行项目
  • F9:编译单个文件
  • F10:切换quickfix窗口

它更像是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 ++命令以运行其他语言代码。

enter image description here

将其保存在gist中,并带有另一个映射以显示输出,该显示也显示在分割的部分中,但是保存在新文件中,因此您可以保存输出。

希望它能对某人有所帮助。

答案 4 :(得分:0)

我也想找到一条捷径。但是由于某些原因,我不想使用autocmd。我使用了bash脚本。我已经在使用bash脚本来编译和运行C / C ++代码。因此,我想,为什么不使用bash脚本并将其用于C和C ++的fltplugin文件中。我制作了两个单独的bash脚本。一种用于C,另一种用于C ++。这是C的脚本(对于C ++,它也类似,只是将编译器更改为clang++ / g++std=c2xstd=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