vim-patch:9.1.0147: Cannot keep a buffer focused in a window
Problem: Cannot keep a buffer focused in a window
(Amit Levy)
Solution: Add the 'winfixbuf' window-local option
(Colin Kennedy)
fixes: vim/vim#6445
closes: vim/vim#13903
2157035637
N/A patch:
vim-patch:58f1e5c0893a
This commit is contained in:
parent
a09ddd7ce5
commit
141182d6c6
|
@ -114,6 +114,13 @@ wiped out a buffer which contains a mark or is referenced in another way.
|
|||
You cannot have two buffers with exactly the same name. This includes the
|
||||
path leading to the file.
|
||||
|
||||
*E1513* >
|
||||
Cannot edit buffer. 'winfixbuf' is enabled
|
||||
|
||||
If a window has 'winfixbuf' enabled, you cannot change that window's current
|
||||
buffer. You need to set 'nowinfixbuf' before continuing. You may use [!] to
|
||||
force the window to switch buffers, if your command supports it.
|
||||
|
||||
*E72* >
|
||||
Close error on swap file
|
||||
|
||||
|
|
|
@ -160,6 +160,8 @@ The following new APIs and features were added.
|
|||
• 'breakindent' performance is significantly improved for wrapped lines.
|
||||
• Cursor movement, insertion with [count] and |screenpos()| are now faster.
|
||||
|
||||
• |'winfixbuf'| keeps a window focused onto a specific buffer
|
||||
|
||||
• |vim.iter()| provides a generic iterator interface for tables and Lua
|
||||
iterators |for-in|.
|
||||
|
||||
|
|
|
@ -6271,6 +6271,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
"split" when both are present.
|
||||
uselast If included, jump to the previously used window when
|
||||
jumping to errors with |quickfix| commands.
|
||||
If a window has 'winfixbuf' enabled, 'switchbuf' is currently not
|
||||
applied to the split window.
|
||||
|
||||
*'synmaxcol'* *'smc'*
|
||||
'synmaxcol' 'smc' number (default 3000)
|
||||
|
@ -7170,6 +7172,15 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
Note: Do not confuse this with the height of the Vim window, use
|
||||
'lines' for that.
|
||||
|
||||
*'winfixbuf'* *'wfb'* *'nowinfixbuf'* *'nowfb'*
|
||||
'winfixbuf' 'wfb' boolean (default off)
|
||||
local to window
|
||||
If enabled, the buffer and any window that displays it are paired.
|
||||
For example, attempting to change the buffer with |:edit| will fail.
|
||||
Other commands which change a window's buffer such as |:cnext| will
|
||||
also skip any window with 'winfixbuf' enabled. However if a command
|
||||
has an "!" option, a window can be forced to switch buffers.
|
||||
|
||||
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
|
||||
'winfixheight' 'wfh' boolean (default off)
|
||||
local to window |local-noglobal|
|
||||
|
|
|
@ -939,6 +939,7 @@ Short explanation of each option: *option-list*
|
|||
'wildoptions' 'wop' specifies how command line completion is done
|
||||
'winaltkeys' 'wak' when the windows system handles ALT keys
|
||||
'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B
|
||||
'winfixbuf' 'wfb' keep window focused on a single buffer
|
||||
'winfixheight' 'wfh' keep window height when opening/closing windows
|
||||
'winfixwidth' 'wfw' keep window width when opening/closing windows
|
||||
'winheight' 'wh' minimum number of lines for the current window
|
||||
|
|
|
@ -402,17 +402,22 @@ If the tag is in the current file this will always work. Otherwise the
|
|||
performed actions depend on whether the current file was changed, whether a !
|
||||
is added to the command and on the 'autowrite' option:
|
||||
|
||||
tag in file autowrite ~
|
||||
current file changed ! option action ~
|
||||
---------------------------------------------------------------------------
|
||||
yes x x x goto tag
|
||||
no no x x read other file, goto tag
|
||||
no yes yes x abandon current file, read other file, goto
|
||||
tag
|
||||
no yes no on write current file, read other file, goto
|
||||
tag
|
||||
no yes no off fail
|
||||
---------------------------------------------------------------------------
|
||||
tag in file autowrite ~
|
||||
current file changed ! winfixbuf option action ~
|
||||
-----------------------------------------------------------------------------
|
||||
yes x x no x goto tag
|
||||
no no x no x read other file, goto tag
|
||||
no yes yes no x abandon current file,
|
||||
read other file, goto tag
|
||||
no yes no no on write current file,
|
||||
read other file, goto tag
|
||||
no yes no no off fail
|
||||
yes x yes x x goto tag
|
||||
no no no yes x fail
|
||||
no yes no yes x fail
|
||||
no yes no yes on fail
|
||||
no yes no yes off fail
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
- If the tag is in the current file, the command will always work.
|
||||
- If the tag is in another file and the current file was not changed, the
|
||||
|
@ -428,6 +433,8 @@ current file changed ! option action ~
|
|||
the changes, use the ":w" command and then use ":tag" without an argument.
|
||||
This works because the tag is put on the stack anyway. If you want to lose
|
||||
the changes you can use the ":tag!" command.
|
||||
- If the tag is in another file and the window includes 'winfixbuf', the
|
||||
command will fail. If the tag is in the same file then it may succeed.
|
||||
|
||||
*tag-security*
|
||||
Note that Vim forbids some commands, for security reasons. This works like
|
||||
|
|
|
@ -6746,6 +6746,8 @@ vim.bo.swf = vim.bo.swapfile
|
|||
--- "split" when both are present.
|
||||
--- uselast If included, jump to the previously used window when
|
||||
--- jumping to errors with `quickfix` commands.
|
||||
--- If a window has 'winfixbuf' enabled, 'switchbuf' is currently not
|
||||
--- applied to the split window.
|
||||
---
|
||||
--- @type string
|
||||
vim.o.switchbuf = "uselast"
|
||||
|
@ -7874,6 +7876,18 @@ vim.o.wi = vim.o.window
|
|||
vim.go.window = vim.o.window
|
||||
vim.go.wi = vim.go.window
|
||||
|
||||
--- If enabled, the buffer and any window that displays it are paired.
|
||||
--- For example, attempting to change the buffer with `:edit` will fail.
|
||||
--- Other commands which change a window's buffer such as `:cnext` will
|
||||
--- also skip any window with 'winfixbuf' enabled. However if a command
|
||||
--- has an "!" option, a window can be forced to switch buffers.
|
||||
---
|
||||
--- @type boolean
|
||||
vim.o.winfixbuf = false
|
||||
vim.o.wfb = vim.o.winfixbuf
|
||||
vim.wo.winfixbuf = vim.o.winfixbuf
|
||||
vim.wo.wfb = vim.wo.winfixbuf
|
||||
|
||||
--- Keep the window height when windows are opened or closed and
|
||||
--- 'equalalways' is set. Also for `CTRL-W_=`. Set by default for the
|
||||
--- `preview-window` and `quickfix-window`.
|
||||
|
|
|
@ -444,6 +444,7 @@ if has("statusline")
|
|||
call <SID>AddOption("statusline", gettext("alternate format to be used for a status line"))
|
||||
call <SID>OptionG("stl", &stl)
|
||||
endif
|
||||
call append("$", "\t" .. s:local_to_window)
|
||||
call <SID>AddOption("equalalways", gettext("make all windows the same size when adding/removing windows"))
|
||||
call <SID>BinOptionG("ea", &ea)
|
||||
call <SID>AddOption("eadirection", gettext("in which direction 'equalalways' works: \"ver\", \"hor\" or \"both\""))
|
||||
|
@ -452,6 +453,8 @@ call <SID>AddOption("winheight", gettext("minimal number of lines used for the c
|
|||
call append("$", " \tset wh=" . &wh)
|
||||
call <SID>AddOption("winminheight", gettext("minimal number of lines used for any window"))
|
||||
call append("$", " \tset wmh=" . &wmh)
|
||||
call <SID>AddOption("winfixbuf", gettext("keep window focused on a single buffer"))
|
||||
call <SID>OptionG("wfb", &wfb)
|
||||
call <SID>AddOption("winfixheight", gettext("keep the height of the window"))
|
||||
call append("$", "\t" .. s:local_to_window)
|
||||
call <SID>BinOptionL("wfh")
|
||||
|
|
|
@ -876,6 +876,11 @@ void nvim_set_current_buf(Buffer buffer, Error *err)
|
|||
return;
|
||||
}
|
||||
|
||||
if (curwin->w_p_wfb) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
try_start();
|
||||
int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0);
|
||||
if (!try_end(err) && result == FAIL) {
|
||||
|
|
|
@ -61,6 +61,12 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
|
|||
if (!win || !buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (win->w_p_wfb) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (win == cmdwin_win || win == cmdwin_old_curwin || buf == cmdwin_buf) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
|
||||
return;
|
||||
|
|
|
@ -623,6 +623,8 @@ void ex_argument(exarg_T *eap)
|
|||
/// Edit file "argn" of the argument lists.
|
||||
void do_argfile(exarg_T *eap, int argn)
|
||||
{
|
||||
bool is_split_cmd = *eap->cmd == 's';
|
||||
|
||||
int old_arg_idx = curwin->w_arg_idx;
|
||||
|
||||
if (argn < 0 || argn >= ARGCOUNT) {
|
||||
|
@ -637,10 +639,16 @@ void do_argfile(exarg_T *eap, int argn)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!is_split_cmd
|
||||
&& (&ARGLIST[argn])->ae_fnum != curbuf->b_fnum
|
||||
&& !check_can_set_curbuf_forceit(eap->forceit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setpcmark();
|
||||
|
||||
// split window or create new tab page first
|
||||
if (*eap->cmd == 's' || cmdmod.cmod_tab != 0) {
|
||||
if (is_split_cmd || cmdmod.cmod_tab != 0) {
|
||||
if (win_split(0, 0) == FAIL) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1305,6 +1305,12 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
|||
}
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (action == DOBUF_GOTO && buf != curbuf && !check_can_set_curbuf_forceit(forceit)) {
|
||||
// disallow navigating to another buffer when 'winfixbuf' is applied
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if ((action == DOBUF_GOTO || action == DOBUF_SPLIT) && (buf->b_flags & BF_DUMMY)) {
|
||||
// disallow navigating to the dummy buffer
|
||||
semsg(_(e_nobufnr), count);
|
||||
|
|
|
@ -139,6 +139,8 @@ typedef struct {
|
|||
#define w_ve_flags w_onebuf_opt.wo_ve_flags // flags for 'virtualedit'
|
||||
OptInt wo_nuw;
|
||||
#define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth'
|
||||
int wo_wfb;
|
||||
#define w_p_wfb w_onebuf_opt.wo_wfb // 'winfixbuf'
|
||||
int wo_wfh;
|
||||
#define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight'
|
||||
int wo_wfw;
|
||||
|
|
|
@ -2008,6 +2008,10 @@ static int check_readonly(int *forceit, buf_T *buf)
|
|||
/// GETFILE_OPEN_OTHER for successfully opening another file.
|
||||
int getfile(int fnum, char *ffname_arg, char *sfname_arg, bool setpm, linenr_T lnum, bool forceit)
|
||||
{
|
||||
if (!check_can_set_curbuf_forceit(forceit)) {
|
||||
return GETFILE_ERROR;
|
||||
}
|
||||
|
||||
char *ffname = ffname_arg;
|
||||
char *sfname = sfname_arg;
|
||||
bool other;
|
||||
|
|
|
@ -812,7 +812,7 @@ module.cmds = {
|
|||
},
|
||||
{
|
||||
command = 'drop',
|
||||
flags = bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
|
||||
flags = bit.bor(BANG, FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
|
||||
addr_type = 'ADDR_NONE',
|
||||
func = 'ex_drop',
|
||||
},
|
||||
|
|
|
@ -444,6 +444,27 @@ int buf_write_all(buf_T *buf, bool forceit)
|
|||
/// ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo"
|
||||
void ex_listdo(exarg_T *eap)
|
||||
{
|
||||
if (curwin->w_p_wfb) {
|
||||
if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) && !eap->forceit) {
|
||||
// Disallow :ldo if 'winfixbuf' is applied
|
||||
semsg("%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (win_valid(prevwin)) {
|
||||
// Change the current window to another because 'winfixbuf' is enabled
|
||||
curwin = prevwin;
|
||||
} else {
|
||||
// Split the window, which will be 'nowinfixbuf', and set curwin to that
|
||||
exarg_T new_eap = {
|
||||
.cmdidx = CMD_split,
|
||||
.cmd = "split",
|
||||
.arg = "",
|
||||
};
|
||||
ex_splitview(&new_eap);
|
||||
}
|
||||
}
|
||||
|
||||
char *save_ei = NULL;
|
||||
|
||||
// Temporarily override SHM_OVER and SHM_OVERALL to avoid that file
|
||||
|
|
|
@ -5334,6 +5334,10 @@ static void ex_resize(exarg_T *eap)
|
|||
/// ":find [+command] <file>" command.
|
||||
static void ex_find(exarg_T *eap)
|
||||
{
|
||||
if (!check_can_set_curbuf_forceit(eap->forceit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *file_to_find = NULL;
|
||||
char *search_ctx = NULL;
|
||||
char *fname = find_file_in_path(eap->arg, strlen(eap->arg),
|
||||
|
@ -5364,6 +5368,14 @@ static void ex_find(exarg_T *eap)
|
|||
/// ":edit", ":badd", ":balt", ":visual".
|
||||
static void ex_edit(exarg_T *eap)
|
||||
{
|
||||
// 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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_exedit(eap, NULL);
|
||||
}
|
||||
|
||||
|
@ -6670,7 +6682,7 @@ static void ex_checkpath(exarg_T *eap)
|
|||
{
|
||||
find_pattern_in_path(NULL, 0, 0, false, false, CHECK_PATH, 1,
|
||||
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
|
||||
1, (linenr_T)MAXLNUM);
|
||||
1, (linenr_T)MAXLNUM, eap->forceit);
|
||||
}
|
||||
|
||||
/// ":psearch"
|
||||
|
@ -6729,7 +6741,7 @@ static void ex_findpat(exarg_T *eap)
|
|||
if (!eap->skip) {
|
||||
find_pattern_in_path(eap->arg, 0, strlen(eap->arg), whole, !eap->forceit,
|
||||
*eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
|
||||
n, action, eap->line1, eap->line2);
|
||||
n, action, eap->line1, eap->line2, eap->forceit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -971,6 +971,9 @@ EXTERN const char e_val_too_large[] INIT(= N_("E1510: Value too large: %s"));
|
|||
EXTERN const char e_undobang_cannot_redo_or_move_branch[]
|
||||
INIT(= N_("E5767: Cannot use :undo! to redo or move to a different undo branch"));
|
||||
|
||||
EXTERN const char e_winfixbuf_cannot_go_to_buffer[]
|
||||
INIT(= N_("E1513: Cannot edit buffer. 'winfixbuf' is enabled"));
|
||||
|
||||
EXTERN const char e_trustfile[] INIT(= N_("E5570: Cannot update trust file: %s"));
|
||||
|
||||
EXTERN const char e_unknown_option2[] INIT(= N_("E355: Unknown option: %s"));
|
||||
|
|
|
@ -3027,7 +3027,7 @@ static void get_next_include_file_completion(int compl_type)
|
|||
((compl_type == CTRL_X_PATH_DEFINES
|
||||
&& !(compl_cont_status & CONT_SOL))
|
||||
? FIND_DEFINE : FIND_ANY),
|
||||
1, ACTION_EXPAND, 1, MAXLNUM);
|
||||
1, ACTION_EXPAND, 1, MAXLNUM, false);
|
||||
}
|
||||
|
||||
/// Get the next set of words matching "compl_pattern" in dictionary or
|
||||
|
|
|
@ -3896,6 +3896,10 @@ static void nv_gotofile(cmdarg_T *cap)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!check_can_set_curbuf_disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *ptr = grab_file_name(cap->count1, &lnum);
|
||||
|
||||
if (ptr != NULL) {
|
||||
|
@ -4232,7 +4236,8 @@ static void nv_brackets(cmdarg_T *cap)
|
|||
(cap->cmdchar == ']'
|
||||
? curwin->w_cursor.lnum + 1
|
||||
: 1),
|
||||
MAXLNUM);
|
||||
MAXLNUM,
|
||||
false);
|
||||
xfree(ptr);
|
||||
curwin->w_set_curswant = true;
|
||||
}
|
||||
|
|
|
@ -4629,6 +4629,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
|
|||
return &(win->w_p_rnu);
|
||||
case PV_NUW:
|
||||
return &(win->w_p_nuw);
|
||||
case PV_WFB:
|
||||
return &(win->w_p_wfb);
|
||||
case PV_WFH:
|
||||
return &(win->w_p_wfh);
|
||||
case PV_WFW:
|
||||
|
|
|
@ -8406,6 +8406,8 @@ return {
|
|||
"split" when both are present.
|
||||
uselast If included, jump to the previously used window when
|
||||
jumping to errors with |quickfix| commands.
|
||||
If a window has 'winfixbuf' enabled, 'switchbuf' is currently not
|
||||
applied to the split window.
|
||||
]=],
|
||||
expand_cb = 'expand_set_switchbuf',
|
||||
full_name = 'switchbuf',
|
||||
|
@ -9816,6 +9818,23 @@ return {
|
|||
type = 'number',
|
||||
varname = 'p_window',
|
||||
},
|
||||
{
|
||||
abbreviation = 'wfb',
|
||||
defaults = { if_true = false },
|
||||
desc = [=[
|
||||
If enabled, the buffer and any window that displays it are paired.
|
||||
For example, attempting to change the buffer with |:edit| will fail.
|
||||
Other commands which change a window's buffer such as |:cnext| will
|
||||
also skip any window with 'winfixbuf' enabled. However if a command
|
||||
has an "!" option, a window can be forced to switch buffers.
|
||||
]=],
|
||||
full_name = 'winfixbuf',
|
||||
pv_name = 'p_wfb',
|
||||
redraw = { 'current_window' },
|
||||
scope = { 'window' },
|
||||
short_desc = N_('pin a window to a specific buffer'),
|
||||
type = 'boolean',
|
||||
},
|
||||
{
|
||||
abbreviation = 'wfh',
|
||||
defaults = { if_true = false },
|
||||
|
|
|
@ -2699,7 +2699,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum)
|
|||
// Didn't find it, go to the window before the quickfix
|
||||
// window, unless 'switchbuf' contains 'uselast': in this case we
|
||||
// try to jump to the previously used window first.
|
||||
if ((swb_flags & SWB_USELAST) && win_valid(prevwin)) {
|
||||
if ((swb_flags & SWB_USELAST) && !prevwin->w_p_wfb && win_valid(prevwin)) {
|
||||
win = prevwin;
|
||||
} else if (altwin != NULL) {
|
||||
win = altwin;
|
||||
|
@ -2714,6 +2714,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum)
|
|||
// Remember a usable window.
|
||||
if (altwin == NULL
|
||||
&& !win->w_p_pvw
|
||||
&& !win->w_p_wfb
|
||||
&& bt_normal(win->w_buffer)) {
|
||||
altwin = win;
|
||||
}
|
||||
|
@ -2802,6 +2803,25 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int
|
|||
ECMD_HIDE + ECMD_SET_HELP,
|
||||
prev_winid == curwin->handle ? curwin : NULL);
|
||||
} else {
|
||||
if (!forceit && curwin->w_p_wfb) {
|
||||
if (qi->qfl_type == QFLT_LOCATION) {
|
||||
// Location lists cannot split or reassign their window
|
||||
// so 'winfixbuf' windows must fail
|
||||
semsg("%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return QF_ABORT;
|
||||
}
|
||||
|
||||
if (!win_valid(prevwin)) {
|
||||
// Split the window, which will be 'nowinfixbuf', and set curwin to that
|
||||
exarg_T new_eap = {
|
||||
.cmdidx = CMD_split,
|
||||
.cmd = "split",
|
||||
.arg = "",
|
||||
};
|
||||
ex_splitview(&new_eap);
|
||||
}
|
||||
}
|
||||
|
||||
retval = buflist_getfile(qf_ptr->qf_fnum, 1,
|
||||
GETF_SETMARK | GETF_SWITCH, forceit);
|
||||
}
|
||||
|
@ -4297,6 +4317,11 @@ static void qf_jump_first(qf_info_T *qi, unsigned save_qfid, int forceit)
|
|||
if (qf_restore_list(qi, save_qfid) == FAIL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!check_can_set_curbuf_forceit(forceit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Autocommands might have cleared the list, check for that
|
||||
if (!qf_list_empty(qf_get_curlist(qi))) {
|
||||
qf_jump(qi, 0, 0, forceit);
|
||||
|
@ -5125,7 +5150,7 @@ void ex_cfile(exarg_T *eap)
|
|||
|
||||
// This function is used by the :cfile, :cgetfile and :caddfile
|
||||
// commands.
|
||||
// :cfile always creates a new quickfix list and jumps to the
|
||||
// :cfile always creates a new quickfix list and may jump to the
|
||||
// first error.
|
||||
// :cgetfile creates a new quickfix list but doesn't jump to the
|
||||
// first error.
|
||||
|
@ -5587,6 +5612,10 @@ theend:
|
|||
/// ":lvimgrepadd {pattern} file(s)"
|
||||
void ex_vimgrep(exarg_T *eap)
|
||||
{
|
||||
if (!check_can_set_curbuf_forceit(eap->forceit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *au_name = vgr_get_auname(eap->cmdidx);
|
||||
if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
|
||||
curbuf->b_fname, true, curbuf)) {
|
||||
|
|
|
@ -3564,8 +3564,10 @@ static char *get_line_and_copy(linenr_T lnum, char *buf)
|
|||
/// @param action What to do when we find it
|
||||
/// @param start_lnum first line to start searching
|
||||
/// @param end_lnum last line for searching
|
||||
/// @param forceit If true, always switch to the found path
|
||||
void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool skip_comments,
|
||||
int type, int count, int action, linenr_T start_lnum, linenr_T end_lnum)
|
||||
int type, int count, int action, linenr_T start_lnum, linenr_T end_lnum,
|
||||
int forceit)
|
||||
{
|
||||
SearchedFile *files; // Stack of included files
|
||||
SearchedFile *bigger; // When we need more space
|
||||
|
@ -4025,7 +4027,7 @@ search_line:
|
|||
break;
|
||||
}
|
||||
if (!GETFILE_SUCCESS(getfile(curwin_save->w_buffer->b_fnum, NULL,
|
||||
NULL, true, lnum, false))) {
|
||||
NULL, true, lnum, forceit))) {
|
||||
break; // failed to jump to file
|
||||
}
|
||||
} else {
|
||||
|
@ -4035,7 +4037,7 @@ search_line:
|
|||
check_cursor();
|
||||
} else {
|
||||
if (!GETFILE_SUCCESS(getfile(0, files[depth].name, NULL, true,
|
||||
files[depth].lnum, false))) {
|
||||
files[depth].lnum, forceit))) {
|
||||
break; // failed to jump to file
|
||||
}
|
||||
// autocommands may have changed the lnum, we don't
|
||||
|
|
|
@ -290,6 +290,10 @@ void set_buflocal_tfu_callback(buf_T *buf)
|
|||
/// @param verbose print "tag not found" message
|
||||
void do_tag(char *tag, int type, int count, int forceit, bool verbose)
|
||||
{
|
||||
if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
taggy_T *tagstack = curwin->w_tagstack;
|
||||
int tagstackidx = curwin->w_tagstackidx;
|
||||
int tagstacklen = curwin->w_tagstacklen;
|
||||
|
@ -2784,6 +2788,10 @@ static char *tag_full_fname(tagptrs_T *tagp)
|
|||
/// @return OK for success, NOTAGFILE when file not found, FAIL otherwise.
|
||||
static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
|
||||
{
|
||||
if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
char *pbuf_end;
|
||||
char *tofree_fname = NULL;
|
||||
tagptrs_T tagp;
|
||||
|
|
|
@ -133,6 +133,35 @@ static void log_frame_layout(frame_T *frame)
|
|||
}
|
||||
#endif
|
||||
|
||||
/// Check if the current window is allowed to move to a different buffer.
|
||||
///
|
||||
/// @return If the window has 'winfixbuf', or this function will return false.
|
||||
bool check_can_set_curbuf_disabled(void)
|
||||
{
|
||||
if (curwin->w_p_wfb) {
|
||||
semsg("%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Check if the current window is allowed to move to a different buffer.
|
||||
///
|
||||
/// @param forceit If true, do not error. If false and 'winfixbuf' is enabled, error.
|
||||
///
|
||||
/// @return If the window has 'winfixbuf', then forceit must be true
|
||||
/// or this function will return false.
|
||||
bool check_can_set_curbuf_forceit(int forceit)
|
||||
{
|
||||
if (!forceit && curwin->w_p_wfb) {
|
||||
semsg("%s", e_winfixbuf_cannot_go_to_buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @return the current window, unless in the cmdline window and "prevwin" is
|
||||
/// set, then return "prevwin".
|
||||
win_T *prevwin_curwin(void)
|
||||
|
@ -597,7 +626,7 @@ wingotofile:
|
|||
ptr = xmemdupz(ptr, len);
|
||||
|
||||
find_pattern_in_path(ptr, 0, len, true, Prenum == 0,
|
||||
type, Prenum1, ACTION_SPLIT, 1, MAXLNUM);
|
||||
type, Prenum1, ACTION_SPLIT, 1, MAXLNUM, false);
|
||||
xfree(ptr);
|
||||
curwin->w_set_curswant = true;
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local clear = helpers.clear
|
||||
local exec_lua = helpers.exec_lua
|
||||
|
||||
describe("Nvim API calls with 'winfixbuf'", function()
|
||||
before_each(function()
|
||||
clear()
|
||||
end)
|
||||
|
||||
it("Calling vim.api.nvim_win_set_buf with 'winfixbuf'", function()
|
||||
local results = exec_lua([[
|
||||
local function _setup_two_buffers()
|
||||
local buffer = vim.api.nvim_create_buf(true, true)
|
||||
|
||||
vim.api.nvim_create_buf(true, true) -- Make another buffer
|
||||
|
||||
local current_window = 0
|
||||
vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window})
|
||||
|
||||
return buffer
|
||||
end
|
||||
|
||||
local other_buffer = _setup_two_buffers()
|
||||
local current_window = 0
|
||||
local results, _ = pcall(vim.api.nvim_win_set_buf, current_window, other_buffer)
|
||||
|
||||
return results
|
||||
]])
|
||||
|
||||
assert(results == false)
|
||||
end)
|
||||
|
||||
it("Calling vim.api.nvim_set_current_buf with 'winfixbuf'", function()
|
||||
local results = exec_lua([[
|
||||
local function _setup_two_buffers()
|
||||
local buffer = vim.api.nvim_create_buf(true, true)
|
||||
|
||||
vim.api.nvim_create_buf(true, true) -- Make another buffer
|
||||
|
||||
local current_window = 0
|
||||
vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window})
|
||||
|
||||
return buffer
|
||||
end
|
||||
|
||||
local other_buffer = _setup_two_buffers()
|
||||
local results, _ = pcall(vim.api.nvim_set_current_buf, other_buffer)
|
||||
|
||||
return results
|
||||
]])
|
||||
|
||||
assert(results == false)
|
||||
end)
|
||||
end)
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue