# HG changeset patch # User Bram Moolenaar # Date 1396378859 -7200 # Node ID 5ab2946f7ce560985830fbc3c453bb0f7a01f385 # Parent eabbe5a74948b9b9333dce725823fabd8dec7f40 updated for version 7.4.235 Problem: It is not easy to get the full path of a command. Solution: Add the exepath() function. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1562,6 +1562,10 @@ v:progname Contains the name (with path v:progpath Contains the command with which Vim was invoked, including the path. Useful if you want to message a Vim server using a |--remote-expr|. + To get the full path use: > + echo exepath(v:progpath) +< NOTE: This does not work when the command is a relative path + and the current directory has changed. Read-only. *v:register* *register-variable* @@ -1762,6 +1766,7 @@ escape( {string}, {chars}) String escape eval( {string}) any evaluate {string} into its value eventhandler( ) Number TRUE if inside an event handler executable( {expr}) Number 1 if executable {expr} exists +exepath( {expr}) String full path of the command {expr} exists( {expr}) Number TRUE if {expr} exists extend( {expr1}, {expr2} [, {expr3}]) List/Dict insert items of {expr2} into {expr1} @@ -2706,6 +2711,15 @@ executable({expr}) *executable()* 0 does not exist -1 not implemented on this system +exepath({expr}) *exepath()* + If {expr} is an executable and is either an absolute path, a + relative path or found in $PATH, return the full path. + Note that the current directory is used when {expr} starts + with "./", which may be a problem for Vim: > + echo exepath(v:progpath) +< If {expr} cannot be found in $PATH or is not executable then + an empty string is returned. + *exists()* exists({expr}) The result is a Number, which is non-zero if {expr} is defined, zero otherwise. The {expr} argument is a string, diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -514,6 +514,7 @@ static void f_escape __ARGS((typval_T *a static void f_eval __ARGS((typval_T *argvars, typval_T *rettv)); static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv)); static void f_executable __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_exepath __ARGS((typval_T *argvars, typval_T *rettv)); static void f_exists __ARGS((typval_T *argvars, typval_T *rettv)); #ifdef FEAT_FLOAT static void f_exp __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7920,6 +7921,7 @@ static struct fst {"eval", 1, 1, f_eval}, {"eventhandler", 0, 0, f_eventhandler}, {"executable", 1, 1, f_executable}, + {"exepath", 1, 1, f_exepath}, {"exists", 1, 1, f_exists}, #ifdef FEAT_FLOAT {"exp", 1, 1, f_exp}, @@ -10046,7 +10048,22 @@ f_executable(argvars, rettv) typval_T *argvars; typval_T *rettv; { - rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0])); + rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]), NULL); +} + +/* + * "exepath()" function + */ + static void +f_exepath(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + char_u *p = NULL; + + (void)mch_can_exe(get_tv_string(&argvars[0]), &p); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = p; } /* diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -10728,7 +10728,7 @@ addfile(gap, f, flags) return; /* If the file isn't executable, may not add it. Do accept directories. */ - if (!isdir && (flags & EW_EXEC) && !mch_can_exe(f)) + if (!isdir && (flags & EW_EXEC) && !mch_can_exe(f, NULL)) 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 @@ -884,8 +884,9 @@ mch_mkdir(name) * Return -1 if unknown. */ int -mch_can_exe(name) +mch_can_exe(name, path) char_u *name; + char_u **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 @@ -2945,14 +2945,17 @@ mch_isdir(char_u *name) * Return -1 if unknown. */ int -mch_can_exe(name) +mch_can_exe(name, path) char_u *name; + char_u **path; { char *p; p = searchpath(name); if (p == NULL || mch_isdir(p)) return FALSE; + if (path != NULL) + *path = vim_strsave(p); return TRUE; } diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2992,8 +2992,9 @@ executable_file(name) * Return -1 if unknown. */ int -mch_can_exe(name) +mch_can_exe(name, path) char_u *name; + char_u **path; { char_u *buf; char_u *p, *e; @@ -3003,7 +3004,18 @@ mch_can_exe(name) if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { - return executable_file(name); + if (executable_file(name)) + { + if (path != NULL) + { + if (name[0] == '.') + *path = FullName_save(name, TRUE); + else + *path = vim_strsave(name); + } + return TRUE; + } + return FALSE; } p = (char_u *)getenv("PATH"); @@ -3032,7 +3044,16 @@ mch_can_exe(name) STRCAT(buf, name); retval = executable_file(buf); if (retval == 1) + { + if (path != NULL) + { + if (buf[0] == '.') + *path = FullName_save(buf, TRUE); + else + *path = vim_strsave(buf); + } break; + } if (*e != ':') break; @@ -5592,7 +5613,7 @@ 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)) + if (!dir && (flags & EW_EXEC) && !mch_can_exe(p, NULL)) continue; if (--files_free == 0) @@ -6090,7 +6111,7 @@ 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])) + if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i], NULL)) continue; p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir)); @@ -6317,7 +6338,7 @@ gpm_close() /* Reads gpm event and adds special keys to input buf. Returns length of * generated key sequence. - * This function is made after gui_send_mouse_event + * This function is styled after gui_send_mouse_event(). */ static int mch_gpm_process() 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,7 @@ 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])) + if (!dir && (flags & EW_EXEC) && !mch_can_exe(vms_fmatch[i], NULL)) continue; /* allocate memory for pointers */ diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -1882,7 +1882,7 @@ theend: * TODO: Should somehow check if it's really executable. */ static int -executable_exists(char *name) +executable_exists(char *name, char_u **path) { char *dum; char fname[_MAX_PATH]; @@ -1905,6 +1905,8 @@ executable_exists(char *name) return FALSE; if (GetFileAttributesW(fnamew) & FILE_ATTRIBUTE_DIRECTORY) return FALSE; + if (path != NULL) + *path = utf16_to_enc(fnamew, NULL); return TRUE; } /* Retry with non-wide function (for Windows 98). */ @@ -1915,6 +1917,8 @@ executable_exists(char *name) return FALSE; if (mch_isdir(fname)) return FALSE; + if (path != NULL) + *path = vim_strsave(fname); return TRUE; } @@ -1996,7 +2000,7 @@ mch_init(void) vimrun_path = (char *)vim_strsave(vimrun_location); s_dont_use_vimrun = FALSE; } - else if (executable_exists("vimrun.exe")) + else if (executable_exists("vimrun.exe", NULL)) s_dont_use_vimrun = FALSE; /* Don't give the warning for a missing vimrun.exe right now, but only @@ -2010,7 +2014,7 @@ mch_init(void) * If "finstr.exe" doesn't exist, use "grep -n" for 'grepprg'. * Otherwise the default "findstr /n" is used. */ - if (!executable_exists("findstr.exe")) + if (!executable_exists("findstr.exe", NULL)) set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0); #ifdef FEAT_CLIPBOARD @@ -3330,7 +3334,7 @@ mch_writable(char_u *name) * Return -1 if unknown. */ int -mch_can_exe(char_u *name) +mch_can_exe(char_u *name, char_u **path) { char_u buf[_MAX_PATH]; int len = (int)STRLEN(name); @@ -3343,7 +3347,7 @@ mch_can_exe(char_u *name) * this with a Unix-shell like 'shell'. */ if (vim_strchr(gettail(name), '.') != NULL || strstr((char *)gettail(p_sh), "sh") != NULL) - if (executable_exists((char *)name)) + if (executable_exists((char *)name, path)) return TRUE; /* @@ -3365,7 +3369,7 @@ mch_can_exe(char_u *name) } else copy_option_part(&p, buf + len, _MAX_PATH - len, ";"); - if (executable_exists((char *)buf)) + if (executable_exists((char *)buf, path)) return TRUE; } return FALSE; 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)); +int mch_can_exe __ARGS((char_u *name, char_u **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)); +int mch_can_exe __ARGS((char_u *name, char_u **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)); +int mch_can_exe __ARGS((char_u *name, char_u **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)); +int mch_can_exe __ARGS((char_u *name, char_u **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 @@ -735,6 +735,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 235, +/**/ 234, /**/ 233,