Автоматическая перезагрузка файла в VIM, как только он изменяется на диске

33

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

Как мне этого добиться?

ГДж.
источник
Я думаю, это то, что вы имеете в виду, но мой конкретный случай использования - когда я проверяю другую ветку git или коммит, я хочу, чтобы vim перезагрузил файл.
Натан Лонг,

Ответы:

32

В вашем ~/.vimrc:

set autoread
Бенджамин Банье
источник
9
Обычно autoreadсрабатывает только после выполнения внешней команды. Этот ответ детализирует решения.
Том Хейл,
Это не работает. Перейдите по ссылке @TomHale, чтобы получить подробный ответ
JonnyRaa
11

Это то, что сработало для меня

set autoread                                                                                                                                                                                    
au CursorHold * checktime  

Первая строка не была достаточно сама по себе. Вы можете положить в себя.vimrc

кредит Фан Хай Куанг

ErichBSchulz
источник
Autocmd не должен быть необходим - контрольное время должно запускаться изнутри в то же время, когда вызывается событие CursorHold. Другими словами, вы просто заставляете Vim делать второй контроль.
Гептит
Для меня это необходимо. Лучшее решение, которое я нашел после большого количества исследований. @ Hepite, у тебя есть глава и стих для твоего утверждения?
Том Хейл,
1
@ TomHale Я просмотрел документы Vim, и там, насколько я могу судить, явно не сказано, но :help timestamp, похоже, "" указывает на то, что я ошибся, а Vim выполняет проверку только определенных событий, поэтому autocmd может понадобиться для более частой проверки.
Гепт
5

Авточитание не работает правильно. Следующие работы для меня:

Вам необходимо сначала установить скрипт здесь .

Я получил лучшие результаты, вызвав функцию настройки напрямую, вот так.

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

Причина этого в том, что я хочу запустить установку ipython / screen / vim.

Вы можете легко преобразовать это в расширенную версию представления.

Сценарий процесса ..

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
Если вы используете один из графических интерфейсов vim, например gVim или MacVim, то команда autoread прекрасно интегрируется с остальной средой. Например, редактирование файла в какой-либо другой программе, другом редакторе или из системы управления версиями, а затем переключение обратно в vim автоматически прочитает обновленные файлы. Кажется, проблема в том, как интегрируется терминальная версия vim. Версия терминала не может определить, когда вы переключаетесь между программами в графическом интерфейсе или с помощью терминальных мультиплексоров, таких как tmux, поэтому она не может автоматически считываться в соответствующие моменты времени. Было бы хорошо, если бы vim просто подписывался на соответствующие события файловой системы.
bames53
3

Плагин vim-autoread сработал для меня до сих пор:

ВИМ-AutoRead

Автоматически заставляет vim перезагружать файлы, которые были записаны на диск, но не изменены в буфере с момента последней записи из vim. Это позволяет редактировать открытый файл в vim с помощью другого приложения и сохранять его. По возвращении в vim, если вы не изменили файл с момента последнего изменения, файл будет автоматически обновлен, чтобы отразить изменения, сделанные на диске, как если бы вы нажали: e вручную.

Войтек Крушевский
источник
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. - Из обзора
Бурги
@Burgi Я добавил описание плагина, которое объясняет, как оно решает проблему.
Войтек Крушевский
Я попробовал это, но я должен напечатать команду навигации (как j), чтобы увидеть эффективное обновление. Я создал здесь проблему по этому поводу: github.com/djoshea/vim-autoread/issues/3
Мартин Делиль
3

из этого ответа (ссылаясь на ответ PhanHaiQuang и комментарий @flukus)

При необходимости можно запустить этот oneliner из ex (с vim) (или поместить каждую команду в vimrc, когда открываются лог-файлы).

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

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

Eli
источник
lhничего не делает, если курсор находится на последней позиции в строке, lhизменит свое местоположение.
Махмуд Аль-Кудси
Именно так и есть. Файл перезагружается с минимальным взаимодействием или изменениями в файле. Вы можете перейти к последней или первой строке, если хотите (просто замените lh на gg или G), но цель здесь - просто перезагрузить файл в vim, и это то, что делает эта однострочная строка, не более того. Что тебе нравится делать здесь?
Или
@ MahmoudAl-Qudsi ... это означает, что "lh" просто запускает действие CursorHold (я упомянул об этом в объяснении), которое затем снова запускает авточитание
eli
1

Есть некоторые плагины , перечисленные здесь , которые могли бы работать в зависимости от версии Vim.

Другой подход заключается в периодической отправке checktimeкоманды vim из внешнего процесса. Вот сценарий ShellJS для этого (требуется shelljs-plugin-sleepNeoVim и 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}`) );
}
Эндрю
источник