当我使用:%!通过筛选器运行文件的内容,并且筛选器失败(它返回0以外的其他代码)并向stderr输出错误消息我将此文件替换为此错误消息。如果过滤器返回指示错误的状态代码和/或忽略过滤器程序写入stderr的输出,有没有办法告诉vim跳过过滤?
在某些情况下,您希望将文件替换为过滤器的输出,但通常这种行为是错误的。当然,我可以用一个按键撤消过滤,但这不是最佳的。
在编写自定义vim脚本进行过滤时,我也遇到了类似的问题。我有一个脚本,用system()调用过滤器程序,并用它的输出替换缓冲区中的文件,但似乎没有办法检测system()返回的行是否写入stdout或stderr 。有没有办法在vim脚本中区分它们?
答案 0 :(得分:5)
:!{cmd}
使用shell执行{cmd}
并设置v:shell_error
。
如果您碰巧设置映射来调用过滤器,则可以执行以下操作:
function! UndoIfShellError()
if v:shell_error
undo
endif
endfuntion
nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR>
答案 1 :(得分:3)
您可以使用Python来区分stdout和stderr:
python import vim, subprocess
python b=vim.current.buffer
python line=vim.current.range.start
python p=subprocess.Popen(["command", "argument", ...], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
python returncode=p.poll()
python if not returncode: b.append(("STDOUT:\n"+p.stdout.read()+"\nSTDERR:\n"+p.stderr.read()).split("\n"), line)
答案 2 :(得分:1)
另一种方法是运行filter命令,例如它修改磁盘上的文件。
例如,对于gofmt(www.golang.org),我有这些映射:
map <f9> :w<CR>:silent !gofmt -w=true %<CR>:e<CR>
imap <f9> <ESC>:w<CR>:silent !gofmt -w=true %<CR>:e<CR>
说明: :w - 保存文件 :沉默 - 避免在最后按Enter键 % - 将文件传递给gofmt -w = true - 告诉gofmt写回文件 :e - 告诉vim重新加载修改后的文件
答案 3 :(得分:1)
在Vim 7中添加了新的自动命令事件:ShellCmdPost
和ShellFilterPost
augroup FILTER_ERROR
au!
autocmd ShellFilterPost * if v:shell_error | undo | endif
augroup END
答案 4 :(得分:0)
这就是我最终做的事情:
function MakeItAFunction(line1, line2, args)
let l:results=system() " call filter via system or systemlist
if v:shell_error
"no changes were ever actually made!
echom "Error with etc etc"
echom results
endif
"process results if anything needed?
" delete lines but don't put in register:
execute a:line1.",".a:line2." normal \"_dd"
call append(a:line1-1, l:result) " add lines
call cursor(a:line1, 1) " back to starting place
" echom any messages
endfunction
command -range <command keys> MakeItAFunction(<line1>,<line2>,<q-args>)
" or <f-args>, etc.
您可以在http://vim.wikia.com/wiki/Perl_compatible_regular_expressions
看到我的完整代码它很复杂,但它有效,当它被使用时,它相当透明和优雅。希望以任何方式有所帮助!