Automatyczne ponowne ładowanie pliku w VIM, gdy tylko zmieni się on na dysku


33

Zakładając, że plik nie ma niezapisanych zmian w buforze VIM, chciałbym, aby przeładował się automatycznie, jeśli plik zmieni się na dysku. Najczęstszym przypadkiem użycia jest to, gdy aktualizuję kopię roboczą, w której znajduje się plik.

Jak mogę to osiągnąć?


Myślę, że właśnie to masz na myśli, ale moim szczególnym przypadkiem użycia jest to, że kiedy sprawdzam inną gałąź lub zatwierdzenie git, chcę, aby vim ponownie załadował plik.
Nathan Long

Odpowiedzi:


32

W twoim ~/.vimrc:

set autoread

9
Zasadniczo autoreaduruchamia się dopiero po wykonaniu zewnętrznego polecenia. Ta odpowiedź szczegółowo opisuje rozwiązania.
Tom Hale

To nie działa Aby uzyskać szczegółową odpowiedź, skorzystaj z łącza
@TomHale

11

To działało dla mnie

set autoread                                                                                                                                                                                    
au CursorHold * checktime  

Pierwszy wiersz sam w sobie nie wystarczał. Możesz w siebie włożyć.vimrc

podziękowania dla Phan Hai Quanga


Autocmd nie powinien być konieczny - checktime ma się uruchamiać wewnętrznie w tym samym czasie, gdy uruchamiane jest zdarzenie CursorHold. Innymi słowy, właśnie zmuszasz Vima do wykonania drugiego przeglądu.
Heptite

Dla mnie jest to konieczne. Najlepsze rozwiązanie, jakie znalazłem po wielu badaniach. @Heptite, czy masz rozdział i wiersz dla swojego twierdzenia?
Tom Hale

1
@TomHale Przejrzałem dokumenty Vima i, o ile wiem, nie mówi wprost, ale „ :help timestamp” wydaje się wskazywać, że to ja popełniłem błąd, i że Vim sprawdza tylko określone zdarzenia, więc autocmd może być konieczne, aby spowodować częstsze sprawdzanie.
Heptyt

5

Autoread nie działa poprawnie. Poniższe działa dla mnie:

Najpierw musisz zainstalować skrypt tutaj .

Najlepsze wyniki uzyskałem, wywołując bezpośrednio funkcję konfiguracji, w ten sposób.

let autoreadargs={'autoread':1} 
execute WatchForChanges("*",autoreadargs) 

Powodem tego jest to, że chcę uruchomić konfigurację ipython / screen / vim.

Możesz łatwo przekonwertować to na ulepszoną wersję widoku.

napisz proces…

mkdir -p ~/bin
cat <<`OUT` > ~/bin/vimviewer
#!/usr/bin/env sh
exec vim -n --cmd "source /home/bryan/.vim/.vimrc.watchforchanges | let autoreadargs={'autoread':1} | execute WatchForChanges('*',autoreadargs)" $@
`OUT`

chmod 755 ~/bin/vimviewer
vimview test.txt

1
Jeśli używasz jednego z graficznych interfejsów użytkownika vim, takich jak gVim lub MacVim, komenda autoread dobrze integruje się z resztą środowiska. Np. Edycja pliku w innym programie, innym edytorze lub z poziomu kontroli źródła, a następnie przełączenie z powrotem na vim spowoduje automatyczne ponowne zaktualizowanie plików. Problemem wydaje się być sposób, w jaki integruje się terminalowa wersja vima. Wersja terminala nie może określić, kiedy przełączasz się między programami w interfejsie GUI lub za pomocą multiplekserów terminali, takich jak tmux, więc nie można automatycznie czytać w odpowiednich momentach. Byłoby miło, gdyby vim subskrybował odpowiednie zdarzenia w systemie plików.
bames53

3

Do tej pory działała dla mnie wtyczka vim-autoread :

vim-autoread

Automatycznie powoduje, że vim przeładowuje pliki, które zostały zapisane na dysku, ale nie zostały zmodyfikowane w buforze od ostatniego zapisu z vima. Umożliwia to edycję pliku otwartego w vimie przy użyciu innej aplikacji i zapisanie go. Po powrocie do vima, dopóki plik nie został zmodyfikowany od ostatniej zmiany, plik zostanie automatycznie zaktualizowany, aby odzwierciedlić zmiany dokonane na dysku, tak jakbyś nacisnął: e ręcznie.


Chociaż ten link może odpowiedzieć na pytanie, lepiej jest dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie. - Z recenzji
Burgi

@Burgi Dodałem opis wtyczki, który wyjaśnia, w jaki sposób rozwiązuje problem.
Wojtek Kruszewski

Próbowałem, ale muszę wpisać polecenie nawigacyjne (jak j), aby zobaczyć skuteczną aktualizację. Stworzyłem tutaj problem na ten temat: github.com/djoshea/vim-autoread/issues/3
Martin Delille

3

z tej odpowiedzi (nawiązującej do odpowiedzi PhanHaiQuang i komentarza @flukus)

Można uruchomić ten oneliner z ex (whithin vim) w razie potrzeby (lub umieścić każde polecenie w vimrc, na wypadek, gdy pliki dziennika są otwarte).

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

Objaśnienie:
- autoread : czyta plik po zmianie z zewnątrz (ale nie działa samodzielnie, nie ma wewnętrznego timera ani czegoś takiego. Odczyta plik tylko wtedy, gdy vim wykona akcję, jak polecenie w ex :!
- CursorHold * checktime : gdy kursor nie zostanie przesunięty przez użytkownika na czas określony w „updatetime” (domyślnie jest to 4000 milisekund), wykonywany jest checktime, który sprawdza zmiany spoza pliku
- wywołuje klawisze feed ((lh)) : kursor przesuwa się raz, w prawo i wstecz w lewo. i wtedy nic się nie dzieje (... co oznacza, że ​​uruchamiane jest CursorHold, co oznacza, że ​​mamy pętlę )


lhnic nie robi, jeśli kursor znajdzie się na ostatniej pozycji w linii, lhzmieni swoje położenie.
Mahmoud Al-Qudsi,

Właśnie o to chodzi. Plik jest ponownie ładowany z minimalną interakcją lub zmianami w pliku. Możesz przeskoczyć do ostatniej lub pierwszej linii, jeśli chcesz (po prostu zamień lh na gg lub G), ale celem tutaj jest po prostu ponowne załadowanie pliku w vimie, i to właśnie jest zrobione przez ten jeden wiersz, nic więcej. Co lubisz tu robić?
eli

@ MahmoudAl-Qudsi ... co oznacza, że ​​„lh” po prostu uruchamia akcję CursorHold (wspomniałem o tym w Objaśnieniu), która następnie ponownie uruchamia autoread
eli

1

Istnieje kilka wtyczek wymienionych tutaj, które mogą działać w zależności od wersji Vima.

Innym podejściem jest okresowe wysyłanie checktimepolecenia vim z zewnętrznego procesu. Oto skrypt ShellJS, aby to zrobić (wymaga shelljs-plugin-sleepNeoVim i nvr)

while (true) {
  sleep(15);
  var servernames = exec('nvr --serverlist').trim().split('\n');
  if (!servernames.length || !servernames[0]) {
    continue;
  }
  servernames.forEach(
    (sn) => exec(`nvr -c "checktime" --servername ${sn}`) );
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.