To: [email protected]
Subject: Patch 6.3a.023
Fcc: outbox
From: Bram Moolenaar <[email protected]>
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
------------

Patch 6.3a.023
Problem:    Completion on the command line doesn't handle backslashes
           properly.  Only the tail of matches is shown, even when not
           completing filenames.
Solution:   When turning the string into a pattern double backslashes.  Don't
           omit the path when not expanding files or directories.
Files:      src/ex_getln.c


*** ../vim-6.3a.022/src/ex_getln.c      Fri May  7 10:59:37 2004
--- src/ex_getln.c      Fri May 14 14:47:41 2004
***************
*** 93,99 ****
 static int    showmatches __ARGS((expand_T *xp, int wildmenu));
 static void   set_expand_context __ARGS((expand_T *xp));
 static int    ExpandFromContext __ARGS((expand_T *xp, char_u *, int *, char_u ***, int));
! static int    glob_in_path_prefix __ARGS((expand_T *xp));
 #ifdef FEAT_CMDL_COMPL
 static int    ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname));
 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
--- 93,99 ----
 static int    showmatches __ARGS((expand_T *xp, int wildmenu));
 static void   set_expand_context __ARGS((expand_T *xp));
 static int    ExpandFromContext __ARGS((expand_T *xp, char_u *, int *, char_u ***, int));
! static int    expand_showtail __ARGS((expand_T *xp));
 #ifdef FEAT_CMDL_COMPL
 static int    ExpandRTDir __ARGS((char_u *pat, int *num_file, char_u ***file, char *dirname));
 # if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
***************
*** 2713,2719 ****
     if (xp->xp_numfiles == -1)
     {
       set_expand_context(xp);
!       cmd_showtail = !glob_in_path_prefix(xp);
     }

     if (xp->xp_context == EXPAND_UNSUCCESSFUL)
--- 2713,2719 ----
     if (xp->xp_numfiles == -1)
     {
       set_expand_context(xp);
!       cmd_showtail = expand_showtail(xp);
     }

     if (xp->xp_context == EXPAND_UNSUCCESSFUL)
***************
*** 3226,3232 ****
       set_expand_context(xp);
       i = expand_cmdline(xp, ccline.cmdbuff, ccline.cmdpos,
                                                   &num_files, &files_found);
!       showtail = !glob_in_path_prefix(xp);
       if (i != EXPAND_OK)
           return i;

--- 3226,3232 ----
       set_expand_context(xp);
       i = expand_cmdline(xp, ccline.cmdbuff, ccline.cmdpos,
                                                   &num_files, &files_found);
!       showtail = expand_showtail(xp);
       if (i != EXPAND_OK)
           return i;

***************
*** 3399,3432 ****
     return t;
 }

!
     static int
! glob_in_path_prefix(xp)
     expand_T  *xp;
 {
     char_u    *s;
     char_u    *end;

     if (xp->xp_context != EXPAND_FILES && xp->xp_context != EXPAND_DIRECTORIES)
       return FALSE;

     end = gettail(xp->xp_pattern);
!     if (end == xp->xp_pattern)
       return FALSE;

     for (s = xp->xp_pattern; s < end; s++)
     {
!       if (*s == '\\') /* skip backslash */
!           if (*++s == 0)
!               break;
!
!       switch (*s)
!       {
!           case '*': case '?': case '[':
!               return TRUE;
!       }
     }
!     return FALSE;
 }

 /*
--- 3399,3434 ----
     return t;
 }

! /*
!  * Return TRUE if we only need to show the tail of completion matches.
!  * When not completing file names or there is a wildcard in the path FALSE is
!  * returned.
!  */
     static int
! expand_showtail(xp)
     expand_T  *xp;
 {
     char_u    *s;
     char_u    *end;

+     /* When not completing file names a "/" may mean something different. */
     if (xp->xp_context != EXPAND_FILES && xp->xp_context != EXPAND_DIRECTORIES)
       return FALSE;

     end = gettail(xp->xp_pattern);
!     if (end == xp->xp_pattern)                /* there is no path separator */
       return FALSE;

     for (s = xp->xp_pattern; s < end; s++)
     {
!       /* Skip escaped wildcards.  Only when the backslash is not a path
!        * separator, on DOS the '*' "path\*\file" must not be skipped. */
!       if (rem_backslash(s))
!           ++s;
!       else if (vim_strchr((char_u *)"*?[", *s) != NULL)
!           return FALSE;
     }
!     return TRUE;
 }

 /*
***************
*** 3434,3440 ****
  * When expanding file names: The string will be used with expand_wildcards().
  * Copy the file name into allocated memory and add a '*' at the end.
  * When expanding other names: The string will be used with regcomp().  Copy
!  * the name into allocated memory and add ".*" at the end.
  */
     char_u *
 addstar(fname, len, context)
--- 3436,3442 ----
  * When expanding file names: The string will be used with expand_wildcards().
  * Copy the file name into allocated memory and add a '*' at the end.
  * When expanding other names: The string will be used with regcomp().  Copy
!  * the name into allocated memory and prepend "^".
  */
     char_u *
 addstar(fname, len, context)
***************
*** 3474,3479 ****
--- 3476,3486 ----
               /* Buffer names are like file names.  "." should be literal */
               if (context == EXPAND_BUFFERS && fname[i] == '.')
                   new_len++;          /* "." becomes "\." */
+
+               /* Custom expansion takes care of special things, match
+                * backslashes literally (perhaps also for other types?) */
+               if (context == EXPAND_USER_DEFINED && fname[i] == '\\')
+                   new_len++;          /* '\' becomes "\\" */
           }
           retval = alloc(new_len);
           if (retval != NULL)
***************
*** 3482,3488 ****
               j = 1;
               for (i = 0; i < len; i++, j++)
               {
!                   if (fname[i] == '\\' && ++i == len) /* skip backslash */
                       break;

                   switch (fname[i])
--- 3489,3498 ----
               j = 1;
               for (i = 0; i < len; i++, j++)
               {
!                   /* Skip backslash.  But why?  At least keep it for custom
!                    * expansion. */
!                   if (context != EXPAND_USER_DEFINED
!                                           && fname[i] == '\\' && ++i == len)
                       break;

                   switch (fname[i])
***************
*** 3496,3501 ****
--- 3506,3514 ----
                       case '.':   if (context == EXPAND_BUFFERS)
                                       retval[j++] = '\\';
                                   break;
+                       case '\\':  if (context == EXPAND_USER_DEFINED)
+                                       retval[j++] = '\\';
+                                   break;
                   }
                   retval[j] = fname[i];
               }
*** ../vim-6.3a.022/src/version.c       Fri May 14 12:52:00 2004
--- src/version.c       Fri May 14 13:32:02 2004
***************
*** 643,644 ****
--- 643,646 ----
 {   /* Add new patch number below this line */
+ /**/
+     23,
 /**/

--
What the word 'politics' means: 'Poli' in Latin meaning 'many' and 'tics'
meaning 'bloodsucking creatures'.

/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\              Project leader for A-A-P -- http://www.A-A-P.org        ///
\\\  Buy at Amazon and help AIDS victims -- http://ICCF.nl/click1.html ///