vim映射,用于使用可选输入文件运行c ++

时间:2019-07-11 12:15:06

标签: c++ vim

我正在配置vimrc文件,以便使用c ++进行竞争性编程。

autocmd filetype cpp nnoremap <F5> :w <CR> 
                                   :!g++ -o %:r % <CR> :!./%:r < input.txt <CR>

下面的映射是当我按F5键时,它保存,编译(%:r是不带.cpp的文件名),并与input.txt文件一起运行。

但是,并不是每个cpp文件都具有input.txt,因此,仅在当前目录中存在input.txt时,我才希望通过管道传输input.txt。

总而言之,在映射过程中检查文件的最佳方法是什么?

4 个答案:

答案 0 :(得分:2)

除非您正在无法使用gnu make或配置不正确(mingw)的环境中工作,否则单文件项目将不需要任何Makefile。在这种情况下,它们不是强制性的,并且IMO比其他任何事情都更加麻烦。

最好通过以下方式进行编译:

:make %<

这样,任何错误都会直接转到quickfix窗口。这样可以提高查找错误(:h quickfix)的效率。另外,无论您的当前文件是C,C ++,Fortran ...还是默认gnumake配置识别的任何语言,都不必根据当前文件类型指定要使用的编译器。例如,如果您确实想为C ++选择另一个编译器,则可以使用

:let $CXX ='clang++'
" $CC for C, and so on

如果您想更改编译选项

:let $CXXFLAGS = '-std=c++17 -Wall -Werror'
" $CFLAGS for C, $LDLIBS, $LDFLAGS for the linker, and so on

请注意,如果您有Makefile,它将被自动使用。

通过执行链

:!make %< && ./%<确实很简单,可以链接两个步骤。 las,我们没有:make的直接等价物。我们必须分析快速修复列表以查看是否存在任何问题

如果filter(getqflist(), 'v:val.valid != 0')不为空,我们可以知道是否已检测到问题。但这并不能说明它们是警告还是错误。我们可以提供以下完整的信息

" From my build-tools-wrapper plugin
function! lh#btw#build#_get_metrics() abort
  let qf = getqflist()
  let recognized = filter(qf, 'get(v:val, "valid", 1)')
  " TODO: support other locales, see lh#po#context().tranlate()
  let errors   = filter(copy(recognized), 'v:val.type == "E" || v:val.text =~ "\\v^ *(error|erreur)"')
  let warnings = filter(copy(recognized), 'v:val.type == "W" || v:val.text =~ "\\v^ *(warning|attention)"')
  let res = { 'all': len(qf), 'errors': len(errors), 'warnings': len(warnings) }
  return res
endfunction

由此,我们可以决定仅停止出现错误,或者停止出现错误和警告。

可选输入

使用filereadable(),我们可以知道输入文件是否在这里。

因此变成:

let exec_line = '!./' . expand('%<') " we could also use the complete path instead
let input = expand('%:p:h')/.'input.txt'
if filereadable(input)
    let exec_line .= ' < ' . input
endif
exe exec_line

如果您想在:terminal中重定向结果,那么不幸的是,这次重定向不能与Vim一起使用(尽管它可以与nvim一起使用)

TL; DR

最终代码(赋予先前的功能以检测错误和警告)成为

function s:build_and_run(file) abort
  let tgt  = fnamemodify(a:file, ':r')
  " to make sure the buffer is saved
  exe 'update ' . a:file
  exe 'make ' . tgt
  if lh#btw#build#_get_metrics().errors
    echom "Error detected, execution aborted"
    copen
    return
  endif

  let path = fnamemodify(a:file, ':p:h')
  let exec_line = '!./' . tgt
  let input = path.'/input.txt'
  if filereadable(input)
    let exec_line .= ' < ' . input
  endif
  exe exec_line
endfunction

nnoremap µ :<C-U>call <sid>build_and_run(expand('%'))<cr>

答案 1 :(得分:1)

通过输入文件运行它是什么意思? 我认为您应该考虑使用Makefile。在这里,对所有构建依赖项(包括包含,链接路径,测试执行等)进行建模。

您的绑定将如下所示,并且对于包含Makefile的所有文件夹来说都是相同的

autocmd filetype cpp nnoremap <F5> :w <CR> :!make all<CR>

答案 2 :(得分:1)

我为此专门创建了一个插件。 Link to Repo

通过一次击键(默认为 F9),它从名为 input.txt 的文件中获取输入并将输出转储到本地目录中名为 output.txt 的文件中。这适用于编译和运行单个 .cpp 文件。

这使用 vim 的 rysnclocal vimrc 插件作为依赖项,尽管您可以使用任何本地 vimrc 插件。

答案 3 :(得分:0)

如@ schorsch312所述,makefile将会更加安全有效。

感谢@Botje,以下配置适用

autocmd filetype cpp nnoremap <F5> :w <CR>
                               :!g++ -o %:r % && cat input.txt 2> /dev/null \| ./%:r <CR>

这是我遇到的几个问题

  • noremap:仅适用于普通模式(more)的非递归映射
  • :回车键(通常与最后一行命令映射一起使用)
  • &&:仅在编译成功(more
  • 时运行
  • 2> dev / null:当input.txt不存在(more)时忽略错误
  • 您必须逃脱|或改用