mirror of
https://github.com/neovim/neovim.git
synced 2026-09-13 01:21:06 +00:00
fix(terminal): check file timestamps on terminal-job exit #41814
Problem:
When a `:!` command runs, file timestamps are checked and W12 or
`FileChangedShell` is triggered. But not when a `:terminal` job exits.
Only `enter_buffer()` checks, so whether you get the W12 warning depends
on how you happen to return to the file: `:term` works, `:tabnew | term`
does not.
echo foo > testfile
nvim --clean testfile
" Edit the buffer, don't save it.
:!mv testfile testfile2
:tabnew | term sh
touch testfile2 && mv testfile2 testfile
exit
'autoread' is defeated because `:!mv` deletes the file, so
`should_watch()` fails and the watcher stops. `ensure_watcher()` only
re-runs on `BufReadPost`/`BufWritePost`/`OptionSet`, so nothing watches
the file when the terminal moves it back.
Solution:
Set `need_check_timestamps` on terminal-job exit, same as `:!cmd`
(`os_shell`).
This commit is contained in:
@@ -779,7 +779,7 @@ FileChangedShell When Vim notices that the modification time of
|
||||
change or when the size of the file changes.
|
||||
|timestamp|
|
||||
Triggered for each changed file, after:
|
||||
- executing a shell command
|
||||
- executing a shell command or |:terminal| job
|
||||
- |:checktime|
|
||||
- |FocusGained|
|
||||
|
||||
@@ -1169,8 +1169,9 @@ SessionWritePost After writing a session file by calling
|
||||
ShellCmdPost After executing a shell command with |:!cmd|,
|
||||
|:make| and |:grep|. Can be used to check for
|
||||
any changed files.
|
||||
|
||||
For non-blocking shell commands, see
|
||||
|job-control|.
|
||||
|TermClose| |job-control|.
|
||||
|
||||
*ShellFilterPost*
|
||||
ShellFilterPost After executing a shell command with
|
||||
|
||||
@@ -1543,11 +1543,10 @@ Vim remembers the modification timestamp, mode and size of a file when you
|
||||
begin editing it. This is used to avoid that you have two different versions
|
||||
of the same file (without you knowing this).
|
||||
|
||||
After a shell command is run (|:!cmd| |suspend| |:read!| |K|) timestamps,
|
||||
file modes and file sizes are compared for all buffers in a window. Vim will
|
||||
run any associated |FileChangedShell| autocommands or display a warning for
|
||||
any files that have changed. In the GUI this happens when Vim regains input
|
||||
focus.
|
||||
After a shell command (|:!cmd| |suspend| |:read!| |K|) or |:terminal| job
|
||||
exits: timestamps, file modes and file sizes are compared for all buffers
|
||||
in a window. Nvim will run |FileChangedShell| autocommands or display
|
||||
a warning for any files that changed.
|
||||
|
||||
*E321* *E462*
|
||||
If you want to automatically reload a file when it has been changed outside of
|
||||
|
||||
@@ -729,6 +729,11 @@ void terminal_close(Terminal **termpp, int status)
|
||||
return;
|
||||
}
|
||||
|
||||
if (status >= 0) { // The job may have changed files on disk, like `do_shell` (":!cmd").
|
||||
did_check_timestamps = false;
|
||||
need_check_timestamps = true;
|
||||
}
|
||||
|
||||
if (buf && !is_autocmd_blocked()) {
|
||||
save_v_event_T save_v_event;
|
||||
dict_T *dict = get_v_event(&save_v_event);
|
||||
|
||||
@@ -639,6 +639,23 @@ end)
|
||||
describe(':terminal buffer', function()
|
||||
before_each(clear)
|
||||
|
||||
it('exit emits FileChangedShell #41759', function()
|
||||
local path = t.tmpname()
|
||||
write_file(path, 'foo\n')
|
||||
command('edit ' .. path)
|
||||
command('set noautoread') -- Disable 'autoread' to exercise :checktime specifically.
|
||||
api.nvim_buf_set_lines(0, 0, -1, true, { 'local change' })
|
||||
n.exec('let g:fcs = 0 | autocmd FileChangedShell * let g:fcs = 1')
|
||||
write_file(path, 'external change\n')
|
||||
|
||||
-- Terminal in another tab, so returning to the buffer is not what triggers the check.
|
||||
command('tabnew')
|
||||
fn.jobstart({ testprg('shell-test'), 'EXIT', '0' }, { term = true })
|
||||
retry(nil, 10000, function()
|
||||
eq(1, api.nvim_get_var('fcs'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('can resume suspended PTY process running in fish', function()
|
||||
skip(is_os('win'), 'N/A for Windows')
|
||||
skip(fn.executable('fish') == 0, 'missing "fish" command')
|
||||
|
||||
Reference in New Issue
Block a user