使用可选输入文件运行c++的vimMap

gijlo24d  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(138)

我正在配置vimrc文件,用于竞争性的c++编程。

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

下面的Map是当我按下F5时,它保存、编译(%:r是不带.cpp的文件名),并运行input.txt文件。
然而,并不是每个cpp文件都有input.txt,所以我希望只有当input.txt存在于当前目录中时才通过管道传输input.txt。
总而言之,在Map过程中检查文件的最佳方法是什么?

ppcbkaq5

ppcbkaq51#

除非你的工作环境中gnu make不可用,或者配置很差(mingw),否则你不需要任何Makefile来处理单文件项目。在这种情况下,它们不是强制性的,IMO比其他任何东西都麻烦。

编译最好使用:

:make %<

这样,任何错误都会直接进入快速修复窗口。这将提高您定位错误的效率(: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 %< && ./%<确实足够简单,可以链接两个步骤。遗憾的是,我们没有与: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

如果你想重定向a: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>
mctunoxg

mctunoxg2#

什么叫用输入文件运行它?我认为你应该考虑使用Makefile。这是一个地方,所有的构建依赖关系都是在这里建模的(比如包含,链接路径,测试的执行,等等)。
然后,您的绑定将如下所示,并且对于包含Makefile的所有文件夹都是相同的

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

v9tzhpje3#

正如@schorsch312所提到的,makefile将更加安全和高效。
感谢@Botje,以下配置工作正常

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

以下是我遇到的几个问题

  • noremap:非递归Map,仅适用于正常模式(more
  • < CR>:回车键(通常用于最后一行命令Map)
  • &&:仅在编译成功时运行(more
  • 2〉设备/空:当input.txt不存在时忽略错误(more
  • 你必须逃走|或使用
4szc88ey

4szc88ey4#

我已经创建了一个插件用于这个确切的目的。Link to Repo
通过一次击键(默认为F9),它从名为input.txt的文件中获取输入,并将输出转储到本地目录中名为output.txt的文件中。这对于编译和运行单个.cpp文件非常有效。
它使用vim的rysnclocal vimrc插件作为依赖项,尽管您可以使用任何本地vimrc插件。

相关问题