| To: vim_dev@googlegroups.com |
| Subject: Patch 7.4.235 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.4.235 |
| Problem: It is not easy to get the full path of a command. |
| Solution: Add the exepath() function. |
| Files: src/eval.c, src/misc1.c, src/os_amiga.c, src/os_msdos.c, |
| src/os_unix.c, src/os_vms.c, src/os_win32.c, |
| src/proto/os_amiga.pro, src/proto/os_msdos.pro, |
| src/proto/os_unix.pro, src/proto/os_win32.pro, |
| runtime/doc/eval.txt |
| |
| |
| |
| |
| |
| *** 514,519 **** |
| --- 514,520 ---- |
| 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,7925 **** |
| --- 7921,7927 ---- |
| {"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,10052 **** |
| typval_T *argvars; |
| typval_T *rettv; |
| { |
| ! rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0])); |
| } |
| |
| /* |
| --- 10048,10069 ---- |
| typval_T *argvars; |
| typval_T *rettv; |
| { |
| ! 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; |
| } |
| |
| /* |
| |
| |
| |
| *** 10728,10734 **** |
| return; |
| |
| /* If the file isn't executable, may not add it. Do accept directories. */ |
| ! if (!isdir && (flags & EW_EXEC) && !mch_can_exe(f)) |
| return; |
| |
| /* Make room for another item in the file list. */ |
| --- 10728,10734 ---- |
| return; |
| |
| /* If the file isn't executable, may not add it. Do accept directories. */ |
| ! if (!isdir && (flags & EW_EXEC) && !mch_can_exe(f, NULL)) |
| return; |
| |
| /* Make room for another item in the file list. */ |
| |
| |
| |
| *** 884,891 **** |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(name) |
| char_u *name; |
| { |
| /* TODO */ |
| return -1; |
| --- 884,892 ---- |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(name, path) |
| char_u *name; |
| + char_u **path; |
| { |
| /* TODO */ |
| return -1; |
| |
| |
| |
| *** 2945,2958 **** |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(name) |
| char_u *name; |
| { |
| char *p; |
| |
| p = searchpath(name); |
| if (p == NULL || mch_isdir(p)) |
| return FALSE; |
| return TRUE; |
| } |
| |
| --- 2945,2961 ---- |
| * Return -1 if unknown. |
| */ |
| int |
| ! 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; |
| } |
| |
| |
| |
| |
| *** 2992,2999 **** |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(name) |
| char_u *name; |
| { |
| char_u *buf; |
| char_u *p, *e; |
| --- 2992,3000 ---- |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(name, path) |
| char_u *name; |
| + char_u **path; |
| { |
| char_u *buf; |
| char_u *p, *e; |
| |
| *** 3003,3009 **** |
| if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/' |
| || (name[1] == '.' && name[2] == '/')))) |
| { |
| ! return executable_file(name); |
| } |
| |
| p = (char_u *)getenv("PATH"); |
| --- 3004,3021 ---- |
| if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/' |
| || (name[1] == '.' && name[2] == '/')))) |
| { |
| ! 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,3038 **** |
| --- 3044,3059 ---- |
| 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,5598 **** |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe(p)) |
| continue; |
| |
| if (--files_free == 0) |
| --- 5613,5619 ---- |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe(p, NULL)) |
| continue; |
| |
| if (--files_free == 0) |
| |
| *** 6090,6096 **** |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i])) |
| continue; |
| |
| p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir)); |
| --- 6111,6117 ---- |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i], NULL)) |
| continue; |
| |
| p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir)); |
| |
| *** 6317,6323 **** |
| |
| /* 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 |
| */ |
| static int |
| mch_gpm_process() |
| --- 6338,6344 ---- |
| |
| /* Reads gpm event and adds special keys to input buf. Returns length of |
| * generated key sequence. |
| ! * This function is styled after gui_send_mouse_event(). |
| */ |
| static int |
| mch_gpm_process() |
| |
| |
| |
| *** 483,489 **** |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe(vms_fmatch[i])) |
| continue; |
| |
| /* allocate memory for pointers */ |
| --- 483,489 ---- |
| continue; |
| |
| /* Skip files that are not executable if we check for that. */ |
| ! if (!dir && (flags & EW_EXEC) && !mch_can_exe(vms_fmatch[i], NULL)) |
| continue; |
| |
| /* allocate memory for pointers */ |
| |
| |
| |
| *** 1882,1888 **** |
| * TODO: Should somehow check if it's really executable. |
| */ |
| static int |
| ! executable_exists(char *name) |
| { |
| char *dum; |
| char fname[_MAX_PATH]; |
| --- 1882,1888 ---- |
| * TODO: Should somehow check if it's really executable. |
| */ |
| static int |
| ! executable_exists(char *name, char_u **path) |
| { |
| char *dum; |
| char fname[_MAX_PATH]; |
| |
| *** 1905,1910 **** |
| --- 1905,1912 ---- |
| 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,1920 **** |
| --- 1917,1924 ---- |
| return FALSE; |
| if (mch_isdir(fname)) |
| return FALSE; |
| + if (path != NULL) |
| + *path = vim_strsave(fname); |
| return TRUE; |
| } |
| |
| |
| *** 1996,2002 **** |
| vimrun_path = (char *)vim_strsave(vimrun_location); |
| s_dont_use_vimrun = FALSE; |
| } |
| ! else if (executable_exists("vimrun.exe")) |
| s_dont_use_vimrun = FALSE; |
| |
| /* Don't give the warning for a missing vimrun.exe right now, but only |
| --- 2000,2006 ---- |
| vimrun_path = (char *)vim_strsave(vimrun_location); |
| s_dont_use_vimrun = FALSE; |
| } |
| ! 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,2016 **** |
| * If "finstr.exe" doesn't exist, use "grep -n" for 'grepprg'. |
| * Otherwise the default "findstr /n" is used. |
| */ |
| ! if (!executable_exists("findstr.exe")) |
| set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0); |
| |
| #ifdef FEAT_CLIPBOARD |
| --- 2014,2020 ---- |
| * If "finstr.exe" doesn't exist, use "grep -n" for 'grepprg'. |
| * Otherwise the default "findstr /n" is used. |
| */ |
| ! if (!executable_exists("findstr.exe", NULL)) |
| set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0); |
| |
| #ifdef FEAT_CLIPBOARD |
| |
| *** 3330,3336 **** |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(char_u *name) |
| { |
| char_u buf[_MAX_PATH]; |
| int len = (int)STRLEN(name); |
| --- 3334,3340 ---- |
| * Return -1 if unknown. |
| */ |
| int |
| ! mch_can_exe(char_u *name, char_u **path) |
| { |
| char_u buf[_MAX_PATH]; |
| int len = (int)STRLEN(name); |
| |
| *** 3343,3349 **** |
| * 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)) |
| return TRUE; |
| |
| /* |
| --- 3347,3353 ---- |
| * 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, path)) |
| return TRUE; |
| |
| /* |
| |
| *** 3365,3371 **** |
| } |
| else |
| copy_option_part(&p, buf + len, _MAX_PATH - len, ";"); |
| ! if (executable_exists((char *)buf)) |
| return TRUE; |
| } |
| return FALSE; |
| --- 3369,3375 ---- |
| } |
| else |
| copy_option_part(&p, buf + len, _MAX_PATH - len, ";"); |
| ! if (executable_exists((char *)buf, path)) |
| return TRUE; |
| } |
| return FALSE; |
| |
| |
| |
| *** 26,32 **** |
| 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_nodetype __ARGS((char_u *name)); |
| void mch_early_init __ARGS((void)); |
| void mch_exit __ARGS((int r)); |
| --- 26,32 ---- |
| 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_nodetype __ARGS((char_u *name)); |
| void mch_early_init __ARGS((void)); |
| void mch_exit __ARGS((int r)); |
| |
| |
| |
| *** 38,44 **** |
| 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_nodetype __ARGS((char_u *name)); |
| int mch_dirname __ARGS((char_u *buf, int len)); |
| int mch_remove __ARGS((char_u *name)); |
| --- 38,44 ---- |
| 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_nodetype __ARGS((char_u *name)); |
| int mch_dirname __ARGS((char_u *buf, int len)); |
| int mch_remove __ARGS((char_u *name)); |
| |
| |
| |
| *** 42,48 **** |
| 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_nodetype __ARGS((char_u *name)); |
| void mch_early_init __ARGS((void)); |
| void mch_free_mem __ARGS((void)); |
| --- 42,48 ---- |
| 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_nodetype __ARGS((char_u *name)); |
| void mch_early_init __ARGS((void)); |
| void mch_free_mem __ARGS((void)); |
| |
| |
| |
| *** 26,32 **** |
| 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_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)); |
| --- 26,32 ---- |
| 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_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)); |
| |
| |
| |
| *** 1561,1566 **** |
| --- 1562,1571 ---- |
| 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* |
| |
| *** 1761,1766 **** |
| --- 1766,1772 ---- |
| 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} |
| |
| *** 2705,2710 **** |
| --- 2711,2725 ---- |
| 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, |
| |
| |
| |
| *** 736,737 **** |
| --- 736,739 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 235, |
| /**/ |
| |
| -- |
| hundred-and-one symptoms of being an internet addict: |
| 19. All of your friends have an @ in their names. |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ an exciting new programming language -- http://www.Zimbu.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |