Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vim] Replace s:fzf_shellescape and s:shellesc with fzf#shellescape #916

Merged
merged 10 commits into from
May 29, 2017
44 changes: 24 additions & 20 deletions plugin/fzf.vim
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,28 @@ if s:is_win
let &shellslash = shellslash
endtry
endfunction

function! s:fzf_shellescape(path)
return substitute(s:fzf_call('shellescape', a:path), '[^\\]\zs\\"$', '\\\\"', '')
endfunction
else
function! s:fzf_call(fn, ...)
return call(a:fn, a:000)
endfunction

function! s:fzf_shellescape(path)
return shellescape(a:path)
endfunction
endif

function! s:shellesc_cmd(arg)
let escaped = substitute(a:arg, '[&|<>()@^]', '^&', 'g')
let escaped = substitute(escaped, '%', '%%', 'g')
let escaped = substitute(escaped, '"', '\\^&', 'g')
let escaped = substitute(escaped, '\\\+\(\\^\)', '\\\\\1', 'g')
return '^"'.substitute(escaped, '[^\\]\zs\\$', '\\\\', '').'^"'
endfunction

function! fzf#shellescape(arg, ...)
let shell = get(a:000, 0, &shell)
if shell =~# 'cmd.exe$'
return s:shellesc_cmd(a:arg)
endif
return s:fzf_call('shellescape', a:arg)
endfunction

function! s:fzf_getcwd()
return s:fzf_call('getcwd')
endfunction
Expand Down Expand Up @@ -108,7 +116,7 @@ function! s:fzf_exec()
throw 'fzf executable not found'
endif
endif
return s:is_win ? s:exec : s:shellesc(s:exec)
return s:is_win ? s:exec : fzf#shellescape(s:exec)
endfunction

function! s:tmux_enabled()
Expand All @@ -128,10 +136,6 @@ function! s:tmux_enabled()
return s:tmux
endfunction

function! s:shellesc(arg)
return '"'.substitute(a:arg, '"', '\\"', 'g').'"'
endfunction

function! s:escape(path)
let escaped_chars = '$%#''"'

Expand Down Expand Up @@ -250,7 +254,7 @@ endfunction

function! s:evaluate_opts(options)
return type(a:options) == type([]) ?
\ join(map(copy(a:options), 's:fzf_shellescape(v:val)')) : a:options
\ join(map(copy(a:options), 'fzf#shellescape(v:val)')) : a:options
endfunction

" [name string,] [opts dict,] [fullscreen boolean]
Expand Down Expand Up @@ -297,7 +301,7 @@ function! fzf#wrap(...)
if !isdirectory(dir)
call mkdir(dir, 'p')
endif
let history = s:is_win ? s:fzf_shellescape(dir.'\'.name) : s:escape(dir.'/'.name)
let history = s:is_win ? fzf#shellescape(dir.'\'.name) : s:escape(dir.'/'.name)
let opts.options = join(['--history', history, opts.options])
endif

Expand Down Expand Up @@ -349,7 +353,7 @@ try
if !has_key(dict, 'source') && !empty($FZF_DEFAULT_COMMAND)
let temps.source = s:fzf_tempname().(s:is_win ? '.bat' : '')
call writefile((s:is_win ? ['@echo off'] : []) + split($FZF_DEFAULT_COMMAND, "\n"), temps.source)
let dict.source = (empty($SHELL) ? &shell : $SHELL) . (s:is_win ? ' /c ' : ' ') . s:shellesc(temps.source)
let dict.source = (empty($SHELL) ? &shell : $SHELL) . (s:is_win ? ' /c ' : ' ') . fzf#shellescape(temps.source)
endif

if has_key(dict, 'source')
Expand All @@ -360,7 +364,7 @@ try
elseif type == 3
let temps.input = s:fzf_tempname()
call writefile(source, temps.input)
let prefix = (s:is_win ? 'type ' : 'cat ').s:shellesc(temps.input).'|'
let prefix = (s:is_win ? 'type ' : 'cat ').fzf#shellescape(temps.input).'|'
else
throw 'Invalid source type'
endif
Expand Down Expand Up @@ -424,7 +428,7 @@ function! s:fzf_tmux(dict)
endif
endfor
return printf('LINES=%d COLUMNS=%d %s %s %s --',
\ &lines, &columns, s:shellesc(s:fzf_tmux), size, (has_key(a:dict, 'source') ? '' : '-'))
\ &lines, &columns, fzf#shellescape(s:fzf_tmux), size, (has_key(a:dict, 'source') ? '' : '-'))
endfunction

function! s:splittable(dict)
Expand Down Expand Up @@ -493,7 +497,7 @@ function! s:execute(dict, command, use_height, temps) abort
if has('unix') && !a:use_height
silent! !clear 2> /dev/null
endif
let escaped = escape(substitute(a:command, '\n', '\\n', 'g'), '%#!')
let escaped = (a:use_height || s:is_win) ? a:command : escape(substitute(a:command, '\n', '\\n', 'g'), '%#!')
if has('gui_running')
let Launcher = get(a:dict, 'launcher', get(g:, 'Fzf_launcher', get(g:, 'fzf_launcher', s:launcher)))
let fmt = type(Launcher) == 2 ? call(Launcher, []) : Launcher
Expand All @@ -502,7 +506,7 @@ function! s:execute(dict, command, use_height, temps) abort
endif
let command = printf(fmt, escaped)
else
let command = a:use_height ? a:command : escaped
let command = escaped
endif
if s:is_win
let batchfile = s:fzf_tempname().'.bat'
Expand Down
18 changes: 18 additions & 0 deletions test/fzf.vader
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,24 @@ Execute (fzf#wrap):
let opts = fzf#wrap({})
Assert opts.options =~ '^--color=fg:'

Execute (fzf#shellescape with sh):
AssertEqual '''''', fzf#shellescape('', 'sh')
AssertEqual '''""''', fzf#shellescape('""', 'sh')
AssertEqual '''foobar>''', fzf#shellescape('foobar>', 'sh')
AssertEqual '''\"''', fzf#shellescape('\"', 'sh')
AssertEqual '''echo ''\''''a''\'''' && echo ''\''''b''\''''''', fzf#shellescape('echo ''a'' && echo ''b''', 'sh')

Execute (fzf#shellescape with cmd.exe):
AssertEqual '^"^"', fzf#shellescape('', 'cmd.exe')
AssertEqual '^"\^"\^"^"', fzf#shellescape('""', 'cmd.exe')
AssertEqual '^"foobar^>^"', fzf#shellescape('foobar>', 'cmd.exe')
AssertEqual '^"\\\^"\\^"', fzf#shellescape('\\\\\\\\"\', 'cmd.exe')
AssertEqual '^"echo ''a'' ^&^& echo ''b''^"', fzf#shellescape('echo ''a'' && echo ''b''', 'cmd.exe')

AssertEqual '^"C:\Program Files ^(x86^)\\^"', fzf#shellescape('C:\Program Files (x86)\', 'cmd.exe')
AssertEqual '^"C:/Program Files ^(x86^)/^"', fzf#shellescape('C:/Program Files (x86)/', 'cmd.exe')
" AssertEqual '^"%%USERPROFILE%%^", fzf#shellescape('%USERPROFILE%', 'cmd.exe')

Execute (Cleanup):
unlet g:dir
Restore