用于使用可选输入文件运行 C++ 的 vim 映射

Sea*_*ean 2 c++ vim

我正在配置 vimrc 文件以进行 C++ 竞争性编程。

autocmd filetype cpp nnoremap <F5> :w <CR> 
                                   :!g++ -o %:r % <CR> :!./%:r < input.txt <CR>
Run Code Online (Sandbox Code Playgroud)

以下映射是当我按 F5 时,它保存、编译(%:r 是不带 .cpp 的文件名),并使用 input.txt 文件运行。

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

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

Luc*_*tte 6

除非您在 gnu make 不可用或配置不当 (mingw) 的环境中工作,否则您不需要任何Makefile单文件项目。在这种情况下,它们不是强制性的,而且在我看来,这比其他任何事情都更麻烦。

\n

编译最好通过以下方式完成:

\n
:make %<\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
:let $CXX =\'clang++\'\n" $CC for C, and so on\n
Run Code Online (Sandbox Code Playgroud)\n

如果您想更改编译选项

\n
:let $CXXFLAGS = \'-std=c++17 -Wall -Werror\'\n" $CFLAGS for C, $LDLIBS, $LDFLAGS for the linker, and so on\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

与执行相链接

\n

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

\n

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

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

由此我们可以决定仅在错误或错误和警告时停止。

\n

可选输入

\n

通过filereadable()我们可以知道输入文件是否在这里。

\n

因此它变成:

\n
let exec_line = \'!./\' . expand(\'%<\') " we could also use the complete path instead\nlet input = expand(\'%:p:h\')/.\'input.txt\'\nif filereadable(input)\n    let exec_line .= \' < \' . input\nendif\nexe exec_line\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

长话短说

\n

最终代码(给出了之前检测错误和警告的函数)。

\n
function s:build_and_run(file) abort\n  let tgt  = fnamemodify(a:file, \':r\')\n  " to make sure the buffer is saved\n  exe \'update \' . a:file\n  exe \'make \' . tgt\n  if lh#btw#build#_get_metrics().errors\n    echom "Error detected, execution aborted"\n    copen\n    return\n  endif\n\n  let path = fnamemodify(a:file, \':p:h\')\n  let exec_line = \'!./\' . tgt\n  let input = path.\'/input.txt\'\n  if filereadable(input)\n    let exec_line .= \' < \' . input\n  endif\n  exe exec_line\nendfunction\n\nnnoremap \xc2\xb5 :<C-U>call <sid>build_and_run(expand(\'%\'))<cr>\n
Run Code Online (Sandbox Code Playgroud)\n