]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.1956: Custom completion skips orig cmdline if it invokes glob() v9.0.1956
authorzeertzjq <zeertzjq@outlook.com>
Fri, 29 Sep 2023 17:58:35 +0000 (19:58 +0200)
committerChristian Brabandt <cb@256bit.org>
Fri, 29 Sep 2023 17:58:35 +0000 (19:58 +0200)
Problem:  Custom cmdline completion skips original cmdline when pressing
          Ctrl-P at first match if completion function invokes glob().
Solution: Move orig_save into struct expand_T.

closes: #13216

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
src/cmdexpand.c
src/structs.h
src/testdir/test_cmdline.vim
src/version.c

index e5b96fbe9c4a7b43e2f0be661bb8bca3ae56e5e8..40778cc219f0e24d33c27e2f0b32f837e0c78ff0 100644 (file)
@@ -696,8 +696,7 @@ win_redr_status_matches(
     static char_u *
 get_next_or_prev_match(
        int             mode,
-       expand_T        *xp,
-       char_u          *orig_save)
+       expand_T        *xp)
 {
     int findex = xp->xp_selected;
     int ht;
@@ -757,14 +756,14 @@ get_next_or_prev_match(
     // When wrapping around, return the original string, set findex to -1.
     if (findex < 0)
     {
-       if (orig_save == NULL)
+       if (xp->xp_orig == NULL)
            findex = xp->xp_numfiles - 1;
        else
            findex = -1;
     }
     if (findex >= xp->xp_numfiles)
     {
-       if (orig_save == NULL)
+       if (xp->xp_orig == NULL)
            findex = 0;
        else
            findex = -1;
@@ -780,7 +779,7 @@ get_next_or_prev_match(
     xp->xp_selected = findex;
 
     if (findex == -1)
-       return vim_strsave(orig_save);
+       return vim_strsave(xp->xp_orig);
 
     return vim_strsave(xp->xp_files[findex]);
 }
@@ -915,8 +914,8 @@ find_longest_match(expand_T *xp, int options)
  * Return NULL for failure.
  *
  * "orig" is the originally expanded string, copied to allocated memory.  It
- * should either be kept in orig_save or freed.  When "mode" is WILD_NEXT or
- * WILD_PREV "orig" should be NULL.
+ * should either be kept in "xp->xp_orig" or freed.  When "mode" is WILD_NEXT
+ * or WILD_PREV "orig" should be NULL.
  *
  * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode"
  * is WILD_EXPAND_FREE or WILD_ALL.
@@ -956,7 +955,6 @@ ExpandOne(
     int                mode)
 {
     char_u     *ss = NULL;
-    static char_u *orig_save = NULL;   // kept value of orig
     int                orig_saved = FALSE;
     int                i;
     long_u     len;
@@ -964,13 +962,13 @@ ExpandOne(
     // first handle the case of using an old match
     if (mode == WILD_NEXT || mode == WILD_PREV
            || mode == WILD_PAGEUP || mode == WILD_PAGEDOWN)
-       return get_next_or_prev_match(mode, xp, orig_save);
+       return get_next_or_prev_match(mode, xp);
 
     if (mode == WILD_CANCEL)
-       ss = vim_strsave(orig_save ? orig_save : (char_u *)"");
+       ss = vim_strsave(xp->xp_orig ? xp->xp_orig : (char_u *)"");
     else if (mode == WILD_APPLY)
        ss = vim_strsave(xp->xp_selected == -1
-                           ? (orig_save ? orig_save : (char_u *)"")
+                           ? (xp->xp_orig ? xp->xp_orig : (char_u *)"")
                            : xp->xp_files[xp->xp_selected]);
 
     // free old names
@@ -978,7 +976,7 @@ ExpandOne(
     {
        FreeWild(xp->xp_numfiles, xp->xp_files);
        xp->xp_numfiles = -1;
-       VIM_CLEAR(orig_save);
+       VIM_CLEAR(xp->xp_orig);
 
        // The entries from xp_files may be used in the PUM, remove it.
        if (compl_match_array != NULL)
@@ -991,8 +989,8 @@ ExpandOne(
 
     if (xp->xp_numfiles == -1 && mode != WILD_APPLY && mode != WILD_CANCEL)
     {
-       vim_free(orig_save);
-       orig_save = orig;
+       vim_free(xp->xp_orig);
+       xp->xp_orig = orig;
        orig_saved = TRUE;
 
        ss = ExpandOne_start(mode, xp, str, options);
@@ -1045,7 +1043,7 @@ ExpandOne(
     if (mode == WILD_EXPAND_FREE || mode == WILD_ALL)
        ExpandCleanup(xp);
 
-    // Free "orig" if it wasn't stored in "orig_save".
+    // Free "orig" if it wasn't stored in "xp->xp_orig".
     if (!orig_saved)
        vim_free(orig);
 
@@ -1075,6 +1073,7 @@ ExpandCleanup(expand_T *xp)
        FreeWild(xp->xp_numfiles, xp->xp_files);
        xp->xp_numfiles = -1;
     }
+    VIM_CLEAR(xp->xp_orig);
 }
 
 /*
index 9813c4e94d31632399b0ccb632ba2c037ad36f8b..d718efec2c671141f63655d0b5262a3533f4f95b 100644 (file)
@@ -610,6 +610,7 @@ typedef struct expand
                                        // file name completion
     int                xp_col;                 // cursor position in line
     int                xp_selected;            // selected index in completion
+    char_u     *xp_orig;               // originally expanded string
     char_u     **xp_files;             // list of files
     char_u     *xp_line;               // text being completed
 #define EXPAND_BUF_LEN 256
index b2566cdfb1aad43528cb2f54ecfc1ce8eb49ca3c..a54c5073874bfe0ac7a52e9e541eb86a318e7c10 100644 (file)
@@ -3549,4 +3549,20 @@ func Test_custom_completion()
   delfunc Check_customlist_completion
 endfunc
 
+func Test_custom_completion_with_glob()
+  func TestGlobComplete(A, L, P)
+    return split(glob('Xglob*'), "\n")
+  endfunc
+
+  command -nargs=* -complete=customlist,TestGlobComplete TestGlobComplete :
+  call writefile([], 'Xglob1', 'D')
+  call writefile([], 'Xglob2', 'D')
+
+  call feedkeys(":TestGlobComplete \<Tab> \<Tab>\<C-N> \<Tab>\<C-P>;\<C-B>\"\<CR>", 'xt')
+  call assert_equal('"TestGlobComplete Xglob1 Xglob2 ;', @:)
+
+  delcommand TestGlobComplete
+  delfunc TestGlobComplete
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index da13c18e1d5534713c4d814250b873d8bd68d3d6..3165cef295e62b9a90d52c3c408f4da04267c183 100644 (file)
@@ -699,6 +699,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1956,
 /**/
     1955,
 /**/