Fix #549 - escape strings more appropriately for use with cmd /c

This commit is contained in:
w0rp 2017-05-26 00:06:16 +01:00
parent fb07971290
commit c89587785b
2 changed files with 59 additions and 5 deletions

View file

@ -135,14 +135,26 @@ function! ale#Set(variable_name, default) abort
return l:value
endfunction
function! s:EscapePercents(str) abort
return substitute(a:str, '%', '%%', 'g')
endfunction
" Escape a string suitably for each platform.
" shellescape does not work on Windows.
function! ale#Escape(str) abort
if fnamemodify(&shell, ':t') ==? 'cmd.exe'
" FIXME: Fix shell escaping for Windows.
return fnameescape(a:str)
else
" An extra space is used here to disable the custom-checks.
return shellescape (a:str)
if a:str =~# '\v^[a-zA-Z0-9-_\\/:%]+$'
return s:EscapePercents(a:str)
endif
if a:str =~# ' '
return '"'
\ . substitute(s:EscapePercents(a:str), '"', '""', 'g')
\ . '"'
endif
return s:EscapePercents(substitute(a:str, '\v([&|<>^])', '^\1', 'g'))
endif
return shellescape (a:str)
endfunction

View file

@ -0,0 +1,42 @@
Before:
Save &shell
let &shell = 'cmd.exe'
After:
Restore
Execute(ale#Escape for cmd.exe should allow not escape paths without special characters):
AssertEqual 'C:', ale#Escape('C:')
AssertEqual 'C:\', ale#Escape('C:\')
AssertEqual 'python', ale#Escape('python')
AssertEqual 'C:\foo\bar', ale#Escape('C:\foo\bar')
AssertEqual '/bar/baz', ale#Escape('/bar/baz')
AssertEqual 'nul', ale#Escape('nul')
AssertEqual '''foo''', ale#Escape('''foo''')
Execute(ale#Escape for cmd.exe should escape Windows paths with spaces appropriately):
AssertEqual '"C:\foo bar\baz"', ale#Escape('C:\foo bar\baz')
AssertEqual '"^foo bar^"', ale#Escape('^foo bar^')
AssertEqual '"&foo bar&"', ale#Escape('&foo bar&')
AssertEqual '"|foo bar|"', ale#Escape('|foo bar|')
AssertEqual '"<foo bar<"', ale#Escape('<foo bar<')
AssertEqual '">foo bar>"', ale#Escape('>foo bar>')
AssertEqual '"^foo bar^"', ale#Escape('^foo bar^')
AssertEqual '"''foo'' ''bar''"', ale#Escape('''foo'' ''bar''')
Execute(ale#Escape for cmd.exe should use caret escapes on special characters):
AssertEqual '^^foo^^', ale#Escape('^foo^')
AssertEqual '^&foo^&', ale#Escape('&foo&')
AssertEqual '^|foo^|', ale#Escape('|foo|')
AssertEqual '^<foo^<', ale#Escape('<foo<')
AssertEqual '^>foo^>', ale#Escape('>foo>')
AssertEqual '^^foo^^', ale#Escape('^foo^')
AssertEqual '''foo''^^''bar''', ale#Escape('''foo''^''bar''')
Execute(ale#Escape for cmd.exe should escape percent characters):
AssertEqual '%%foo%%', ale#Escape('%foo%')
AssertEqual 'C:\foo%%\bar\baz%%', ale#Escape('C:\foo%\bar\baz%')
AssertEqual '"C:\foo bar%%\baz%%"', ale#Escape('C:\foo bar%\baz%')
AssertEqual '^^%%foo%%', ale#Escape('^%foo%')
AssertEqual '"^%%foo%% %%bar%%"', ale#Escape('^%foo% %bar%')
AssertEqual '"^%%foo%% %%bar%% """""', ale#Escape('^%foo% %bar% ""')