mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.4685: when a swap file is found for a popup there is no dialog
Problem: When a swap file is found for a popup there is no dialog and the buffer is loaded anyway. Solution: Silently load the buffer read-only. (closes #10073)
This commit is contained in:
@@ -271,6 +271,11 @@ popup_create({what}, {options}) *popup_create()*
|
||||
'buftype' set to "popup". That buffer will be wiped out once
|
||||
the popup closes.
|
||||
|
||||
if {what} is a buffer number and loading the buffer runs into
|
||||
an existing swap file, it is silently opened read-only, as if
|
||||
a |SwapExists| autocommand had set |v:swapchoice| to 'o'.
|
||||
This is because we assume the buffer is only used for viewing.
|
||||
|
||||
{options} is a dictionary with many possible entries.
|
||||
See |popup_create-arguments| for details.
|
||||
|
||||
|
@@ -150,6 +150,7 @@ buffer_ensure_loaded(buf_T *buf)
|
||||
aco_save_T aco;
|
||||
|
||||
aucmd_prepbuf(&aco, buf);
|
||||
if (swap_exists_action != SEA_READONLY)
|
||||
swap_exists_action = SEA_NONE;
|
||||
open_buffer(FALSE, NULL, 0);
|
||||
aucmd_restbuf(&aco);
|
||||
@@ -1053,9 +1054,11 @@ goto_buffer(
|
||||
int count)
|
||||
{
|
||||
bufref_T old_curbuf;
|
||||
int save_sea = swap_exists_action;
|
||||
|
||||
set_bufref(&old_curbuf, curbuf);
|
||||
|
||||
if (swap_exists_action == SEA_NONE)
|
||||
swap_exists_action = SEA_DIALOG;
|
||||
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
|
||||
start, dir, count, eap->forceit);
|
||||
@@ -1071,7 +1074,7 @@ goto_buffer(
|
||||
|
||||
// Quitting means closing the split window, nothing else.
|
||||
win_close(curwin, TRUE);
|
||||
swap_exists_action = SEA_NONE;
|
||||
swap_exists_action = save_sea;
|
||||
swap_exists_did_quit = TRUE;
|
||||
|
||||
#if defined(FEAT_EVAL)
|
||||
|
@@ -4631,19 +4631,22 @@ attention_message(
|
||||
--no_wait_return;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
SEA_CHOICE_NONE = 0,
|
||||
SEA_CHOICE_READONLY = 1,
|
||||
SEA_CHOICE_EDIT = 2,
|
||||
SEA_CHOICE_RECOVER = 3,
|
||||
SEA_CHOICE_DELETE = 4,
|
||||
SEA_CHOICE_QUIT = 5,
|
||||
SEA_CHOICE_ABORT = 6
|
||||
} sea_choice_T;
|
||||
|
||||
#if defined(FEAT_EVAL)
|
||||
/*
|
||||
* Trigger the SwapExists autocommands.
|
||||
* Returns a value for equivalent to do_dialog() (see below):
|
||||
* 0: still need to ask for a choice
|
||||
* 1: open read-only
|
||||
* 2: edit anyway
|
||||
* 3: recover
|
||||
* 4: delete it
|
||||
* 5: quit
|
||||
* 6: abort
|
||||
* Returns a value for equivalent to do_dialog().
|
||||
*/
|
||||
static int
|
||||
static sea_choice_T
|
||||
do_swapexists(buf_T *buf, char_u *fname)
|
||||
{
|
||||
set_vim_var_string(VV_SWAPNAME, fname, -1);
|
||||
@@ -4659,15 +4662,15 @@ do_swapexists(buf_T *buf, char_u *fname)
|
||||
|
||||
switch (*get_vim_var_str(VV_SWAPCHOICE))
|
||||
{
|
||||
case 'o': return 1;
|
||||
case 'e': return 2;
|
||||
case 'r': return 3;
|
||||
case 'd': return 4;
|
||||
case 'q': return 5;
|
||||
case 'a': return 6;
|
||||
case 'o': return SEA_CHOICE_READONLY;
|
||||
case 'e': return SEA_CHOICE_EDIT;
|
||||
case 'r': return SEA_CHOICE_RECOVER;
|
||||
case 'd': return SEA_CHOICE_DELETE;
|
||||
case 'q': return SEA_CHOICE_QUIT;
|
||||
case 'a': return SEA_CHOICE_ABORT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return SEA_CHOICE_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4986,7 +4989,7 @@ findswapname(
|
||||
if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
|
||||
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
|
||||
{
|
||||
int choice = 0;
|
||||
sea_choice_T choice = SEA_CHOICE_NONE;
|
||||
stat_T st;
|
||||
#ifdef CREATE_DUMMY_FILE
|
||||
int did_use_dummy = FALSE;
|
||||
@@ -5013,7 +5016,7 @@ findswapname(
|
||||
if (mch_stat((char *)buf->b_fname, &st) == 0
|
||||
&& swapfile_unchanged(fname))
|
||||
{
|
||||
choice = 4;
|
||||
choice = SEA_CHOICE_DELETE;
|
||||
if (p_verbose > 0)
|
||||
verb_msg(_("Found a swap file that is not useful, deleting it"));
|
||||
}
|
||||
@@ -5024,13 +5027,20 @@ findswapname(
|
||||
* the response, trigger it. It may return 0 to ask the
|
||||
* user anyway.
|
||||
*/
|
||||
if (choice == 0
|
||||
if (choice == SEA_CHOICE_NONE
|
||||
&& swap_exists_action != SEA_NONE
|
||||
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
|
||||
choice = do_swapexists(buf, fname);
|
||||
|
||||
if (choice == 0)
|
||||
#endif
|
||||
|
||||
if (choice == SEA_CHOICE_NONE
|
||||
&& swap_exists_action == SEA_READONLY)
|
||||
{
|
||||
// always open readonly.
|
||||
choice = SEA_CHOICE_READONLY;
|
||||
}
|
||||
|
||||
if (choice == SEA_CHOICE_NONE)
|
||||
{
|
||||
#ifdef FEAT_GUI
|
||||
// If we are supposed to start the GUI but it wasn't
|
||||
@@ -5053,9 +5063,11 @@ findswapname(
|
||||
}
|
||||
|
||||
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
|
||||
if (swap_exists_action != SEA_NONE && choice == 0)
|
||||
if (swap_exists_action != SEA_NONE
|
||||
&& choice == SEA_CHOICE_NONE)
|
||||
{
|
||||
char_u *name;
|
||||
int dialog_result;
|
||||
|
||||
name = alloc(STRLEN(fname)
|
||||
+ STRLEN(_("Swap file \""))
|
||||
@@ -5067,7 +5079,7 @@ findswapname(
|
||||
1000, TRUE);
|
||||
STRCAT(name, _("\" already exists!"));
|
||||
}
|
||||
choice = do_dialog(VIM_WARNING,
|
||||
dialog_result = do_dialog(VIM_WARNING,
|
||||
(char_u *)_("VIM - ATTENTION"),
|
||||
name == NULL
|
||||
? (char_u *)_("Swap file already exists!")
|
||||
@@ -5079,9 +5091,11 @@ findswapname(
|
||||
(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL, FALSE);
|
||||
|
||||
# ifdef HAVE_PROCESS_STILL_RUNNING
|
||||
if (process_still_running && choice >= 4)
|
||||
choice++; // Skip missing "Delete it" button
|
||||
if (process_still_running && dialog_result >= 4)
|
||||
// compensate for missing "Delete it" button
|
||||
dialog_result++;
|
||||
# endif
|
||||
choice = dialog_result;
|
||||
vim_free(name);
|
||||
|
||||
// pretend screen didn't scroll, need redraw anyway
|
||||
@@ -5090,42 +5104,38 @@ findswapname(
|
||||
}
|
||||
#endif
|
||||
|
||||
if (choice > 0)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case 1:
|
||||
case SEA_CHOICE_READONLY:
|
||||
buf->b_p_ro = TRUE;
|
||||
break;
|
||||
case 2:
|
||||
case SEA_CHOICE_EDIT:
|
||||
break;
|
||||
case 3:
|
||||
case SEA_CHOICE_RECOVER:
|
||||
swap_exists_action = SEA_RECOVER;
|
||||
break;
|
||||
case 4:
|
||||
case SEA_CHOICE_DELETE:
|
||||
mch_remove(fname);
|
||||
break;
|
||||
case 5:
|
||||
case SEA_CHOICE_QUIT:
|
||||
swap_exists_action = SEA_QUIT;
|
||||
break;
|
||||
case 6:
|
||||
case SEA_CHOICE_ABORT:
|
||||
swap_exists_action = SEA_QUIT;
|
||||
got_int = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the file was deleted this fname can be used.
|
||||
if (mch_getperm(fname) < 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
case SEA_CHOICE_NONE:
|
||||
msg_puts("\n");
|
||||
if (msg_silent == 0)
|
||||
// call wait_return() later
|
||||
need_wait_return = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the file was deleted this fname can be used.
|
||||
if (choice != SEA_CHOICE_NONE && mch_getperm(fname) < 0)
|
||||
break;
|
||||
|
||||
#ifdef CREATE_DUMMY_FILE
|
||||
// Going to try another name, need the dummy file again.
|
||||
if (did_use_dummy)
|
||||
|
@@ -1989,7 +1989,9 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
||||
new_buffer = FALSE;
|
||||
win_init_popup_win(wp, buf);
|
||||
set_local_options_default(wp, FALSE);
|
||||
swap_exists_action = SEA_READONLY;
|
||||
buffer_ensure_loaded(buf);
|
||||
swap_exists_action = SEA_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -2775,6 +2775,26 @@ func Test_popupwin_with_buffer()
|
||||
call delete('XsomeFile')
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_buffer_with_swapfile()
|
||||
call writefile(['some text', 'in a buffer'], 'XopenFile')
|
||||
call writefile([''], '.XopenFile.swp')
|
||||
let g:ignoreSwapExists = 1
|
||||
|
||||
let bufnr = bufadd('XopenFile')
|
||||
call assert_equal(0, bufloaded(bufnr))
|
||||
let winid = popup_create(bufnr, {'hidden': 1})
|
||||
call assert_equal(1, bufloaded(bufnr))
|
||||
call popup_close(winid)
|
||||
|
||||
exe 'buffer ' .. bufnr
|
||||
call assert_equal(1, &readonly)
|
||||
bwipe!
|
||||
|
||||
call delete('XopenFile')
|
||||
call delete('.XopenFile.swp')
|
||||
unlet g:ignoreSwapExists
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_terminal_buffer()
|
||||
CheckFeature terminal
|
||||
CheckUnix
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
4685,
|
||||
/**/
|
||||
4684,
|
||||
/**/
|
||||
|
@@ -1250,6 +1250,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
||||
#define SEA_DIALOG 1 // use dialog when possible
|
||||
#define SEA_QUIT 2 // quit editing the file
|
||||
#define SEA_RECOVER 3 // recover the file
|
||||
#define SEA_READONLY 4 // no dialog, mark buffer as read-only
|
||||
|
||||
/*
|
||||
* Minimal size for block 0 of a swap file.
|
||||
|
Reference in New Issue
Block a user