代码之家  ›  专栏  ›  技术社区  ›  ahe

VIM过滤器和stdout/stderr

vim
  •  9
  • ahe  · 技术社区  · 14 年前

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

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

    另外,在编写自定义VIM脚本进行过滤时,我也遇到了类似的问题。我有一个脚本,它用System()调用一个过滤器程序,并用它的输出替换缓冲区中的文件,但似乎没有一种方法来检测System()返回的行是写入stdout还是stderr。有没有办法在vim脚本中区分它们?

    4 回复  |  直到 14 年前
        1
  •  3
  •   ZyX    14 年前

    您可以使用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
  •  5
  •   Curt Nelson    14 年前

    :!{cmd} 执行 {cmd} 有壳有套 v:shell_error .

    如果您碰巧设置了调用过滤器的映射,则可以执行以下操作:

    function! UndoIfShellError()
        if v:shell_error
            undo
        endif
    endfuntion
    
    nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR>
    
        3
  •  1
  •   sergeant    14 年前

    另一种方法是运行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>
    

    说明: 保存文件 :静音-避免在末尾按Enter键 %-将文件传递给gofmt -w=真-告诉gofmt写回文件 :e-告诉VIM重新加载修改过的文件

        4
  •  0
  •   Peter Kay    7 年前

    这就是我最后所做的:

    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

    它很复杂,但它很管用,而且使用后,它相当透明和优雅。希望这有任何帮助!