Hello all, That entry in todo.txt has been the source of my itch for quite some time.
I had resorted to writing custom zsh command line completion for completing files found in my .vimrc path setting to start vim with. That means to comfortably find and edit any file in my path setting I have to drop down to the command line. With this patch that the itch is gone, at least for me. What works: expanding files found in path for simple path settings (absolute and relative) What does not work: it does not grok path_extra-specific thingy. I'm sure I have overlooked hundreds of issues while patching it hence the 'TOY PATCH' :) The patch is against the latest pull from repo.or.cz's vim repository. Patch it with -p1 from your ~/src/vim. nazri. --~--~---------~--~----~------------~-------~--~----~ You received this message from the "vim_dev" maillist. For more information, visit http://www.vim.org/maillist.php -~----------~----~----~----~------~----~------~--~---
commit a4ad40c77f5b90717e4ed4be02a13e2add7ccdb5 Author: Nazri Ramliy <[email protected]> Date: Sun Feb 1 15:36:01 2009 +0800 Expand files found in 'path' for :find and :sfind diff --git a/src/ex_docmd.c b/src/ex_docmd.c index b5d76c1..b747388 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3422,6 +3422,10 @@ set_one_cmd_context(xp, buff) */ switch (ea.cmdidx) { + case CMD_find: + case CMD_sfind: + xp->xp_context = EXPAND_FILES_IN_PATH; + break; case CMD_cd: case CMD_chdir: case CMD_lcd: diff --git a/src/ex_getln.c b/src/ex_getln.c index e324e7e..c09985b 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -4063,6 +4063,7 @@ addstar(fname, len, context) char_u *tail; if (context != EXPAND_FILES + && context != EXPAND_FILES_IN_PATH && context != EXPAND_SHELLCMD && context != EXPAND_DIRECTORIES) { @@ -4377,7 +4378,9 @@ ExpandFromContext(xp, pat, num_file, file, options) if (options & WILD_SILENT) flags |= EW_SILENT; - if (xp->xp_context == EXPAND_FILES || xp->xp_context == EXPAND_DIRECTORIES) + if (xp->xp_context == EXPAND_FILES + || xp->xp_context == EXPAND_DIRECTORIES + || xp->xp_context == EXPAND_FILES_IN_PATH) { /* * Expand file or directory names. @@ -4407,6 +4410,8 @@ ExpandFromContext(xp, pat, num_file, file, options) if (xp->xp_context == EXPAND_FILES) flags |= EW_FILE; + else if (xp->xp_context == EXPAND_FILES_IN_PATH) + flags |= (EW_FILE | EW_PATH); else flags = (flags | EW_DIR) & ~EW_FILE; ret = expand_wildcards(1, &pat, num_file, file, flags); diff --git a/src/misc1.c b/src/misc1.c index 0487290..d2aa91d 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -9205,7 +9205,65 @@ gen_expand_wildcards(num_pat, pat, num_file, file, flags) * when EW_NOTFOUND is given. */ if (mch_has_exp_wildcard(p)) - add_pat = mch_expandpath(&ga, p, flags); + { + if (flags & EW_PATH) + { + /* Expand stuff in each 'path' values */ + int dcount; + char_u **dnames; + char_u *cwd_orig; + char_u *cwd; + char_u *dir; + char_u *path_option = *curbuf->b_p_path == NUL ? + p_path : curbuf->b_p_path; + int c = 0; + + if ((cwd_orig = alloc((int)(MAXPATHL))) == NULL || + (cwd = alloc((int)(MAXPATHL))) == NULL || + (dir = alloc((int)(MAXPATHL))) == NULL) + mch_exit(0); + + if (getcwd((char *)cwd_orig, MAXPATHL) == NULL) + /* Ignore it */ ; + + for(;;) + { + STRCPY(cwd, cwd_orig); + + dir[0] = 0; + copy_option_part(&path_option, dir, MAXPATHL, " ;,"); + STRCPY(cwd, dir); + + if (!mch_isFullName(dir)) + { + char_u *joined; + joined = concat_fnames(cwd_orig, dir, TRUE); + STRNCPY(cwd, joined, MAXPATHL); + vim_free(joined); + } else { + STRCPY(cwd, dir); + } + + if (mch_chdir(cwd) == 0) + c += mch_expandpath(&ga, p, flags); + + if (path_option == NULL || *path_option == NUL) + break; + } + + add_pat = c; + if (mch_chdir(cwd_orig) != 0) + /* Ignore it */ ; + + vim_free(dir); + vim_free(cwd); + vim_free(cwd_orig); + } + else + { + add_pat = mch_expandpath(&ga, p, flags); + } + } } if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) diff --git a/src/misc2.c b/src/misc2.c index 427708c..8615aff 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -5372,6 +5372,135 @@ find_directory_in_path(ptr, len, options, rel_fname) } char_u * +find_dir_in_path_option(ptr, len, options, first, path_option, find_what, rel_fname, suffixes) + char_u *ptr; /* file name */ + int len; /* length of file name */ + int options; + int first; /* use count'th matching file name */ + char_u *path_option; /* p_path or p_cdpath */ + int find_what; /* FINDFILE_FILE, _DIR or _BOTH */ + char_u *rel_fname; /* file name we are looking relative to. */ + char_u *suffixes; /* list of suffixes, 'suffixesadd' option */ +{ + static char_u *dir; + static int did_findfile_init = FALSE; + char_u save_char; + char_u *file_name = NULL; + char_u *buf = NULL; + int rel_to_curdir; +#ifdef AMIGA + struct Process *proc = (struct Process *)FindTask(0L); + APTR save_winptr = proc->pr_WindowPtr; + + /* Avoid a requester here for a volume that doesn't exist. */ + proc->pr_WindowPtr = (APTR)-1L; +#endif + + if (first == TRUE) + { + /* copy file name into NameBuff, expanding environment variables */ + save_char = ptr[len]; + ptr[len] = NUL; + expand_env(ptr, NameBuff, MAXPATHL); + ptr[len] = save_char; + + vim_free(ff_file_to_find); + ff_file_to_find = vim_strsave(NameBuff); + if (ff_file_to_find == NULL) /* out of memory */ + { + file_name = NULL; + goto theend; + } + } + + /* + * Loop over all paths in the 'path' or 'cdpath' option. + * When "first" is set, first setup to the start of the option. + * Otherwise continue to find the next match. + */ + if (first == TRUE) + { + /* vim_findfile_free_visited can handle a possible NULL pointer */ + vim_findfile_free_visited(fdip_search_ctx); + dir = path_option; + did_findfile_init = FALSE; + } + + for (;;) + { + if (did_findfile_init) + { + file_name = vim_findfile(fdip_search_ctx); + // if (file_name != NULL) + // break; + printf("\r\nfilename=[%s]", file_name); + + did_findfile_init = FALSE; + } + else + { + char_u *r_ptr; + + if (dir == NULL || *dir == NUL) + { + /* We searched all paths of the option, now we can + * free the search context. */ + vim_findfile_cleanup(fdip_search_ctx); + fdip_search_ctx = NULL; + break; + } + + if ((buf = alloc((int)(MAXPATHL))) == NULL) + break; + + /* copy next path */ + buf[0] = 0; + copy_option_part(&dir, buf, MAXPATHL, " ,"); + +#ifdef FEAT_PATH_EXTRA + /* get the stopdir string */ + r_ptr = vim_findfile_stopdir(buf); +#else + r_ptr = NULL; +#endif + fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find, + r_ptr, 100, FALSE, find_what, + fdip_search_ctx, FALSE, rel_fname); + if (fdip_search_ctx != NULL) + did_findfile_init = TRUE; + vim_free(buf); + } + } + if (file_name == NULL && (options & FNAME_MESS)) + { + if (first == TRUE) + { + if (find_what == FINDFILE_DIR) + EMSG2(_("E344: Can't find directory \"%s\" in cdpath"), + ff_file_to_find); + else + EMSG2(_("E345: Can't find file \"%s\" in path"), + ff_file_to_find); + } + else + { + if (find_what == FINDFILE_DIR) + EMSG2(_("E346: No more directory \"%s\" found in cdpath"), + ff_file_to_find); + else + EMSG2(_("E347: No more file \"%s\" found in path"), + ff_file_to_find); + } + } + +theend: +#ifdef AMIGA + proc->pr_WindowPtr = save_winptr; +#endif + return file_name; +} + + char_u * find_file_in_path_option(ptr, len, options, first, path_option, find_what, rel_fname, suffixes) char_u *ptr; /* file name */ int len; /* length of file name */ diff --git a/src/os_msdos.c b/src/os_msdos.c index 6748e6a..8db6036 100644 --- a/src/os_msdos.c +++ b/src/os_msdos.c @@ -2037,6 +2037,7 @@ mch_has_wildcard(char_u *p) int mch_chdir(char *path) { +printf("\nhaha\n"); if (path[0] == NUL) /* just checking... */ return 0; if (path[1] == ':') /* has a drive name */ diff --git a/src/vim.h b/src/vim.h index 0a979e4..70d2cdd 100644 --- a/src/vim.h +++ b/src/vim.h @@ -708,6 +708,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); #define EXPAND_USER_DEFINED 30 #define EXPAND_USER_LIST 31 #define EXPAND_SHELLCMD 32 +#define EXPAND_FILES_IN_PATH 33 /* Values for exmode_active (0 is no exmode) */ #define EXMODE_NORMAL 1 @@ -739,6 +740,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname); #define EW_KEEPALL 0x10 /* keep all matches */ #define EW_SILENT 0x20 /* don't print "1 returned" from shell */ #define EW_EXEC 0x40 /* executable files */ +#define EW_PATH 0x80 /* search in 'path' too */ /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND * is used when executing commands and EW_SILENT for interactive expanding. */
