Vim은 파일의 실시간 변경 사항을 모니터링 할 수 있습니다.


104

내 질문은 실시간으로 텍스트 파일을 모니터링하는 방법 과 비슷 하지만 vim에서하고 싶습니다. 열린 파일 사용 tail -f sample.xml파일을 읽을 수 있다는 것을 알고 있으며 새 콘텐츠가 파일에 기록되면 새 콘텐츠도 내 화면에 기록됩니다. 파일이 업데이트 될 때 vim이 새 데이터를 자동으로 채우도록 할 수 있습니까?

답변:


101

당신은 할 수 있습니다 :set autoread파일이 변경 될 때 vim이 파일을 읽도록 . 그러나 (플랫폼에 따라) 초점을 맞춰야합니다.

도움말에서 :

파일이 Vim 외부에서 변경된 것으로 감지되고 Vim 내부에서 변경되지 않은 경우 자동으로 다시 읽습니다. 파일이 삭제되면 이것은 수행되지 않습니다.


5
힌트 주셔서 감사합니다! 이것은 꽤 유망 해 보이지만 내 시스템에서는 작동하지 않습니다. (저는 MacVim으로 컴파일 된 vim 버전 7.2.303과 함께 Mac10.6.2 iTerm을 사용하고 있습니다. 시도 할 수있는 추가 의견이 있습니까?
Patrick

음, 꽤 이상 해요. macvim gui 또는 터미널 버전을 사용하고 있습니까? 그것은 미리 컴파일 된 macvim gui 다운로드와 함께 작동합니다. (하지만 내가 언급했듯이 초점을 맞추려면 앱을 클릭해야합니다.)
Peter

1
터미널에서 테스트하고 있었는데 gvim (MacVim GUI)을 사용한 후 기능이 작동하기 시작했습니다! 그래도 언급했듯이 콘텐츠를 업데이트하려면 gvim에 집중해야합니다. 집중하지 않아도 업데이트 할 수있는 트릭이 있습니까? 다시 도와 주셔서 감사합니다.
Patrick

3
불행히도 그에 대한 해결책을 모르겠습니다. vim이 포커스를 변경하지 않고 할 수 있다면 깜짝 놀랐을 것입니다. vim이 파일 시스템을 폴링하여 언제 변경되는지 확인해야합니다. 나는 당신이 그것을 위해 플러그인이 필요하다고 생각합니다.
피터

2
@Peter 얼마 전에 그런 플러그인을 만들었습니다 . 또한 이 질문과 그것에 대한 나의 대답을 참조하십시오 . autoread작동 방식 및 제한 사항에 대한 자세한 내용은
Martin Tournoij

63

자동으로 알지 못하지만 다음을 입력 할 수 있습니다.

:e!

파일을 다시로드하려면


이 접근 방식은 콘텐츠를 자동으로 업데이트하지 않지만 업데이트 된 콘텐츠를 표시합니다. 답변 해 주셔서 감사합니다!
Patrick

31

다음을 입력하십시오 .vimrc.

"정상 모드에서 4 초 동안 활동이 없으면 한 번 확인
자동 읽기 설정                                                                                                                                                                                    
au CursorHold * 체크 타임                                                                                                                                                                       

큰! 마지막으로 다시로드 한 후 해당 파일을 변경 한 경우 경고가 표시 되더라도 잘 작동합니다.
zoujyjs

1
첫 번째 대답은 저에게 효과가 없었지만 효과가 있습니다! :-)
Ionică Bizău

4
"4 초마다"는 사실이 아닙니다. 일반 모드에서 4 초 동안 사용하지 않으면 번만 확인 됩니다. 따라서 오랫동안 다른 버퍼에서 아무것도하지 않으면 업데이트되지 않지만 커서를 움직이고 4 초 동안 기다리면 업데이트됩니다. 또 다른 옵션은 ": checktime"을 수동으로 호출하여 업데이트하는 것입니다 (자동 읽기 설정 후). 불행히도 vim에는 어떤 종류의 폴링 지원도없는 것 같으므로 OP 질문에 대한 진정한 대답은 없습니다.
David Ljung Madison Stellar

1
방금 이것을 발견했습니다. 사용자 정의 함수를 호출하도록 체크 타임을 변경하고 함수 끝에 "call feedkeys ("lh ")"를 추가하면 4 초마다 실행됩니다.
flukus

당신이 맞다 @DavidLjungMadison,이 실수를 방지하기 위해 편집에 게시물을 갈거야
판 하이 꽝

9

@flukus가 이전 답변 에 대한 의견에서 말했듯 이 call feedkeys["lh"](커서를 오른쪽으로 이동하고 왼쪽으로 다시 이동하므로 로그 파일을 볼 때 일반적으로 해를 끼치 지 않습니다)

따라서 나머지 답변 을 결합 하면 필요할 때 ex (whithin vim)에서 실행할 수있는 oneliner가 있습니다.

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


((거의) 파일의 끝으로 이동하려면 피드 키와 함께 "lh"대신 "G"를 사용하십시오.)

설명 :
- autoread은 : 더 내부 타이머 또는 그런 일이없는, 외부에서 변경된 파일을 읽고 (하지만 자신의 작업을 나던 그것은 단지 정력이 예에서 명령과 같은 작업을 수행하는 파일을 읽습니다. :!
- CursorHold * checktime : 'updatetime'(기본값은 4000 밀리 초)에 지정된 시간 동안 사용자가 커서를 이동하지 않은 경우 파일 외부에서 변경 사항을 확인하는 checktime이 실행됩니다.
- feedkeys ( "lh") 호출 : 커서가 한 번, 오른쪽 및 왼쪽 뒤로 이동 한 다음 아무 일도 일어나지 않습니다 (... 즉, CursorHold가 트리거됨을 의미하며 루프 가 있음을 의미 합니다 ).

또한 :set syntax=logtalk로그에 색상을 지정할 수 있습니다.

를 사용할 때 스크롤을 중지하려면 다음을 call feedkeys("G")실행하십시오 :set noautoread. 이제 vim이 파일이 변경되었음을 알리고 변경 내용을 읽을 것인지 묻습니다)

(부작용이 있습니까?)

편집 : 한 가지 부작용이 있습니다. 피드 키에 "G"를 사용하면 현재 열려있는 모든 버퍼가 아래로 스크롤됩니다. 따라서 오른쪽 버퍼가 로그 파일을 자동으로 아래로 스크롤하는 동안 분할 창의 왼쪽 버퍼에서 작업 할 수 없습니다.


4

이것을 .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
이것은 터미널 자동 읽기 단점을 해결하기 위해 선호되는 답변입니다.
mcanfield

3
@mcanfield 아니요, 아직 "변경 사항을 감시"하지 않기 때문입니다. 당신은 여전히 빔이 활성화되어 있어야합니다과는 여전히 사건의 제한된에 폴링 (보고하지 않음). 한 번CursorHold 실행 됩니다. 따라서 나가서 커피를 마시거나 다른 창에서 무언가를하는 경우 업데이트 되지 않습니다 .
Martin Tournoij 2016 년

4
이 스크립트는 Vim 플러그인 : vim-autoread 로도 번들로 제공됩니다 .
stephen.hanson

1
@ stephen.hanson 링크 주셔서 감사합니다, 그 플러그인은 저에게 잘 작동합니다!
Tropilio


2

Unix + neovim 인 경우

:term tail -f <filename>

분명히 이것이 모든 사람에게 효과가있는 것은 아니지만 내가하는 방법입니다.



0

VIM은 파일이 업데이트 될 때 경고를 표시하므로 파일을 연 이후에 변경된 내용을 덮어 쓰지 않습니다. 이때 파일을 다시로드하라는 메시지가 표시됩니다.


1
답변 해 주셔서 감사합니다.하지만 내 시스템에서 파일이 변경되었을 때 vim이 경고하지 않았습니다. (
Patrick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.