Patch 8.2.4483

7 views
Skip to first unread message

Bram Moolenaar

unread,
Feb 28, 2022, 8:30:58 AM2/28/22
to vim...@googlegroups.com

Patch 8.2.4483
Problem: Command completion makes two rounds to collect matches.
Solution: Use a growarray to collect matches. (Yegappan Lakshmanan,
closes #9860)
Files: src/buffer.c, src/cmdexpand.c, src/map.c,
src/testdir/test_cmdline.vim


*** ../vim-8.2.4482/src/buffer.c 2022-02-24 13:28:36.570222354 +0000
--- src/buffer.c 2022-02-28 13:20:51.285350690 +0000
***************
*** 2814,2851 ****
}
}

! if (p != NULL)
{
! if (round == 1)
! ++count;
! else
! {
! if (options & WILD_HOME_REPLACE)
! p = home_replace_save(buf, p);
! else
! p = vim_strsave(p);

! if (!fuzzy)
! {
#ifdef FEAT_VIMINFO
! if (matches != NULL)
! {
! matches[count].buf = buf;
! matches[count].match = p;
! count++;
! }
! else
! #endif
! (*file)[count++] = p;
! }
! else
! {
! fuzmatch[count].idx = count;
! fuzmatch[count].str = p;
! fuzmatch[count].score = score;
! count++;
! }
}
}
}
if (count == 0) // no match found, break here
--- 2814,2852 ----
}
}

! if (p == NULL)
! continue;
!
! if (round == 1)
{
! ++count;
! continue;
! }
!
! if (options & WILD_HOME_REPLACE)
! p = home_replace_save(buf, p);
! else
! p = vim_strsave(p);

! if (!fuzzy)
! {
#ifdef FEAT_VIMINFO
! if (matches != NULL)
! {
! matches[count].buf = buf;
! matches[count].match = p;
! count++;
}
+ else
+ #endif
+ (*file)[count++] = p;
+ }
+ else
+ {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
}
}
if (count == 0) // no match found, break here
*** ../vim-8.2.4482/src/cmdexpand.c 2022-02-27 21:03:17.937471865 +0000
--- src/cmdexpand.c 2022-02-28 13:25:48.676936485 +0000
***************
*** 2633,2748 ****
int escaped)
{
int i;
! int count = 0;
! int round;
char_u *str;
fuzmatch_str_T *fuzmatch = NULL;
! int score = 0;
int fuzzy;
- int funcsort = FALSE;
int match;

fuzzy = cmdline_fuzzy_complete(pat);

! // do this loop twice:
! // round == 0: count the number of matching names
! // round == 1: copy the matching names into allocated memory
! for (round = 0; round <= 1; ++round)
{
! for (i = 0; ; ++i)
! {
! str = (*func)(xp, i);
! if (str == NULL) // end of list
! break;
! if (*str == NUL) // skip empty strings
! continue;

if (!fuzzy)
! match = vim_regexec(regmatch, str, (colnr_T)0);
else
{
score = fuzzy_match_str(str, pat);
match = (score != 0);
}

! if (!match)
! continue;

! if (round)
! {
! if (escaped)
! str = vim_strsave_escaped(str, (char_u *)" \t\\.");
! else
! str = vim_strsave(str);
! if (str == NULL)
! {
! if (fuzzy)
! fuzmatch_str_free(fuzmatch, count);
! else if (count > 0)
! FreeWild(count, *matches);
! *numMatches = 0;
! *matches = NULL;
! return FAIL;
! }
! if (fuzzy)
! {
! fuzmatch[count].idx = count;
! fuzmatch[count].str = str;
! fuzmatch[count].score = score;
! }
! else
! (*matches)[count] = str;
! # ifdef FEAT_MENU
! if (func == get_menu_names && str != NULL)
! {
! // test for separator added by get_menu_names()
! str += STRLEN(str) - 1;
! if (*str == '\001')
! *str = '.';
! }
! # endif
! }
! ++count;
! }
! if (round == 0)
{
! if (count == 0)
! return OK;
! if (fuzzy)
! fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
! else
! *matches = ALLOC_MULT(char_u *, count);
! if ((!fuzzy && (*matches == NULL))
! || (fuzzy && (fuzmatch == NULL)))
{
! *numMatches = 0;
! *matches = NULL;
return FAIL;
}
! *numMatches = count;
! count = 0;
}
}

// Sort the results. Keep menu's in the specified order.
! if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS)
{
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
- {
// <SNR> functions should be sorted to the end.
! funcsort = TRUE;
! if (!fuzzy)
! qsort((void *)*matches, (size_t)*numMatches, sizeof(char_u *),
sort_func_compare);
- }
else
! {
! if (!fuzzy)
! sort_strings(*matches, *numMatches);
! }
}

#if defined(FEAT_SYN_HL)
--- 2633,2766 ----
int escaped)
{
int i;
! garray_T ga;
char_u *str;
fuzmatch_str_T *fuzmatch = NULL;
! int score = 0;
int fuzzy;
int match;

fuzzy = cmdline_fuzzy_complete(pat);
+ *matches = NULL;
+ *numMatches = 0;
+
+ if (!fuzzy)
+ ga_init2(&ga, sizeof(char *), 30);
+ else
+ ga_init2(&ga, sizeof(fuzmatch_str_T), 30);

! for (i = 0; ; ++i)
{
! str = (*func)(xp, i);
! if (str == NULL) // end of list
! break;
! if (*str == NUL) // skip empty strings
! continue;

+ if (xp->xp_pattern[0] != NUL)
+ {
if (!fuzzy)
! match = vim_regexec(regmatch, str, (colnr_T)0);
else
{
score = fuzzy_match_str(str, pat);
match = (score != 0);
}
+ }
+ else
+ match = TRUE;

! if (!match)
! continue;

! if (escaped)
! str = vim_strsave_escaped(str, (char_u *)" \t\\.");
! else
! str = vim_strsave(str);
! if (str == NULL)
{
! if (!fuzzy)
{
! ga_clear_strings(&ga);
return FAIL;
}
!
! for (i = 0; i < ga.ga_len; ++i)
! {
! fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[i];
! vim_free(fuzmatch->str);
! }
! ga_clear(&ga);
! return FAIL;
}
+
+ if (ga_grow(&ga, 1) == FAIL)
+ {
+ vim_free(str);
+ break;
+ }
+
+ if (fuzzy)
+ {
+ fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
+ fuzmatch->idx = ga.ga_len;
+ fuzmatch->str = str;
+ fuzmatch->score = score;
+ }
+ else
+ ((char_u **)ga.ga_data)[ga.ga_len] = str;
+
+ # ifdef FEAT_MENU
+ if (func == get_menu_names)
+ {
+ // test for separator added by get_menu_names()
+ str += STRLEN(str) - 1;
+ if (*str == '\001')
+ *str = '.';
+ }
+ # endif
+
+ ++ga.ga_len;
}

+ if (ga.ga_len == 0)
+ return OK;
+
// Sort the results. Keep menu's in the specified order.
! if (!fuzzy && xp->xp_context != EXPAND_MENUNAMES
! && xp->xp_context != EXPAND_MENUS)
{
if (xp->xp_context == EXPAND_EXPRESSION
|| xp->xp_context == EXPAND_FUNCTIONS
|| xp->xp_context == EXPAND_USER_FUNC
|| xp->xp_context == EXPAND_DISASSEMBLE)
// <SNR> functions should be sorted to the end.
! qsort((void *)ga.ga_data, (size_t)ga.ga_len, sizeof(char_u *),
sort_func_compare);
else
! sort_strings((char_u **)ga.ga_data, ga.ga_len);
! }
!
! if (!fuzzy)
! {
! *matches = ga.ga_data;
! *numMatches = ga.ga_len;
! }
! else
! {
! int funcsort = FALSE;
!
! if (xp->xp_context == EXPAND_EXPRESSION
! || xp->xp_context == EXPAND_FUNCTIONS
! || xp->xp_context == EXPAND_USER_FUNC
! || xp->xp_context == EXPAND_DISASSEMBLE)
! // <SNR> functions should be sorted to the end.
! funcsort = TRUE;
!
! if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
! funcsort) == FAIL)
! return FAIL;
! *numMatches = ga.ga_len;
}

#if defined(FEAT_SYN_HL)
***************
*** 2751,2760 ****
reset_expand_highlight();
#endif

- if (fuzzy && fuzzymatches_to_strmatches(fuzmatch, matches, count,
- funcsort) == FAIL)
- return FAIL;
-
return OK;
}

--- 2769,2774 ----
***************
*** 2990,3001 ****
int fuzzy;
int match;
int score;
- int count = 0;

fuzzy = cmdline_fuzzy_complete(pat);
-
*matches = NULL;
*numMatches = 0;
retstr = call_user_expand_func(call_func_retstr, xp);
if (retstr == NULL)
return FAIL;
--- 3004,3014 ----
int fuzzy;
int match;
int score;

fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
*numMatches = 0;
+
retstr = call_user_expand_func(call_func_retstr, xp);
if (retstr == NULL)
return FAIL;
***************
*** 3013,3019 ****
keep = *e;
*e = NUL;

! if (xp->xp_pattern[0] || fuzzy)
{
if (!fuzzy)
match = vim_regexec(regmatch, s, (colnr_T)0);
--- 3026,3032 ----
keep = *e;
*e = NUL;

! if (xp->xp_pattern[0] != NUL)
{
if (!fuzzy)
match = vim_regexec(regmatch, s, (colnr_T)0);
***************
*** 3038,3049 ****
{
fuzmatch_str_T *fuzmatch =
&((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
! fuzmatch->idx = count;
fuzmatch->str = vim_strnsave(s, e - s);
fuzmatch->score = score;
}
++ga.ga_len;
- count++;
}

if (*e != NUL)
--- 3051,3061 ----
{
fuzmatch_str_T *fuzmatch =
&((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
! fuzmatch->idx = ga.ga_len;
fuzmatch->str = vim_strnsave(s, e - s);
fuzmatch->score = score;
}
++ga.ga_len;
}

if (*e != NUL)
***************
*** 3051,3056 ****
--- 3063,3071 ----
}
vim_free(retstr);

+ if (ga.ga_len == 0)
+ return OK;
+
if (!fuzzy)
{
*matches = ga.ga_data;
***************
*** 3058,3067 ****
}
else
{
! if (fuzzymatches_to_strmatches(ga.ga_data, matches, count,
! FALSE) == FAIL)
return FAIL;
! *numMatches = count;
}
return OK;
}
--- 3073,3082 ----
}
else
{
! if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
! FALSE) == FAIL)
return FAIL;
! *numMatches = ga.ga_len;
}
return OK;
}
*** ../vim-8.2.4482/src/map.c 2022-02-27 12:07:26.666960401 +0000
--- src/map.c 2022-02-28 13:20:51.289350682 +0000
***************
*** 1263,1277 ****
char_u ***matches)
{
mapblock_T *mp;
int hash;
int count;
- int round;
char_u *p;
int i;
int fuzzy;
int match;
int score;
! fuzmatch_str_T *fuzmatch = NULL;

fuzzy = cmdline_fuzzy_complete(pat);

--- 1263,1277 ----
char_u ***matches)
{
mapblock_T *mp;
+ garray_T ga;
int hash;
int count;
char_u *p;
int i;
int fuzzy;
int match;
int score;
! fuzmatch_str_T *fuzmatch;

fuzzy = cmdline_fuzzy_complete(pat);

***************
*** 1280,1311 ****
*numMatches = 0; // return values in case of FAIL
*matches = NULL;

! // round == 1: Count the matches.
! // round == 2: Build the array to keep the matches.
! for (round = 1; round <= 2; ++round)
! {
! count = 0;

! // First search in map modifier arguments
! for (i = 0; i < 7; ++i)
! {
! if (i == 0)
! p = (char_u *)"<silent>";
! else if (i == 1)
! p = (char_u *)"<unique>";
#ifdef FEAT_EVAL
! else if (i == 2)
! p = (char_u *)"<script>";
! else if (i == 3)
! p = (char_u *)"<expr>";
#endif
! else if (i == 4 && !expand_buffer)
! p = (char_u *)"<buffer>";
! else if (i == 5)
! p = (char_u *)"<nowait>";
! else if (i == 6)
! p = (char_u *)"<special>";
! else
continue;

if (!fuzzy)
--- 1280,1357 ----
*numMatches = 0; // return values in case of FAIL
*matches = NULL;

! if (!fuzzy)
! ga_init2(&ga, sizeof(char *), 3);
! else
! ga_init2(&ga, sizeof(fuzmatch_str_T), 3);

! // First search in map modifier arguments
! for (i = 0; i < 7; ++i)
! {
! if (i == 0)
! p = (char_u *)"<silent>";
! else if (i == 1)
! p = (char_u *)"<unique>";
#ifdef FEAT_EVAL
! else if (i == 2)
! p = (char_u *)"<script>";
! else if (i == 3)
! p = (char_u *)"<expr>";
#endif
! else if (i == 4 && !expand_buffer)
! p = (char_u *)"<buffer>";
! else if (i == 5)
! p = (char_u *)"<nowait>";
! else if (i == 6)
! p = (char_u *)"<special>";
! else
! continue;
!
! if (!fuzzy)
! match = vim_regexec(regmatch, p, (colnr_T)0);
! else
! {
! score = fuzzy_match_str(p, pat);
! match = (score != 0);
! }
!
! if (!match)
! continue;
!
! if (ga_grow(&ga, 1) == FAIL)
! break;
!
! if (fuzzy)
! {
! fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
! fuzmatch->idx = ga.ga_len;
! fuzmatch->str = vim_strsave(p);
! fuzmatch->score = score;
! }
! else
! ((char_u **)ga.ga_data)[ga.ga_len] = vim_strsave(p);
! ++ga.ga_len;
! }
!
! for (hash = 0; hash < 256; ++hash)
! {
! if (expand_isabbrev)
! {
! if (hash > 0) // only one abbrev list
! break; // for (hash)
! mp = first_abbr;
! }
! else if (expand_buffer)
! mp = curbuf->b_maphash[hash];
! else
! mp = maphash[hash];
! for (; mp; mp = mp->m_next)
! {
! if (!(mp->m_mode & expand_mapmodes))
! continue;
!
! p = translate_mapping(mp->m_keys);
! if (p == NULL)
continue;

if (!fuzzy)
***************
*** 1317,1411 ****
}

if (!match)
- continue;
-
- if (round == 2)
{
! if (fuzzy)
! {
! fuzmatch[count].idx = count;
! fuzmatch[count].str = vim_strsave(p);
! fuzmatch[count].score = score;
! }
! else
! (*matches)[count] = vim_strsave(p);
}
- ++count;
- }

! for (hash = 0; hash < 256; ++hash)
! {
! if (expand_isabbrev)
{
! if (hash > 0) // only one abbrev list
! break; // for (hash)
! mp = first_abbr;
}
- else if (expand_buffer)
- mp = curbuf->b_maphash[hash];
- else
- mp = maphash[hash];
- for (; mp; mp = mp->m_next)
- {
- if (mp->m_mode & expand_mapmodes)
- {
- p = translate_mapping(mp->m_keys);
- if (p != NULL)
- {
- if (!fuzzy)
- match = vim_regexec(regmatch, p, (colnr_T)0);
- else
- {
- score = fuzzy_match_str(p, pat);
- match = (score != 0);
- }
-
- if (match)
- {
- if (round == 2)
- {
- if (fuzzy)
- {
- fuzmatch[count].idx = count;
- fuzmatch[count].str = p;
- fuzmatch[count].score = score;
- }
- else
- (*matches)[count] = p;
- p = NULL;
- }
- ++count;
- }
- }
- vim_free(p);
- }
- } // for (mp)
- } // for (hash)

- if (count == 0) // no match found
- break; // for (round)
-
- if (round == 1)
- {
if (fuzzy)
{
! fuzmatch = ALLOC_MULT(fuzmatch_str_T, count);
! if (fuzmatch == NULL)
! return FAIL;
}
else
! {
! *matches = ALLOC_MULT(char_u *, count);
! if (*matches == NULL)
! return FAIL;
! }
! }
! } // for (round)

! if (fuzzy && fuzzymatches_to_strmatches(fuzmatch, matches, count,
! FALSE) == FAIL)
return FAIL;

if (count > 1)
{
char_u **ptr1;
--- 1363,1410 ----
}

if (!match)
{
! vim_free(p);
! continue;
}

! if (ga_grow(&ga, 1) == FAIL)
{
! vim_free(p);
! break;
}

if (fuzzy)
{
! fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
! fuzmatch->idx = ga.ga_len;
! fuzmatch->str = p;
! fuzmatch->score = score;
}
else
! ((char_u **)ga.ga_data)[ga.ga_len] = p;

! ++ga.ga_len;
! } // for (mp)
! } // for (hash)
!
! if (ga.ga_len == 0)
return FAIL;

+ if (!fuzzy)
+ {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ }
+ else
+ {
+ if (fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len,
+ FALSE) == FAIL)
+ return FAIL;
+ *numMatches = ga.ga_len;
+ }
+
+ count = *numMatches;
if (count > 1)
{
char_u **ptr1;
*** ../vim-8.2.4482/src/testdir/test_cmdline.vim 2022-02-27 21:03:17.937471865 +0000
--- src/testdir/test_cmdline.vim 2022-02-28 13:20:51.289350682 +0000
***************
*** 2661,2666 ****
--- 2661,2684 ----
set wildoptions&
endfunc

+ " <SNR> functions should be sorted to the end
+ func Test_fuzzy_completion_userdefined_snr_func()
+ func s:Sendmail()
+ endfunc
+ func SendSomemail()
+ endfunc
+ func S1e2n3dmail()
+ endfunc
+ set wildoptions=fuzzy
+ call feedkeys(":call sendmail\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call SendSomemail() S1e2n3dmail() '
+ \ .. expand("<SID>") .. 'Sendmail()', @:)
+ set wildoptions&
+ delfunc s:Sendmail
+ delfunc SendSomemail
+ delfunc S1e2n3dmail
+ endfunc
+
" user defined command name completion
func Test_fuzzy_completion_userdefined_cmd()
set wildoptions&
*** ../vim-8.2.4482/src/version.c 2022-02-27 21:03:17.937471865 +0000
--- src/version.c 2022-02-28 13:22:51.085181069 +0000
***************
*** 756,757 ****
--- 756,759 ----
{ /* Add new patch number below this line */
+ /**/
+ 4483,
/**/

--
hundred-and-one symptoms of being an internet addict:
122. You ask if the Netaholics Anonymous t-shirt you ordered can be
sent to you via e-mail.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages