在Vim中,我可以“流式传输”例如输出“w!ruby”进入缓冲区,逐行输出?

时间:2011-03-16 18:24:54

标签: vim

我现在正在做这样的事情:

redir => m
  silent w ! ruby
redir END
new
put=m

它以Ruby代码的形式执行当前缓冲区的内容,并将输出放在新的缓冲区中。

但是如果我运行的Ruby代码类似于

puts "start"
sleep 10
puts "end"

然后我会看到没有输出10秒,然后同时“开始”和“结束”。

是否有某种方法将输出“流”输出到缓冲区,逐行显示?所以我会看到“开始”,然后10秒后我会看到“结束”?类似于我刚刚做的事情

w ! ruby

并查看命令行下的输出。

3 个答案:

答案 0 :(得分:2)

Vim并没有真正公开这种I / O的原语,但你可以从其中一个嵌入式语言接口中完成它。

这是使用Python和subprocess的草图(Ruby看起来很相似;请参阅if_ruby):

python << EOF
import vim
import subprocess

def output_lines_to_buffer(cmd):
    """
    Append the given shell command's output linewise to the current buffer.
    """
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    for line in iter(p.stdout.readline, ''):
        vim.current.buffer.append(line)
        vim.command('redraw')
EOF

使用:

:python output_lines_to_buffer('my command')

这将简单地将每行输出附加到当前缓冲区的末尾,因为my command会发出它。您可以相当直接地扩展它以支持输入和输出范围等,具体取决于您的需要。

答案 1 :(得分:0)

所以一个可能的解决方案(希望不是最好的解决方案)是写入磁盘上的文件,在缓冲区中打开该文件并执行:setlocal autoread,以便文件在更改时自动更新。

这种自动更新看起来非常粗糙。 Tail Bundle.vim似乎有所改善。

希望得到更好的答案。

答案 2 :(得分:0)

如何使用使用tee的tee:make

let fname = tempname()
exec "w ! ruby 2>&1 | tee ".fname
exec "new ".fname

编辑:看起来像是在Linux上,或者是在管道化进程之间创建4K缓冲区的操作系统。要解决此问题,请安装expectsudo apt-get install expect-dev)并使用unbuffer命令逐行进行流式传输(请参阅:https://stackoverflow.com/questions/1000674/turn-off-buffering-in-pipe)。

let fname = tempname()
exec "! unbuffer ruby % 2>&1 | tee ".fname
exec "new ".fname