]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0568: Cannot expand paths from 'cdpath' setting v9.1.0568
authorLemonBoy <thatlemon@gmail.com>
Thu, 11 Jul 2024 20:35:53 +0000 (22:35 +0200)
committerChristian Brabandt <cb@256bit.org>
Thu, 11 Jul 2024 20:45:42 +0000 (22:45 +0200)
Problem:  Cannot expand paths from 'cdpath' setting
          (Daniel Hahler)
Solution: Implement 'cdpath' completion, add the new 'dir_in_path'
          completion type (LemonBoy)

fixes #374
closes: #15205

Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
14 files changed:
runtime/doc/builtin.txt
runtime/doc/map.txt
runtime/doc/todo.txt
runtime/doc/version9.txt
runtime/syntax/vim.vim
src/cmdexpand.c
src/filepath.c
src/findfile.c
src/proto/findfile.pro
src/testdir/test_cd.vim
src/testdir/test_cmdline.vim
src/usercmd.c
src/version.c
src/vim.h

index b25bb93902cf7278dbbe136f64f510dcc8c400ad..5c8d9d89b95b871f2156438619d2fcc8fa9457d5 100644 (file)
@@ -4065,6 +4065,7 @@ getcompletion({pat}, {type} [, {filtered}])               *getcompletion()*
                customlist,{func} custom completion, defined via {func}
                diff_buffer     |:diffget| and |:diffput| completion
                dir             directory names
+               dir_in_path     directory names in |'cdpath'|
                environment     environment variable names
                event           autocommand events
                expression      Vim expression
index 365f49ad19ff916e516e06baff84944d172bebed..432a98671bce5effdaa009f6ee82089750c3e9ce 100644 (file)
@@ -1,4 +1,4 @@
-*map.txt*       For Vim version 9.1.  Last change: 2024 May 05
+*map.txt*       For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1631,6 +1631,7 @@ completion can be enabled:
        -complete=compiler      compilers
        -complete=cscope        |:cscope| suboptions
        -complete=dir           directory names
+       -complete=dir_in_path   directory names in |'cdpath'|
        -complete=environment   environment variable names
        -complete=event         autocommand events
        -complete=expression    Vim expression
index 5b15a46b8c6fd5f80318d69b32fff60c9c997062..e0ebe7eedb5ac6626529f4019a6f841d695fe28d 100644 (file)
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 9.1.  Last change: 2024 Jul 04
+*todo.txt*      For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -539,7 +539,6 @@ SpellCap doesn't show below a closed fold. #12420
 - Adding "~" to 'cdpath' doesn't work for completion?  (Davido, 2013 Aug 19)
 - Problem with 'cdpath' on MS-Windows when a directory is equal to $HOME.
   (2006 Jul 26, Gary Johnson)
-- Completion of ":cd" doesn't use 'cdpath'. #374.
 
 Make "g>" and "g<" in Visual mode move the text right or left.
 Also for a block selection.  #8558
index cfeb28c7b941529145f9bdac826b87f4e1726d79..7a2cbe416403cb67e63de122ad6cd16edf58b04c 100644 (file)
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 10
+*version9.txt*  For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41583,6 +41583,9 @@ Changed~
 - moving in the buffer list using |:bnext| and similar commands, behaves as
   documented and skips help buffers (if not run from a help buffer, else 
   moves to the next/previous help buffer).
+- allow to complete directories from 'cdpath' for |:cd| and similar commands,
+  add the "cd_in_path" completion type for e.g. |:command-complete| and
+  |getcompletion()|
 
                                                        *added-9.2*
 Added ~
index 8ea2c1c1301678d76af6adf52fe0faeb82f2c9f0..b10531e961a1ff24231dfd83ff87b26496eaeb5a 100644 (file)
@@ -400,7 +400,7 @@ endif
 syn case ignore
 syn keyword    vimUserAttrbKey   contained     bar     ban[g]  cou[nt] ra[nge] com[plete]      n[args] re[gister]
 " GEN_SYN_VIM: vimUserAttrbCmplt, START_STR='syn keyword vimUserAttrbCmplt contained', END_STR=''
-syn keyword vimUserAttrbCmplt contained arglist augroup behave buffer color command compiler cscope diff_buffer dir environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages syntax syntime option packadd runtime shellcmd sign tag tag_listfiles user var breakpoint scriptnames
+syn keyword vimUserAttrbCmplt contained arglist augroup behave buffer color command compiler cscope diff_buffer dir environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages syntax syntime option packadd runtime shellcmd sign tag tag_listfiles user var breakpoint scriptnames dir_in_path
 syn keyword    vimUserAttrbCmplt contained     custom customlist nextgroup=vimUserAttrbCmpltFunc,vimUserCmdError
 syn match      vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%([.#]\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError
 
index 8d8bf06b5fb9f836ef3b3c0190c0fafaa8370cd9..0267d28e0f7127e5656cdec82931f20e4974c5a1 100644 (file)
@@ -46,6 +46,7 @@ cmdline_fuzzy_completion_supported(expand_T *xp)
            && xp->xp_context != EXPAND_COLORS
            && xp->xp_context != EXPAND_COMPILER
            && xp->xp_context != EXPAND_DIRECTORIES
+           && xp->xp_context != EXPAND_DIRS_IN_CDPATH
            && xp->xp_context != EXPAND_FILES
            && xp->xp_context != EXPAND_FILES_IN_PATH
            && xp->xp_context != EXPAND_FILETYPE
@@ -107,7 +108,8 @@ wildescape(
            || xp->xp_context == EXPAND_FILES_IN_PATH
            || xp->xp_context == EXPAND_SHELLCMD
            || xp->xp_context == EXPAND_BUFFERS
-           || xp->xp_context == EXPAND_DIRECTORIES)
+           || xp->xp_context == EXPAND_DIRECTORIES
+           || xp->xp_context == EXPAND_DIRS_IN_CDPATH)
     {
        // Insert a backslash into a file name before a space, \, %, #
        // and wildmatch characters, except '~'.
@@ -1404,7 +1406,8 @@ addstar(
     if (context != EXPAND_FILES
            && context != EXPAND_FILES_IN_PATH
            && context != EXPAND_SHELLCMD
-           && context != EXPAND_DIRECTORIES)
+           && context != EXPAND_DIRECTORIES
+           && context != EXPAND_DIRS_IN_CDPATH)
     {
        // Matching will be done internally (on something other than files).
        // So we convert the file-matching-type wildcards into our kind for
@@ -2138,7 +2141,7 @@ set_context_by_cmdname(
        case CMD_lcd:
        case CMD_lchdir:
            if (xp->xp_context == EXPAND_FILES)
-               xp->xp_context = EXPAND_DIRECTORIES;
+               xp->xp_context = EXPAND_DIRS_IN_CDPATH;
            break;
        case CMD_help:
            xp->xp_context = EXPAND_HELP;
@@ -2845,6 +2848,8 @@ expand_files_and_dirs(
        flags |= EW_FILE;
     else if (xp->xp_context == EXPAND_FILES_IN_PATH)
        flags |= (EW_FILE | EW_PATH);
+    else if (xp->xp_context == EXPAND_DIRS_IN_CDPATH)
+       flags = (flags | EW_DIR | EW_CDPATH) & ~EW_FILE;
     else
        flags = (flags | EW_DIR) & ~EW_FILE;
     if (options & WILD_ICASE)
@@ -3098,7 +3103,8 @@ ExpandFromContext(
 
     if (xp->xp_context == EXPAND_FILES
            || xp->xp_context == EXPAND_DIRECTORIES
-           || xp->xp_context == EXPAND_FILES_IN_PATH)
+           || xp->xp_context == EXPAND_FILES_IN_PATH
+           || xp->xp_context == EXPAND_DIRS_IN_CDPATH)
        return expand_files_and_dirs(xp, pat, matches, numMatches, flags,
                                                                options);
 
index 788d3bbe5b3cac75ad6061362edb789180da1b0f..d514aaf8efedabdfc2c2ae5ab8e35b91f0f2a28a 100644 (file)
@@ -4003,6 +4003,8 @@ gen_expand_wildcards(
     int                        add_pat;
     int                        retval = OK;
     int                        did_expand_in_path = FALSE;
+    char_u             *path_option = *curbuf->b_p_path == NUL ?
+                                       p_path : curbuf->b_p_path;
 
     /*
      * expand_env() is called to expand things like "~user".  If this fails,
@@ -4092,7 +4094,7 @@ gen_expand_wildcards(
             */
            if (mch_has_exp_wildcard(p) || (flags & EW_ICASE))
            {
-               if ((flags & EW_PATH)
+               if ((flags & (EW_PATH | EW_CDPATH))
                        && !mch_isFullName(p)
                        && !(p[0] == '.'
                            && (vim_ispathsep(p[1])
@@ -4126,8 +4128,8 @@ gen_expand_wildcards(
                vim_free(t);
        }
 
-       if (did_expand_in_path && ga.ga_len > 0 && (flags & EW_PATH))
-           uniquefy_paths(&ga, p);
+       if (did_expand_in_path && ga.ga_len > 0 && (flags & (EW_PATH | EW_CDPATH)))
+           uniquefy_paths(&ga, p, path_option);
        if (p != pat[i])
            vim_free(p);
     }
index d1cd5f06148e73457ad12ed77e6240b7f98cb7c3..4310a508c1c1898a29002ad2433f821df0dea240 100644 (file)
@@ -2211,10 +2211,11 @@ is_unique(char_u *maybe_unique, garray_T *gap, int i)
  * expanding each into their equivalent path(s).
  */
     static void
-expand_path_option(char_u *curdir, garray_T *gap)
+expand_path_option(
+       char_u          *curdir,
+       char_u          *path_option,   // p_path or p_cdpath
+       garray_T        *gap)
 {
-    char_u     *path_option = *curbuf->b_p_path == NUL
-                                                 ? p_path : curbuf->b_p_path;
     char_u     *buf;
     char_u     *p;
     int                len;
@@ -2329,7 +2330,10 @@ get_path_cutoff(char_u *fname, garray_T *gap)
  * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len".
  */
     void
-uniquefy_paths(garray_T *gap, char_u *pattern)
+uniquefy_paths(
+       garray_T *gap,
+       char_u *pattern,
+       char_u *path_option)    // p_path or p_cdpath
 {
     int                i;
     int                len;
@@ -2372,7 +2376,7 @@ uniquefy_paths(garray_T *gap, char_u *pattern)
     if ((curdir = alloc(MAXPATHL)) == NULL)
        goto theend;
     mch_dirname(curdir, MAXPATHL);
-    expand_path_option(curdir, &path_ga);
+    expand_path_option(curdir, path_option, &path_ga);
 
     in_curdir = ALLOC_CLEAR_MULT(char_u *, gap->ga_len);
     if (in_curdir == NULL)
@@ -2520,13 +2524,17 @@ expand_in_path(
     garray_T   path_ga;
     char_u     *paths = NULL;
     int                glob_flags = 0;
+    char_u     *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
 
     if ((curdir = alloc(MAXPATHL)) == NULL)
        return 0;
     mch_dirname(curdir, MAXPATHL);
 
     ga_init2(&path_ga, sizeof(char_u *), 1);
-    expand_path_option(curdir, &path_ga);
+    if (flags & EW_CDPATH)
+       expand_path_option(curdir, p_cdpath, &path_ga);
+    else
+       expand_path_option(curdir, path_option, &path_ga);
     vim_free(curdir);
     if (path_ga.ga_len == 0)
        return 0;
@@ -2540,7 +2548,7 @@ expand_in_path(
        glob_flags |= WILD_ICASE;
     if (flags & EW_ADDSLASH)
        glob_flags |= WILD_ADD_SLASH;
-    globpath(paths, pattern, gap, glob_flags, FALSE);
+    globpath(paths, pattern, gap, glob_flags, !!(flags & EW_CDPATH));
     vim_free(paths);
 
     return gap->ga_len;
index 95601011aca608b875fd916ceea14725238ffd72..1c28221576efb86f554d1079425f42b3fbc222c0 100644 (file)
@@ -12,7 +12,7 @@ char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum);
 char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u *rel_fname, linenr_T *file_lnum);
 char_u *find_file_name_in_path(char_u *ptr, int len, int options, long count, char_u *rel_fname);
 int vim_ispathlistsep(int c);
-void uniquefy_paths(garray_T *gap, char_u *pattern);
+void uniquefy_paths(garray_T *gap, char_u *pattern, char_u *path_option);
 int expand_in_path(garray_T *gap, char_u *pattern, int flags);
 void simplify_filename(char_u *filename);
 void f_simplify(typval_T *argvars, typval_T *rettv);
index 9fb5958fe66cff940767e864b8d9fddb6cfbc15a..13a3eba3707e0603a8e52371d3e618be3f9deeec 100644 (file)
@@ -200,12 +200,20 @@ endfunc
 func Test_cd_completion()
   call mkdir('XComplDir1', 'D')
   call mkdir('XComplDir2', 'D')
+  call mkdir('sub/XComplDir3', 'pD')
   call writefile([], 'XComplFile', 'D')
 
   for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir']
     call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx')
     call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/', @:)
   endfor
+
+  set cdpath+=sub
+  for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir']
+    call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx')
+    call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/ XComplDir3/', @:)
+  endfor
+  set cdpath&
 endfunc
 
 func Test_cd_unknown_dir()
index 8651a9dbba4a274e324bf1d2bde9432b1f9592e5..f83d673346cf931a840de00a04a565e4f4e7a227 100644 (file)
@@ -658,7 +658,8 @@ func Test_getcompletion()
   unlet g:cmdline_compl_params
 
   " For others test if the name is recognized.
-  let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user']
+  let names = ['buffer', 'environment', 'file_in_path', 'dir_in_path', 'mapping', 'tag',
+      \ 'tag_listfiles', 'user']
   if has('cmdline_hist')
     call add(names, 'history')
   endif
index e2c0114ca3ca8ce585f39b90e311e65a64dd4baa..3f0781c4fcfb253f98f85b208e08b2f790c793bf 100644 (file)
@@ -102,6 +102,7 @@ static struct
     {EXPAND_BREAKPOINT, "breakpoint"},
     {EXPAND_SCRIPTNAMES, "scriptnames"},
 #endif
+    {EXPAND_DIRS_IN_CDPATH, "dir_in_path"},
     {0, NULL}
 };
 
index c7499bb3f5f1f92eeca2324a9b1d8fb81e2355fe..3b4cca66d413f69307a12825ad0981501cdb3c9d 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    568,
 /**/
     567,
 /**/
index a35916246e0b8940f4e2c0c8a6528f0e07708529..c022f2e7f4025a6c35687e5397feacb135c8d6c9 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -843,6 +843,8 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define EXPAND_ARGOPT          56
 #define EXPAND_TERMINALOPT     57
 #define EXPAND_KEYMAP          58
+#define EXPAND_DIRS_IN_CDPATH  59
+
 
 // Values for exmode_active (0 is no exmode)
 #define EXMODE_NORMAL          1
@@ -898,6 +900,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define EW_DODOT       0x4000  // also files starting with a dot
 #define EW_EMPTYOK     0x8000  // no matches is not an error
 #define EW_NOTENV      0x10000 // do not expand environment variables
+#define EW_CDPATH      0x20000 // search in 'cdpath' too
 
 // Flags for find_file_*() functions.
 #define FINDFILE_FILE  0       // only files