mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 14:38:32 +00:00
vim-patch:8.2.4685: when a swap file is found for a popup there is no dialog (#26207)
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 vim/vim#10073)
188639d75c
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -930,10 +930,14 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
|
|||||||
/// Go to another buffer. Handles the result of the ATTENTION dialog.
|
/// Go to another buffer. Handles the result of the ATTENTION dialog.
|
||||||
void goto_buffer(exarg_T *eap, int start, int dir, int count)
|
void goto_buffer(exarg_T *eap, int start, int dir, int count)
|
||||||
{
|
{
|
||||||
|
const int save_sea = swap_exists_action;
|
||||||
|
|
||||||
bufref_T old_curbuf;
|
bufref_T old_curbuf;
|
||||||
set_bufref(&old_curbuf, curbuf);
|
set_bufref(&old_curbuf, curbuf);
|
||||||
swap_exists_action = SEA_DIALOG;
|
|
||||||
|
|
||||||
|
if (swap_exists_action == SEA_NONE) {
|
||||||
|
swap_exists_action = SEA_DIALOG;
|
||||||
|
}
|
||||||
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
|
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
|
||||||
start, dir, count, eap->forceit);
|
start, dir, count, eap->forceit);
|
||||||
|
|
||||||
@@ -946,7 +950,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
|
|||||||
|
|
||||||
// Quitting means closing the split window, nothing else.
|
// Quitting means closing the split window, nothing else.
|
||||||
win_close(curwin, true, false);
|
win_close(curwin, true, false);
|
||||||
swap_exists_action = SEA_NONE;
|
swap_exists_action = save_sea;
|
||||||
swap_exists_did_quit = true;
|
swap_exists_did_quit = true;
|
||||||
|
|
||||||
// Restore the error/interrupt/exception state if not discarded by a
|
// Restore the error/interrupt/exception state if not discarded by a
|
||||||
|
@@ -298,7 +298,9 @@ void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr)
|
|||||||
buf_T *buf = get_buf_arg(&argvars[0]);
|
buf_T *buf = get_buf_arg(&argvars[0]);
|
||||||
|
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
|
if (swap_exists_action != SEA_READONLY) {
|
||||||
swap_exists_action = SEA_NONE;
|
swap_exists_action = SEA_NONE;
|
||||||
|
}
|
||||||
buf_ensure_loaded(buf);
|
buf_ensure_loaded(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -684,6 +684,7 @@ EXTERN bool in_assert_fails INIT( = false); // assert_fails() active
|
|||||||
#define SEA_DIALOG 1 // use dialog when possible
|
#define SEA_DIALOG 1 // use dialog when possible
|
||||||
#define SEA_QUIT 2 // quit editing the file
|
#define SEA_QUIT 2 // quit editing the file
|
||||||
#define SEA_RECOVER 3 // recover the file
|
#define SEA_RECOVER 3 // recover the file
|
||||||
|
#define SEA_READONLY 4 // no dialog, mark buffer as read-only
|
||||||
|
|
||||||
EXTERN int swap_exists_action INIT( = SEA_NONE); ///< For dialog when swap file already exists.
|
EXTERN int swap_exists_action INIT( = SEA_NONE); ///< For dialog when swap file already exists.
|
||||||
EXTERN bool swap_exists_did_quit INIT( = false); ///< Selected "quit" at the dialog.
|
EXTERN bool swap_exists_did_quit INIT( = false); ///< Selected "quit" at the dialog.
|
||||||
|
@@ -235,6 +235,16 @@ typedef enum {
|
|||||||
UB_SAME_DIR, // update the B0_SAME_DIR flag
|
UB_SAME_DIR, // update the B0_SAME_DIR flag
|
||||||
} upd_block0_T;
|
} upd_block0_T;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "memline.c.generated.h"
|
# include "memline.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -3235,15 +3245,8 @@ static void attention_message(buf_T *buf, char *fname)
|
|||||||
|
|
||||||
/// Trigger the SwapExists autocommands.
|
/// Trigger the SwapExists autocommands.
|
||||||
///
|
///
|
||||||
/// @return a value for equivalent to do_dialog() (see below):
|
/// @return a value for equivalent to do_dialog().
|
||||||
/// 0: still need to ask for a choice
|
static sea_choice_T do_swapexists(buf_T *buf, char *fname)
|
||||||
/// 1: open read-only
|
|
||||||
/// 2: edit anyway
|
|
||||||
/// 3: recover
|
|
||||||
/// 4: delete it
|
|
||||||
/// 5: quit
|
|
||||||
/// 6: abort
|
|
||||||
static int do_swapexists(buf_T *buf, char *fname)
|
|
||||||
{
|
{
|
||||||
set_vim_var_string(VV_SWAPNAME, fname, -1);
|
set_vim_var_string(VV_SWAPNAME, fname, -1);
|
||||||
set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
|
set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
|
||||||
@@ -3258,20 +3261,20 @@ static int do_swapexists(buf_T *buf, char *fname)
|
|||||||
|
|
||||||
switch (*get_vim_var_str(VV_SWAPCHOICE)) {
|
switch (*get_vim_var_str(VV_SWAPCHOICE)) {
|
||||||
case 'o':
|
case 'o':
|
||||||
return 1;
|
return SEA_CHOICE_READONLY;
|
||||||
case 'e':
|
case 'e':
|
||||||
return 2;
|
return SEA_CHOICE_EDIT;
|
||||||
case 'r':
|
case 'r':
|
||||||
return 3;
|
return SEA_CHOICE_RECOVER;
|
||||||
case 'd':
|
case 'd':
|
||||||
return 4;
|
return SEA_CHOICE_DELETE;
|
||||||
case 'q':
|
case 'q':
|
||||||
return 5;
|
return SEA_CHOICE_QUIT;
|
||||||
case 'a':
|
case 'a':
|
||||||
return 6;
|
return SEA_CHOICE_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return SEA_CHOICE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find out what name to use for the swapfile for buffer 'buf'.
|
/// Find out what name to use for the swapfile for buffer 'buf'.
|
||||||
@@ -3384,13 +3387,13 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
|||||||
// - the buffer was not recovered
|
// - the buffer was not recovered
|
||||||
if (differ == false && !(curbuf->b_flags & BF_RECOVERED)
|
if (differ == false && !(curbuf->b_flags & BF_RECOVERED)
|
||||||
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
|
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
|
||||||
int choice = 0;
|
sea_choice_T choice = SEA_CHOICE_NONE;
|
||||||
|
|
||||||
// It's safe to delete the swapfile if all these are true:
|
// It's safe to delete the swapfile if all these are true:
|
||||||
// - the edited file exists
|
// - the edited file exists
|
||||||
// - the swapfile has no changes and looks OK
|
// - the swapfile has no changes and looks OK
|
||||||
if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) {
|
if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) {
|
||||||
choice = 4;
|
choice = SEA_CHOICE_DELETE;
|
||||||
if (p_verbose > 0) {
|
if (p_verbose > 0) {
|
||||||
verb_msg(_("Found a swap file that is not useful, deleting it"));
|
verb_msg(_("Found a swap file that is not useful, deleting it"));
|
||||||
}
|
}
|
||||||
@@ -3398,14 +3401,19 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
|||||||
|
|
||||||
// If there is a SwapExists autocommand and we can handle the
|
// If there is a SwapExists autocommand and we can handle the
|
||||||
// response, trigger it. It may return 0 to ask the user anyway.
|
// 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
|
&& swap_exists_action != SEA_NONE
|
||||||
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf)) {
|
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf)) {
|
||||||
choice = do_swapexists(buf, fname);
|
choice = do_swapexists(buf, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (choice == SEA_CHOICE_NONE && swap_exists_action == SEA_READONLY) {
|
||||||
|
// always open readonly.
|
||||||
|
choice = SEA_CHOICE_READONLY;
|
||||||
|
}
|
||||||
|
|
||||||
process_running = 0; // Set by attention_message..swapfile_info.
|
process_running = 0; // Set by attention_message..swapfile_info.
|
||||||
if (choice == 0) {
|
if (choice == SEA_CHOICE_NONE) {
|
||||||
// Show info about the existing swapfile.
|
// Show info about the existing swapfile.
|
||||||
attention_message(buf, fname);
|
attention_message(buf, fname);
|
||||||
|
|
||||||
@@ -3418,7 +3426,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
|||||||
flush_buffers(FLUSH_TYPEAHEAD);
|
flush_buffers(FLUSH_TYPEAHEAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swap_exists_action != SEA_NONE && choice == 0) {
|
if (swap_exists_action != SEA_NONE && choice == SEA_CHOICE_NONE) {
|
||||||
const char *const sw_msg_1 = _("Swap file \"");
|
const char *const sw_msg_1 = _("Swap file \"");
|
||||||
const char *const sw_msg_2 = _("\" already exists!");
|
const char *const sw_msg_2 = _("\" already exists!");
|
||||||
|
|
||||||
@@ -3432,56 +3440,57 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
|
|||||||
memcpy(name, sw_msg_1, sw_msg_1_len + 1);
|
memcpy(name, sw_msg_1, sw_msg_1_len + 1);
|
||||||
home_replace(NULL, fname, &name[sw_msg_1_len], fname_len, true);
|
home_replace(NULL, fname, &name[sw_msg_1_len], fname_len, true);
|
||||||
xstrlcat(name, sw_msg_2, name_len);
|
xstrlcat(name, sw_msg_2, name_len);
|
||||||
choice = do_dialog(VIM_WARNING, _("VIM - ATTENTION"),
|
int dialog_result
|
||||||
|
= do_dialog(VIM_WARNING,
|
||||||
|
_("VIM - ATTENTION"),
|
||||||
name,
|
name,
|
||||||
process_running
|
process_running
|
||||||
? _("&Open Read-Only\n&Edit anyway\n&Recover"
|
? _("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort")
|
||||||
"\n&Quit\n&Abort")
|
: _("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"),
|
||||||
: _("&Open Read-Only\n&Edit anyway\n&Recover"
|
|
||||||
"\n&Delete it\n&Quit\n&Abort"),
|
|
||||||
1, NULL, false);
|
1, NULL, false);
|
||||||
|
|
||||||
if (process_running && choice >= 4) {
|
if (process_running && dialog_result >= 4) {
|
||||||
choice++; // Skip missing "Delete it" button.
|
// compensate for missing "Delete it" button
|
||||||
|
dialog_result++;
|
||||||
}
|
}
|
||||||
|
choice = (sea_choice_T)dialog_result;
|
||||||
xfree(name);
|
xfree(name);
|
||||||
|
|
||||||
// pretend screen didn't scroll, need redraw anyway
|
// pretend screen didn't scroll, need redraw anyway
|
||||||
msg_reset_scroll();
|
msg_reset_scroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (choice > 0) {
|
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case 1: // "Open Read-Only"
|
case SEA_CHOICE_READONLY: // "Open Read-Only"
|
||||||
buf->b_p_ro = true;
|
buf->b_p_ro = true;
|
||||||
break;
|
break;
|
||||||
case 2: // "Edit anyway"
|
case SEA_CHOICE_EDIT: // "Edit anyway"
|
||||||
break;
|
break;
|
||||||
case 3: // "Recover"
|
case SEA_CHOICE_RECOVER: // "Recover"
|
||||||
swap_exists_action = SEA_RECOVER;
|
swap_exists_action = SEA_RECOVER;
|
||||||
break;
|
break;
|
||||||
case 4: // "Delete it"
|
case SEA_CHOICE_DELETE: // "Delete it"
|
||||||
os_remove(fname);
|
os_remove(fname);
|
||||||
break;
|
break;
|
||||||
case 5: // "Quit"
|
case SEA_CHOICE_QUIT: // "Quit"
|
||||||
swap_exists_action = SEA_QUIT;
|
swap_exists_action = SEA_QUIT;
|
||||||
break;
|
break;
|
||||||
case 6: // "Abort"
|
case SEA_CHOICE_ABORT: // "Abort"
|
||||||
swap_exists_action = SEA_QUIT;
|
swap_exists_action = SEA_QUIT;
|
||||||
got_int = true;
|
got_int = true;
|
||||||
break;
|
break;
|
||||||
}
|
case SEA_CHOICE_NONE:
|
||||||
|
|
||||||
// If the swapfile was deleted this `fname` can be used.
|
|
||||||
if (!os_path_exists(fname)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg_puts("\n");
|
msg_puts("\n");
|
||||||
if (msg_silent == 0) {
|
if (msg_silent == 0) {
|
||||||
// call wait_return() later
|
// call wait_return() later
|
||||||
need_wait_return = true;
|
need_wait_return = true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the swapfile was deleted this `fname` can be used.
|
||||||
|
if (choice != SEA_CHOICE_NONE && !os_path_exists(fname)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user