vim过滤器和标准输出/标准输出
当我使用:%!要通过筛选器运行文件内容,筛选器失败(它返回的代码不是0)并向stderr打印错误消息,我将用此错误消息替换我的文件。如果过滤器返回指示错误和/或忽略过滤器程序写入stderr的输出的状态代码,是否有方法告诉vim跳过过滤 在某些情况下,您希望用过滤器的输出替换文件,但这种行为通常是错误的。当然,我可以用一个键取消过滤,但这不是最优的vim过滤器和标准输出/标准输出,vim,Vim,当我使用:%!要通过筛选器运行文件内容,筛选器失败(它返回的代码不是0)并向stderr打印错误消息,我将用此错误消息替换我的文件。如果过滤器返回指示错误和/或忽略过滤器程序写入stderr的输出的状态代码,是否有方法告诉vim跳过过滤 在某些情况下,您希望用过滤器的输出替换文件,但这种行为通常是错误的。当然,我可以用一个键取消过滤,但这不是最优的 在编写自定义vim脚本进行过滤时,我也遇到了类似的问题。我有一个脚本,它用system()调用一个过滤器程序,并用它的输出替换缓冲区中的文件,但似乎
在编写自定义vim脚本进行过滤时,我也遇到了类似的问题。我有一个脚本,它用system()调用一个过滤器程序,并用它的输出替换缓冲区中的文件,但似乎没有办法检测system()返回的行是否写入到stdout或stderr。有没有办法在vim脚本中区分它们?您可以使用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)
:!{cmd}
使用shell执行{cmd}
,并设置v:shell\u错误
如果您碰巧设置了映射以调用过滤器,则可以执行以下操作:
function! UndoIfShellError()
if v:shell_error
undo
endif
endfuntion
nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR>
函数!UndoIfShellError()
如果v:shell\u错误
解开
恩迪夫
终末功能
nmap筛选器:%/路径/to/filter:调用UndoIfShellError()
另一种方法是运行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:安静!gofmt-w=真%:e
女:安静!gofmt-w=真%:e
说明:
:w-保存文件
:静音-避免在结束时按enter键
%-将文件传递给gofmt
-w=true-告诉gofmt写回文件
:e-告诉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.
函数MakeItAFunction(第1行、第2行、参数)
让l:results=system()“通过system或systemlist调用筛选器
如果v:shell\u错误
“事实上没有任何改变!
echom“etc错误”
回波结果
恩迪夫
“如果需要,处理结果如何?
“删除行但不放入寄存器:
执行a:line1.,.a:line2.“正常\”\u dd
调用append(a:line1-1,l:result)“添加行
将光标(a:line1,1)“调回起始位置
“回传任何信息
端功能
命令范围函数(,,)
”“或者,等等。
您可以在以下位置查看我的完整代码:
它很复杂,但可以工作,而且在使用时相当透明和优雅。希望这能有所帮助!在Vim 7中添加了新的自动命令事件:
ShellCmdPost
和ShellFilterPost
augroup FILTER_ERROR
au!
autocmd ShellFilterPost * if v:shell_error | undo | endif
augroup END
当然!对于每一种“真正的”脚本语言来说,这根本不是问题。我没有考虑过这一点。尽管我更喜欢vim脚本,如果可能的话,因为我不想对脚本有太多的依赖性。我只知道另一种方法:使用
system()
,将stderr重定向到临时文件(或/dev/null
),将stdout保存到某个变量,并使用v:shell_error
确定在覆盖缓冲区之前命令是否失败。注意,:!
过滤器将«!»替换为以前的命令,«%»替换为当前文件名,而系统()
则不会。这是一个很好的技巧:)。实际上,我希望为:!{cmd}语法,我刚刚忽略了它。但是我越来越担心没有这样的替代语法存在。