vim-patch:7.4.191

Problem:    Escaping a file name for shell commands can't be done without a
            function.
Solution:   Add the :S file name modifier.

https://code.google.com/p/vim/source/detail?r=40f18a1c1592c8b4047f6f2a413557f48a99c55f
This commit is contained in:
oni-link 2014-04-12 23:04:49 +02:00 committed by Thiago de Arruda
parent 644ccdafe0
commit a881273dad
8 changed files with 95 additions and 14 deletions

View File

@ -13715,7 +13715,7 @@ static void f_sha256(typval_T *argvars, typval_T *rettv)
static void f_shellescape(typval_T *argvars, typval_T *rettv) static void f_shellescape(typval_T *argvars, typval_T *rettv)
{ {
rettv->vval.v_string = vim_strsave_shellescape( rettv->vval.v_string = vim_strsave_shellescape(
get_tv_string(&argvars[0]), non_zero_arg(&argvars[1])); get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), true);
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
} }
@ -19645,6 +19645,14 @@ repeat:
} }
} }
if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S') {
p = vim_strsave_shellescape(*fnamep, false, false);
vim_free(*bufp);
*bufp = *fnamep = p;
*fnamelen = (int)STRLEN(p);
*usedlen += 2;
}
return valid; return valid;
} }

View File

@ -691,11 +691,12 @@ int csh_like_shell(void)
* This uses single quotes, except when we know we need to use double quotes * This uses single quotes, except when we know we need to use double quotes
* (MS-DOS and MS-Windows without 'shellslash' set). * (MS-DOS and MS-Windows without 'shellslash' set).
* Escape a newline, depending on the 'shell' option. * Escape a newline, depending on the 'shell' option.
* When "do_special" is TRUE also replace "!", "%", "#" and things starting * When "do_special" is true also replace "!", "%", "#" and things starting
* with "<" like "<cfile>". * with "<" like "<cfile>".
* Returns the result in allocated memory, NULL if we have run out. * When "do_newline" is false do not escape newline unless it is csh shell.
* Returns the result in allocated memory.
*/ */
char_u *vim_strsave_shellescape(char_u *string, int do_special) char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline)
{ {
unsigned length; unsigned length;
char_u *p; char_u *p;
@ -715,7 +716,8 @@ char_u *vim_strsave_shellescape(char_u *string, int do_special)
for (p = string; *p != NUL; mb_ptr_adv(p)) { for (p = string; *p != NUL; mb_ptr_adv(p)) {
if (*p == '\'') if (*p == '\'')
length += 3; /* ' => '\'' */ length += 3; /* ' => '\'' */
if (*p == '\n' || (*p == '!' && (csh_like || do_special))) { if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
++length; /* insert backslash */ ++length; /* insert backslash */
if (csh_like && do_special) if (csh_like && do_special)
++length; /* insert backslash */ ++length; /* insert backslash */
@ -742,7 +744,8 @@ char_u *vim_strsave_shellescape(char_u *string, int do_special)
++p; ++p;
continue; continue;
} }
if (*p == '\n' || (*p == '!' && (csh_like || do_special))) { if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
*d++ = '\\'; *d++ = '\\';
if (csh_like && do_special) if (csh_like && do_special)
*d++ = '\\'; *d++ = '\\';

View File

@ -31,7 +31,7 @@ char_u *vim_strsave_escaped_ext(char_u *string, char_u *esc_chars,
int cc, int cc,
int bsl); int bsl);
int csh_like_shell(void); int csh_like_shell(void);
char_u *vim_strsave_shellescape(char_u *string, int do_special); char_u *vim_strsave_shellescape(char_u *string, bool do_special, bool do_newline);
char_u *vim_strsave_up(char_u *string); char_u *vim_strsave_up(char_u *string);
char_u *vim_strnsave_up(char_u *string, int len); char_u *vim_strnsave_up(char_u *string, int len);
void vim_strup(char_u *p); void vim_strup(char_u *p);

View File

@ -4493,12 +4493,8 @@ static void nv_ident(cmdarg_T *cap)
if (cmdchar == 'K' && !kp_help) { if (cmdchar == 'K' && !kp_help) {
/* Escape the argument properly for a shell command */ /* Escape the argument properly for a shell command */
ptr = vim_strnsave(ptr, n); ptr = vim_strnsave(ptr, n);
p = vim_strsave_shellescape(ptr, TRUE); p = vim_strsave_shellescape(ptr, true, true);
vim_free(ptr); vim_free(ptr);
if (p == NULL) {
vim_free(buf);
return;
}
newbuf = (char_u *)xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1); newbuf = (char_u *)xrealloc(buf, STRLEN(buf) + STRLEN(p) + 1);
buf = newbuf; buf = newbuf;
STRCAT(buf, p); STRCAT(buf, p);

View File

@ -26,7 +26,7 @@ SCRIPTS := test1.out test2.out test3.out test4.out test5.out test6.out \
test89.out test90.out test91.out test92.out test93.out \ test89.out test90.out test91.out test92.out test93.out \
test94.out test95.out test96.out test97.out test98.out \ test94.out test95.out test96.out test97.out test98.out \
test99.out test100.out test101.out test102.out test103.out \ test99.out test100.out test101.out test102.out test103.out \
test104.out test106.out test104.out test105.out test106.out
SCRIPTS_GUI := test16.out SCRIPTS_GUI := test16.out

45
src/testdir/test105.in Normal file
View File

@ -0,0 +1,45 @@
Test filename modifiers vim: set ft=vim :
STARTTEST
:source small.vim
:%delete _
:set shell=sh
:set shellslash
:let tab="\t"
:command -nargs=1 Put :let expr=<q-args> | $put =expr.tab.strtrans(string(eval(expr)))
:let $HOME=fnamemodify('.', ':p:h:h:h')
:Put fnamemodify('.', ':p' )[-1:]
:Put fnamemodify('.', ':p:h' )[-1:]
:Put fnamemodify('test.out', ':p' )[-1:]
:Put fnamemodify('test.out', ':.' )
:Put fnamemodify('../testdir/a', ':.' )
:Put fnamemodify('test.out', ':~' )
:Put fnamemodify('../testdir/a', ':~' )
:Put fnamemodify('../testdir/a', ':t' )
:Put fnamemodify('.', ':p:t' )
:Put fnamemodify('test.out', ':p:t' )
:Put fnamemodify('test.out', ':p:e' )
:Put fnamemodify('test.out', ':p:t:e' )
:Put fnamemodify('abc.fb2.tar.gz', ':r' )
:Put fnamemodify('abc.fb2.tar.gz', ':r:r' )
:Put fnamemodify('abc.fb2.tar.gz', ':r:r:r' )
:Put substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(src/testdir/.*\)', '\1', '')
:Put fnamemodify('abc.fb2.tar.gz', ':e' )
:Put fnamemodify('abc.fb2.tar.gz', ':e:e' )
:Put fnamemodify('abc.fb2.tar.gz', ':e:e:e' )
:Put fnamemodify('abc.fb2.tar.gz', ':e:e:e:e')
:Put fnamemodify('abc.fb2.tar.gz', ':e:e:r' )
:Put fnamemodify('abc def', ':S' )
:Put fnamemodify('abc" "def', ':S' )
:Put fnamemodify('abc"%"def', ':S' )
:Put fnamemodify('abc'' ''def', ':S' )
:Put fnamemodify('abc''%''def', ':S' )
:Put fnamemodify("abc\ndef", ':S' )
:set shell=tcsh
:Put fnamemodify("abc\ndef", ':S' )
:$put ='vim: ts=8'
:1 delete _
:w! test.out
:qa!
ENDTEST

29
src/testdir/test105.ok Normal file
View File

@ -0,0 +1,29 @@
fnamemodify('.', ':p' )[-1:] '/'
fnamemodify('.', ':p:h' )[-1:] 'r'
fnamemodify('test.out', ':p' )[-1:] 't'
fnamemodify('test.out', ':.' ) 'test.out'
fnamemodify('../testdir/a', ':.' ) 'a'
fnamemodify('test.out', ':~' ) '~/src/testdir/test.out'
fnamemodify('../testdir/a', ':~' ) '~/src/testdir/a'
fnamemodify('../testdir/a', ':t' ) 'a'
fnamemodify('.', ':p:t' ) ''
fnamemodify('test.out', ':p:t' ) 'test.out'
fnamemodify('test.out', ':p:e' ) 'out'
fnamemodify('test.out', ':p:t:e' ) 'out'
fnamemodify('abc.fb2.tar.gz', ':r' ) 'abc.fb2.tar'
fnamemodify('abc.fb2.tar.gz', ':r:r' ) 'abc.fb2'
fnamemodify('abc.fb2.tar.gz', ':r:r:r' ) 'abc'
substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(src/testdir/.*\)', '\1', '') 'src/testdir/abc.fb2'
fnamemodify('abc.fb2.tar.gz', ':e' ) 'gz'
fnamemodify('abc.fb2.tar.gz', ':e:e' ) 'tar.gz'
fnamemodify('abc.fb2.tar.gz', ':e:e:e' ) 'fb2.tar.gz'
fnamemodify('abc.fb2.tar.gz', ':e:e:e:e') 'fb2.tar.gz'
fnamemodify('abc.fb2.tar.gz', ':e:e:r' ) 'tar'
fnamemodify('abc def', ':S' ) '''abc def'''
fnamemodify('abc" "def', ':S' ) '''abc" "def'''
fnamemodify('abc"%"def', ':S' ) '''abc"%"def'''
fnamemodify('abc'' ''def', ':S' ) '''abc''\'''' ''\''''def'''
fnamemodify('abc''%''def', ':S' ) '''abc''\''''%''\''''def'''
fnamemodify("abc\ndef", ':S' ) '''abc^@def'''
fnamemodify("abc\ndef", ':S' ) '''abc\^@def'''
vim: ts=8

View File

@ -216,7 +216,7 @@ static int included_patches[] = {
//194, //194,
193, 193,
192, 192,
//191, 191,
//190, //190,
//189, //189,
//188, //188,