Merge pull request #33381 from zeertzjq/vim-9.1.1283

vim-patch:9.1.{1253,1283,1287}
This commit is contained in:
zeertzjq
2025-04-08 13:24:43 +08:00
committed by GitHub
14 changed files with 554 additions and 64 deletions

View File

@@ -78,6 +78,7 @@ LUA
OPTIONS
• 'chistory' and 'lhistory' set size of the |quickfix-stack|.
• 'diffopt' `inline:` configures diff highlighting for changes within a line.
• 'pummaxwidth' sets maximum width for the completion popup menu.

View File

@@ -1326,6 +1326,17 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
*'chistory'* *'chi'*
'chistory' 'chi' number (default 10)
global
Number of quickfix lists that should be remembered for the quickfix
stack. Must be between 1 and 100. If the option is set to a value
that is lower than the amount of entries in the quickfix list stack,
entries will be removed starting from the oldest one. If the current
quickfix list was removed, then the quickfix list at top of the stack
(the most recently created) will be used in its place. For additional
info, see |quickfix-stack|.
*'cindent'* *'cin'* *'nocindent'* *'nocin'*
'cindent' 'cin' boolean (default off)
local to buffer
@@ -3780,6 +3791,17 @@ A jump table for the options with a short description can be found at |Q_op|.
temporarily when performing an operation where redrawing may cause
flickering or cause a slowdown.
*'lhistory'* *'lhi'*
'lhistory' 'lhi' number (default 10)
local to window
Like 'chistory', but for the location list stack associated with the
current window. If the option is changed in either the location list
window itself or the the window that is associated with the location
list stack, the new value will also be applied to the other one. This
means this value will always be the same for a given location list
window and its corresponding window. See |quickfix-stack| for
additional info.
*'linebreak'* *'lbr'* *'nolinebreak'* *'nolbr'*
'linebreak' 'lbr' boolean (default off)
local to window

View File

@@ -31,12 +31,12 @@ From inside Vim an easy way to run a command and handle the output is with the
The 'errorformat' option should be set to match the error messages from your
compiler (see |errorformat| below).
*quickfix-ID*
*quickfix-stack* *quickfix-ID*
Each quickfix list has a unique identifier called the quickfix ID and this
number will not change within a Vim session. The |getqflist()| function can be
used to get the identifier assigned to a list. There is also a quickfix list
number which may change whenever more than ten lists are added to a quickfix
stack.
number which may change whenever more than 'chistory' lists are added to a
quickfix stack.
*location-list* *E776*
A location list is a window-local quickfix list. You get one after commands
@@ -848,10 +848,12 @@ using these functions are below:
=============================================================================
3. Using more than one list of errors *quickfix-error-lists*
So far has been assumed that there is only one list of errors. Actually the
ten last used lists are remembered. When starting a new list, the previous
ones are automatically kept. Two commands can be used to access older error
lists. They set one of the existing error lists as the current one.
So far it has been assumed that there is only one list of errors. Actually
there can be multiple used lists that are remembered; see 'chistory' and
'lhistory'.
When starting a new list, the previous ones are automatically kept. Two
commands can be used to access older error lists. They set one of the
existing error lists as the current one.
*:colder* *:col* *E380*
:col[der] [count] Go to older error list. When [count] is given, do

View File

@@ -651,6 +651,7 @@ Short explanation of each option: *option-list*
'cdpath' 'cd' list of directories searched with ":cd"
'cedit' key used to open the command-line window
'charconvert' 'ccv' expression for character encoding conversion
'chistory' 'chi' maximum number of quickfix lists in history
'cindent' 'cin' do C program indenting
'cinkeys' 'cink' keys that trigger indent when 'cindent' is set
'cinoptions' 'cino' how to do indenting when 'cindent' is set
@@ -768,6 +769,7 @@ Short explanation of each option: *option-list*
'langremap' 'lrm' do apply 'langmap' to mapped characters
'laststatus' 'ls' tells when last window has status lines
'lazyredraw' 'lz' don't redraw while executing macros
'lhistory' 'lhi' maximum number of location lists in history
'linebreak' 'lbr' wrap long lines at a blank
'lines' number of lines in the display
'linespace' 'lsp' number of pixel lines to use between characters

View File

@@ -799,6 +799,20 @@ vim.o.ccv = vim.o.charconvert
vim.go.charconvert = vim.o.charconvert
vim.go.ccv = vim.go.charconvert
--- Number of quickfix lists that should be remembered for the quickfix
--- stack. Must be between 1 and 100. If the option is set to a value
--- that is lower than the amount of entries in the quickfix list stack,
--- entries will be removed starting from the oldest one. If the current
--- quickfix list was removed, then the quickfix list at top of the stack
--- (the most recently created) will be used in its place. For additional
--- info, see `quickfix-stack`.
---
--- @type integer
vim.o.chistory = 10
vim.o.chi = vim.o.chistory
vim.go.chistory = vim.o.chistory
vim.go.chi = vim.go.chistory
--- Enables automatic C program indenting. See 'cinkeys' to set the keys
--- that trigger reindenting in insert mode and 'cinoptions' to set your
--- preferred indent style.
@@ -3730,6 +3744,20 @@ vim.o.lz = vim.o.lazyredraw
vim.go.lazyredraw = vim.o.lazyredraw
vim.go.lz = vim.go.lazyredraw
--- Like 'chistory', but for the location list stack associated with the
--- current window. If the option is changed in either the location list
--- window itself or the the window that is associated with the location
--- list stack, the new value will also be applied to the other one. This
--- means this value will always be the same for a given location list
--- window and its corresponding window. See `quickfix-stack` for
--- additional info.
---
--- @type integer
vim.o.lhistory = 10
vim.o.lhi = vim.o.lhistory
vim.wo.lhistory = vim.o.lhistory
vim.wo.lhi = vim.wo.lhistory
--- If on, Vim will wrap long lines at a character in 'breakat' rather
--- than at the last character that fits on the screen. Unlike
--- 'wrapmargin' and 'textwidth', this does not insert <EOL>s in the file,

View File

@@ -1,7 +1,7 @@
" These commands create the option window.
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
" Last Change: 2025 Mar 28
" Last Change: 2025 Apr 06
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" If there already is an option window, jump to that one.
@@ -367,6 +367,13 @@ if has("linebreak")
call append("$", "\t" .. s:local_to_window)
call <SID>OptionL("nuw")
endif
if has("quickfix")
call <SID>AddOption("chistory", gettext("maximum number of quickfix lists that can be stored in history"))
call <SID>OptionL("chi")
call <SID>AddOption("lhistory", gettext("maximum number of location lists that can be stored in history"))
call append("$", "\t" .. s:local_to_window)
call <SID>OptionL("lhi")
endif
if has("conceal")
call <SID>AddOption("conceallevel", gettext("controls whether concealable text is hidden"))
call append("$", "\t" .. s:local_to_window)

View File

@@ -149,6 +149,8 @@ typedef struct {
#define w_p_wfw w_onebuf_opt.wo_wfw // 'winfixwidth'
int wo_pvw;
#define w_p_pvw w_onebuf_opt.wo_pvw // 'previewwindow'
OptInt wo_lhi;
#define w_p_lhi w_onebuf_opt.wo_lhi // 'lhistory'
int wo_rl;
#define w_p_rl w_onebuf_opt.wo_rl // 'rightleft'
char *wo_rlc;

View File

@@ -238,6 +238,9 @@ void early_init(mparm_T *paramp)
TIME_MSG("inits 1");
set_lang_var(); // set v:lang and v:ctype
// initialize quickfix list
qf_init_stack();
}
#ifdef MAKE_LIB

View File

@@ -126,6 +126,10 @@ static const char e_number_required_after_equal[]
= N_("E521: Number required after =");
static const char e_preview_window_already_exists[]
= N_("E590: A preview window already exists");
static const char e_cannot_have_negative_or_zero_number_of_quickfix[]
= N_("E1542: Cannot have a negative or zero number of quickfix/location lists");
static const char e_cannot_have_more_than_hundred_quickfix[]
= N_("E1543: Cannot have more than a hundred quickfix/location lists");
static char *p_term = NULL;
static char *p_ttytype = NULL;
@@ -2701,6 +2705,23 @@ static const char *did_set_wrap(optset_T *args)
return NULL;
}
/// Process the new 'chistory' or 'lhistory' option value. 'chistory' will
/// be used if args->os_varp is the same as p_chi, else 'lhistory'.
static const char *did_set_xhistory(optset_T *args)
{
win_T *win = (win_T *)args->os_win;
bool is_p_chi = (OptInt *)args->os_varp == &p_chi;
OptInt *arg = is_p_chi ? &p_chi : (OptInt *)args->os_varp;
if (is_p_chi) {
qf_resize_stack((int)(*arg));
} else {
ll_resize_stack(win, (int)(*arg));
}
return NULL;
}
// When 'syntax' is set, load the syntax of that name
static void do_syntax_autocmd(buf_T *buf, bool value_changed)
{
@@ -2942,6 +2963,14 @@ static const char *validate_num_option(OptIndex opt_idx, OptInt *newval, char *e
return e_invarg;
}
break;
case kOptChistory:
case kOptLhistory:
if (value < 1) {
return e_cannot_have_negative_or_zero_number_of_quickfix;
} else if (value > 100) {
return e_cannot_have_more_than_hundred_quickfix;
}
break;
default:
break;
}
@@ -4604,6 +4633,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return &(win->w_p_wfw);
case kOptPreviewwindow:
return &(win->w_p_pvw);
case kOptLhistory:
return &(win->w_p_lhi);
case kOptRightleft:
return &(win->w_p_rl);
case kOptRightleftcmd:
@@ -4883,6 +4914,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_fdt = copy_option_val(from->wo_fdt);
to->wo_fmr = copy_option_val(from->wo_fmr);
to->wo_scl = copy_option_val(from->wo_scl);
to->wo_lhi = from->wo_lhi;
to->wo_winhl = copy_option_val(from->wo_winhl);
to->wo_winbl = from->wo_winbl;
to->wo_stc = copy_option_val(from->wo_stc);

View File

@@ -444,6 +444,7 @@ EXTERN OptInt p_rdt; ///< 'redrawtime'
EXTERN OptInt p_re; ///< 'regexpengine'
EXTERN OptInt p_report; ///< 'report'
EXTERN OptInt p_pvh; ///< 'previewheight'
EXTERN OptInt p_chi; ///< 'chistory'
EXTERN int p_ari; ///< 'allowrevins'
EXTERN int p_ri; ///< 'revins'
EXTERN int p_ru; ///< 'ruler'

View File

@@ -1122,6 +1122,25 @@ local options = {
tags = { 'E202', 'E214', 'E513' },
varname = 'p_ccv',
},
{
abbreviation = 'chi',
cb = 'did_set_xhistory',
defaults = 10,
desc = [=[
Number of quickfix lists that should be remembered for the quickfix
stack. Must be between 1 and 100. If the option is set to a value
that is lower than the amount of entries in the quickfix list stack,
entries will be removed starting from the oldest one. If the current
quickfix list was removed, then the quickfix list at top of the stack
(the most recently created) will be used in its place. For additional
info, see |quickfix-stack|.
]=],
full_name = 'chistory',
scope = { 'global' },
short_desc = N_('number of quickfix lists stored in history'),
type = 'number',
varname = 'p_chi',
},
{
abbreviation = 'cin',
defaults = false,
@@ -5022,6 +5041,24 @@ local options = {
type = 'boolean',
varname = 'p_lz',
},
{
abbreviation = 'lhi',
cb = 'did_set_xhistory',
defaults = 10,
desc = [=[
Like 'chistory', but for the location list stack associated with the
current window. If the option is changed in either the location list
window itself or the the window that is associated with the location
list stack, the new value will also be applied to the other one. This
means this value will always be the same for a given location list
window and its corresponding window. See |quickfix-stack| for
additional info.
]=],
full_name = 'lhistory',
scope = { 'win' },
short_desc = N_('number of location lists stored in history'),
type = 'number',
},
{
abbreviation = 'lbr',
defaults = false,

View File

@@ -101,7 +101,6 @@ struct qfline_S {
};
// There is a stack of error lists.
#define LISTCOUNT 10
#define INVALID_QFIDX (-1)
#define INVALID_QFBUFNR (0)
@@ -153,12 +152,14 @@ struct qf_info_S {
int qf_refcount;
int qf_listcount; // current number of lists
int qf_curlist; // current error list
qf_list_T qf_lists[LISTCOUNT];
int qf_maxcount; // maximum number of lists
qf_list_T *qf_lists;
qfltype_T qfl_type; // type of list
int qf_bufnr; // quickfix window buffer number
};
static qf_info_T ql_info; // global quickfix list
static qf_info_T ql_info_actual; // global quickfix list
static qf_info_T *ql_info; // points to ql_info_actual after allocation
static unsigned last_qf_id = 0; // Last Used quickfix list id
#define FMT_PATTERNS 14 // maximum number of % recognized
@@ -382,7 +383,8 @@ static int qf_init_process_nextline(qf_list_T *qfl, efm_T *fmt_first, qfstate_T
int qf_init(win_T *wp, const char *restrict efile, char *restrict errorformat, int newlist,
const char *restrict qf_title, char *restrict enc)
{
qf_info_T *qi = wp == NULL ? &ql_info : ll_get_or_alloc_list(wp);
qf_info_T *qi = wp == NULL ? ql_info : ll_get_or_alloc_list(wp);
assert(qi != NULL);
return qf_init_ext(qi, qi->qf_curlist, efile, curbuf, NULL, errorformat,
newlist, 0, 0, qf_title, enc);
@@ -1260,6 +1262,31 @@ static qf_list_T *qf_get_curlist(qf_info_T *qi)
return qf_get_list(qi, qi->qf_curlist);
}
/// Pop a quickfix list from the quickfix/location list stack
/// Automatically adjust qf_curlist so that it stays pointed
/// to the same list, unless it is deleted, if so then use the
/// newest created list instead. qf_listcount will be set correctly.
/// The above will only happen if <adjust> is true.
static void qf_pop_stack(qf_info_T *qi, bool adjust)
{
qf_free(&qi->qf_lists[0]);
for (int i = 1; i < qi->qf_listcount; i++) {
qi->qf_lists[i - 1] = qi->qf_lists[i];
}
// fill with zeroes now unused list at the top
memset(qi->qf_lists + qi->qf_listcount - 1, 0, sizeof(*qi->qf_lists));
if (adjust) {
qi->qf_listcount--;
if (qi->qf_curlist == 0) {
qi->qf_curlist = qi->qf_listcount - 1;
} else {
qi->qf_curlist--;
}
}
}
/// Prepare for adding a new quickfix list. If the current list is in the
/// middle of the stack, then all the following lists are freed and then
/// the new list is added.
@@ -1274,15 +1301,13 @@ static void qf_new_list(qf_info_T *qi, const char *qf_title)
// When the stack is full, remove to oldest entry
// Otherwise, add a new entry.
if (qi->qf_listcount == LISTCOUNT) {
qf_free(&qi->qf_lists[0]);
for (int i = 1; i < LISTCOUNT; i++) {
qi->qf_lists[i - 1] = qi->qf_lists[i];
}
qi->qf_curlist = LISTCOUNT - 1;
if (qi->qf_listcount == qi->qf_maxcount) {
qf_pop_stack(qi, false);
qi->qf_curlist = qi->qf_listcount - 1; // point to new empty list
} else {
qi->qf_curlist = qi->qf_listcount++;
}
qf_list_T *qfl = qf_get_curlist(qi);
CLEAR_POINTER(qfl);
qf_store_title(qfl, qf_title);
@@ -1731,7 +1756,8 @@ static void locstack_queue_delreq(qf_info_T *qi)
/// Return the global quickfix stack window buffer number.
int qf_stack_get_bufnr(void)
{
return ql_info.qf_bufnr;
assert(ql_info != NULL);
return ql_info->qf_bufnr;
}
/// Wipe the quickfix window buffer (if present) for the specified
@@ -1745,13 +1771,44 @@ static void wipe_qf_buffer(qf_info_T *qi)
buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
bool buf_was_null = false;
// can happen when curwin is going to be closed e.g. curwin->w_buffer
// was already closed in win_close(), and we are now closing the
// window related location list buffer from win_free_mem()
// but close_buffer() calls CHECK_CURBUF() macro and requires
// curwin->w_buffer == curbuf
if (curwin->w_buffer == NULL) {
curwin->w_buffer = curbuf;
buf_was_null = true;
}
// If the quickfix buffer is not loaded in any window, then
// wipe the buffer.
close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
qi->qf_bufnr = INVALID_QFBUFNR;
if (buf_was_null) {
curwin->w_buffer = NULL;
}
}
}
/// Free all lists in the stack (not including the stack)
static void qf_free_list_stack_items(qf_info_T *qi)
{
for (int i = 0; i < qi->qf_listcount; i++) {
qf_free(qf_get_list(qi, i));
}
}
/// Free a qf_info_T struct completely
static void qf_free_lists(qf_info_T *qi)
{
qf_free_list_stack_items(qi);
xfree(qi->qf_lists);
xfree(qi);
}
/// Free a location list stack
static void ll_free_all(qf_info_T **pqi)
{
@@ -1774,26 +1831,21 @@ static void ll_free_all(qf_info_T **pqi)
// If the quickfix window buffer is loaded, then wipe it
wipe_qf_buffer(qi);
for (int i = 0; i < qi->qf_listcount; i++) {
qf_free(qf_get_list(qi, i));
}
xfree(qi);
qf_free_lists(qi);
}
}
/// Free all the quickfix/location lists in the stack.
void qf_free_all(win_T *wp)
{
qf_info_T *qi = ql_info;
if (wp != NULL) {
// location list
ll_free_all(&wp->w_llist);
ll_free_all(&wp->w_llist_ref);
} else {
// quickfix list
qf_info_T *qi = &ql_info;
for (int i = 0; i < qi->qf_listcount; i++) {
qf_free(qf_get_list(qi, i));
}
} else if (qi != NULL) {
qf_free_list_stack_items(qi); // quickfix list
}
}
@@ -1949,18 +2001,119 @@ static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, in
return QF_OK;
}
/// Allocate a new quickfix/location list stack
static qf_info_T *qf_alloc_stack(qfltype_T qfltype)
/// Resize quickfix stack to be able to hold n amount of lists.
void qf_resize_stack(int n)
{
assert(ql_info != NULL);
qf_resize_stack_base(ql_info, n);
}
/// Resize location list stack for window 'wp' to be able to hold n amount of lists.
void ll_resize_stack(win_T *wp, int n)
{
// check if current window is a location list window;
// if so then sync its 'lhistory' to the parent window or vice versa
if (IS_LL_WINDOW(curwin)) {
qf_sync_llw_to_win(wp);
} else {
qf_sync_win_to_llw(wp);
}
qf_info_T *qi = ll_get_or_alloc_list(wp);
qf_resize_stack_base(qi, n);
}
/// Resize quickfix/location lists stack to be able to hold n amount of lists.
static void qf_resize_stack_base(qf_info_T *qi, int n)
FUNC_ATTR_NONNULL_ALL
{
int amount_to_rm = 0;
size_t lsz = sizeof(*qi->qf_lists);
if (n == qi->qf_maxcount) {
return;
} else if (n < qi->qf_maxcount && n < qi->qf_listcount) {
// We have too many lists to store them all in the new stack,
// pop lists until we can fit them all in the newly resized stack
amount_to_rm = qi->qf_listcount - n;
for (int i = 0; i < amount_to_rm; i++) {
qf_pop_stack(qi, true);
}
}
qf_list_T *new = xrealloc(qi->qf_lists, lsz * (size_t)n);
// fill with zeroes any newly allocated memory
if (n > qi->qf_maxcount) {
memset(new + qi->qf_maxcount, 0, lsz * (size_t)(n - qi->qf_maxcount));
}
qi->qf_lists = new;
qi->qf_maxcount = n;
qf_update_buffer(qi, NULL);
}
/// Initialize quickfix list, should only be called once.
void qf_init_stack(void)
{
ql_info = qf_alloc_stack(QFLT_QUICKFIX, (int)p_chi);
}
/// Sync a location list window's 'lhistory' value to the parent window
static void qf_sync_llw_to_win(win_T *llw)
{
win_T *wp = qf_find_win_with_loclist(llw->w_llist_ref);
if (wp != NULL) {
wp->w_p_lhi = llw->w_p_lhi;
}
}
/// Sync a window's 'lhistory' value to its location list window, if any
static void qf_sync_win_to_llw(win_T *pwp)
{
qf_info_T *llw = pwp->w_llist;
if (llw != NULL) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_llist_ref == llw && bt_quickfix(wp->w_buffer)) {
wp->w_p_lhi = pwp->w_p_lhi;
return;
}
}
}
}
/// Allocate a new quickfix/location list stack that is able to hold
/// up to n amount of lists
static qf_info_T *qf_alloc_stack(qfltype_T qfltype, int n)
FUNC_ATTR_NONNULL_RET
{
qf_info_T *qi = xcalloc(1, sizeof(qf_info_T));
qi->qf_refcount++;
qf_info_T *qi;
if (qfltype == QFLT_QUICKFIX) {
qi = &ql_info_actual;
} else {
qi = xcalloc(1, sizeof(qf_info_T));
qi->qf_refcount++;
}
qi->qfl_type = qfltype;
qi->qf_bufnr = INVALID_QFBUFNR;
qi->qf_lists = qf_alloc_list_stack(n);
qi->qf_maxcount = n;
return qi;
}
/// Allocate memory for qf_lists member of qf_info_T struct.
/// 'actual' is the actual amount of lists that have been allocated for
static qf_list_T *qf_alloc_list_stack(int n)
FUNC_ATTR_NONNULL_RET
{
return xcalloc((size_t)n, sizeof(qf_list_T));
}
/// Return the location list stack for window 'wp'.
/// If not present, allocate a location list stack
static qf_info_T *ll_get_or_alloc_list(win_T *wp)
@@ -1976,8 +2129,10 @@ static qf_info_T *ll_get_or_alloc_list(win_T *wp)
ll_free_all(&wp->w_llist_ref);
if (wp->w_llist == NULL) {
wp->w_llist = qf_alloc_stack(QFLT_LOCATION); // new location list
// new location list
wp->w_llist = qf_alloc_stack(QFLT_LOCATION, (int)wp->w_p_lhi);
}
return wp->w_llist;
}
@@ -1987,7 +2142,8 @@ static qf_info_T *ll_get_or_alloc_list(win_T *wp)
/// message if 'print_emsg' is true.
static qf_info_T *qf_cmd_get_stack(exarg_T *eap, bool print_emsg)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
if (is_loclist_cmd(eap->cmdidx)) {
qi = GET_LOC_LIST(curwin);
@@ -2009,7 +2165,7 @@ static qf_info_T *qf_cmd_get_stack(exarg_T *eap, bool print_emsg)
static qf_info_T *qf_cmd_get_or_alloc_stack(const exarg_T *eap, win_T **pwinp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
if (is_loclist_cmd(eap->cmdidx)) {
qi = ll_get_or_alloc_list(curwin);
@@ -2122,8 +2278,10 @@ void copy_loclist_stack(win_T *from, win_T *to)
return;
}
// allocate a new location list
to->w_llist = qf_alloc_stack(QFLT_LOCATION);
// allocate a new location list, set size of stack to 'from' window value
to->w_llist = qf_alloc_stack(QFLT_LOCATION, (int)from->w_p_lhi);
// set 'to' lhi to reflect new value
to->w_p_lhi = to->w_llist->qf_maxcount;
to->w_llist->qf_listcount = qi->qf_listcount;
@@ -2340,16 +2498,16 @@ static char *qf_guess_filepath(qf_list_T *qfl, char *filename)
/// Returns true, if a quickfix/location list with the given identifier exists.
static bool qflist_valid(win_T *wp, unsigned qf_id)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
if (wp) {
if (!win_valid(wp)) {
return false;
}
qi = GET_LOC_LIST(wp); // Location list
if (!qi) {
return false;
}
}
if (!qi) {
return false;
}
for (int i = 0; i < qi->qf_listcount; i++) {
@@ -3063,7 +3221,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
const bool old_KeyTyped = KeyTyped; // getting file may reset it
if (qi == NULL) {
qi = &ql_info;
assert(ql_info != NULL);
qi = ql_info;
}
if (qf_stack_empty(qi) || qf_list_empty(qf_get_curlist(qi))) {
@@ -3504,7 +3663,8 @@ static void qf_free(qf_list_T *qfl)
bool qf_mark_adjust(buf_T *buf, win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount,
linenr_T amount_after)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
if (!(buf->b_has_qf_entry & buf_has_flag)) {
@@ -3593,7 +3753,8 @@ static char *qf_types(int c, int nr)
// When "split" is true: Open the entry/result under the cursor in a new window.
void qf_view_result(bool split)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
if (IS_LL_WINDOW(curwin)) {
qi = GET_LOC_LIST(curwin);
@@ -3869,7 +4030,8 @@ void ex_cbottom(exarg_T *eap)
// window).
linenr_T qf_current_entry(win_T *wp)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
if (IS_LL_WINDOW(wp)) {
// In the location list window, use the referenced location list
@@ -4445,7 +4607,8 @@ void ex_make(exarg_T *eap)
int res = qf_init(wp, fname, errorformat, newlist, qf_cmdtitle(*eap->cmdlinep), enc);
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
if (wp != NULL) {
qi = GET_LOC_LIST(wp);
if (qi == NULL) {
@@ -5132,7 +5295,8 @@ static char *cfile_get_auname(cmdidx_T cmdidx)
void ex_cfile(exarg_T *eap)
{
win_T *wp = NULL;
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
char *au_name = NULL;
au_name = cfile_get_auname(eap->cmdidx);
@@ -5921,12 +6085,12 @@ static int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, lis
qf_info_T *qi = qi_arg;
if (qi == NULL) {
qi = &ql_info;
qi = ql_info;
if (wp != NULL) {
qi = GET_LOC_LIST(wp);
if (qi == NULL) {
return FAIL;
}
}
if (qi == NULL) {
return FAIL;
}
}
@@ -6004,14 +6168,15 @@ static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
}
list_T *l = tv_list_alloc(kListLenMayKnow);
qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL);
qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL, 1);
if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
true, 0, 0, NULL, NULL) > 0) {
get_errorlist(qi, NULL, 0, 0, l);
qf_free(&qi->qf_lists[0]);
}
xfree(qi);
qf_free_lists(qi);
tv_dict_add_list(retdict, S_LEN("items"), l);
status = OK;
@@ -6288,7 +6453,8 @@ static int qf_getprop_qftf(qf_list_T *qfl, dict_T *retdict)
/// then current list is used. Otherwise the specified list is used.
static int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
dictitem_T *di = NULL;
int status = OK;
int qf_idx = INVALID_QFIDX;
@@ -6866,7 +7032,7 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
} 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);
qf_info_T *new_ll = qf_alloc_stack(QFLT_LOCATION, (int)wp->w_p_lhi);
new_ll->qf_bufnr = qfwin->w_buffer->b_fnum;
// first free the list reference in the location list window
@@ -6886,11 +7052,13 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
/// When "what" is not NULL then only set some properties.
int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi;
if (wp != NULL) {
qi = ll_get_or_alloc_list(wp);
} else {
qi = ql_info;
}
assert(qi != NULL);
if (action == 'f') {
// Free the entire quickfix or location list stack
@@ -6924,7 +7092,7 @@ int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what
static bool mark_quickfix_user_data(qf_info_T *qi, int copyID)
{
bool abort = false;
for (int i = 0; i < LISTCOUNT && !abort; i++) {
for (int i = 0; i < qi->qf_maxcount && !abort; i++) {
qf_list_T *qfl = &qi->qf_lists[i];
if (!qfl->qf_has_user_data) {
continue;
@@ -6948,7 +7116,7 @@ static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
{
bool abort = false;
for (int i = 0; i < LISTCOUNT && !abort; i++) {
for (int i = 0; i < qi->qf_maxcount && !abort; i++) {
typval_T *ctx = qi->qf_lists[i].qf_ctx;
if (ctx != NULL && ctx->v_type != VAR_NUMBER
&& ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) {
@@ -6966,8 +7134,9 @@ static bool mark_quickfix_ctx(qf_info_T *qi, int copyID)
/// "in use". So that garbage collection doesn't free the context.
bool set_ref_in_quickfix(int copyID)
{
if (mark_quickfix_ctx(&ql_info, copyID)
|| mark_quickfix_user_data(&ql_info, copyID)
assert(ql_info != NULL);
if (mark_quickfix_ctx(ql_info, copyID)
|| mark_quickfix_user_data(ql_info, copyID)
|| set_ref_in_callback(&qftf_cb, copyID, NULL, NULL)) {
return true;
}
@@ -7215,7 +7384,7 @@ static qf_info_T *hgr_get_ll(bool *new_ll)
qf_info_T *qi = wp == NULL ? NULL : wp->w_llist;
if (qi == NULL) {
// Allocate a new location list for help text matches
qi = qf_alloc_stack(QFLT_LOCATION);
qi = qf_alloc_stack(QFLT_LOCATION, 1);
*new_ll = true;
}
@@ -7326,7 +7495,8 @@ static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, const char
// ":helpgrep {pattern}"
void ex_helpgrep(exarg_T *eap)
{
qf_info_T *qi = &ql_info;
qf_info_T *qi = ql_info;
assert(qi != NULL);
char *au_name = NULL;
switch (eap->cmdidx) {

View File

@@ -106,6 +106,7 @@ let test_values = {
\ []],
\
"\ number options
\ 'chistory': [[1, 2, 10, 50], [1000, -1]],
\ 'cmdheight': [[0, 1, 2, 10], [-1]],
\ 'cmdwinheight': [[1, 2, 10], [-1, 0]],
\ 'columns': [[12, 80, 10000], [-1, 0, 10]],
@@ -116,6 +117,7 @@ let test_values = {
"\ 'iminsert': [[0, 1, 2], [-1, 3, 999]],
"\ 'imsearch': [[-1, 0, 1, 2], [-2, 3, 999]],
"\ 'imstyle': [[0, 1], [-1, 2, 999]],
\ 'lhistory': [[1, 2, 10, 50], [1000, -1]],
\ 'lines': [[2, 24, 1000], [-1, 0, 1]],
\ 'linespace': [[-1, 0, 2, 4, 999], ['']],
\ 'numberwidth': [[1, 4, 8, 10, 11, 20], [-1, 0, 21]],

View File

@@ -43,6 +43,8 @@ func s:setup_commands(cchar)
command! -count=1 -nargs=0 Xabove <mods><count>cabove
command! -count=1 -nargs=0 Xbefore <mods><count>cbefore
command! -count=1 -nargs=0 Xafter <mods><count>cafter
command! -nargs=1 Xsethist <mods>set chistory=<args>
command! -nargs=0 Xsethistdefault <mods>set chistory&
let g:Xgetlist = function('getqflist')
let g:Xsetlist = function('setqflist')
call setqflist([], 'f')
@@ -80,6 +82,9 @@ func s:setup_commands(cchar)
command! -count=1 -nargs=0 Xabove <mods><count>labove
command! -count=1 -nargs=0 Xbefore <mods><count>lbefore
command! -count=1 -nargs=0 Xafter <mods><count>lafter
command! -nargs=1 Xsethist <mods>set lhistory=<args>
command! -nargs=1 Xsetlocalhist <mods>setlocal lhistory=<args>
command! -nargs=0 Xsethistdefault <mods>set lhistory&
let g:Xgetlist = function('getloclist', [0])
let g:Xsetlist = function('setloclist', [0])
call setloclist(0, [], 'f')
@@ -6596,4 +6601,180 @@ func Test_hardlink_fname()
call Xtest_hardlink_fname('l')
endfunc
" Test for checking if correct number of tests are deleted
" and current list stays the same after setting Xhistory
" to a smaller number. Do roughly the same for growing the stack.
func Xtest_resize_list_stack(cchar)
call s:setup_commands(a:cchar)
Xsethist 100
for i in range(1, 100)
Xexpr string(i)
endfor
Xopen
call assert_equal(g:Xgetlist({'nr': '$'}).nr, 100)
call assert_equal("|| 100", getline(1))
Xsethist 8
call assert_equal("|| 100", getline(1))
Xolder 5
call assert_equal("|| 95", getline(1))
Xsethist 6
call assert_equal("|| 95", getline(1))
Xsethist 1
call assert_equal("|| 100", getline(1))
" grow array again
Xsethist 100
for i in range(1, 99)
Xexpr string(i)
endfor
call assert_equal("|| 99", getline(1))
Xolder 99
call assert_equal("|| 100", getline(1))
Xsethistdefault
endfunc
func Test_resize_list_stack()
call Xtest_resize_list_stack('c')
call Xtest_resize_list_stack('l')
endfunc
" Test to check if order of lists is from
" oldest at the bottom to newest at the top
func Xtest_Xhistory_check_order(cchar)
Xsethist 100
for i in range(1, 100)
Xexpr string(i)
endfor
Xopen
for i in range(100, 1, -1)
let l:ret = assert_equal("|| " .. i, getline(1))
if ret == 1 || i == 1
break
endif
Xolder
endfor
for i in range(1, 50)
Xexpr string(i)
endfor
for i in range(50, 1, -1)
let l:ret = assert_equal("|| " .. i, getline(1))
if ret == 1 || i == 50
break
endif
Xolder
endfor
for i in range(50, 1, -1)
let l:ret = assert_equal("|| " .. i, getline(1))
if ret == 1 || i == 50
break
endif
Xolder
endfor
Xsethistdefault
endfunc
func Test_set_history_to_check_order()
call Xtest_Xhistory_check_order('c')
call Xtest_Xhistory_check_order('l')
endfunc
" Check if 'lhistory' is the same between the location list window
" and associated normal window
func Test_win_and_loc_synced()
new
set lhistory=2
lexpr "Text"
lopen
" check if lhistory is synced when modified inside the
" location list window
setlocal lhistory=1
wincmd k
call assert_equal(&lhistory, 1)
" check if lhistory is synced when modified inside the
" normal window
setlocal lhistory=10
lopen
call assert_equal(&lhistory, 10)
wincmd k
lclose
wincmd q
set lhistory&
endfunc
" Test if setting the lhistory of one window doesn't affect the other
func Test_two_win_are_independent_of_history()
setlocal lhistory=10
new
setlocal lhistory=20
wincmd w
call assert_equal(&lhistory, 10)
wincmd w
wincmd q
set lhistory&
endfunc
" Test if lhistory is copied over to a new window
func Test_lhistory_copied_over()
setlocal lhistory=3
split
call assert_equal(&lhistory, 3)
wincmd q
set lhistory&
endfunc
" Test if error occurs when given invalid history number
func Xtest_invalid_history_num(cchar)
call s:setup_commands(a:cchar)
call assert_fails('Xsethist -10000', "E1542:")
call assert_fails('Xsethist 10000', "E1543:")
Xsethistdefault
endfunc
func Test_invalid_history_num()
call Xtest_invalid_history_num('c')
call Xtest_invalid_history_num('l')
endfunc
" Test if chistory and lhistory don't affect each other
func Test_chi_and_lhi_are_independent()
set chistory=100
set lhistory=100
set chistory=10
call assert_equal(&lhistory, 100)
set lhistory=1
call assert_equal(&chistory, 10)
set chistory&
set lhistory&
endfunc
func Test_quickfix_close_buffer_crash()
new
lexpr 'test' | lopen
wincmd k
lclose
wincmd q
endfunc
" vim: shiftwidth=2 sts=2 expandtab