Hello,
Attached patch fixes handling of backslashes in <f-args>
according to the Bram's table, below. Doc patch is included, too.

Pair of backslashes is translated into single backslash.
Otherwise backslash is special before whitespace, otherwise
backslash is not special (single backslash represents single
backslash except before whitespace or before another backslash).

Yakov

Bram Moolenaar wrote:
        command        new <f-args>            old <f-args>
        XX ab             ab                      ab
        XX a\b            a\b                     a\b
        XX a\ b           a b                     a b
        XX a\\b           a\b                     a\\b
        XX a\\ b          a\      b               a\ b
        XX a\\\b          a\\b                    a\\\b
        XX a\\\ b         a\ b                    a\\ b
        XX a\\\\b         a\\b                    a\\\\b
        XX a\\\\ b        a\\     b               a\\\\ b
--- src/ex_docmd.c.000	2006-09-27 20:12:10.000000000 +0300
+++ src/ex_docmd.c	2006-09-27 20:36:26.000000000 +0300
@@ -5551,6 +5551,9 @@
 	mch_memmove(cmd, cmd + 1, (gap->ga_len - i) * sizeof(ucmd_T));
 }
 
+/*
+ * split and quote args for <f-args>
+ */
     static char_u *
 uc_split_args(arg, lenp)
     char_u *arg;
@@ -5567,7 +5570,12 @@
 
     while (*p)
     {
-	if (p[0] == '\\' && vim_iswhite(p[1]))
+	if (p[0] == '\\' && p[1] == '\\')
+	{
+	    len += 2;
+	    p += 2;
+	}
+	else if (p[0] == '\\' && vim_iswhite(p[1]))
 	{
 	    len += 1;
 	    p += 2;
@@ -5603,7 +5611,13 @@
     *q++ = '"';
     while (*p)
     {
-	if (p[0] == '\\' && vim_iswhite(p[1]))
+	if (p[0] == '\\' && p[1] == '\\')
+	{
+	    *q++ = '\\';
+	    *q++ = '\\';
+	    p += 2;
+	}
+	else if (p[0] == '\\' && vim_iswhite(p[1]))
 	{
 	    *q++ = p[1];
 	    p += 2;
@@ -5735,7 +5749,7 @@
 	    }
 
 	    break;
-	case 2: /* Quote and split */
+	case 2: /* Quote and split (<f-args>) */
 	    /* This is hard, so only do it once, and cache the result */
 	    if (*split_buf == NULL)
 		*split_buf = uc_split_args(eap->arg, split_len);
--- runtime/doc/map.txt.000	2006-09-27 20:06:17.000000000 +0300
+++ runtime/doc/map.txt	2006-09-27 20:30:38.000000000 +0300
@@ -1303,12 +1303,16 @@
 <q-args>) then the value is quoted in such a way as to make it a valid value
 for use in an expression.  This uses the argument as one single value.
 When there is no argument <q-args> is an empty string.
-
+                                                        *<f-args>*
 To allow commands to pass their arguments on to a user-defined function, there
 is a special form <f-args> ("function args").  This splits the command
 arguments at spaces and Tabs, quotes each argument individually, and the
 <f-args> sequence is replaced by the comma-separated list of quoted arguments.
 See the Mycmd example below.  If no arguments are given <f-args> is removed.
+To embed whitespace into argument of <f-args>, prepend backslash(\) before
+the whitespace. <f-args> replaces every pair of backslashes (\\) to one
+backslash.  Single backslash represent single backslash (except before
+other backslash and before whitespace).
 
 Examples >
 
--- runtime/doc/todo.txt.000	2006-09-27 20:06:03.000000000 +0300
+++ runtime/doc/todo.txt	2006-09-27 20:06:39.000000000 +0300
@@ -650,9 +650,6 @@
 7   "[p" doesn't work in Visual mode. (David Brown)
 7   The Cygwin and MingW makefiles define "PC", but it's not used anywhere.
     Remove? (Dan Sharp)
-9   The argument <f-args> of a user command doesn't handle backslashes
-    properly.  "Cmd \ e" is one argument, "Cmd \\ e" still is one argument.
-    "Cmd \  e" is two arguments, first one ending in space. (Kontra Gergely)
 9   User commands use the context of the script they were defined in.  This
     causes a "s:var" argument to unexpectedly use a variable in the defining
     script, not the calling script.  Add an argument to ":command":

Reply via email to