vim:用variables执行shell命令并将输出redirect到新的缓冲区

我想从下面的函数调用msbuild并将输出redirect到一个新的缓冲区。

我的问题是,我需要使用一个variables,文件名,因此不能使用'!' (我可以吗?),当我使用EXE或系统()读抱怨,我没有给它一个适当的文件。

func! myFunction() let findstr = "findstr /s /m " . '"' . expand("%:t") . '"' . " *.vcxproj" for project in split(system(findstr), nr2char(10)) echo "Building '" . project . "'" let msbuild = "c:\\windows\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe" . " " . project . " " . "/t:rebuild /p:configuration=debug" :tabnew | r system(msbuild) "<--THIS LINE HERE endfor endfunc 

:read命令需要一个不是vim表达式的文件。 但是它可以通过:read !{cmd}从标准输出中:read !{cmd} 。 例如:%r!ls 。 使用:execute命令,你可以用你的变量建立新的命令。

 exe '%r!' . msbuild 

或者你可以使用:put如果你想使用一个像system()这样的表达式,可以使用表达式寄存器。 (可能要跟着这个:0d_删除第一个空行)

 put=system(msbuild) 

现在看起来您正在尝试构建您的项目并获取错误列表。 我建议你看看:make'makeprg'选项和quickfix列表,因为这是构建项目的更多vim方法。

更多帮助请看:

 :h :r! :h :exe :h :pu :h @= :h :make :h 'makeprg' :h quickfix 

这是一个可以用来执行任意shell命令并在新窗口中显示它们的输出的函数(你可以把它放在你的_vimrc中):

 let s:lastcmd = '' function! s:RunShellCommand(cmdline, bang) " Support for repeating last cmd with bang: let _ = a:bang != '' ? s:lastcmd : a:cmdline == '' ? '' : join(map(split(a:cmdline), 'expand(v:val)')) if _ == '' return endif let s:lastcmd = _ let bufnr = bufnr('%') let winnr = bufwinnr(_) " You can position the new window whenever you want, I chose below + right: silent! execute winnr < 0 ? 'belowright new ' . fnameescape(_) : winnr . 'wincmd w' " I could set buftype=nofile, but then no switching back and forth buffers. " The results are presented just for viewing, not editing, modify at will: setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile wrap number setlocal modifiable silent! :%d " Useful for debugging, if you encounter issues with fnameescape(): call setline(1, 'You entered: ' . a:cmdline) call setline(2, 'Expanded to: ' . _) call append(line('$'), substitute(getline(2), '.', '=', 'g')) silent execute '$read !' . _ silent! execute 'autocmd BufUnload <buffer> execute bufwinnr(' . bufnr . ') . ''wincmd w''' " If resizing is unwanted for commands with too much output, remove this line: silent! execute 'autocmd BufEnter <buffer> execute ''resize '' . line(''$'')' " You can use <localleader>r to re-execute the last command: silent! execute 'nnoremap <silent> <buffer> <localleader>r :call <SID>RunShellCommand(''' . _ . ''', '''')<CR>' execute 'resize ' . line('$') setlocal nomodifiable 1 endfunction " RunShellCommand(cmdline) command! -complete=shellcmd -nargs=* -bang Shell call s:RunShellCommand(<q-args>, '<bang>') 

使用像:

 :Shell gcc -ggdb -o test test.c && ./test