Может ли Vim отслеживать изменения в файле в реальном времени - PullRequest
97 голосов
/ 29 января 2010

Мой вопрос похож на этот , как контролировать текстовый файл в режиме реального времени но я хочу сделать это в VIM. Я знаю, что могу прочитать открытый файл, используя файл tail -f sample.xml, и когда новое содержимое записывается в файл, оно также записывает новое содержимое на мой экран. Могу ли я, чтобы vim автоматически заполнял новые данные при обновлении файла?

Ответы [ 9 ]

94 голосов
/ 29 января 2010

Вы можете :set autoread, чтобы vim читал файл при его изменении. Однако (в зависимости от вашей платформы) вы должны уделить этому внимание.

Из справки:

Когда файл был обнаружен, чтобы иметь был изменен за пределами Vim, и это не был изменен внутри Vim, автоматически прочитайте это снова. Когда файл был удален это не сделано.

62 голосов
/ 29 января 2010

Не знаю автоматически, но вы можете ввести:

:e!

для перезагрузки файла

29 голосов
/ 18 сентября 2013

Добавьте в ваш .vimrc следующее:

" check one time after 4s of inactivity in normal mode
set autoread                                                                                                                                                                                    
au CursorHold * checktime                                                                                                                                                                       
8 голосов
/ 17 января 2018

как @flukus сказал в комментарии к предыдущему ответу вы можете call feedkeys["lh"] (он перемещает курсор вправо и назад влево, что обычно не приносит вреда при просмотре журнала файл)

Итак, если вы объедините оставшуюся часть ответа , у вас будет oneliner, который вы можете запускать из ex (с vim) при необходимости:

:set autoread | au CursorHold * checktime | call feedkeys("lh")


(если вы хотите перейти (почти) к концу файла, просто используйте «G» вместо «lh» с клавишами подачи)

Пояснение:
- autoread : читает файл при изменении извне (но он не работает сам по себе, нет внутреннего таймера или чего-то в этом роде. Он будет читать файл только когда vim выполняет действие, например, команда в ex :!
- CursorHold * checktime : когда пользователь не перемещает курсор в течение времени, указанного в 'updatetime' (которое по умолчанию составляет 4000 миллисекунд), выполняется контрольное время, которое проверяет изменения вне файла
- call feedkeys ("lh") : курсор перемещается один раз, вправо и назад влево. и тогда ничего не происходит (... что означает, что CursorHold запущен, что означает, что у нас есть loop )

Дополнительно вы можете :set syntax=logtalk раскрасить бревно

Чтобы остановить прокрутку при использовании call feedkeys("G"), выполните :set noautoread - теперь vim скажет, что файл был изменен и спросит, хотите ли вы прочитать изменения или нет)

(есть ли у него побочные эффекты?)

Редактировать: Я вижу один побочный эффект: если кто-то использует "G" в качестве кнопки подачи, он будет прокручивать вниз каждый текущий открытый буфер ?! Таким образом, невозможно работать в левом буфере окна разделенного окна, пока правый буфер автоматически прокручивает файл журнала вниз

3 голосов
/ 29 января 2010

Tail Bundle должен делать то, что вы хотите. Обратите внимание, я не использовал его сам.

2 голосов
/ 29 сентября 2016

Если unix + неовим

:term tail -f <filename>

Очевидно, что это не будет работать для всех, но я так и делаю.

2 голосов
/ 16 августа 2015

Вставьте это в свой .vimrc, и он должен работать как босс (Взято из: http://vim.wikia.com/wiki/Have_Vim_check_automatically_if_the_file_has_changed_externally)

" Function to Watch for changes if buffer changed on disk
function! WatchForChanges(bufname, ...)
  " Figure out which options are in effect
  if a:bufname == '*'
    let id = 'WatchForChanges'.'AnyBuffer'
    " If you try to do checktime *, you'll get E93: More than one match for * is given
    let bufspec = ''
  else
    if bufnr(a:bufname) == -1
      echoerr "Buffer " . a:bufname . " doesn't exist"
      return
    end
    let id = 'WatchForChanges'.bufnr(a:bufname)
    let bufspec = a:bufname
  end
  if len(a:000) == 0
    let options = {}
  else
    if type(a:1) == type({})
      let options = a:1
    else
      echoerr "Argument must be a Dict"
    end
  end
  let autoread    = has_key(options, 'autoread')    ? options['autoread']    : 0
  let toggle      = has_key(options, 'toggle')      ? options['toggle']      : 0
  let disable     = has_key(options, 'disable')     ? options['disable']     : 0
  let more_events = has_key(options, 'more_events') ? options['more_events'] : 1
  let while_in_this_buffer_only = has_key(options, 'while_in_this_buffer_only') ? options['while_in_this_buffer_only'] : 0
  if while_in_this_buffer_only
    let event_bufspec = a:bufname
  else
    let event_bufspec = '*'
  end
  let reg_saved = @"
  "let autoread_saved = &autoread
  let msg = "\n"
  " Check to see if the autocommand already exists
  redir @"
    silent! exec 'au '.id
  redir END
  let l:defined = (@" !~ 'E216: No such group or event:')
  " If not yet defined...
  if !l:defined
    if l:autoread
      let msg = msg . 'Autoread enabled - '
      if a:bufname == '*'
        set autoread
      else
        setlocal autoread
      end
    end
    silent! exec 'augroup '.id
      if a:bufname != '*'
        "exec "au BufDelete    ".a:bufname . " :silent! au! ".id . " | silent! augroup! ".id
        "exec "au BufDelete    ".a:bufname . " :echomsg 'Removing autocommands for ".id."' | au! ".id . " | augroup! ".id
        exec "au BufDelete    ".a:bufname . " execute 'au! ".id."' | execute 'augroup! ".id."'"
      end
        exec "au BufEnter     ".event_bufspec . " :checktime ".bufspec
        exec "au CursorHold   ".event_bufspec . " :checktime ".bufspec
        exec "au CursorHoldI  ".event_bufspec . " :checktime ".bufspec
      " The following events might slow things down so we provide a way to disable them...
      " vim docs warn:
      "   Careful: Don't do anything that the user does
      "   not expect or that is slow.
      if more_events
        exec "au CursorMoved  ".event_bufspec . " :checktime ".bufspec
        exec "au CursorMovedI ".event_bufspec . " :checktime ".bufspec
      end
    augroup END
    let msg = msg . 'Now watching ' . bufspec . ' for external updates...'
  end
  " If they want to disable it, or it is defined and they want to toggle it,
  if l:disable || (l:toggle && l:defined)
    if l:autoread
      let msg = msg . 'Autoread disabled - '
      if a:bufname == '*'
        set noautoread
      else
        setlocal noautoread
      end
    end
    " Using an autogroup allows us to remove it easily with the following
    " command. If we do not use an autogroup, we cannot remove this
    " single :checktime command
    " augroup! checkforupdates
    silent! exec 'au! '.id
    silent! exec 'augroup! '.id
    let msg = msg . 'No longer watching ' . bufspec . ' for external updates.'
  elseif l:defined
    let msg = msg . 'Already watching ' . bufspec . ' for external updates'
  end
  echo msg
  let @"=reg_saved
endfunction

let autoreadargs={'autoread':1}
execute WatchForChanges("*",autoreadargs)
1 голос
/ 31 марта 2017

Есть также плагин:

https://github.com/djoshea/vim-autoread

Это был единственный способ заставить эту работу работать на OSX.

0 голосов
/ 29 января 2010

VIM предупредит вас, когда файл будет обновлен, чтобы вы не перезаписывали изменения, внесенные с момента его открытия. В этот момент вам будет предложено перезагрузить файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...