vim-patch:9.1.0208: winfixbuf does not allow to re-edit current buffer (#28054)

Problem:  winfixbuf does not allow to re-edit current buffer
          (Tim Pope, after v9.1.0147)
Solution: Explicitly allow :e even when 'winfixbuf' is set,
          since it just re-loads the current buffer
          (Colin Kennedy)

fixes: vim/vim#14237
closes: vim/vim#14286

65e580bd56
This commit is contained in:
Colin Kennedy 2024-03-27 08:22:33 +00:00 committed by GitHub
parent 00e9c69551
commit 61e25b7200
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 175 additions and 1 deletions

View File

@ -216,6 +216,38 @@ static void restore_dbg_stuff(struct dbg_stuff *dsp)
current_exception = dsp->current_exception;
}
/// Check if ffname differs from fnum.
/// fnum is a buffer number. 0 == current buffer, 1-or-more must be a valid buffer ID.
/// ffname is a full path to where a buffer lives on-disk or would live on-disk.
static bool is_other_file(int fnum, char *ffname)
{
if (fnum != 0) {
if (fnum == curbuf->b_fnum) {
return false;
}
return true;
}
if (ffname == NULL) {
return true;
}
if (*ffname == NUL) {
return false;
}
if (!curbuf->file_id_valid
&& curbuf->b_sfname != NULL
&& *curbuf->b_sfname != NUL) {
// This occurs with unsaved buffers. In which case `ffname`
// actually corresponds to curbuf->b_sfname
return path_fnamecmp(ffname, curbuf->b_sfname) != 0;
}
return otherfile(ffname);
}
/// Repeatedly get commands for Ex mode, until the ":vi" command is given.
void do_exmode(void)
{
@ -5371,11 +5403,13 @@ static void ex_find(exarg_T *eap)
/// ":edit", ":badd", ":balt", ":visual".
static void ex_edit(exarg_T *eap)
{
char *ffname = eap->cmdidx == CMD_enew ? NULL : eap->arg;
// Exclude commands which keep the window's current buffer
if (eap->cmdidx != CMD_badd
&& eap->cmdidx != CMD_balt
// All other commands must obey 'winfixbuf' / ! rules
&& !check_can_set_curbuf_forceit(eap->forceit)) {
&& (is_other_file(0, ffname) && !check_can_set_curbuf_forceit(eap->forceit))) {
return;
}

View File

@ -1125,6 +1125,146 @@ func Test_edit()
call assert_equal(l:other, bufnr())
endfunc
" Fail :e when selecting a buffer from a relative path if in a different folder
"
" In this tests there's 2 buffers
"
" foo - lives on disk, in some folder. e.g. /tmp/foo
" foo - an in-memory buffer that has not been saved to disk. If saved, it
" would live in a different folder, /other/foo.
"
" The 'winfixbuf' is looking at the in-memory buffer and trying to switch to
" the buffer on-disk (and fails, because it's a different buffer)
func Test_edit_different_buffer_on_disk_and_relative_path_to_disk()
call s:reset_all_buffers()
let l:file_on_disk = tempname()
let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h")
let l:name = fnamemodify(l:file_on_disk, ":t")
execute "edit " . l:file_on_disk
write!
let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else"
if !isdirectory(l:directory_on_disk2)
call mkdir(l:directory_on_disk2)
endif
execute "cd " . l:directory_on_disk2
execute "edit " l:name
let l:current = bufnr()
call assert_equal(l:current, bufnr())
set winfixbuf
call assert_fails("edit " . l:file_on_disk, "E1513:")
call assert_equal(l:current, bufnr())
call delete(l:directory_on_disk1)
call delete(l:directory_on_disk2)
endfunc
" Fail :e when selecting a buffer from a relative path if in a different folder
"
" In this tests there's 2 buffers
"
" foo - lives on disk, in some folder. e.g. /tmp/foo
" foo - an in-memory buffer that has not been saved to disk. If saved, it
" would live in a different folder, /other/foo.
"
" The 'winfixbuf' is looking at the on-disk buffer and trying to switch to
" the in-memory buffer (and fails, because it's a different buffer)
func Test_edit_different_buffer_on_disk_and_relative_path_to_memory()
call s:reset_all_buffers()
let l:file_on_disk = tempname()
let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h")
let l:name = fnamemodify(l:file_on_disk, ":t")
execute "edit " . l:file_on_disk
write!
let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else"
if !isdirectory(l:directory_on_disk2)
call mkdir(l:directory_on_disk2)
endif
execute "cd " . l:directory_on_disk2
execute "edit " l:name
execute "cd " . l:directory_on_disk1
execute "edit " l:file_on_disk
execute "cd " . l:directory_on_disk2
let l:current = bufnr()
call assert_equal(l:current, bufnr())
set winfixbuf
call assert_fails("edit " . l:name, "E1513:")
call assert_equal(l:current, bufnr())
call delete(l:directory_on_disk1)
call delete(l:directory_on_disk2)
endfunc
" Fail to call `:e first` if called from a starting, in-memory buffer
func Test_edit_first_buffer()
call s:reset_all_buffers()
set winfixbuf
let l:current = bufnr()
call assert_fails("edit first", "E1513:")
call assert_equal(l:current, bufnr())
edit! first
call assert_equal(l:current, bufnr())
edit! somewhere_else
call assert_notequal(l:current, bufnr())
endfunc
" Allow reloading a buffer using :e
func Test_edit_no_arguments()
call s:reset_all_buffers()
let l:current = bufnr()
file some_buffer
call assert_equal(l:current, bufnr())
set winfixbuf
edit
call assert_equal(l:current, bufnr())
endfunc
" Allow :e selecting the current buffer
func Test_edit_same_buffer_in_memory()
call s:reset_all_buffers()
let l:current = bufnr()
file same_buffer
call assert_equal(l:current, bufnr())
set winfixbuf
edit same_buffer
call assert_equal(l:current, bufnr())
endfunc
" Allow :e selecting the current buffer as a full path
func Test_edit_same_buffer_on_disk_absolute_path()
call s:reset_all_buffers()
let l:file = tempname()
let l:current = bufnr()
execute "edit " . l:file
write!
call assert_equal(l:current, bufnr())
set winfixbuf
execute "edit " l:file
call assert_equal(l:current, bufnr())
call delete(l:file)
endfunc
" Fail :enew but :enew! is allowed
func Test_enew()
call s:reset_all_buffers()