A couple of problems were detected when the Unix shell is used to expand file names containing characters such as a single quote. This applies to completion on the command line and glob().
I made a patch that defines a function to echo each file name separately. Inspired by a patch that Dasn made, but staying on the safe side. The patch for ex_docmd.c changes detecting the end of the file name when doing command line completion. This specifically fixes a file name containing "&". Please try it out and let me know if there are any new problems. *** ../vim-7.1.197/src/os_unix.c Thu Jan 3 18:55:21 2008 --- src/os_unix.c Fri Jan 4 12:59:41 2008 *************** *** 4946,4951 **** --- 4946,4954 ---- char_u *p; int dir; #ifdef __EMX__ + /* + * This is the OS/2 implementation. + */ # define EXPL_ALLOC_INC 16 char_u **expl_files; size_t files_alloced, files_free; *************** *** 5056,5075 **** return OK; #else /* __EMX__ */ ! int j; char_u *tempname; char_u *command; FILE *fd; char_u *buffer; ! #define STYLE_ECHO 0 /* use "echo" to expand */ ! #define STYLE_GLOB 1 /* use "glob" to expand, for csh */ ! #define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */ ! #define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */ int shell_style = STYLE_ECHO; int check_spaces; static int did_find_nul = FALSE; int ampersent = FALSE; *num_file = 0; /* default: no files found */ *file = NULL; --- 5059,5084 ---- return OK; #else /* __EMX__ */ ! /* ! * This is the non-OS/2 implementation (really Unix). ! */ int j; char_u *tempname; char_u *command; FILE *fd; char_u *buffer; ! #define STYLE_ECHO 0 /* use "echo", the default */ ! #define STYLE_GLOB 1 /* use "glob", for csh */ ! #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */ ! #define STYLE_PRINT 3 /* use "print -N", for zsh */ ! #define STYLE_BT 4 /* `cmd` expansion, execute the pattern ! * directly */ int shell_style = STYLE_ECHO; int check_spaces; static int did_find_nul = FALSE; int ampersent = FALSE; + /* vimglob() function to define for Posix shell */ + static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo -n \"$1\"; echo; shift; done }; vimglob >"; *num_file = 0; /* default: no files found */ *file = NULL; *************** *** 5107,5115 **** /* * Let the shell expand the patterns and write the result into the temp ! * file. if expanding `cmd` execute it directly. ! * If we use csh, glob will work better than echo. ! * If we use zsh, print -N will work better than glob. */ if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 --- 5116,5132 ---- /* * Let the shell expand the patterns and write the result into the temp ! * file. ! * STYLE_BT: NL separated ! * If expanding `cmd` execute it directly. ! * STYLE_GLOB: NUL separated ! * If we use *csh, "glob" will work better than "echo". ! * STYLE_PRINT: NL or NUL separated ! * If we use *zsh, "print -N" will work better than "glob". ! * STYLE_VIMGLOB: NL separated ! * If we use *sh*, we define "vimglob()". ! * STYLE_ECHO: space separated. ! * A shell we don't know, stay safe and use "echo". */ if (num_pat == 1 && *pat[0] == '`' && (len = STRLEN(pat[0])) > 2 *************** *** 5122,5130 **** else if (STRCMP(p_sh + len - 3, "zsh") == 0) shell_style = STYLE_PRINT; } ! /* "unset nonomatch; print -N >" plus two is 29 */ len = STRLEN(tempname) + 29; for (i = 0; i < num_pat; ++i) { /* Count the length of the patterns in the same way as they are put in --- 5139,5154 ---- else if (STRCMP(p_sh + len - 3, "zsh") == 0) shell_style = STYLE_PRINT; } + else if (strstr((char *)p_sh, "sh") != NULL) + shell_style = STYLE_VIMGLOB; ! /* Compute the length of the command. We need 2 extra bytes: for the ! * optional '&' and for the NUL. ! * Worst case: "unset nonomatch; print -N >" plus two is 29 */ len = STRLEN(tempname) + 29; + if (shell_style == STYLE_VIMGLOB) + len += STRLEN(sh_vimglob_func); + for (i = 0; i < num_pat; ++i) { /* Count the length of the patterns in the same way as they are put in *************** *** 5183,5192 **** --- 5207,5220 ---- STRCAT(command, "glob >"); else if (shell_style == STYLE_PRINT) STRCAT(command, "print -N >"); + else if (shell_style == STYLE_VIMGLOB) + STRCAT(command, sh_vimglob_func); else STRCAT(command, "echo >"); } + STRCAT(command, tempname); + if (shell_style != STYLE_BT) for (i = 0; i < num_pat; ++i) { *************** *** 5232,5239 **** if (flags & EW_SILENT) show_shell_mess = FALSE; if (ampersent) ! STRCAT(command, "&"); /* put the '&' back after the ! redirection */ /* * Using zsh -G: If a pattern has no matches, it is just deleted from --- 5260,5266 ---- if (flags & EW_SILENT) show_shell_mess = FALSE; if (ampersent) ! STRCAT(command, "&"); /* put the '&' after the redirection */ /* * Using zsh -G: If a pattern has no matches, it is just deleted from *************** *** 5265,5271 **** show_shell_mess = TRUE; vim_free(command); ! if (i) /* mch_call_shell() failed */ { mch_remove(tempname); vim_free(tempname); --- 5292,5298 ---- show_shell_mess = TRUE; vim_free(command); ! if (i != 0) /* mch_call_shell() failed */ { mch_remove(tempname); vim_free(tempname); *************** *** 5336,5342 **** } vim_free(tempname); ! #if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */ p = buffer; for (i = 0; i < len; ++i) --- 5363,5369 ---- } vim_free(tempname); ! # if defined(__CYGWIN__) || defined(__CYGWIN32__) /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */ p = buffer; for (i = 0; i < len; ++i) *************** *** 5359,5365 **** } } /* file names are separated with NL */ ! else if (shell_style == STYLE_BT) { buffer[len] = NUL; /* make sure the buffer ends in NUL */ p = buffer; --- 5386,5392 ---- } } /* file names are separated with NL */ ! else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { buffer[len] = NUL; /* make sure the buffer ends in NUL */ p = buffer; *************** *** 5438,5444 **** { (*file)[i] = p; /* Space or NL separates */ ! if (shell_style == STYLE_ECHO || shell_style == STYLE_BT) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) --- 5465,5472 ---- { (*file)[i] = p; /* Space or NL separates */ ! if (shell_style == STYLE_ECHO || shell_style == STYLE_BT ! || shell_style == STYLE_VIMGLOB) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) *** ../vim-7.1.197/src/ex_docmd.c Wed Jan 2 21:07:32 2008 --- src/ex_docmd.c Thu Jan 3 22:04:21 2008 *************** *** 3338,3349 **** } in_quote = !in_quote; } #ifdef SPACE_IN_FILENAME ! else if (!vim_isfilec_or_wc(c) ! && (!(ea.argt & NOSPC) || usefilter)) ! #else ! else if (!vim_isfilec_or_wc(c)) #endif { while (*p != NUL) { --- 3338,3350 ---- } in_quote = !in_quote; } + /* An argument can contain just about everything, except + * characters that end the command and white space. */ + else if (c == '|' || c == '\n' || c == '"' || (vim_iswhite(c) #ifdef SPACE_IN_FILENAME ! && (!(ea.argt & NOSPC) || usefilter) #endif + )) { while (*p != NUL) { -- CUSTOMER: You're not fooling anyone y'know. Look, isn't there something you can do? DEAD PERSON: I feel happy... I feel happy. [whop] CUSTOMER: Ah, thanks very much. MORTICIAN: Not at all. See you on Thursday. CUSTOMER: Right. The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ download, build and distribute -- http://www.A-A-P.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org /// --~--~---------~--~----~------------~-------~--~----~ You received this message from the "vim_dev" maillist. For more information, visit http://www.vim.org/maillist.php -~----------~----~----~----~------~----~------~--~---