vim过滤器和stdout/stderr

问题描述:

当我使用:%!通过过滤器运行文件的内容并且过滤器失败(它返回的是另一个不是0的代码)并将错误消息打印到stderr我的文件被替换为此错误消息。如果过滤器返回指示错误的状态代码和/或忽略过滤程序写入stderr的输出,是否有办法告诉vim跳过过滤?vim过滤器和stdout/stderr

有些情况下,您希望将文件替换为过滤器的输出,但大多数情况下这种行为是错误的。当然,我可以用一个按键撤消过滤,但这不是最佳的。

另外我写一个自定义vim脚本来做过滤时也有类似的问题。我有一个脚本,用system()调用一个过滤器程序,并用它的输出替换缓冲区中的文件,但似乎没有办法检测到system()写入stdout或stderr 。有没有办法在vim脚本中区分它们?

您可以使用Python输出和错误之间的区别:

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) 
+0

当然!对于每一种“真正”的脚本语言,这根本就不是问题。没有想到这一点。尽管如果可能的话,我宁愿使用vim脚本,因为我不希望对脚本有更多的依赖关系。 – ahe 2010-04-04 20:49:07

+1

我只知道另一种方法:使用'system()',将stderr重定向到一个临时文件(或'/ dev/null'),将stdout保存到某个变量并使用'v:shell_error'来确定命令是否失败覆盖缓冲区。请注意,':!'过滤器用前一个命令替换«!»,用'当前文件名替换«%»,而'system()'不替换。 – ZyX 2010-04-04 20:56:37

:!{cmd}执行{cmd}与外壳并设置v:shell_error

如果你碰巧设置映射打电话给你的过滤器,你可以不喜欢以下:

function! UndoIfShellError() 
    if v:shell_error 
     undo 
    endif 
endfuntion 

nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR> 
+0

好戏:)。实际上,我希望为我刚刚忽略的!{cmd}语法提供一个错误敏感的挂件。但越来越多的人担心没有这样的替代语法存在。 – ahe 2010-04-06 20:03:02

另一种方法是,运行过滤器的命令,比如它会修改磁盘上的文件。

例如,对于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 - 保存文件 :无声 - 避免压在年底 %进入 - 传递给gofmt文件 -w =真 - 告诉gofmt写回文件 :电子 - 告诉Vim重新载入修改后的文件

这是我落得这样做:

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

它的复杂看到我的完整的代码,但它的工作原理,当它的使用,这是相当透明和优雅。希望以任何方式提供帮助!