Hello all,
This is the follow up to my implementation[1] of command line
completion for :find and :sfind.
Attached is the improved patch, now against r1341 from svn.
It now handles paths with * and **, e.g: set path=~/src/vim/*,/usr/include/**
It partially handles the path-extra combinations, i.e., it works with
the first method (downward search) and second method (upward search)
but not with the third method (combined up/downward search) as
mentioned in :help file-searching.
The only caveat (that I'm aware of):
If there are more than one files with the same name in the paths, the
:find command will always go to the first one in the wildmenu list,
even if we selected the second or third. The solution for this is to
manually prepend the number at the beginning of the :find command to
get to the corresponding match, e.g.: :3find file.txt will find and
open the third match of the file file.txt found in the paths.
When I got the time (and brain power :) later on I'll try to find out
how to automagically prepend the appropriate number according to the
selected entry in the list of possible completion result (going
forward on the list with the same file name increases the count, going
backward decreases the count, and reset the count when the
previous/next file name is different from the current one).
nazri.
[1] http://article.gmane.org/gmane.editors.vim.devel/22520
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
Index: src/ex_docmd.c
===================================================================
--- src/ex_docmd.c (revision 1341)
+++ src/ex_docmd.c (working copy)
@@ -3422,6 +3422,10 @@
*/
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:
Index: src/ex_getln.c
===================================================================
--- src/ex_getln.c (revision 1341)
+++ src/ex_getln.c (working copy)
@@ -4063,6 +4063,7 @@
char_u *tail;
if (context != EXPAND_FILES
+ && context != EXPAND_FILES_IN_PATH
&& context != EXPAND_SHELLCMD
&& context != EXPAND_DIRECTORIES)
{
@@ -4377,7 +4378,9 @@
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 @@
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);
Index: src/misc1.c
===================================================================
--- src/misc1.c (revision 1341)
+++ src/misc1.c (working copy)
@@ -1740,7 +1740,7 @@
col += 1;
/*
- * Add column offset for 'number' and 'foldcolumn'.
+ * Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
*/
width = W_WIDTH(wp) - win_col_off(wp);
if (width <= 0)
@@ -1801,7 +1801,7 @@
col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1;
/*
- * Add column offset for 'number', 'foldcolumn', etc.
+ * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
*/
width = W_WIDTH(wp) - win_col_off(wp);
if (width <= 0)
@@ -9038,6 +9038,7 @@
&& vim_regexec(®match, (char_u *)dp->d_name, (colnr_T)0))
{
STRCPY(s, dp->d_name);
+ fflush(stdout);
len = STRLEN(buf);
if (starstar && stardepth < 100)
@@ -9205,7 +9206,97 @@
* when EW_NOTFOUND is given.
*/
if (mch_has_exp_wildcard(p))
- add_pat = mch_expandpath(&ga, p, flags);
+ {
+ if ( ! (flags & EW_PATH) )
+ {
+ add_pat = mch_expandpath(&ga, p, flags);
+ }
+ else
+ {
+ /*
+ * Expand stuff in each expandable 'path' values.
+ *
+ * For each expandable 'path' values we get the list of all
+ * directories and expand the file names in each the
+ * directories.
+ */
+ int c = 0;
+ char_u *cwd;
+ char_u *cwd_orig;
+ char_u *dir;
+ char_u *path_option = *curbuf->b_p_path == NUL ?
+ p_path : curbuf->b_p_path;
+
+ if ((cwd_orig = alloc((int)(MAXPATHL))) == NULL ||
+ (cwd = alloc((int)(MAXPATHL))) == NULL ||
+ (dir = alloc((int)(MAXPATHL))) == NULL)
+ return FAIL;
+
+ if (getcwd((char *)cwd_orig, MAXPATHL) == NULL)
+ /* Ignore it */ ;
+
+ for(;;)
+ {
+ /*
+ * Go through each path in 'path' option.
+ */
+ int dir_count;
+ garray_T ga_dirs;
+
+ STRCPY(cwd, cwd_orig);
+
+ dir[0] = 0;
+ copy_option_part(&path_option, dir, MAXPATHL, " ;,");
+
+ if (mch_isFullName(dir))
+ {
+ STRCPY(cwd, dir);
+ }
+ else
+ {
+ char_u *fullpath;
+ fullpath = concat_fnames(cwd_orig, dir, TRUE);
+ if (fullpath == NULL)
+ return FAIL; // Is it better to give emsg instead?
+ STRNCPY(cwd, fullpath, MAXPATHL);
+ vim_free(fullpath);
+ }
+
+ ga_init2(&ga_dirs, (int)sizeof(char_u *), 30);
+ dir_count = mch_expandpath(&ga_dirs, cwd, EW_DIR|EW_SILENT);
+
+ if (dir_count == 0)
+ {
+ if (mch_chdir(cwd) == 0)
+ c += mch_expandpath(&ga, p, flags);
+ }
+ else
+ {
+ /*
+ * Add files from each expanded path.
+ */
+ int i;
+ char_u **file;
+ file = (ga_dirs.ga_data != NULL) ? (char_u **)ga_dirs.ga_data : (char_u **)"";
+ for (i = 0; i < dir_count ; i++)
+ if (mch_chdir(file[i]) == 0)
+ c += mch_expandpath(&ga, p, flags);
+ }
+ ga_clear(&ga_dirs);
+
+ 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);
+ }
+ }
}
if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND)))
Index: src/vim.h
===================================================================
--- src/vim.h (revision 1341)
+++ src/vim.h (working copy)
@@ -708,6 +708,7 @@
#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 @@
#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. */