Skip to content

Commit

Permalink
Reload 'fileformat', etc with v:fcs_choice
Browse files Browse the repository at this point in the history
This allows per-buffer customisation of reloading, so for certain
buffers all file options can be reloaded, e.g. if a code formatter has
changed the 'fileformat'.
  • Loading branch information
bobrippling committed Feb 9, 2022
1 parent 78a8404 commit 3775278
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 16 deletions.
5 changes: 5 additions & 0 deletions runtime/doc/editing.txt
Expand Up @@ -1650,6 +1650,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
aren't reloaded.
See |v:fcs_choice| to reload these too (for example, if
a code formatting tools has changed them).

:[N]checkt[ime] {filename}
:[N]checkt[ime] [N]
Expand Down
4 changes: 4 additions & 0 deletions runtime/doc/eval.txt
Expand Up @@ -2070,6 +2070,10 @@ 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 options such as
'fileformat', 'fileencoding', 'binary',
etc (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
Expand Down
43 changes: 29 additions & 14 deletions src/fileio.c
Expand Up @@ -2697,7 +2697,7 @@ readfile_linenr(
}

/*
* Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary to be
* Fill "*eap" to force the 'fileencoding', 'fileformat' and 'binary' to be
* equal to the buffer "buf". Used for calling readfile().
* Returns OK or FAIL.
*/
Expand Down Expand Up @@ -4041,7 +4041,7 @@ buf_check_timestamp(
char *mesg = NULL;
char *mesg2 = "";
int helpmesg = FALSE;
int reload = FALSE;
int reload = 0; // 0: no reload, 1: reload, 2: reload including 'ff', 'fenc', etc
char *reason;
#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
int can_reload = FALSE;
Expand Down Expand Up @@ -4117,7 +4117,7 @@ buf_check_timestamp(
*/
else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
&& !bufIsChanged(buf) && stat_res >= 0)
reload = TRUE;
reload = 1;
else
{
if (stat_res < 0)
Expand Down Expand Up @@ -4158,7 +4158,9 @@ buf_check_timestamp(
#ifdef FEAT_EVAL
s = get_vim_var_str(VV_FCS_CHOICE);
if (STRCMP(s, "reload") == 0 && *reason != 'd')
reload = TRUE;
reload = 1;
else if (STRCMP(s, "edit") == 0)
reload = 2;
else if (STRCMP(s, "ask") == 0)
n = FALSE;
else
Expand Down Expand Up @@ -4239,10 +4241,17 @@ buf_check_timestamp(
STRCAT(tbuf, "\n");
STRCAT(tbuf, mesg2);
}
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 = 1;
break;
case 3:
reload = 2;
break;
}
}
else
#endif
Expand Down Expand Up @@ -4290,7 +4299,7 @@ buf_check_timestamp(
if (reload)
{
// Reload the buffer.
buf_reload(buf, orig_mode);
buf_reload(buf, orig_mode, reload == 2);
#ifdef FEAT_PERSISTENT_UNDO
if (buf->b_p_udf && buf->b_ffname != NULL)
{
Expand Down Expand Up @@ -4326,7 +4335,7 @@ buf_check_timestamp(
* buf->b_orig_mode may have been reset already.
*/
void
buf_reload(buf_T *buf, int orig_mode)
buf_reload(buf_T *buf, int orig_mode, int reload_options)
{
exarg_T ea;
pos_T old_cursor;
Expand All @@ -4337,14 +4346,20 @@ buf_reload(buf_T *buf, int orig_mode)
int saved = OK;
aco_save_T aco;
int flags = READ_NEW;
int prepped = OK;

// 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.
if (prep_exarg(&ea, buf) == OK)
// 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
prepped = prep_exarg(&ea, buf);

if (prepped == OK)
{
old_cursor = curwin->w_cursor;
old_topline = curwin->w_topline;
Expand Down
2 changes: 2 additions & 0 deletions src/message.c
Expand Up @@ -3752,6 +3752,8 @@ msg_advance(int col)
* Other buttons- use your imagination!
* A '&' in a button name becomes a shortcut, so each '&' should be before a
* different letter.
*
* Returns 0 if cancelled, otherwise the nth button (1-indexed).
*/
int
do_dialog(
Expand Down
2 changes: 1 addition & 1 deletion src/proto/fileio.pro
Expand Up @@ -28,7 +28,7 @@ int vim_fgets(char_u *buf, int size, FILE *fp);
int vim_rename(char_u *from, char_u *to);
int check_timestamps(int focus);
int buf_check_timestamp(buf_T *buf, int focus);
void buf_reload(buf_T *buf, int orig_mode);
void buf_reload(buf_T *buf, int orig_mode, int reload_options);
void buf_store_time(buf_T *buf, stat_T *st, char_u *fname);
void write_lnum_adjust(linenr_T offset);
int readdir_core(garray_T *gap, char_u *path, int withattr, void *context, int (*checkitem)(void *context, void *item), int sort);
Expand Down
2 changes: 1 addition & 1 deletion src/spellfile.c
Expand Up @@ -6336,7 +6336,7 @@ spell_add_word(

// 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);
}
Expand Down
94 changes: 94 additions & 0 deletions src/testdir/test_filechanged.vim
Expand Up @@ -91,6 +91,100 @@ 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')
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')
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()
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()
CheckUnix
CheckNotGui
Expand Down

0 comments on commit 3775278

Please sign in to comment.