From b5971141dff0c69355fd64196fcc0d0d071d4c82 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 21 Mar 2015 17:32:19 +0100 Subject: 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. --- src/eval.c | 8 ++++++-- src/ex_getln.c | 18 +++++++++++++++--- src/misc1.c | 6 ++++-- src/os_amiga.c | 4 +++- src/os_msdos.c | 11 ++++++++++- src/os_unix.c | 21 ++++++++++++++------- src/os_vms.c | 3 ++- src/proto/os_amiga.pro | 2 +- src/proto/os_msdos.pro | 2 +- src/proto/os_unix.pro | 2 +- src/proto/os_win32.pro | 2 +- src/version.c | 2 ++ src/vim.h | 2 ++ 13 files changed, 62 insertions(+), 21 deletions(-) diff --git a/src/eval.c b/src/eval.c index 7aefdb58fd..ebd7e379e8 100644 --- 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 index e18a8ede93..31e61d0945 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -4885,6 +4885,7 @@ expand_shellcmd(filepat, num_file, file, flagsarg) 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, flagsarg) 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, flagsarg) /* * 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 index 940a3e917e..bd1fe255b1 100644 --- 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 index 324fc367b7..ccd3b0c1c5 100644 --- 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 index f24a6f8ead..1b75a30f7f 100644 --- 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 index 8f6b9143ee..df045a50f6 100644 --- 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_file, file, flags) 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_file, file, flags) 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 index 12eceedd0c..7c2d872553 100644 --- a/src/os_vms.c +++ b/src/os_vms.c @@ -483,7 +483,8 @@ mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, i 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 index 16ee6571df..24c1f7248b 100644 --- a/src/proto/os_amiga.pro +++ b/src/proto/os_amiga.pro @@ -26,7 +26,7 @@ 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_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 index e75521110a..e035b9509e 100644 --- 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 index a59b6aa5e5..23434ba9fd 100644 --- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -42,7 +42,7 @@ void mch_set_acl __ARGS((char_u *fname, vim_acl_T aclent)); 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 index c149bc89f5..cbabe3a9f1 100644 --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -26,7 +26,7 @@ int mch_is_symbolic_link __ARGS((char_u *fname)); 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 index 405b8a7cee..344c327dde 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 672, /**/ 671, /**/ diff --git a/src/vim.h b/src/vim.h index 825c844c2c..fe8f558288 100644 --- a/src/vim.h +++ b/src/vim.h @@ -841,6 +841,8 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); /* 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 */ -- cgit v1.2.3