Merge pull request #33918 from zeertzjq/vim-9.1.1373

vim-patch:9.1.{1373,1374}
This commit is contained in:
zeertzjq
2025-05-09 07:21:21 +08:00
committed by GitHub
8 changed files with 115 additions and 15 deletions

View File

@@ -1297,6 +1297,7 @@ use all space available.
The 'pumwidth' option can be used to set a minimum width. The default is 15 The 'pumwidth' option can be used to set a minimum width. The default is 15
characters. characters.
*compl-states*
There are three states: There are three states:
1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P. 1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P.
2. A cursor key has been used to select another match. The match was not 2. A cursor key has been used to select another match. The match was not

View File

@@ -211,6 +211,7 @@ CHANGED FEATURES *news-changed*
These existing features changed their behavior. These existing features changed their behavior.
• 'smartcase' applies to completion filtering.
• 'spellfile' location defaults to `stdpath("data").."/site/spell/"` instead of • 'spellfile' location defaults to `stdpath("data").."/site/spell/"` instead of
the first writable directory in 'runtimepath'. the first writable directory in 'runtimepath'.
• |vim.version.range()| doesn't exclude `to` if it is equal to `from`. • |vim.version.range()| doesn't exclude `to` if it is equal to `from`.

View File

@@ -5718,9 +5718,11 @@ A jump table for the options with a short description can be found at |Q_op|.
Override the 'ignorecase' option if the search pattern contains upper Override the 'ignorecase' option if the search pattern contains upper
case characters. Only used when the search pattern is typed and case characters. Only used when the search pattern is typed and
'ignorecase' option is on. Used for the commands "/", "?", "n", "N", 'ignorecase' option is on. Used for the commands "/", "?", "n", "N",
":g" and ":s". Not used for "*", "#", "gd", tag search, etc. After ":g" and ":s" and when filtering matches for the completion menu
"*" and "#" you can make 'smartcase' used by doing a "/" command, |compl-states|.
recalling the search pattern from history and hitting <Enter>. Not used for "*", "#", "gd", tag search, etc. After "*" and "#" you
can make 'smartcase' used by doing a "/" command, recalling the search
pattern from history and hitting <Enter>.
*'smartindent'* *'si'* *'nosmartindent'* *'nosi'* *'smartindent'* *'si'* *'nosmartindent'* *'nosi'*
'smartindent' 'si' boolean (default off) 'smartindent' 'si' boolean (default off)

View File

@@ -6084,9 +6084,11 @@ vim.wo.scl = vim.wo.signcolumn
--- Override the 'ignorecase' option if the search pattern contains upper --- Override the 'ignorecase' option if the search pattern contains upper
--- case characters. Only used when the search pattern is typed and --- case characters. Only used when the search pattern is typed and
--- 'ignorecase' option is on. Used for the commands "/", "?", "n", "N", --- 'ignorecase' option is on. Used for the commands "/", "?", "n", "N",
--- ":g" and ":s". Not used for "*", "#", "gd", tag search, etc. After --- ":g" and ":s" and when filtering matches for the completion menu
--- "*" and "#" you can make 'smartcase' used by doing a "/" command, --- `compl-states`.
--- recalling the search pattern from history and hitting <Enter>. --- Not used for "*", "#", "gd", tag search, etc. After "*" and "#" you
--- can make 'smartcase' used by doing a "/" command, recalling the search
--- pattern from history and hitting <Enter>.
--- ---
--- @type boolean --- @type boolean
vim.o.smartcase = false vim.o.smartcase = false

View File

@@ -820,8 +820,7 @@ static inline void free_cptext(char *const *const cptext)
/// Returns true if matches should be sorted based on proximity to the cursor. /// Returns true if matches should be sorted based on proximity to the cursor.
static bool is_nearest_active(void) static bool is_nearest_active(void)
{ {
unsigned flags = get_cot_flags(); return (get_cot_flags() & (kOptCotFlagNearest|kOptCotFlagFuzzy)) == kOptCotFlagNearest;
return (flags & kOptCotFlagNearest) && !(flags & kOptCotFlagFuzzy);
} }
/// Repositions a match in the completion list based on its proximity score. /// Repositions a match in the completion list based on its proximity score.
@@ -984,9 +983,7 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
match->cp_user_kind_hlattr = user_hl ? user_hl[1] : -1; match->cp_user_kind_hlattr = user_hl ? user_hl[1] : -1;
if (cptext != NULL) { if (cptext != NULL) {
int i; for (int i = 0; i < CPT_COUNT; i++) {
for (i = 0; i < CPT_COUNT; i++) {
if (cptext[i] == NULL) { if (cptext[i] == NULL) {
continue; continue;
} }
@@ -1394,6 +1391,12 @@ static int ins_compl_build_pum(void)
comp->cp_score = fuzzy_match_str(comp->cp_str.data, compl_leader.data); comp->cp_score = fuzzy_match_str(comp->cp_str.data, compl_leader.data);
} }
// Apply 'smartcase' behavior during normal mode
if (ctrl_x_mode_normal() && !p_inf && compl_leader.data
&& !ignorecase(compl_leader.data) && !fuzzy_filter) {
comp->cp_flags &= ~CP_ICASE;
}
if (!match_at_original_text(comp) if (!match_at_original_text(comp)
&& (compl_leader.data == NULL && (compl_leader.data == NULL
|| ins_compl_equal(comp, compl_leader.data, compl_leader.size) || ins_compl_equal(comp, compl_leader.data, compl_leader.size)
@@ -4834,6 +4837,7 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
} }
startcol -= head_off; startcol -= head_off;
} }
compl_col += ++startcol; compl_col += ++startcol;
compl_length = (int)curs_col - startcol; compl_length = (int)curs_col - startcol;
if (compl_length == 1) { if (compl_length == 1) {
@@ -4972,6 +4976,7 @@ static int get_userdefined_compl_info(colnr_T curs_col)
if (col == -2 || aborting()) { if (col == -2 || aborting()) {
return FAIL; return FAIL;
} }
// Return value -3 does the same as -2 and leaves CTRL-X mode. // Return value -3 does the same as -2 and leaves CTRL-X mode.
if (col == -3) { if (col == -3) {
ctrl_x_mode = CTRL_X_NORMAL; ctrl_x_mode = CTRL_X_NORMAL;

View File

@@ -8095,9 +8095,11 @@ local options = {
Override the 'ignorecase' option if the search pattern contains upper Override the 'ignorecase' option if the search pattern contains upper
case characters. Only used when the search pattern is typed and case characters. Only used when the search pattern is typed and
'ignorecase' option is on. Used for the commands "/", "?", "n", "N", 'ignorecase' option is on. Used for the commands "/", "?", "n", "N",
":g" and ":s". Not used for "*", "#", "gd", tag search, etc. After ":g" and ":s" and when filtering matches for the completion menu
"*" and "#" you can make 'smartcase' used by doing a "/" command, |compl-states|.
recalling the search pattern from history and hitting <Enter>. Not used for "*", "#", "gd", tag search, etc. After "*" and "#" you
can make 'smartcase' used by doing a "/" command, recalling the search
pattern from history and hitting <Enter>.
]=], ]=],
full_name = 'smartcase', full_name = 'smartcase',
scope = { 'global' }, scope = { 'global' },

View File

@@ -391,7 +391,7 @@ int ignorecase(char *pat)
return ignorecase_opt(pat, p_ic, p_scs); return ignorecase_opt(pat, p_ic, p_scs);
} }
/// As ignorecase() put pass the "ic" and "scs" flags. /// As ignorecase() but pass the "ic" and "scs" flags.
int ignorecase_opt(char *pat, int ic_in, int scs) int ignorecase_opt(char *pat, int ic_in, int scs)
{ {
int ic = ic_in; int ic = ic_in;

View File

@@ -3484,6 +3484,93 @@ func Test_complete_append_selected_match_default()
delfunc PrintMenuWords delfunc PrintMenuWords
endfunc endfunc
" Test normal mode (^N/^P/^X^N/^X^P) with smartcase when 1) matches are first
" found and 2) matches are filtered (when a character is typed).
func Test_smartcase_normal_mode()
func! PrintMenu()
let info = complete_info(["matches"])
call map(info.matches, {_, v -> v.word})
return info
endfunc
func! TestInner(key)
let pr = "\<c-r>=PrintMenu()\<cr>"
new
set completeopt=menuone,noselect ignorecase smartcase
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}{pr}"
call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'',
\ ''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}a{pr}"
call assert_equal('Fa{''matches'': [''Fast'', ''False'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}a\<bs>{pr}"
call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'',
\ ''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}ax{pr}"
call assert_equal('Fax{''matches'': []}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}ax\<bs>{pr}"
call assert_equal('Fa{''matches'': [''Fast'', ''False'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}A{pr}"
call assert_equal('FA{''matches'': [''FAST'', ''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}A\<bs>{pr}"
call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'',
\ ''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}AL{pr}"
call assert_equal('FAL{''matches'': [''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}ALx{pr}"
call assert_equal('FALx{''matches'': []}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOF{a:key}ALx\<bs>{pr}"
call assert_equal('FAL{''matches'': [''FALSE'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOf{a:key}{pr}"
call assert_equal('f{''matches'': [''Fast'', ''FAST'', ''False'', ''FALSE'',
\ ''fast'', ''false'']}', getline(1))
%d
call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"])
exe $"normal! ggOf{a:key}a{pr}"
call assert_equal('fa{''matches'': [''Fast'', ''FAST'', ''False'', ''FALSE'',
\ ''fast'', ''false'']}', getline(1))
%d
exe $"normal! ggOf{a:key}{pr}"
call assert_equal('f{''matches'': []}', getline(1))
exe $"normal! ggOf{a:key}a\<bs>{pr}"
call assert_equal('f{''matches'': []}', getline(1))
set ignorecase& smartcase& completeopt&
bw!
endfunc
call TestInner("\<c-n>")
call TestInner("\<c-p>")
call TestInner("\<c-x>\<c-n>")
call TestInner("\<c-x>\<c-p>")
delfunc PrintMenu
delfunc TestInner
endfunc
" Test 'nearest' flag of 'completeopt' " Test 'nearest' flag of 'completeopt'
func Test_nearest_cpt_option() func Test_nearest_cpt_option()