Merge pull request #17394 from zeertzjq/vim-8.2.4343

vim-patch:8.2.4343: when reloading not all properties are detected
This commit is contained in:
zeertzjq 2022-02-15 08:10:21 +08:00 committed by GitHub
commit 8051fa1aff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 216 additions and 42 deletions

View File

@ -1450,6 +1450,11 @@ If you don't get warned often enough you can use the following command.
if it exists now.
Once a file has been checked the timestamp is reset,
you will not be warned again.
Syntax highlighting, marks, diff status,
'fileencoding', 'fileformat' and 'binary' options
are not changed. See |v:fcs_choice| to reload these
too (for example, if a code formatting tools has
changed the file).
:[N]checkt[ime] {filename}
:[N]checkt[ime] [N]

View File

@ -1882,6 +1882,11 @@ v:fcs_choice What should happen after a |FileChangedShell| event was
do with the affected buffer:
reload Reload the buffer (does not work if
the file was deleted).
edit Reload the buffer and detect the
values for options such as
'fileformat', 'fileencoding', 'binary'
(does not work if the file was
deleted).
ask Ask the user what to do, as if there
was no autocommand. Except that when
only the timestamp changed nothing

View File

@ -2013,10 +2013,8 @@ static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp)
return lnum;
}
/*
* Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
* equal to the buffer "buf". Used for calling readfile().
*/
/// Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary' to be
/// equal to the buffer "buf". Used for calling readfile().
void prep_exarg(exarg_T *eap, const buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
@ -4901,13 +4899,11 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
return retval;
}
/*
* Check if buffer "buf" has been changed.
* Also check if the file for a new buffer unexpectedly appeared.
* return 1 if a changed buffer was found.
* return 2 if a message has been displayed.
* return 0 otherwise.
*/
/// Check if buffer "buf" has been changed.
/// Also check if the file for a new buffer unexpectedly appeared.
/// return 1 if a changed buffer was found.
/// return 2 if a message has been displayed.
/// return 0 otherwise.
int buf_check_timestamp(buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
@ -4916,7 +4912,11 @@ int buf_check_timestamp(buf_T *buf)
char *mesg = NULL;
char *mesg2 = "";
bool helpmesg = false;
bool reload = false;
enum {
RELOAD_NONE,
RELOAD_NORMAL,
RELOAD_DETECT
} reload = RELOAD_NONE;
bool can_reload = false;
uint64_t orig_size = buf->b_orig_size;
int orig_mode = buf->b_orig_mode;
@ -4969,7 +4969,7 @@ int buf_check_timestamp(buf_T *buf)
// If 'autoread' is set, the buffer has no changes and the file still
// exists, reload the buffer. Use the buffer-local option value if it
// was set, the global option value otherwise.
reload = true;
reload = RELOAD_NORMAL;
} else {
if (!file_info_ok) {
reason = "deleted";
@ -5000,7 +5000,9 @@ int buf_check_timestamp(buf_T *buf)
}
s = get_vim_var_str(VV_FCS_CHOICE);
if (STRCMP(s, "reload") == 0 && *reason != 'd') {
reload = true;
reload = RELOAD_NORMAL;
} else if (STRCMP(s, "edit") == 0) {
reload = RELOAD_DETECT;
} else if (STRCMP(s, "ask") == 0) {
n = false;
} else {
@ -5064,9 +5066,15 @@ int buf_check_timestamp(buf_T *buf)
xstrlcat(tbuf, "\n", tbuf_len - 1);
xstrlcat(tbuf, mesg2, tbuf_len - 1);
}
if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), (char_u *)tbuf,
(char_u *)_("&OK\n&Load File"), 1, NULL, true) == 2) {
reload = true;
switch (do_dialog(VIM_WARNING, (char_u *)_("Warning"), (char_u *)tbuf,
(char_u *)_("&OK\n&Load File\nLoad File &and Options"),
1, NULL, true)) {
case 2:
reload = RELOAD_NORMAL;
break;
case 3:
reload = RELOAD_DETECT;
break;
}
} else if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned) {
if (*mesg2 != NUL) {
@ -5100,9 +5108,9 @@ int buf_check_timestamp(buf_T *buf)
xfree(tbuf);
}
if (reload) {
if (reload != RELOAD_NONE) {
// Reload the buffer.
buf_reload(buf, orig_mode);
buf_reload(buf, orig_mode, reload == RELOAD_DETECT);
if (buf->b_p_udf && buf->b_ffname != NULL) {
char_u hash[UNDO_HASH_SIZE];
@ -5120,13 +5128,11 @@ int buf_check_timestamp(buf_T *buf)
return retval;
}
/*
* Reload a buffer that is already loaded.
* Used when the file was changed outside of Vim.
* "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
* buf->b_orig_mode may have been reset already.
*/
void buf_reload(buf_T *buf, int orig_mode)
/// Reload a buffer that is already loaded.
/// Used when the file was changed outside of Vim.
/// "orig_mode" is buf->b_orig_mode before the need for reloading was detected.
/// buf->b_orig_mode may have been reset already.
void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
{
exarg_T ea;
pos_T old_cursor;
@ -5141,11 +5147,15 @@ void buf_reload(buf_T *buf, int orig_mode)
// set curwin/curbuf for "buf" and save some things
aucmd_prepbuf(&aco, buf);
// We only want to read the text from the file, not reset the syntax
// highlighting, clear marks, diff status, etc. Force the fileformat and
// encoding to be the same.
// Unless reload_options is set, we only want to read the text from the
// file, not reset the syntax highlighting, clear marks, diff status, etc.
// Force the fileformat and encoding to be the same.
if (reload_options) {
memset(&ea, 0, sizeof(ea));
} else {
prep_exarg(&ea, buf);
}
prep_exarg(&ea, buf);
old_cursor = curwin->w_cursor;
old_topline = curwin->w_topline;

View File

@ -3464,6 +3464,7 @@ void msg_advance(int col)
///
/// @param textfiel IObuff for inputdialog(), NULL otherwise
/// @param ex_cmd when TRUE pressing : accepts default and starts Ex command
/// @returns 0 if cancelled, otherwise the nth button (1-indexed).
int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton,
char_u *textfield, int ex_cmd)
{

View File

@ -5654,7 +5654,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo
// If the .add file is edited somewhere, reload it.
if (buf != NULL) {
buf_reload(buf, buf->b_orig_mode);
buf_reload(buf, buf->b_orig_mode, false);
}
redraw_all_later(SOME_VALID);

View File

@ -10,6 +10,7 @@ let s:did_load = 1
set backspace=
set directory^=.
set fillchars=vert:\|,fold:-
set fsync
set laststatus=1
set listchars=eol:$
set joinspaces

View File

@ -1,9 +1,10 @@
" Tests for when a file was changed outside of Vim.
source check.vim
func Test_FileChangedShell_reload()
if !has('unix')
return
endif
CheckUnix
augroup testreload
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'reload'
augroup END
@ -90,11 +91,107 @@ func Test_FileChangedShell_reload()
call delete('Xchanged_r')
endfunc
func Test_FileChangedShell_edit()
CheckUnix
new Xchanged_r
call setline(1, 'reload this')
set fileformat=unix
write
" File format changed, reload (content only, no 'ff' etc)
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'reload'
augroup END
call assert_equal(&fileformat, 'unix')
sleep 10m " make the test less flaky in Nvim
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'unix')
call assert_equal("line1\r", getline(1))
call assert_equal("line2\r", getline(2))
%s/\r
write
" File format changed, reload with 'ff', etc
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'edit'
augroup END
call assert_equal(&fileformat, 'unix')
sleep 10m " make the test less flaky in Nvim
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'dos')
call assert_equal('line1', getline(1))
call assert_equal('line2', getline(2))
set fileformat=unix
write
au! testreload
bwipe!
call delete(undofile('Xchanged_r'))
call delete('Xchanged_r')
endfunc
func Test_FileChangedShell_edit_dialog()
throw 'Skipped: requires a UI to be active'
CheckNotGui
new Xchanged_r
call setline(1, 'reload this')
set fileformat=unix
write
" File format changed, reload (content only) via prompt
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
augroup END
call assert_equal(&fileformat, 'unix')
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
call feedkeys('L', 'L') " load file content only
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'unix')
call assert_equal("line1\r", getline(1))
call assert_equal("line2\r", getline(2))
%s/\r
write
" File format changed, reload (file and options) via prompt
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
augroup END
call assert_equal(&fileformat, 'unix')
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
call feedkeys('a', 'L') " load file content and options
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'dos')
call assert_equal("line1", getline(1))
call assert_equal("line2", getline(2))
set fileformat=unix
write
au! testreload
bwipe!
call delete(undofile('Xchanged_r'))
call delete('Xchanged_r')
endfunc
func Test_file_changed_dialog()
throw 'Skipped: requires a UI to a active'
if !has('unix') || has('gui_running')
return
endif
throw 'Skipped: requires a UI to be active'
CheckUnix
CheckNotGui
au! FileChangedShell
new Xchanged_d

View File

@ -11,6 +11,11 @@ describe('file changed dialog', function()
clear()
meths.ui_attach(80, 24, {})
meths.set_option('autoread', false)
meths.set_option('fsync', true)
end)
it('works', function()
if helpers.pending_win32(pending) then return end
source([[
func Test_file_changed_dialog()
au! FileChangedShell
@ -66,11 +71,61 @@ describe('file changed dialog', function()
call delete('Xchanged_d')
endfunc
]])
end)
it('works', function()
if helpers.pending_win32(pending) then return end
call('Test_file_changed_dialog')
expected_empty()
end)
it('works with FileChangedShell', function()
source([[
func Test_FileChangedShell_edit_dialog()
new Xchanged_r
call setline(1, 'reload this')
set fileformat=unix
silent write " Use :silent to prevent a hit-enter prompt
" File format changed, reload (content only) via prompt
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
augroup END
call assert_equal(&fileformat, 'unix')
sleep 10m " make the test less flaky in Nvim
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
call nvim_input('L') " load file content only
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'unix')
call assert_equal("line1\r", getline(1))
call assert_equal("line2\r", getline(2))
%s/\r
silent write " Use :silent to prevent a hit-enter prompt
" File format changed, reload (file and options) via prompt
augroup testreload
au!
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
augroup END
call assert_equal(&fileformat, 'unix')
sleep 10m " make the test less flaky in Nvim
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
let g:reason = ''
call nvim_input('a') " load file content and options
checktime
call assert_equal('changed', g:reason)
call assert_equal(&fileformat, 'dos')
call assert_equal("line1", getline(1))
call assert_equal("line2", getline(2))
set fileformat=unix
silent write " Use :silent to prevent a hit-enter prompt
au! testreload
bwipe!
call delete(undofile('Xchanged_r'))
call delete('Xchanged_r')
endfunc
]])
call('Test_FileChangedShell_edit_dialog')
expected_empty()
end)
end)