Merge pull request #17702 from zeertzjq/vim-8.1.0877

vim-patch:8.1.{0877,0892,1015},8.2.{3759,3762}: quickfix patches
This commit is contained in:
zeertzjq 2022-03-13 14:21:37 +08:00 committed by GitHub
commit c9b94188d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 289 additions and 131 deletions

View File

@ -1284,7 +1284,7 @@ complete_info([{what}]) *complete_info()*
<
*confirm()*
confirm({msg} [, {choices} [, {default} [, {type}]]])
Confirm() offers the user a dialog, from which a choice can be
confirm() offers the user a dialog, from which a choice can be
made. It returns the number of the choice. For the first
choice this is 1.
@ -3039,10 +3039,16 @@ getloclist({nr} [, {what}]) *getloclist()*
If the optional {what} dictionary argument is supplied, then
returns the items listed in {what} as a dictionary. Refer to
|getqflist()| for the supported items in {what}.
If {what} contains 'filewinid', then returns the id of the
window used to display files from the location list. This
field is applicable only when called from a location list
window. See |location-list-file-window| for more details.
In addition to the items supported by |getqflist()| in {what},
the following item is supported by |getloclist()|:
filewinid id of the window used to display files
from the location list. This field is
applicable only when called from a
location list window. See
|location-list-file-window| for more
details.
Returns a |Dictionary| with default values if there is no
location list for the window {nr}.
@ -3218,6 +3224,9 @@ getqflist([{what}]) *getqflist()*
nr get information for this quickfix list; zero
means the current quickfix list and "$" means
the last quickfix list
qfbufnr number of the buffer displayed in the quickfix
window. Returns 0 if the quickfix buffer is
not present. See |quickfix-buffer|.
size number of entries in the quickfix list
title get the list title |quickfix-title|
winid get the quickfix |window-ID|
@ -3246,6 +3255,8 @@ getqflist([{what}]) *getqflist()*
items quickfix list entries. If not present, set to
an empty list.
nr quickfix list number. If not present, set to 0
qfbufnr number of the buffer displayed in the quickfix
window. If not present, set to 0.
size number of entries in the quickfix list. If not
present, set to 0.
title quickfix list title text. If not present, set

View File

@ -3225,14 +3225,14 @@ text...
commands are skipped.
When {pattern} is omitted all errors are caught.
Examples: >
:catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C)
:catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors
:catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts
:catch /^Vim(write):/ " catch all errors in :write
:catch /^Vim\%((\a\+)\)\=:E123/ " catch error E123
:catch /my-exception/ " catch user exception
:catch /.*/ " catch everything
:catch " same as /.*/
:catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C)
:catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors
:catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts
:catch /^Vim(write):/ " catch all errors in :write
:catch /^Vim\%((\a\+)\)\=:E123:/ " catch error E123
:catch /my-exception/ " catch user exception
:catch /.*/ " catch everything
:catch " same as /.*/
<
Another character can be used instead of / around the
{pattern}, so long as it does not have a special

View File

@ -571,6 +571,7 @@ location list.
second quickfix window. If [height] is given the
existing window will be resized to it.
*quickfix-buffer*
The window will contain a special buffer, with
'buftype' equal to "quickfix". Don't change this!
The window will have the w:quickfix_title variable set
@ -579,7 +580,11 @@ location list.
status line if the value of 'statusline' is adjusted
properly. Whenever this buffer is modified by a
quickfix command or function, the |b:changedtick|
variable is incremented.
variable is incremented. You can get the number of
this buffer using the getqflist() and getloclist()
functions by passing the 'qfbufnr' item. For a
location list, this buffer is wiped out when the
location list is removed.
*:lop* *:lopen*
:lop[en] [height] Open a window to show the location list for the
@ -768,12 +773,18 @@ using these functions are below:
" get the quickfix list window id
:echo getqflist({'winid' : 0}).winid
" get the quickfix list window buffer number
:echo getqflist({'qfbufnr' : 0}).qfbufnr
" get the context of the current location list
:echo getloclist(0, {'context' : 0}).context
" get the location list window id of the third window
:echo getloclist(3, {'winid' : 0}).winid
" get the location list window buffer number of the third window
:echo getloclist(3, {'qfbufnr' : 0}).qfbufnr
" get the file window id of a location list window (winnr: 4)
:echo getloclist(4, {'filewinid' : 0}).filewinid
<

View File

@ -5333,16 +5333,12 @@ bool buf_hide(const buf_T *const buf)
char_u *buf_spname(buf_T *buf)
{
if (bt_quickfix(buf)) {
win_T *win;
tabpage_T *tp;
// For location list window, w_llist_ref points to the location list.
// For quickfix window, w_llist_ref is NULL.
if (find_win_for_buf(buf, &win, &tp) && win->w_llist_ref != NULL) {
return (char_u *)_(msg_loclist);
} else {
// Differentiate between the quickfix and location list buffers using
// the buffer number stored in the global quickfix stack.
if (buf->b_fnum == qf_stack_get_bufnr()) {
return (char_u *)_(msg_qflist);
}
return (char_u *)_(msg_loclist);
}
// There is no _file_ when 'buftype' is "nofile", b_sfname
// contains the name as specified by the user.

View File

@ -6436,7 +6436,7 @@ win_T *find_win_by_nr_or_id(typval_T *vp)
int nr = (int)tv_get_number_chk(vp, NULL);
if (nr >= LOWEST_WIN_ID) {
return win_id2wp(vp);
return win_id2wp(tv_get_number(vp));
}
return find_win_by_nr(vp, NULL);

View File

@ -2197,12 +2197,13 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// "win_execute(win_id, command)" function
static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *tp;
win_T *wp = win_id2wp_tp(argvars, &tp);
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
int id = tv_get_number(argvars);
tabpage_T *tp;
win_T *wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL) {
WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
}
@ -4130,7 +4131,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_alloc_ret(rettv, kListLenMayKnow);
if (argvars[0].v_type != VAR_UNKNOWN) {
wparg = win_id2wp(argvars);
wparg = win_id2wp(tv_get_number(&argvars[0]));
if (wparg == NULL) {
return;
}
@ -5917,10 +5918,10 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int fnum;
if (argvars[1].v_type != VAR_UNKNOWN) {
tabpage_T *tp;
// use window specified in the second argument
win_T *wp = win_id2wp_tp(&argvars[1], &tp);
int id = (int)tv_get_number(&argvars[1]);
tabpage_T *tp;
win_T *wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL) {
switchwin_T switchwin;
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {

View File

@ -75,6 +75,7 @@ struct qfline_S {
// There is a stack of error lists.
#define LISTCOUNT 10
#define INVALID_QFIDX (-1)
#define INVALID_QFBUFNR (0)
/// Quickfix list type.
typedef enum
@ -126,6 +127,7 @@ struct qf_info_S {
int qf_curlist; // current error list
qf_list_T qf_lists[LISTCOUNT];
qfltype_T qfl_type; // type of list
int qf_bufnr; // quickfix window buffer number
};
static qf_info_T ql_info; // global quickfix list
@ -1703,6 +1705,28 @@ static void locstack_queue_delreq(qf_info_T *qi)
qf_delq_head = q;
}
/// Return the global quickfix stack window buffer number.
int qf_stack_get_bufnr(void)
{
return ql_info.qf_bufnr;
}
/// Wipe the quickfix window buffer (if present) for the specified
/// quickfix/location list.
static void wipe_qf_buffer(qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL
{
if (qi->qf_bufnr != INVALID_QFBUFNR) {
buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
// If the quickfix buffer is not loaded in any window, then
// wipe the buffer.
close_buffer(NULL, qfbuf, DOBUF_WIPE, false);
qi->qf_bufnr = INVALID_QFBUFNR;
}
}
}
/// Free a location list stack
static void ll_free_all(qf_info_T **pqi)
{
@ -1715,19 +1739,23 @@ static void ll_free_all(qf_info_T **pqi)
}
*pqi = NULL; // Remove reference to this list
// If the location list is still in use, then queue the delete request
// to be processed later.
if (quickfix_busy > 0) {
locstack_queue_delreq(qi);
return;
}
qi->qf_refcount--;
if (qi->qf_refcount < 1) {
// No references to this location list.
// If the location list is still in use, then queue the delete request
// to be processed later.
if (quickfix_busy > 0) {
locstack_queue_delreq(qi);
} else {
for (i = 0; i < qi->qf_listcount; i++) {
qf_free(qf_get_list(qi, i));
}
xfree(qi);
// If the quickfix window buffer is loaded, then wipe it
wipe_qf_buffer(qi);
for (i = 0; i < qi->qf_listcount; i++) {
qf_free(qf_get_list(qi, i));
}
xfree(qi);
}
}
@ -1885,6 +1913,7 @@ static qf_info_T *qf_alloc_stack(qfltype_T qfltype)
qf_info_T *qi = xcalloc(1, sizeof(qf_info_T));
qi->qf_refcount++;
qi->qfl_type = qfltype;
qi->qf_bufnr = INVALID_QFBUFNR;
return qi;
}
@ -2446,7 +2475,7 @@ static qfline_T *qf_get_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfi
return qf_ptr;
}
// Find a window displaying a Vim help file.
// Find a window displaying a Vim help file in the current tab page.
static win_T *qf_find_help_win(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@ -2520,8 +2549,9 @@ static int jump_to_help_window(qf_info_T *qi, bool newwin, int *opened_window)
return OK;
}
// Find a non-quickfix window using the given location list.
// Returns NULL if a matching window is not found.
/// Find a non-quickfix window using the given location list stack in the
/// current tabpage.
/// Returns NULL if a matching window is not found.
static win_T *qf_find_win_with_loclist(const qf_info_T *ll)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@ -2533,7 +2563,7 @@ static win_T *qf_find_win_with_loclist(const qf_info_T *ll)
return NULL;
}
// Find a window containing a normal buffer
/// Find a window containing a normal buffer in the current tab page.
static win_T *qf_find_win_with_normal_buf(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@ -2589,7 +2619,7 @@ static void qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, qf_info_T *ll_
win_T *win = use_win;
if (win == NULL) {
// Find the window showing the selected file
// Find the window showing the selected file in the current tab page.
FOR_ALL_WINDOWS_IN_TAB(win2, curtab) {
if (win2->w_buffer->b_fnum == qf_fnum) {
win = win2;
@ -2721,7 +2751,7 @@ static int qf_jump_to_usable_window(int qf_fnum, bool newwin, int *opened_window
}
/// Edit the selected file or help file.
static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win_T *oldwin,
static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int prev_winid,
int *opened_window)
{
qf_list_T *qfl = qf_get_curlist(qi);
@ -2740,7 +2770,7 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win
} else {
retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
ECMD_HIDE + ECMD_SET_HELP,
oldwin == curwin ? curwin : NULL);
prev_winid == curwin->handle ? curwin : NULL);
}
} else {
retval = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1,
@ -2748,10 +2778,13 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win
}
// If a location list, check whether the associated window is still
// present.
if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin)) {
emsg(_("E924: Current window was closed"));
*opened_window = false;
return NOTDONE;
if (qfl_type == QFLT_LOCATION) {
win_T *wp = win_id2wp(prev_winid);
if (wp == NULL && curwin->w_llist != qi) {
emsg(_("E924: Current window was closed"));
*opened_window = false;
return NOTDONE;
}
}
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) {
@ -2906,7 +2939,7 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int
/// NOTDONE if the quickfix/location list is freed by an autocmd when opening
/// the file.
static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit,
win_T *oldwin, int *opened_window, int openfold, int print_message)
int prev_winid, int *opened_window, int openfold, int print_message)
{
buf_T *old_curbuf;
linenr_T old_lnum;
@ -2918,7 +2951,7 @@ static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int
old_lnum = curwin->w_cursor.lnum;
if (qf_ptr->qf_fnum != 0) {
retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid,
opened_window);
if (retval != OK) {
return retval;
@ -2967,8 +3000,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
int old_qf_index;
char_u *old_swb = p_swb;
unsigned old_swb_flags = swb_flags;
int prev_winid;
int opened_window = false;
win_T *oldwin = curwin;
int print_message = true;
const bool old_KeyTyped = KeyTyped; // getting file may reset it
int retval = OK;
@ -2982,6 +3015,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
return;
}
incr_quickfix_busy();
qfl = qf_get_curlist(qi);
qf_ptr = qfl->qf_ptr;
@ -3004,6 +3039,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
print_message = false;
}
prev_winid = curwin->handle;
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
if (retval == FAIL) {
goto failed;
@ -3012,7 +3049,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
goto theend;
}
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin,
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
&opened_window, old_KeyTyped, print_message);
if (retval == NOTDONE) {
// Quickfix/location list is freed by an autocmd
@ -3037,12 +3074,13 @@ theend:
qfl->qf_ptr = qf_ptr;
qfl->qf_index = qf_index;
}
if (p_swb != old_swb && p_swb == empty_option && opened_window) {
if (p_swb != old_swb && p_swb == empty_option) {
// Restore old 'switchbuf' value, but not when an autocommand or
// modeline has changed the value.
p_swb = old_swb;
swb_flags = old_swb_flags;
}
decr_quickfix_busy();
}
@ -3612,7 +3650,7 @@ static void qf_set_cwindow_options(void)
// switch off 'swapfile'
set_option_value("swf", 0L, NULL, OPT_LOCAL);
set_option_value("bt", 0L, "quickfix", OPT_LOCAL);
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
set_option_value("bh", 0L, "hide", OPT_LOCAL);
RESET_BINDING(curwin);
curwin->w_p_diff = false;
set_option_value("fdm", 0L, "manual", OPT_LOCAL);
@ -3646,22 +3684,13 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
if (win_split(height, flags) == FAIL) {
return FAIL; // not enough room for window
}
// User autocommands may have invalidated the previous window after calling
// win_split, so add a check to ensure that the win is still here
if (IS_LL_STACK(qi) && !win_valid(win)) {
// close the window that was supposed to be for the loclist
win_close(curwin, false, false);
return FAIL;
}
RESET_BINDING(curwin);
if (IS_LL_STACK(qi)) {
// For the location list window, create a reference to the
// location list from the window 'win'.
curwin->w_llist_ref = win->w_llist;
win->w_llist->qf_refcount++;
// location list stack from the window 'win'.
curwin->w_llist_ref = qi;
qi->qf_refcount++;
}
if (oldwin != curwin) {
@ -3678,6 +3707,8 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE + ECMD_NOWINENTER, oldwin) == FAIL) {
return FAIL;
}
// save the number of the new buffer
qi->qf_bufnr = curbuf->b_fnum;
}
// Set the options for the quickfix buffer/window (if not already done)
@ -3856,8 +3887,8 @@ static int is_qf_win(const win_T *win, const qf_info_T *qi)
return false;
}
/// Find a window displaying the quickfix/location stack 'qi'
/// Only searches in the current tabpage.
/// Find a window displaying the quickfix/location stack 'qi' in the current tab
/// page.
static win_T *qf_find_win(const qf_info_T *qi)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@ -3870,11 +3901,20 @@ static win_T *qf_find_win(const qf_info_T *qi)
return NULL;
}
// Find a quickfix buffer.
// Searches in windows opened in all the tabs.
/// Find a quickfix buffer.
/// Searches in windows opened in all the tab pages.
static buf_T *qf_find_buf(qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
if (qi->qf_bufnr != INVALID_QFBUFNR) {
buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
if (qfbuf != NULL) {
return qfbuf;
}
// buffer is no longer present
qi->qf_bufnr = INVALID_QFBUFNR;
}
FOR_ALL_TAB_WINDOWS(tp, win) {
if (is_qf_win(win, qi)) {
return win->w_buffer;
@ -5979,6 +6019,21 @@ static int qf_winid(qf_info_T *qi)
return 0;
}
/// Returns the number of the buffer displayed in the quickfix/location list
/// window. If there is no buffer associated with the list or the buffer is
/// wiped out, then returns 0.
static int qf_getprop_qfbufnr(const qf_info_T *qi, dict_T *retdict)
FUNC_ATTR_NONNULL_ARG(2)
{
int bufnum = 0;
if (qi != NULL && buflist_findnr(qi->qf_bufnr) != NULL) {
bufnum = qi->qf_bufnr;
}
return tv_dict_add_nr(retdict, S_LEN("qfbufnr"), bufnum);
}
/// Convert the keys in 'what' to quickfix list property flags.
static int qf_getprop_keys2flags(const dict_T *what, bool loclist)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
@ -6022,6 +6077,9 @@ static int qf_getprop_keys2flags(const dict_T *what, bool loclist)
if (loclist && tv_dict_find(what, S_LEN("filewinid")) != NULL) {
flags |= QF_GETLIST_FILEWINID;
}
if (tv_dict_find(what, S_LEN("qfbufnr")) != NULL) {
flags |= QF_GETLIST_QFBUFNR;
}
if (tv_dict_find(what, S_LEN("quickfixtextfunc")) != NULL) {
flags |= QF_GETLIST_QFTF;
}
@ -6113,6 +6171,9 @@ static int qf_getprop_defaults(qf_info_T *qi, int flags, int locstack, dict_T *r
if ((status == OK) && locstack && (flags & QF_GETLIST_FILEWINID)) {
status = tv_dict_add_nr(retdict, S_LEN("filewinid"), 0);
}
if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
status = qf_getprop_qfbufnr(qi, retdict);
}
if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
status = tv_dict_add_str(retdict, S_LEN("quickfixtextfunc"), "");
}
@ -6282,6 +6343,9 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
if ((status == OK) && (wp != NULL) && (flags & QF_GETLIST_FILEWINID)) {
status = qf_getprop_filewinid(wp, qi, retdict);
}
if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
status = qf_getprop_qfbufnr(qi, retdict);
}
if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
status = qf_getprop_qftf(qfl, retdict);
}
@ -6670,20 +6734,6 @@ static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char
return retval;
}
/// Find the non-location list window with the specified location list stack in
/// the current tabpage.
static win_T *find_win_with_ll(const qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer)) {
return wp;
}
}
return NULL;
}
// Free the entire quickfix/location list stack.
// If the quickfix/location list window is open, then clear it.
static void qf_free_stack(win_T *wp, qf_info_T *qi)
@ -6698,12 +6748,10 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
qf_update_buffer(qi, NULL);
}
win_T *llwin = NULL;
win_T *orig_wp = wp;
if (wp != NULL && IS_LL_WINDOW(wp)) {
// If in the location list window, then use the non-location list
// window with this location list (if present)
llwin = find_win_with_ll(qi);
win_T *const llwin = qf_find_win_with_loclist(qi);
if (llwin != NULL) {
wp = llwin;
}
@ -6714,16 +6762,17 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
// quickfix list
qi->qf_curlist = 0;
qi->qf_listcount = 0;
} else if (IS_LL_WINDOW(orig_wp)) {
} else if (qfwin != NULL) {
// If the location list window is open, then create a new empty location
// list
qf_info_T *new_ll = qf_alloc_stack(QFLT_LOCATION);
new_ll->qf_bufnr = qfwin->w_buffer->b_fnum;
// first free the list reference in the location list window
ll_free_all(&orig_wp->w_llist_ref);
ll_free_all(&qfwin->w_llist_ref);
orig_wp->w_llist_ref = new_ll;
if (llwin != NULL) {
qfwin->w_llist_ref = new_ll;
if (wp != qfwin) {
win_set_loclist(wp, new_ll);
}
}

View File

@ -1,4 +1,4 @@
" Test for the quickfix commands.
" Test for the quickfix feature.
source check.vim
CheckFeature quickfix
@ -169,8 +169,8 @@ func XlistTests(cchar)
\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
let l = split(execute('Xlist', ""), "\n")
call assert_equal([' 1 Data.Text:10 col 5 warning 11: ModuleWarning',
\ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning',
\ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l)
\ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning',
\ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l)
" For help entries in the quickfix list, only the filename without directory
" should be displayed
@ -1655,7 +1655,7 @@ func XquickfixSetListWithAct(cchar)
\ {'filename': 'fnameD', 'text': 'D'},
\ {'filename': 'fnameE', 'text': 'E'}]
" {action} is unspecified. Same as specifing ' '.
" {action} is unspecified. Same as specifying ' '.
new | only
silent! Xnewer 99
call g:Xsetlist(list1)
@ -2020,6 +2020,7 @@ func s:test_xgrep(cchar)
enew
set makeef=Temp_File_##
silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
call assert_true(len(g:Xgetlist()) == 9)
" Try with 'grepprg' set to 'internal'
set grepprg=internal
@ -2028,12 +2029,12 @@ func s:test_xgrep(cchar)
call assert_true(len(g:Xgetlist()) == 9)
set grepprg&vim
call writefile(['Vim'], 'XtestTempFile')
set makeef=XtestTempFile
silent Xgrep Grep_Test_Text: test_quickfix.vim
call assert_equal(5, len(g:Xgetlist()))
call assert_false(filereadable('XtestTempFile'))
set makeef&vim
call writefile(['Vim'], 'XtestTempFile')
set makeef=XtestTempFile
silent Xgrep Grep_Test_Text: test_quickfix.vim
call assert_equal(5, len(g:Xgetlist()))
call assert_false(filereadable('XtestTempFile'))
set makeef&vim
endfunc
func Test_grep()
@ -2706,7 +2707,7 @@ func Test_cwindow_jump()
" Open a new window and create a location list
" Open the location list window and close the other window
" Jump to an entry.
" Should create a new window and jump to the entry. The scrtach buffer
" Should create a new window and jump to the entry. The scratch buffer
" should not be used.
enew | only
set buftype=nofile
@ -2739,6 +2740,25 @@ func Test_cwindow_jump()
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
" open the quickfix buffer in two windows and jump to an entry. Should open
" the file in the first quickfix window.
enew | only
copen
let bnum = bufnr('')
exe 'sbuffer ' . bnum
wincmd b
cfirst
call assert_equal(2, winnr())
call assert_equal('F1', bufname(''))
enew | only
exe 'sb' bnum
exe 'botright sb' bnum
wincmd t
clast
call assert_equal(2, winnr())
call assert_equal('quickfix', getwinvar(1, '&buftype'))
call assert_equal('quickfix', getwinvar(3, '&buftype'))
" Jumping to a file from the location list window should find a usable
" window by wrapping around the window list.
enew | only
@ -3548,20 +3568,21 @@ func Xgetlist_empty_tests(cchar)
call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
\ 'title' : '', 'winid' : 0, 'changedtick': 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
\ 'quickfixtextfunc' : ''},
\ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
\ g:Xgetlist({'all' : 0}))
endif
" Quickfix window with empty stack
silent! Xopen
let qfwinid = (a:cchar == 'c') ? win_getid() : 0
let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
Xclose
@ -3593,12 +3614,12 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'quickfixtextfunc' : '',
\ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''},
\ g:Xgetlist({'id' : qfid, 'all' : 0}))
endif
@ -3616,12 +3637,12 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0,
\ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0,
\ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
endif
endfunc
@ -4360,7 +4381,7 @@ func Test_splitview()
new | only
" When split opening files from a helpgrep location list window, a new help
" window should be opend with a copy of the location list.
" window should be opened with a copy of the location list.
lhelpgrep window
let locid = getloclist(0, {'id' : 0}).id
lwindow
@ -4456,11 +4477,19 @@ func Xqfbuf_test(cchar)
Xclose
" Even after the quickfix window is closed, the buffer should be loaded
call assert_true(bufloaded(qfbnum))
call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
Xopen
" Buffer should be reused when opening the window again
call assert_equal(qfbnum, bufnr(''))
Xclose
" When quickfix buffer is wiped out, getqflist() should return 0
%bw!
Xexpr ""
Xopen
bw!
call assert_equal(0, g:Xgetlist({'qfbufnr': 0}).qfbufnr)
if a:cchar == 'l'
%bwipe
" For a location list, when both the file window and the location list
@ -4474,7 +4503,7 @@ func Xqfbuf_test(cchar)
close
" When the location list window is closed, the buffer name should not
" change to 'Quickfix List'
call assert_match(qfbnum . ' h- "\[Location List]"', execute('ls'))
call assert_match(qfbnum . 'u h- "\[Location List]"', execute('ls!'))
call assert_true(bufloaded(qfbnum))
" After deleting a location list buffer using ":bdelete", opening the
@ -4491,6 +4520,7 @@ func Xqfbuf_test(cchar)
" removed
call setloclist(0, [], 'f')
call assert_false(bufexists(qfbnum))
call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
" When the location list is freed with the location list window open, the
" location list buffer should not be lost. It should be reused when the
@ -4515,11 +4545,36 @@ func Xqfbuf_test(cchar)
endfunc
func Test_qfbuf()
throw 'skipped: enable after porting patch 8.1.0877'
call Xqfbuf_test('c')
call Xqfbuf_test('l')
endfunc
" If there is an autocmd to use only one window, then opening the location
" list window used to crash Vim.
func Test_winonly_autocmd()
call s:create_test_file('Xtest1')
" Autocmd to show only one Vim window at a time
autocmd WinEnter * only
new
" Load the location list
lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
let loclistid = getloclist(0, {'id' : 0}).id
" Open the location list window. Only this window will be shown and the file
" window is closed.
lopen
call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
" Jump to an entry in the location list and make sure that the cursor is
" positioned correctly.
ll 3
call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
call assert_equal('Xtest1', bufname(''))
call assert_equal(15, line('.'))
" Cleanup
autocmd! WinEnter
new | only
call delete('Xtest1')
endfunc
" Test to make sure that an empty quickfix buffer is not reused for loading
" a normal buffer.
func Test_empty_qfbuf()
@ -5207,16 +5262,14 @@ func Xtest_qftextfunc(cchar)
" Non-existing function
set quickfixtextfunc=Tabc
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
call assert_fails("Xwindow", 'E117:')
Xclose
set quickfixtextfunc&
" set option to a non-function
set quickfixtextfunc=[10,\ 20]
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
call assert_fails("Xwindow", 'E117:')
Xclose
set quickfixtextfunc&
@ -5226,8 +5279,7 @@ func Xtest_qftextfunc(cchar)
return a:a .. a:b .. a:c
endfunc
set quickfixtextfunc=Xqftext
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
call assert_fails("Xwindow", 'E119:')
Xclose
@ -5236,9 +5288,8 @@ func Xtest_qftextfunc(cchar)
return ['one', [], 'two']
endfunc
set quickfixtextfunc=Xqftext2
" call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
" \ 'E730:')
Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']
call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
\ 'E730:')
call assert_fails('Xwindow', 'E730:')
call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
\ getline(1, '$'))
@ -5402,4 +5453,40 @@ func Test_win_gettype()
lclose
endfunc
" Test for opening the quickfix window in two tab pages and then closing one
" of the quickfix windows. This should not make the quickfix buffer unlisted.
" (github issue #9300).
func Test_two_qf_windows()
cexpr "F1:1:line1"
copen
tabnew
copen
call assert_true(&buflisted)
cclose
tabfirst
call assert_true(&buflisted)
let bnum = bufnr()
cclose
" if all the quickfix windows are closed, then buffer should be unlisted.
call assert_false(buflisted(bnum))
%bw!
" Repeat the test for a location list
lexpr "F2:2:line2"
lopen
let bnum = bufnr()
tabnew
exe "buffer" bnum
tabfirst
lclose
tablast
call assert_true(buflisted(bnum))
tabclose
lopen
call assert_true(buflisted(bnum))
lclose
call assert_false(buflisted(bnum))
%bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -1420,13 +1420,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
p_wh = i;
}
if (!win_valid(oldwin)) {
return FAIL;
if (win_valid(oldwin)) {
// Send the window positions to the UI
oldwin->w_pos_changed = true;
}
// Send the window positions to the UI
oldwin->w_pos_changed = true;
return OK;
}
@ -2598,6 +2596,13 @@ int win_close(win_T *win, bool free_buf, bool force)
reset_synblock(win);
}
// When a quickfix/location list window is closed and the buffer is
// displayed in only one window, then unlist the buffer.
if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)
&& win->w_buffer->b_nwindows == 1) {
win->w_buffer->b_p_bl = false;
}
/*
* Close the link to the buffer.
*/
@ -7197,16 +7202,14 @@ void win_id2tabwin(typval_T *const argvars, typval_T *const rettv)
tv_list_append_number(list, winnr);
}
win_T *win_id2wp(typval_T *argvars)
win_T *win_id2wp(int id)
{
return win_id2wp_tp(argvars, NULL);
return win_id2wp_tp(id, NULL);
}
// Return the window and tab pointer of window "id".
win_T *win_id2wp_tp(typval_T *argvars, tabpage_T **tpp)
win_T *win_id2wp_tp(int id, tabpage_T **tpp)
{
int id = tv_get_number(&argvars[0]);
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->handle == id) {
if (tpp != NULL) {