# HG changeset patch # User Bram Moolenaar # Date 1426955539 -3600 # Node ID 6529590f6c436594c3ba177c61efd9b42b3cbc08 # Parent c0df98c0770c53d03449fbd3babc7865976ba0fb updated for version 7.4.672 Problem: When completing a shell command, directories in the current directory are not listed. Solution: When "." is not in $PATH also look in the current directory for directories. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -10271,7 +10271,11 @@ f_executable(argvars, rettv) typval_T *argvars; typval_T *rettv; { - rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]), NULL); + char_u *name = get_tv_string(&argvars[0]); + + /* Check in $PATH and also check directly if there is a directory name. */ + rettv->vval.v_number = mch_can_exe(name, NULL, TRUE) + || (gettail(name) != name && mch_can_exe(name, NULL, FALSE)); } /* @@ -10284,7 +10288,7 @@ f_exepath(argvars, rettv) { char_u *p = NULL; - (void)mch_can_exe(get_tv_string(&argvars[0]), &p); + (void)mch_can_exe(get_tv_string(&argvars[0]), &p, TRUE); rettv->v_type = VAR_STRING; rettv->vval.v_string = p; } diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -4885,6 +4885,7 @@ expand_shellcmd(filepat, num_file, file, char_u *s, *e; int flags = flagsarg; int ret; + int did_curdir = FALSE; if (buf == NULL) return FAIL; @@ -4896,7 +4897,7 @@ expand_shellcmd(filepat, num_file, file, if (pat[i] == '\\' && pat[i + 1] == ' ') STRMOVE(pat + i, pat + i + 1); - flags |= EW_FILE | EW_EXEC; + flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; /* For an absolute name we don't use $PATH. */ if (mch_isFullName(pat)) @@ -4913,11 +4914,22 @@ expand_shellcmd(filepat, num_file, file, /* * Go over all directories in $PATH. Expand matches in that directory and - * collect them in "ga". + * collect them in "ga". When "." is not in $PATH also expand for the + * current directory, to find "subdir/cmd". */ ga_init2(&ga, (int)sizeof(char *), 10); - for (s = path; *s != NUL; s = e) + for (s = path; ; s = e) { + if (*s == NUL) + { + if (did_curdir) + break; + /* Find directories in the current directory, path is empty. */ + did_curdir = TRUE; + } + else if (*s == '.') + did_curdir = TRUE; + if (*s == ' ') ++s; /* Skip space used for absolute path name. */ diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -10987,8 +10987,10 @@ addfile(gap, f, flags) if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) return; - /* If the file isn't executable, may not add it. Do accept directories. */ - if (!isdir && (flags & EW_EXEC) && !mch_can_exe(f, NULL)) + /* If the file isn't executable, may not add it. Do accept directories. + * When invoked from expand_shellcmd() do not use $PATH. */ + if (!isdir && (flags & EW_EXEC) + && !mch_can_exe(f, NULL, !(flags & EW_SHELLCMD))) return; /* Make room for another item in the file list. */ diff --git a/src/os_amiga.c b/src/os_amiga.c --- a/src/os_amiga.c +++ b/src/os_amiga.c @@ -881,12 +881,14 @@ mch_mkdir(name) /* * Return 1 if "name" can be executed, 0 if not. + * If "use_path" is FALSE only check if "name" is executable. * Return -1 if unknown. */ int -mch_can_exe(name, path) +mch_can_exe(name, path, use_path) char_u *name; char_u **path; + int use_path; { /* TODO */ return -1; diff --git a/src/os_msdos.c b/src/os_msdos.c --- a/src/os_msdos.c +++ b/src/os_msdos.c @@ -2942,15 +2942,24 @@ mch_isdir(char_u *name) /* * Return 1 if "name" can be executed, 0 if not. + * If "use_path" is FALSE only check if "name" is executable. * Return -1 if unknown. */ int -mch_can_exe(name, path) +mch_can_exe(name, path, use_path) char_u *name; char_u **path; + int use_path; { char *p; + int mode; + if (!use_path) + { + /* TODO: proper check if file is executable. */ + mode = vim_chmod(name); + return mode != -1 && (mode & FA_DIREC) == 0; + } p = searchpath(name); if (p == NULL || mch_isdir(p)) return FALSE; diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3104,22 +3104,27 @@ executable_file(name) /* * Return 1 if "name" can be found in $PATH and executed, 0 if not. + * If "use_path" is FALSE only check if "name" is executable. * Return -1 if unknown. */ int -mch_can_exe(name, path) +mch_can_exe(name, path, use_path) char_u *name; char_u **path; + int use_path; { char_u *buf; char_u *p, *e; int retval; - /* If it's an absolute or relative path don't need to use $PATH. */ - if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/' - || (name[1] == '.' && name[2] == '/')))) + /* When "use_path" is false and if it's an absolute or relative path don't + * need to use $PATH. */ + if (!use_path || mch_isFullName(name) || (name[0] == '.' + && (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { - if (executable_file(name)) + /* There must be a path separator, files in the current directory + * can't be executed. */ + if (gettail(name) != name && executable_file(name)) { if (path != NULL) { @@ -5730,7 +5735,8 @@ mch_expand_wildcards(num_pat, pat, num_f continue; /* Skip files that are not executable if we check for that. */ - if (!dir && (flags & EW_EXEC) && !mch_can_exe(p, NULL)) + if (!dir && (flags & EW_EXEC) + && !mch_can_exe(p, NULL, !(flags & EW_SHELLCMD))) continue; if (--files_free == 0) @@ -6230,7 +6236,8 @@ mch_expand_wildcards(num_pat, pat, num_f continue; /* Skip files that are not executable if we check for that. */ - if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i], NULL)) + if (!dir && (flags & EW_EXEC) + && !mch_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD))) continue; p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir)); diff --git a/src/os_vms.c b/src/os_vms.c --- a/src/os_vms.c +++ b/src/os_vms.c @@ -483,7 +483,8 @@ mch_expand_wildcards(int num_pat, char_u continue; /* Skip files that are not executable if we check for that. */ - if (!dir && (flags & EW_EXEC) && !mch_can_exe(vms_fmatch[i], NULL)) + if (!dir && (flags & EW_EXEC) + && !mch_can_exe(vms_fmatch[i], NULL, !(flags & EW_SHELLCMD))) continue; /* allocate memory for pointers */ diff --git a/src/proto/os_amiga.pro b/src/proto/os_amiga.pro --- a/src/proto/os_amiga.pro +++ b/src/proto/os_amiga.pro @@ -26,7 +26,7 @@ int mch_setperm __ARGS((char_u *name, lo void mch_hide __ARGS((char_u *name)); int mch_isdir __ARGS((char_u *name)); int mch_mkdir __ARGS((char_u *name)); -int mch_can_exe __ARGS((char_u *name, char_u **path)); +int mch_can_exe __ARGS((char_u *name, char_u **path, int use_path)); int mch_nodetype __ARGS((char_u *name)); void mch_early_init __ARGS((void)); void mch_exit __ARGS((int r)); diff --git a/src/proto/os_msdos.pro b/src/proto/os_msdos.pro --- a/src/proto/os_msdos.pro +++ b/src/proto/os_msdos.pro @@ -38,7 +38,7 @@ long mch_getperm __ARGS((char_u *name)); int mch_setperm __ARGS((char_u *name, long perm)); void mch_hide __ARGS((char_u *name)); int mch_isdir __ARGS((char_u *name)); -int mch_can_exe __ARGS((char_u *name, char_u **path)); +int mch_can_exe __ARGS((char_u *name, char_u **path, int use_path)); int mch_nodetype __ARGS((char_u *name)); int mch_dirname __ARGS((char_u *buf, int len)); int mch_remove __ARGS((char_u *name)); diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -42,7 +42,7 @@ void mch_set_acl __ARGS((char_u *fname, void mch_free_acl __ARGS((vim_acl_T aclent)); void mch_hide __ARGS((char_u *name)); int mch_isdir __ARGS((char_u *name)); -int mch_can_exe __ARGS((char_u *name, char_u **path)); +int mch_can_exe __ARGS((char_u *name, char_u **path, int use_path)); int mch_nodetype __ARGS((char_u *name)); void mch_early_init __ARGS((void)); void mch_free_mem __ARGS((void)); diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -26,7 +26,7 @@ int mch_is_symbolic_link __ARGS((char_u int mch_is_linked __ARGS((char_u *fname)); int win32_fileinfo __ARGS((char_u *fname, BY_HANDLE_FILE_INFORMATION *info)); int mch_writable __ARGS((char_u *name)); -int mch_can_exe __ARGS((char_u *name, char_u **path)); +int mch_can_exe __ARGS((char_u *name, char_u **path, int use_path)); int mch_nodetype __ARGS((char_u *name)); vim_acl_T mch_get_acl __ARGS((char_u *fname)); void mch_set_acl __ARGS((char_u *fname, vim_acl_T acl)); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 672, +/**/ 671, /**/ 670, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -841,6 +841,8 @@ extern char *(*dyn_libintl_textdomain)(c /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND * is used when executing commands and EW_SILENT for interactive expanding. */ #define EW_ALLLINKS 0x1000 /* also links not pointing to existing file */ +#define EW_SHELLCMD 0x2000 /* called from expand_shellcmd(), don't check + * if executable is in $PATH */ /* Flags for find_file_*() functions. */ #define FINDFILE_FILE 0 /* only files */