diff src/map.c @ 27916:6efa2f193c94 v8.2.4483

patch 8.2.4483: command completion makes two rounds to collect matches Commit: https://github.com/vim/vim/commit/5de4c4372d4366bc85cb66efb3e373439b9471c5 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Mon Feb 28 13:28:38 2022 +0000 patch 8.2.4483: command completion makes two rounds to collect matches Problem: Command completion makes two rounds to collect matches. Solution: Use a growarray to collect matches. (Yegappan Lakshmanan, closes #9860)
author Bram Moolenaar <Bram@vim.org>
date Mon, 28 Feb 2022 14:30:04 +0100
parents 099c2e612827
children 86bf2dabc93a
line wrap: on
line diff
--- a/src/map.c
+++ b/src/map.c
@@ -1263,15 +1263,15 @@ ExpandMappings(
     char_u	***matches)
 {
     mapblock_T	*mp;
+    garray_T	ga;
     int		hash;
     int		count;
-    int		round;
     char_u	*p;
     int		i;
     int		fuzzy;
     int		match;
     int		score;
-    fuzmatch_str_T  *fuzmatch = NULL;
+    fuzmatch_str_T  *fuzmatch;
 
     fuzzy = cmdline_fuzzy_complete(pat);
 
@@ -1280,32 +1280,78 @@ ExpandMappings(
     *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)
+    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)
     {
-	count = 0;
+	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;
 
-	// First search in map modifier arguments
-	for (i = 0; i < 7; ++i)
+	if (!fuzzy)
+	    match = vim_regexec(regmatch, p, (colnr_T)0);
+	else
 	{
-	    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
+	    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,95 +1363,48 @@ ExpandMappings(
 	    }
 
 	    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);
-			}
+		vim_free(p);
+		continue;
+	    }
 
-			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 (ga_grow(&ga, 1) == FAIL)
+	    {
+		vim_free(p);
+		break;
+	    }
 
-	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;
+		fuzmatch = &((fuzmatch_str_T *)ga.ga_data)[ga.ga_len];
+		fuzmatch->idx = ga.ga_len;
+		fuzmatch->str = p;
+		fuzmatch->score = score;
 	    }
 	    else
-	    {
-		*matches = ALLOC_MULT(char_u *, count);
-		if (*matches == NULL)
-		    return FAIL;
-	    }
-	}
-    } // for (round)
+		((char_u **)ga.ga_data)[ga.ga_len] = p;
 
-    if (fuzzy && fuzzymatches_to_strmatches(fuzmatch, matches, count,
-							FALSE) == FAIL)
+	    ++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;