mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
vim-patch:9.1.0469: Cannot have buffer-local value for 'completeopt'
Problem: Cannot have buffer-local value for 'completeopt'
(Nick Jensen).
Solution: Make 'completeopt' global-local (zeertzjq).
Also for some reason test Test_ColonEight_MultiByte seems to be failing
sporadically now. Let's mark it as flaky.
fixes: vim/vim#5487
closes: vim/vim#14922
529b9ad62a
This commit is contained in:
parent
c235a063d6
commit
1d4e894403
@ -1495,7 +1495,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
|
||||
*'completeopt'* *'cot'*
|
||||
'completeopt' 'cot' string (default "menu,preview")
|
||||
global
|
||||
global or local to buffer |global-local|
|
||||
A comma-separated list of options for Insert mode completion
|
||||
|ins-completion|. The supported values are:
|
||||
|
||||
|
2
runtime/lua/vim/_meta/options.lua
generated
2
runtime/lua/vim/_meta/options.lua
generated
@ -1084,6 +1084,8 @@ vim.bo.cfu = vim.bo.completefunc
|
||||
--- @type string
|
||||
vim.o.completeopt = "menu,preview"
|
||||
vim.o.cot = vim.o.completeopt
|
||||
vim.bo.completeopt = vim.o.completeopt
|
||||
vim.bo.cot = vim.bo.completeopt
|
||||
vim.go.completeopt = vim.o.completeopt
|
||||
vim.go.cot = vim.go.completeopt
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
" These commands create the option window.
|
||||
"
|
||||
" Maintainer: The Vim Project <https://github.com/vim/vim>
|
||||
" Last Change: 2023 Aug 31
|
||||
" Last Change: 2024 Jun 05
|
||||
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
|
||||
" If there already is an option window, jump to that one.
|
||||
@ -723,7 +723,7 @@ if has("insert_expand")
|
||||
call append("$", "\t" .. s:local_to_buffer)
|
||||
call <SID>OptionL("cpt")
|
||||
call <SID>AddOption("completeopt", gettext("whether to use a popup menu for Insert mode completion"))
|
||||
call <SID>OptionG("cot", &cot)
|
||||
call <SID>OptionL("cot")
|
||||
call <SID>AddOption("pumheight", gettext("maximum height of the popup menu"))
|
||||
call <SID>OptionG("ph", &ph)
|
||||
call <SID>AddOption("pumwidth", gettext("minimum width of the popup menu"))
|
||||
|
@ -2077,6 +2077,7 @@ void free_buf_options(buf_T *buf, bool free_p_ff)
|
||||
clear_string_option(&buf->b_p_lop);
|
||||
clear_string_option(&buf->b_p_cinsd);
|
||||
clear_string_option(&buf->b_p_cinw);
|
||||
clear_string_option(&buf->b_p_cot);
|
||||
clear_string_option(&buf->b_p_cpt);
|
||||
clear_string_option(&buf->b_p_cfu);
|
||||
callback_free(&buf->b_cfu_cb);
|
||||
|
@ -533,6 +533,8 @@ struct file_buffer {
|
||||
char *b_p_cinsd; ///< 'cinscopedecls'
|
||||
char *b_p_com; ///< 'comments'
|
||||
char *b_p_cms; ///< 'commentstring'
|
||||
char *b_p_cot; ///< 'completeopt' local value
|
||||
unsigned b_cot_flags; ///< flags for 'completeopt'
|
||||
char *b_p_cpt; ///< 'complete'
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
char *b_p_csl; ///< 'completeslash'
|
||||
|
@ -226,14 +226,6 @@ static char *compl_leader = NULL;
|
||||
|
||||
static bool compl_get_longest = false; ///< put longest common string in compl_leader
|
||||
|
||||
static bool compl_no_insert = false; ///< false: select & insert
|
||||
///< true: noinsert
|
||||
static bool compl_no_select = false; ///< false: select & insert
|
||||
///< true: noselect
|
||||
static bool compl_longest = false; ///< false: insert full match
|
||||
///< true: insert longest prefix
|
||||
static bool compl_fuzzy_match = false; ///< true: fuzzy match enabled
|
||||
|
||||
/// Selected one of the matches. When false the match was edited or using the
|
||||
/// longest common string.
|
||||
static bool compl_used_match;
|
||||
@ -1051,26 +1043,10 @@ bool ins_compl_long_shown_match(void)
|
||||
&& (colnr_T)strlen(compl_shown_match->cp_str) > curwin->w_cursor.col - compl_col;
|
||||
}
|
||||
|
||||
/// Set variables that store noselect and noinsert behavior from the
|
||||
/// 'completeopt' value.
|
||||
void completeopt_was_set(void)
|
||||
/// Get the local or global value of 'completeopt' flags.
|
||||
unsigned get_cot_flags(void)
|
||||
{
|
||||
compl_no_insert = false;
|
||||
compl_no_select = false;
|
||||
compl_longest = false;
|
||||
compl_fuzzy_match = false;
|
||||
if (strstr(p_cot, "noselect") != NULL) {
|
||||
compl_no_select = true;
|
||||
}
|
||||
if (strstr(p_cot, "noinsert") != NULL) {
|
||||
compl_no_insert = true;
|
||||
}
|
||||
if (strstr(p_cot, "longest") != NULL) {
|
||||
compl_longest = true;
|
||||
}
|
||||
if (strstr(p_cot, "fuzzy") != NULL) {
|
||||
compl_fuzzy_match = true;
|
||||
}
|
||||
return curbuf->b_cot_flags != 0 ? curbuf->b_cot_flags : cot_flags;
|
||||
}
|
||||
|
||||
/// "compl_match_array" points the currently displayed list of entries in the
|
||||
@ -1094,7 +1070,7 @@ bool pum_wanted(void)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
// "completeopt" must contain "menu" or "menuone"
|
||||
return vim_strchr(p_cot, 'm') != NULL;
|
||||
return (get_cot_flags() & COT_ANY_MENU) != 0;
|
||||
}
|
||||
|
||||
/// Check that there are two or more matches to be shown in the popup menu.
|
||||
@ -1113,7 +1089,7 @@ static bool pum_enough_matches(void)
|
||||
comp = comp->cp_next;
|
||||
} while (!is_first_match(comp));
|
||||
|
||||
if (strstr(p_cot, "menuone") != NULL) {
|
||||
if (get_cot_flags() & COT_MENUONE) {
|
||||
return i >= 1;
|
||||
}
|
||||
return i >= 2;
|
||||
@ -1193,6 +1169,9 @@ static int ins_compl_build_pum(void)
|
||||
|
||||
const int lead_len = compl_leader != NULL ? (int)strlen(compl_leader) : 0;
|
||||
int max_fuzzy_score = 0;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0;
|
||||
bool compl_fuzzy_match = (cur_cot_flags & COT_FUZZY) != 0;
|
||||
|
||||
do {
|
||||
// When 'completeopt' contains "fuzzy" and leader is not NULL or empty,
|
||||
@ -2229,7 +2208,7 @@ bool ins_compl_prep(int c)
|
||||
// Set "compl_get_longest" when finding the first matches.
|
||||
if (ctrl_x_mode_not_defined_yet()
|
||||
|| (ctrl_x_mode_normal() && !compl_started)) {
|
||||
compl_get_longest = compl_longest;
|
||||
compl_get_longest = (get_cot_flags() & COT_LONGEST) != 0;
|
||||
compl_used_match = true;
|
||||
}
|
||||
|
||||
@ -2649,6 +2628,10 @@ static void restore_orig_extmarks(void)
|
||||
static void set_completion(colnr_T startcol, list_T *list)
|
||||
{
|
||||
int flags = CP_ORIGINAL_TEXT;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_longest = (cur_cot_flags & COT_LONGEST) != 0;
|
||||
bool compl_no_insert = (cur_cot_flags & COT_NOINSERT) != 0;
|
||||
bool compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0;
|
||||
|
||||
// If already doing completions stop it.
|
||||
if (ctrl_x_mode_not_default()) {
|
||||
@ -3692,6 +3675,9 @@ static int find_next_completion_match(bool allow_get_expansion, int todo, bool a
|
||||
{
|
||||
bool found_end = false;
|
||||
compl_T *found_compl = NULL;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0;
|
||||
bool compl_fuzzy_match = (cur_cot_flags & COT_FUZZY) != 0;
|
||||
|
||||
while (--todo >= 0) {
|
||||
if (compl_shows_dir_forward() && compl_shown_match->cp_next != NULL) {
|
||||
@ -3794,6 +3780,9 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
|
||||
int todo = count;
|
||||
const bool started = compl_started;
|
||||
buf_T *const orig_curbuf = curbuf;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool compl_no_insert = (cur_cot_flags & COT_NOINSERT) != 0;
|
||||
bool compl_fuzzy_match = (cur_cot_flags & COT_FUZZY) != 0;
|
||||
|
||||
// When user complete function return -1 for findstart which is next
|
||||
// time of 'always', compl_shown_match become NULL.
|
||||
@ -3932,7 +3921,7 @@ void ins_compl_check_keys(int frequency, bool in_compl_func)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (compl_pending != 0 && !got_int && !compl_no_insert) {
|
||||
if (compl_pending != 0 && !got_int && !(cot_flags & COT_NOINSERT)) {
|
||||
int todo = compl_pending > 0 ? compl_pending : -compl_pending;
|
||||
|
||||
compl_pending = 0;
|
||||
|
@ -4570,6 +4570,8 @@ void *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
|
||||
return &(buf->b_p_def);
|
||||
case PV_INC:
|
||||
return &(buf->b_p_inc);
|
||||
case PV_COT:
|
||||
return &(buf->b_p_cot);
|
||||
case PV_DICT:
|
||||
return &(buf->b_p_dict);
|
||||
case PV_TSR:
|
||||
@ -4653,6 +4655,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
|
||||
return *buf->b_p_def != NUL ? &(buf->b_p_def) : p->var;
|
||||
case PV_INC:
|
||||
return *buf->b_p_inc != NUL ? &(buf->b_p_inc) : p->var;
|
||||
case PV_COT:
|
||||
return *buf->b_p_cot != NUL ? &(buf->b_p_cot) : p->var;
|
||||
case PV_DICT:
|
||||
return *buf->b_p_dict != NUL ? &(buf->b_p_dict) : p->var;
|
||||
case PV_TSR:
|
||||
@ -5332,6 +5336,8 @@ void buf_copy_options(buf_T *buf, int flags)
|
||||
buf->b_p_inc = empty_string_option;
|
||||
buf->b_p_inex = xstrdup(p_inex);
|
||||
COPY_OPT_SCTX(buf, BV_INEX);
|
||||
buf->b_p_cot = empty_string_option;
|
||||
buf->b_cot_flags = 0;
|
||||
buf->b_p_dict = empty_string_option;
|
||||
buf->b_p_tsr = empty_string_option;
|
||||
buf->b_p_tsrfu = empty_string_option;
|
||||
|
@ -430,6 +430,19 @@ EXTERN char *p_cpt; ///< 'complete'
|
||||
EXTERN OptInt p_columns; ///< 'columns'
|
||||
EXTERN int p_confirm; ///< 'confirm'
|
||||
EXTERN char *p_cot; ///< 'completeopt'
|
||||
EXTERN unsigned cot_flags; ///< flags from 'completeopt'
|
||||
// Keep in sync with p_cot_values in optionstr.c
|
||||
#define COT_MENU 0x001
|
||||
#define COT_MENUONE 0x002
|
||||
#define COT_ANY_MENU 0x003 // combination of menu flags
|
||||
#define COT_LONGEST 0x004 // false: insert full match,
|
||||
// true: insert longest prefix
|
||||
#define COT_PREVIEW 0x008
|
||||
#define COT_POPUP 0x010
|
||||
#define COT_ANY_PREVIEW 0x018 // combination of preview flags
|
||||
#define COT_NOINSERT 0x020 // false: select & insert, true: noinsert
|
||||
#define COT_NOSELECT 0x040 // false: select & insert, true: noselect
|
||||
#define COT_FUZZY 0x080 // true: fuzzy match enabled
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
EXTERN char *p_csl; ///< 'completeslash'
|
||||
#endif
|
||||
|
@ -1466,7 +1466,7 @@ return {
|
||||
expand_cb = 'expand_set_completeopt',
|
||||
full_name = 'completeopt',
|
||||
list = 'onecomma',
|
||||
scope = { 'global' },
|
||||
scope = { 'global', 'buffer' },
|
||||
short_desc = N_('options for Insert mode completion'),
|
||||
type = 'string',
|
||||
varname = 'p_cot',
|
||||
|
@ -158,6 +158,7 @@ void didset_string_options(void)
|
||||
opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true);
|
||||
opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, true);
|
||||
opt_strings_flags(p_bo, p_bo_values, &bo_flags, true);
|
||||
opt_strings_flags(p_cot, p_cot_values, &cot_flags, true);
|
||||
opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true);
|
||||
opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
|
||||
opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
|
||||
@ -219,6 +220,7 @@ void check_buf_options(buf_T *buf)
|
||||
check_string_option(&buf->b_p_ft);
|
||||
check_string_option(&buf->b_p_cinw);
|
||||
check_string_option(&buf->b_p_cinsd);
|
||||
check_string_option(&buf->b_p_cot);
|
||||
check_string_option(&buf->b_p_cpt);
|
||||
check_string_option(&buf->b_p_cfu);
|
||||
check_string_option(&buf->b_p_ofu);
|
||||
@ -993,10 +995,23 @@ int expand_set_complete(optexpand_T *args, int *numMatches, char ***matches)
|
||||
/// The 'completeopt' option is changed.
|
||||
const char *did_set_completeopt(optset_T *args FUNC_ATTR_UNUSED)
|
||||
{
|
||||
if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
|
||||
buf_T *buf = (buf_T *)args->os_buf;
|
||||
char *cot = p_cot;
|
||||
unsigned *flags = &cot_flags;
|
||||
|
||||
if (args->os_flags & OPT_LOCAL) {
|
||||
cot = buf->b_p_cot;
|
||||
flags = &buf->b_cot_flags;
|
||||
}
|
||||
|
||||
if (check_opt_strings(cot, p_cot_values, true) != OK) {
|
||||
return e_invarg;
|
||||
}
|
||||
completeopt_was_set();
|
||||
|
||||
if (opt_strings_flags(cot, p_cot_values, flags, true) != OK) {
|
||||
return e_invarg;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -700,7 +700,7 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma
|
||||
}
|
||||
// delete the empty last line
|
||||
ml_delete_buf(buf, buf->b_ml.ml_line_count, false);
|
||||
if (strstr(p_cot, "popup") != NULL) {
|
||||
if (get_cot_flags() & COT_POPUP) {
|
||||
extmark_splice(buf, 1, 0, 1, 0, 0, buf->b_ml.ml_line_count, 0, inserted_bytes, kExtmarkNoUndo);
|
||||
}
|
||||
}
|
||||
@ -795,7 +795,8 @@ static bool pum_set_selected(int n, int repeat)
|
||||
int prev_selected = pum_selected;
|
||||
|
||||
pum_selected = n;
|
||||
bool use_float = strstr(p_cot, "popup") != NULL;
|
||||
unsigned cur_cot_flags = get_cot_flags();
|
||||
bool use_float = (cur_cot_flags & COT_POPUP) != 0;
|
||||
// when new leader add and info window is shown and no selected we still
|
||||
// need use the first index item to update the info float window position.
|
||||
bool force_select = use_float && pum_selected < 0 && win_float_find_preview();
|
||||
@ -861,7 +862,7 @@ static bool pum_set_selected(int n, int repeat)
|
||||
if ((pum_array[pum_selected].pum_info != NULL)
|
||||
&& (Rows > 10)
|
||||
&& (repeat <= 1)
|
||||
&& (vim_strchr(p_cot, 'p') != NULL)) {
|
||||
&& (cur_cot_flags & COT_ANY_PREVIEW)) {
|
||||
win_T *curwin_save = curwin;
|
||||
tabpage_T *curtab_save = curtab;
|
||||
|
||||
|
@ -884,6 +884,74 @@ func Test_complete_with_longest()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
" Test for buffer-local value of 'completeopt'
|
||||
func Test_completeopt_buffer_local()
|
||||
set completeopt=menu
|
||||
new
|
||||
call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
|
||||
call assert_equal('', &l:completeopt)
|
||||
call assert_equal('menu', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
|
||||
setlocal bufhidden=hide
|
||||
enew
|
||||
call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
|
||||
call assert_equal('', &l:completeopt)
|
||||
call assert_equal('menu', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
|
||||
setlocal completeopt+=fuzzy,noinsert
|
||||
call assert_equal('menu,fuzzy,noinsert', &l:completeopt)
|
||||
call assert_equal('menu,fuzzy,noinsert', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix')
|
||||
call assert_equal('foobaz', getline('.'))
|
||||
|
||||
setlocal completeopt=
|
||||
call assert_equal('', &l:completeopt)
|
||||
call assert_equal('menu', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix')
|
||||
call assert_equal('foofoo', getline('.'))
|
||||
|
||||
setlocal completeopt+=longest
|
||||
call assert_equal('menu,longest', &l:completeopt)
|
||||
call assert_equal('menu,longest', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
|
||||
call assert_equal('foo', getline('.'))
|
||||
|
||||
setlocal bufhidden=hide
|
||||
buffer #
|
||||
call assert_equal('', &l:completeopt)
|
||||
call assert_equal('menu', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix')
|
||||
call assert_equal('foofoo', getline('.'))
|
||||
|
||||
setlocal completeopt+=fuzzy,noinsert
|
||||
call assert_equal('menu,fuzzy,noinsert', &l:completeopt)
|
||||
call assert_equal('menu,fuzzy,noinsert', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix')
|
||||
call assert_equal('foobaz', getline('.'))
|
||||
|
||||
buffer #
|
||||
call assert_equal('menu,longest', &l:completeopt)
|
||||
call assert_equal('menu,longest', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
|
||||
call assert_equal('foo', getline('.'))
|
||||
|
||||
setlocal bufhidden=wipe
|
||||
buffer! #
|
||||
bwipe!
|
||||
call assert_equal('', &l:completeopt)
|
||||
call assert_equal('menu', &completeopt)
|
||||
call assert_equal('menu', &g:completeopt)
|
||||
|
||||
set completeopt&
|
||||
endfunc
|
||||
|
||||
" Test for completing words following a completed word in a line
|
||||
func Test_complete_wrapscan()
|
||||
|
Loading…
Reference in New Issue
Block a user