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)
:!{cmd}
执行{cmd}
与外壳并设置v:shell_error
。
如果你碰巧设置映射打电话给你的过滤器,你可以不喜欢以下:
function! UndoIfShellError()
if v:shell_error
undo
endif
endfuntion
nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR>
好戏:)。实际上,我希望为我刚刚忽略的!{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
它的复杂看到我的完整的代码,但它的工作原理,当它的使用,这是相当透明和优雅。希望以任何方式提供帮助!
当然!对于每一种“真正”的脚本语言,这根本就不是问题。没有想到这一点。尽管如果可能的话,我宁愿使用vim脚本,因为我不希望对脚本有更多的依赖关系。 – ahe 2010-04-04 20:49:07
我只知道另一种方法:使用'system()',将stderr重定向到一个临时文件(或'/ dev/null'),将stdout保存到某个变量并使用'v:shell_error'来确定命令是否失败覆盖缓冲区。请注意,':!'过滤器用前一个命令替换«!»,用'当前文件名替换«%»,而'system()'不替换。 – ZyX 2010-04-04 20:56:37