I want vim to open up the :Explorer when no file is opened or created. Eg. when I call vim without any options.
calling vim newfile.txt should still behave the normal way though.
How would I go about doing this? I can't seem to find the correct autocmd for it.
If you want to do this for vim invocation only, the best way is to use argc():
autocmd VimEnter * :if argc() is 0 | Explore | endif
argc() function returns a number of filenames specified on command-line when vim was invoked unless something modified arguments list, more information at :h argc().
Found the answer myself:
"open to Explorer when no file is opened
function! TabIsEmpty()
" Remember which window we're in at the moment
let initial_win_num = winnr()
let win_count = 0
" Add the length of the file name on to count:
" this will be 0 if there is no file name
windo let win_count += len(expand('%'))
" Go back to the initial window
exe initial_win_num . "wincmd w"
" Check count
if win_count == 0
" Tab page is empty
return 1
else
return 0
endif
endfunction
" Test it like this:
" echo TabIsEmpty()
function! OpenExplorer()
if (TabIsEmpty())
:Explore
end
endfunction
The greatest part of this code was taken from this question.
Related
I have 8 square (equal) windows in my vim screen spanning over 2 large monitors and I want to refer each of them with shortcuts < A-1 >, < A-2 > ... . There is a command in vim N-wincmd-wincmd that allows to to reference to the window by its number, but it is useless for me because other plugins sometimes create windows (like syntastic for syntax checking) and referring by number doesn't exactly matches the correct window. I thought maybe I could reference windows by names, so the question is, how do I set a name to some window, and then make a short cut so the cursor goes to the window with that name when pressing < A - n > where n is the window number?
The following lets you save a static extra window number for each visible window, and then jump to it quickly.
Just call :MarkWins when your layout is clean, and then the mappings <A-1>, <A-2>... will jump to the good window, even if new windows were created after that.
" Mark all visible windows from 1 :
command! MarkWins call s:mark_windows()
" Go to a previously marked window :
command! -nargs=1 GoToMarkedWin call s:go_to_marked_win(<f-args>)
" Mappings (Alt-1, Alt-2...) :
for s:n in range(1,8)
exe printf('noremap <silent> <a-%d> :GoToMarkedWin %d<cr>', s:n, s:n)
endfor
function! s:mark_windows()
let l:old_winnr = winnr()
windo let w:win_mark = winnr()
exe printf('%d wincmd w', l:old_winnr)
endf
function! s:go_to_marked_win(n)
let l:old_winnr = winnr()
while 1
if exists('w:win_mark') && w:win_mark == a:n
return
endif
wincmd w
if winnr() == l:old_winnr | return | endif
endw
endf
I can traverse NERDTree, but to see file content I press go, and once opened file's buffer stays open until I explicitely close it. That makes viewing files too uncomfortable.
when I traverse NERDTree nodes I'd like to see the highlighted file content in a temporary viewer buffer and I'd like to explicitely select some of traversed files for editing, say by pressing e.
When I close NERDTree buffer, the temporary viewer buffer shall close as well, and there should only be opened buffers for those explicitely selected files, not for all viewed files.
Is that possible?
Looks like that could be a nice feature request for NERDTree :)
Meanwhile, you could put in your ~/.vimrc something like the following:
let g:nerd_preview_enabled = 0
let g:preview_last_buffer = 0
function! NerdTreePreview()
" Only on nerdtree window
if (&ft ==# 'nerdtree')
" Get filename
let l:filename = substitute(getline("."), "^\\s\\+\\|\\s\\+$","","g")
" Preview if it is not a folder
let l:lastchar = strpart(l:filename, strlen(l:filename) - 1, 1)
if (l:lastchar != "/" && strpart(l:filename, 0 ,2) != "..")
let l:store_buffer_to_close = 1
if (bufnr(l:filename) > 0)
" Don't close if the buffer is already open
let l:store_buffer_to_close = 0
endif
" Do preview
execute "normal go"
" Close previews buffer
if (g:preview_last_buffer > 0)
execute "bwipeout " . g:preview_last_buffer
let g:preview_last_buffer = 0
endif
" Set last buffer to close it later
if (l:store_buffer_to_close)
let g:preview_last_buffer = bufnr(l:filename)
endif
endif
elseif (g:preview_last_buffer > 0)
" Close last previewed buffer
let g:preview_last_buffer = 0
endif
endfunction
function! NerdPreviewToggle()
if (g:nerd_preview_enabled)
let g:nerd_preview_enabled = 0
augroup nerdpreview
autocmd!
augroup END
else
let g:nerd_preview_enabled = 1
augroup nerdpreview
autocmd!
autocmd CursorMoved * nested call NerdTreePreview()
augroup END
endif
endfunction
This is probably quite naive and nasty code, but with some tweaking could do what you intend to do.
Edited, changes in version 2:
Added nested on the autocommand so syntax highlight works
Not enabled by default, execute :call NerdPreviewToggle() to enable/disable
I built on DavidEG's answer by taking tabs into account, because I ran into multiple nerdtree tab edge-cases.
function! PreviewNERDTreeFile()
if !exists('t:previous_preview_buffer') | let t:previous_preview_buffer = 0 | endif
let filename = substitute(getline('.'), '^\s*\|\s*$', '','g')
let should_close_buffer_next_time = 1
if (bufnr(filename) > 0) | let should_close_buffer_next_time = 0 | endif
normal go
if t:previous_preview_buffer > 0
exe 'bwipeout ' . t:previous_preview_buffer
let t:previous_preview_buffer = 0
endif
if should_close_buffer_next_time
let t:previous_preview_buffer = bufnr(filename)
endif
endfunction
Here's a NERDTree extension that uses the last active buffer as a preview window, and either hijacks that window or splits it with the original content depending on if you open with o, s, i, gs, gi etc.
https://github.com/numEricL/nerdtree-live-preview
In my .hgrc I can provide an editor or a command to launch an editor with options on commit.
I want to write a method or alias that launches $ hg ci, it would not only open up message in Vim, but also would split window and there print out $ hg diff.
I know that I can give parameters to vim by using +{command} option. So launching $ vim "+vsplit" does the split but any other options goes to first opened window. So I assume i need a specific function, yet I have no experience in writing my own Vim scripts.
The script should:
Open new vertical split with empty buffer (with vnew possibly)
In empty buffer launch :.!hg diff
Set empty buffer file type as diff :set ft=diff
I've written such function:
function! HgCiDiff()
vnew
:.!hg diff
set ft=diff
endfunction
And in .hgrc I've added option: editor = vim "+HgCiDiff()"
It kind of works, but I would like that splited window would be in right side (now it opens up in left) and mercurial message would be focused window. Also :wq could be setted as temporary shortcut to :wq<CR>:q! (having an assumption that mercurial message is is focused).
Any suggestions to make this a bit more useful and less chunky?
UPDATE: I found vim split guide so changing vnew with rightbelow vnew opens up diff on the right side.
So I expanded my own code:
function! HgCiDiff()
"In .hgrc editor option I call vim "+HgCiDiff()"
"It opens new split with diff inside
rightbelow vnew
:.!hg diff
set ft=diff
saveas! /tmp/hgdiff.txt
execute "normal \<c-w>w"
endfunction
Yet It missed :wq mapping as :wqa, yet using :wqa is not that hard.
Sources of my vimrc is located here: http://hg.jackleo.info/vim-configs/src/08df5cb9d143/vimrc
Sources of my hgrc is located here: http://hg.jackleo.info/home-configs/src/22f5fb47a7d2/.hgrc
Update: as suggested by Randy Morris I updated my code and now it works just as I wanted. Thanks! Also added few extra features as the time went by.
function! HgCiDiff()
"In .hgrc editor option I call vim "+HgCiDiff()"
"It opens new split with diff inside
rightbelow vnew
setlocal buftype=nofile
:.!hg diff
setlocal ft=diff
wincmd p
setlocal spell spelllang=en_us
cnoremap wq wqa
cnoremap q qa
start
endfunction
Edit
Hmm I think this might not be what you are after on second reading. I understand you want a multi-file (unified) diff. I'd really use a hg-aware UI tool and a separate vim editor for the commit message. Sorry about that.
I'll leave the 'original' response stand in case you didn't know VCSCommand + Hg + Vim yet:
My weapon of choice is to abstract it all away with
vcscommand.vim : CVS/SVN/SVK/git/hg/bzr integration plugin
You would
:VCSVimDiff
to diffsplit against the repo version (also with Leadercv)
:VCSVimDiff <revid>
to compare against a specific revision.
My solution consists of three vim files. It doesn't require hg configuration changes, and only shows the diff for the files you're committing, if you've used hg commit file1 file2:
~/.vim/ftdetect/hg.vim
au BufRead,BufNewFile /tmp/hg-editor-*.txt set filetype=hg
~/.vim/syntax/hg.vim
" Vim syntax file
" Language: hg commit file
" Maintainer: Marius Gedminas <marius#gedmin.as>
" Filenames: /tmp/hg-editor-*.txt
" Last Change: 2012 July 8
" Based on gitcommit.vim by Tim Pope
if exists("b:current_syntax")
finish
endif
syn case match
syn sync minlines=50
if has("spell")
syn spell toplevel
endif
syn match hgComment "^HG: .*"
hi def link hgComment Comment
let b:current_syntax = "hg"
~/.vim/ftplugin/hg.vim
" Show diff while editing a Mercurial commit message
" Inspired by http://stackoverflow.com/questions/8009333/vim-show-diff-on-commit-in-mercurial
" and Michael Scherer' svn.vim
function! HgCiDiff()
let i = 0
let list_of_files = ''
while i <= line('$') && getline(i) != 'HG: --'
let i = i + 1
endwhile
while i <= line('$')
let line = getline(i)
if line =~ '^HG: \(added\|changed\)'
let file = substitute(line, '^HG: \(added\|changed\) ', '', '')
let file = "'".substitute(file, "'", "'\''", '')."'"
let list_of_files = list_of_files . ' '.file
endif
let i = i + 1
endwhile
if list_of_files == ""
return
endif
pclose
new
setlocal ft=diff previewwindow bufhidden=delete nobackup noswf nobuflisted nowrap buftype=nofile
silent exec ':0r!hg diff ' . list_of_files
setlocal nomodifiable
goto 1
redraw!
" nooo idea why I have to do this
syn enable
endfunction
call HgCiDiff()
Here's my variation based on Marius Gedminas and JackLeo's versions:
function! HgCiDiff()
" find files that were changed (not interested in added or deleted)
let changed_files = []
let pattern = '\vHG: changed \zs(.+)\ze'
while search("HG: changed", "W") > 0
let line_text = getline(line("."))
call add(changed_files, matchstr(line_text, pattern))
endwhile
let diff_cmd = "hg diff " . join(changed_files, " ")
" Reset cursor to beginning of the buffer
call cursor(1, 1)
rightbelow vnew
setlocal buftype=nofile
let diff_output = system(diff_cmd)
call append(0, split(diff_output, "\n"))
" Reset cursor to beginning of the buffer
call cursor(1, 1)
setlocal ft=diff
wincmd p
setlocal spell spelllang=en_us
cnoremap wq wqa
cnoremap q qa!
startinsert
endfunction
I am using vim with the fugitive extension. It has a :Gdiff command which brings you into vimdiff mode, but what is the right/quick way to close/quit vimdiff mode?
I.e., let's say I am editing the file FooBar.txt under Git repository. I fire up :Gdiff, review my changes in vimdiff, and then I want to get back and continue editing FooBar.txt or any other file :)
UPDATE1: I'm going to give these quick combos a try next working day :)
"vimdiff current vs git head (fugitive extension)
nnoremap <Leader>gd :Gdiff<cr>
"switch back to current file and closes fugitive buffer
nnoremap <Leader>gD :diffoff!<cr><c-w>h:bd<cr>
UPDATE2: My current mappings (closes diff window only!)
"vimdiff current vs git head (fugitive extension)
nnoremap <Leader>gd :Gdiff<cr>
"switch back to current file and closes fugitive buffer
nnoremap <Leader>gD <c-w>h<c-w>c
Also, please help me decide if the following should be an anwser: https://stackoverflow.com/a/15975201/275980
You can execute windo set nodiff noscrollbind and then close the second window.
Update: there is a diffoff command. Use windo diffoff, not what I wrote in previous line.
According to: https://github.com/tpope/vim-fugitive/issues/36
Close the other window. The easiest way to do this if you haven't shifted focus to it is <C-W><C-O>, which means "make this Window the Only window."
I had no luck with diffoff, but I just learned that :Gedit with no argument will bring you back to the working-directory version of the file, as opposed to some earlier version you were reviewing.
And as q (no need for :q) will close the diff sidebar, you can do q followed by :Gedit to get rid of the sidebar and then go back to the current version of the file.
None of the above solutions worked for me. Ended up doing this instead:
nnoremap <Leader>D :Gedit<CR><C-w>h :q<CR><C-w>k
This works fine for me, combining some of the existing ideas here:
function! MyCloseDiff()
if (&diff == 0 || getbufvar('#', '&diff') == 0)
\ && (bufname('%') !~ '^fugitive:' && bufname('#') !~ '^fugitive:')
echom "Not in diff view."
return
endif
" close current buffer if alternate is not fugitive but current one is
if bufname('#') !~ '^fugitive:' && bufname('%') =~ '^fugitive:'
if bufwinnr("#") == -1
b #
bd #
else
bd
endif
else
bd #
endif
endfunction
nnoremap <Leader>gD :call MyCloseDiff()<cr>
An alternative to <C-W><C-O>, if you have multiple windows, would be move to the other diff window and do <C-W>c, which close only one window.
If you close the wrong diff window do a :Gedit
Be careful and don't confuse <C-W>c with <C-W><C-C>
I've found a simple solution for this. You can check it here: https://gist.github.com/radmen/5048080
" Simple way to turn off Gdiff splitscreen
" works only when diff buffer is focused
if !exists(":Gdiffoff")
command Gdiffoff diffoff | q | Gedit
endif
Check the vimdiff toggling between diffthis and diffoff here
at this page.
The code:
nnoremap <silent> <Leader>df :call DiffToggle()<CR>
function! DiffToggle()
if &diff
diffoff
else
diffthis
endif
:endfunction
Method 1:
open a compare by:
:windo diffthis
close it by:
:windo diffoff
Method 2:
I recommend just using the most simple command: :q<CR>
when you want to do it quickly, add the mapping:
" Set mapleader
let mapleader = ","
let g:mapleader = ","
and
" Quickly close the current window
nnoremap <leader>q :q<CR>
It works well for me. Exit vimdiff just by ,q, because normally your cursor in the old file.
this is what I have to leave the vimdiff windows after using :Gdiff
nnoremap gD :q!<CR> :Gedit!<CR>
noremap <leader>do :diffoff \| windo if &diff \| hide \| endif<cr>
Quite diff mode and close other diff windows. (Note: fugitive will auto delete its hidden buffers.)
My function will work both from diff window and file window. But probably won't handle itself with multiple diffs opened. For that you'll need to use fugitive#buffer(n).path() to scan and match.
command! Gdiffoff call Gdiffoff()
function! Gdiffoff()
let diffbufnr = bufnr('^fugitive:')
if diffbufnr > -1 && &diff
diffoff | q
if bufnr('%') == diffbufnr | Gedit | endif
setlocal nocursorbind
else
echo 'Error: Not in diff or file'
endif
endfunction
Add a key binding:
nnoremap <silent> <leader>gD :Gdiffoff<CR>
Yet another way. What I have in fugitive.vim - first save some info (s:gitbufname) when diff starts:
function! s:Diff(vert,...) abort
call sy#toggle()
let s:startcol = winwidth(0)
let &columns=(winwidth(0) * 2 - 20)
...
if getwinvar('#', '&diff')
let s:gitbufname = bufname("%")
wincmd p
call feedkeys(winnr."\<C-W>w", 'n')
endif
...
endfunction
and later when leaving the buffer switch window to the saved buffer and restore:
augroup fugitive_diff
autocmd!
autocmd BufWinLeave *
\ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 2 |
\ if exists('s:gitbufname') && winnr() != bufwinnr(s:gitbufname) |
\ let nr = bufnr("%") | exe bufwinnr(s:gitbufname).'wincmd w' | exe 'buf'.nr |
\ endif |
\ call s:diffoff_all(getbufvar(+expand('<abuf>'), 'git_dir')) |
\ call sy#toggle() |
\ call airline#load_theme() | call airline#update_statusline() |
\ let &columns=s:startcol |
\ endif
...
Was using the code below based on https://stackoverflow.com/a/15113951/10999673 :
if !exists(":Gdiffoff")
command Gdiffoff bw! fugitive://*
endif
but it gave me an error "E93: more than one match for ..." in a 3 way diff, so i instead used the answer from https://stackoverflow.com/a/4867969/10999673 and finally have this:
function! GetBufferList()
return filter(range(1,bufnr('$')), 'buflisted(v:val)')
endfunction
function! GetMatchingBuffers(pattern)
return filter(GetBufferList(), 'bufname(v:val) =~ a:pattern')
endfunction
function! WipeMatchingBuffers(pattern)
let l:matchList = GetMatchingBuffers(a:pattern)
let l:count = len(l:matchList)
if l:count < 1
echo 'No buffers found matching pattern ' . a:pattern
return
endif
if l:count == 1
let l:suffix = ''
else
let l:suffix = 's'
endif
exec 'bw ' . join(l:matchList, ' ')
echo 'Wiped ' . l:count . ' buffer' . l:suffix . '.'
endfunction
command! -nargs=1 Gdiffoff call WipeMatchingBuffers('fugitive://')
I just tweaked, copied and pasted the code into my .vimrc
Running :Gwrite after merging to your satisfaction will close the other two diff panes in addition to updating the git cache to mark the file as merged.
My question is similar to this how to monitor a text file in realtime
but I want to do it in vim. I know I can read an opened file use tail -f sample.xml file, and when new content is written to the file, it'll also write the new content to my screen. Can I have vim automatically fill the new data when a file is updated?
You can :set autoread so that vim reads the file when it changes. However (depending on your platform), you have to give it focus.
From the help:
When a file has been detected to have
been changed outside of Vim and it
has not been changed inside of Vim,
automatically read it again. When the
file has been deleted this is not
done.
Don't know about automatically, but you can type:
:e!
to reload the file
Put the following in your .vimrc:
" check one time after 4s of inactivity in normal mode
set autoread
au CursorHold * checktime
like #flukus said in a comment to a previous answer you can call feedkeys["lh"] (it moves the cursor to the right and back to the left, which normaly doesn't do harm when viewing a log file)
So, if you combine the rest of the answer you have a oneliner you can run from ex (whithin vim) when needed:
:set autoread | au CursorHold * checktime | call feedkeys("lh")
***(if you would want to jump (nearly) to the end of the file, just use "G" instead of "lh" with feedkeys)***
Explanation:
autoread: reads the file when changed from the outside (but it doesnt work on its own, there is no internal timer or something like that. It will only read the file when vim does an action, like a command in ex :!
CursorHold * checktime: when the cursor isn't moved by the user for the time specified in 'updatetime' (which is 4000 miliseconds by default) checktime is executed, which checks for changes from outside the file
call feedkeys("lh"): the cursor is moved once, right and back left. and then nothing happens (... which means, that CursorHold is triggered, which means we have a loop)
Additionally you can :set syntax=logtalk to color the log
To stop the scrolling when using call feedkeys("G"), execute :set noautoread - now vim will tell, that the file was change ans ask if one wants to read the changes or not)
(Does this have any sideeffects?)
Edit: I see one side-effect: if one uses "G" as the feedkey, it will scroll down every currently opened buffer?! So, it's not possible to work in the left buffer of a splittet window while having the right buffer scroll down a logfile automatically
Edit2: Another side effect is that when you enter the command line window(by using q:) an error message always pops up.
Stick this in your .vimrc and it should work like a boss. (Taken from: 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)
Tail Bundle should do what you want. Note, haven't used it myself.
There is a plugin also:
https://github.com/djoshea/vim-autoread
This was the only way I could make this work on OSX.
If unix + neovim
:term tail -f <filename>
Obviously this won't work for everyone, but it's how I do it.
To enable reloading if you open a specific file, you can add this to your .vimrc and use a modeline like vim: set ft+=.watch:. It takes advantage of the feature to set multiple filetypes for a buffer (see below):
vim9script
command WatchFiles {
autocmd! AUWatchFile FocusGained,VimResume,BufEnter,WinEnter,CursorHold * checktime
autocmd! AUWatchFile BufEnter,InsertEnter,CursorHold,CursorHoldI <buffer> checktime
setlocal autoread
checktime
}
command UnwatchFiles {
autocmd! AUWatchFile
set autoread<
}
# To enable this, you may use e.g. a modeline: `vim: set ft+=.watch`
def WatchAutomatically()
# Check if the "list" of filetypes (a dot separated string) contains 'watch'.
if -1 != match(&filetype, "\\(^\\|\\.\\)watch\\($\\|\\.\\)")
WatchFiles
endif
enddef
augroup AUWatchFile | augroup END
autocmd BufWinEnter * call WatchAutomatically()
More details
You are able to set multiple filetypes separated by .:
When a dot appears in the value then this separates two filetype
names. Example:
/* vim: set filetype=c.doxygen : */ ~
See :help 'filetype'.
Keep in mind that you should manipulate the filetype first and set additional options after that in the modeline. Otherwise these options may be overridden by the settings specific for the filetype.
Btw, the above is a Vim9 script (which I discovered today). Translating it back to a good-old Vim script is trivial:
Use " for comments.
Transform multi-line commands like this:
command UnwatchFiles
\ autocmd! AUWatchFile
\ | set autoread<
Remove the vim9script line.
See :help Vim9-script for details.
Shortcomings
Reloading is not limited to the buffer which contains the modeline. You may disable it again with :UnwatchFiles.
It is still dump polling.
VIM will warn you when a file has been updated so that you don't overwrite changes that have been made since you opened it. It will prompt you at that point to reload the file.