summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autoload/ale.vim22
-rw-r--r--test/test_windows_escaping.vader42
2 files changed, 59 insertions, 5 deletions
diff --git a/autoload/ale.vim b/autoload/ale.vim
index d8db3bfd..066bfa07 100644
--- a/autoload/ale.vim
+++ b/autoload/ale.vim
@@ -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
diff --git a/test/test_windows_escaping.vader b/test/test_windows_escaping.vader
new file mode 100644
index 00000000..22cad888
--- /dev/null
+++ b/test/test_windows_escaping.vader
@@ -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% ""')