autoread
来使Vim重读该文件,只要我将键盘焦点切换到该文件,它就会执行该操作。即使我不切换键盘焦点,也可以使Vim更新缓冲区吗? ?我已经尝试设置
checktime
,但是当键盘焦点位于其他位置时,它似乎没有任何作用。我正在监视的输出将完全替换输出文件。而且我不希望Q4312079q它。还有其他选择,例如每次都管道传输到新实例,或管道传输到
tail -f
之类,但是如果可以使用VIm完成,那将是很酷的。#1 楼
:help 'autoread'
没有很多有关它如何工作的信息,但是Vim会检查打开的文件在某些事件中是否被修改(它总是这样做),如果能够启用autoread
,它将自动重新加载它。具体来说,它检查何时:
使用
:checktime
; 输入缓冲区;
使用
:diffupdate
; :e
是针对已经具有缓冲区的文件发出的; 使用
!
执行外部命令; 返回到前台(
^Z
,fg
,仅当Shell具有作业控制权时) ; 对于gVim,也可以在以下情况下完成:
关闭“右键单击”菜单(通过选择某些内容或仅通过关闭它) ;
焦点已更改(这是您已经注意到的);
如果从菜单中使用“文件->打开”,“文件->另存为”,则关闭弹出的文件浏览器对话框。以及其他一些地方)。
我通过查找所有对Vim的调用从Vim源中收集了这些信息。
buf_check_timestamp()
,check_timestamps()
功能和need_check_timestamps
设置为TRUE
的位置。该列表可能由于我查看了2015年而过时,但乍一看似乎仍然(大多数)准确。关键是Vim仅检查文件是否在文件中被修改。情况非常有限。这是有道理的,因为每n秒轮询潜在的大量缓冲区可能会非常昂贵。
自Vim 7.4.1578(2016年3月)以来,就有一些计时器,您可以使用它们在每n次运行
checktime
秒(此答案的先前版本是2015年的版本,使用了变通方法)。例如,仅对某些缓冲区执行此操作,您可以使用以下命令:set autoread
fun! s:checktime(timer_id)
checktime
endfun
autocmd BufNewFile,BufReadPost xxx
\ call timer_start(3000, function('s:checktime'), {'repeat': -1})
的缺点是设置了很多计时器,所以也许更好的方法是设置一个在所有缓冲区上循环的计时器,然后再次设置计时器(这样就不必冒着同时运行两个计时器的风险) :
set autoread
fun! s:checktime(timer_id)
for buf in filter(map(getbufinfo(), {_, v -> v.bufnr}), {_, v -> buflisted(v)})
echom buf
exe 'checktime' buf
endfor
call timer_start(3000, function('s:checktime'))
endfun
call timer_start(3000, function('s:checktime'))
我确实注意到Vim眨了眨眼,即使没有任何变化。不知道是否有解决该问题的方法(没有看);因此,您可能希望将其添加为仅在需要时运行的命令:
set autoread
let s:autoread_timer = -1
fun! s:checktime(timer_id)
checktime
endfun
command! -bang Autoread
\ if <bang>0
\| call timer_stop(s:autoread_timer)
\| else
\| let s:autoread_timer = timer_start(1000,
\ function('s:checktime'), {'repeat': -1})
\| endif
有很多方法可以对此进行进一步改进,例如仅针对当前缓冲区,对运行频率的更多控制等等),但是这个想法应该很清楚:-)
#2 楼
从这个答案(参考PhanHaiQuang的答案和flukus的评论)一个人可以在需要时从ex(whitin vim)运行此oneliner(或将每个命令放在vimrc中,以获取日志文件)打开。)
:set autoread | au CursorHold * checktime | call feedkeys("lh")
说明:
-自动读取:从外部更改时读取文件(但它本身不能工作,没有内部计时器或类似的计时器。它只会在vim进行操作时读取文件,例如ex
:!
中的命令-CursorHold * checktime:当用户在'中指定的时间未移动光标时updatetime”(默认为4000毫秒),将执行checktime,它检查文件外部的更改
-调用feedkeys(“ lh”):光标向左,向右和向左移动一次,然后什么也没有发生(...,这意味着CursorHold被触发,这意味着我们有一个循环)
#3 楼
我做了一个小插件vim-autoread,它使用tail -f
异步更新后台的缓冲区。显然,这需要Vim版本8的工作功能。使用
:AutoRead
将其打开,并使用:AutoRead!
将其关闭。 评论
兼容NeoVim的版本会很棒!
–安德鲁(Andrew)
17年8月1日在22:05
@AndrewMacFie我不明白,为什么这在Neovim上不起作用。
–克里斯蒂安·布拉班特(Christian Brabandt)
17年8月2日在6:10
我认为NeoVim中缺少Vim 8工作支持吗?
–安德鲁(Andrew)
17年8月2日在17:52
@AndrewMacFie哦,那可能是真的。由于我不使用neovim,因此无法使其兼容NeoVim。但是,公关将是受欢迎的:)
–克里斯蒂安·布拉班特(Christian Brabandt)
17年8月2日在19:05
很公平 : )
–安德鲁(Andrew)
17年8月2日在22:18
#4 楼
在Neovim中,您可以使用以下命令来打开运行tail命令的终端缓冲区。:enew | call termopen('tail --follow=name --retry /path/to/file.log')
即使删除并重新创建了文件,该命令也将继续起作用。
或将以下内容添加到您的
$MYVIMRC
" :Tail /path/to/file
function! Tail(file)
enew
call termopen('tail --follow=name --retry ' . fnameescape(a:file))
endfunction
command! -nargs=1 Tail call Tail(<f-args>)
评论
@Carpetsmoker CursorHold事件如何?如果Vim没有焦点,它应该每n秒触发一次。@muru不,CursorHold仅执行一次,其明确记录为:“如果您离开Vim来煮咖啡,则不会每隔'updatetime'ms触发一次。:)“
我再次删除了gvim标记,希望没问题;-)正如我所看到的,这个问题与gVim无关,因为焦点更改只是Vim检查文件是否已更改的一个事件(有一整堆,请参阅我的答案以了解详细信息)。大多数(如果不是全部)的改进方法在Vim和gVim中都可以正常工作。
@Carpetsmoker啊,我的印象是gVim在有键盘焦点的情况下会定期检查(因此使它成为gVim问题),但看来我弄错了。感谢您清理。