diff --git a/ale_linters/asm/gcc.vim b/ale_linters/asm/gcc.vim index 1ff348d..39b1f7c 100644 --- a/ale_linters/asm/gcc.vim +++ b/ale_linters/asm/gcc.vim @@ -5,7 +5,7 @@ let g:ale_asm_gcc_options = get(g:, 'ale_asm_gcc_options', '-Wall') function! ale_linters#asm#gcc#GetCommand(buffer) abort return 'gcc -x assembler -fsyntax-only ' - \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -' endfunction diff --git a/ale_linters/c/clang.vim b/ale_linters/c/clang.vim index 8a5c84c..ae96ba4 100644 --- a/ale_linters/c/clang.vim +++ b/ale_linters/c/clang.vim @@ -13,7 +13,7 @@ function! ale_linters#c#clang#GetCommand(buffer) abort " -iquote with the directory the file is in makes #include work for " headers in the same directory. return 'clang -S -x c -fsyntax-only ' - \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . ale#Var(a:buffer, 'c_clang_options') . ' -' endfunction diff --git a/ale_linters/c/gcc.vim b/ale_linters/c/gcc.vim index b783a7d..79c6eb2 100644 --- a/ale_linters/c/gcc.vim +++ b/ale_linters/c/gcc.vim @@ -13,7 +13,7 @@ function! ale_linters#c#gcc#GetCommand(buffer) abort " -iquote with the directory the file is in makes #include work for " headers in the same directory. return 'gcc -S -x c -fsyntax-only ' - \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . ale#Var(a:buffer, 'c_gcc_options') . ' -' endfunction diff --git a/ale_linters/cpp/clang.vim b/ale_linters/cpp/clang.vim index bd4d26e..430903f 100644 --- a/ale_linters/cpp/clang.vim +++ b/ale_linters/cpp/clang.vim @@ -10,7 +10,7 @@ function! ale_linters#cpp#clang#GetCommand(buffer) abort " -iquote with the directory the file is in makes #include work for " headers in the same directory. return 'clang++ -S -x c++ -fsyntax-only ' - \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . ale#Var(a:buffer, 'cpp_clang_options') . ' -' endfunction diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim index f538d14..f98b085 100644 --- a/ale_linters/cpp/clangtidy.vim +++ b/ale_linters/cpp/clangtidy.vim @@ -11,7 +11,7 @@ let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '') function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks') let l:check_option = !empty(l:check_list) - \ ? '-checks=' . shellescape(join(l:check_list, ',')) . ' ' + \ ? '-checks=' . ale#Escape(join(l:check_list, ',')) . ' ' \ : '' let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options') let l:extra_options = !empty(l:user_options) diff --git a/ale_linters/cpp/gcc.vim b/ale_linters/cpp/gcc.vim index 981caec..e85f189 100644 --- a/ale_linters/cpp/gcc.vim +++ b/ale_linters/cpp/gcc.vim @@ -20,7 +20,7 @@ function! ale_linters#cpp#gcc#GetCommand(buffer) abort " -iquote with the directory the file is in makes #include work for " headers in the same directory. return 'gcc -S -x c++ -fsyntax-only ' - \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . ale#Var(a:buffer, 'cpp_gcc_options') . ' -' endfunction diff --git a/ale_linters/crystal/crystal.vim b/ale_linters/crystal/crystal.vim index 8059e77..8f38a61 100644 --- a/ale_linters/crystal/crystal.vim +++ b/ale_linters/crystal/crystal.vim @@ -25,7 +25,7 @@ endfunction function! ale_linters#crystal#crystal#GetCommand(buffer) abort let l:crystal_cmd = 'crystal build -f json --no-codegen -o ' - let l:crystal_cmd .= shellescape(g:ale#util#nul_file) + let l:crystal_cmd .= ale#Escape(g:ale#util#nul_file) let l:crystal_cmd .= ' %s' return l:crystal_cmd diff --git a/ale_linters/css/csslint.vim b/ale_linters/css/csslint.vim index 83698f5..98b7fdd 100644 --- a/ale_linters/css/csslint.vim +++ b/ale_linters/css/csslint.vim @@ -4,7 +4,7 @@ function! ale_linters#css#csslint#GetCommand(buffer) abort let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc') let l:config_option = !empty(l:csslintrc) - \ ? '--config=' . shellescape(l:csslintrc) + \ ? '--config=' . ale#Escape(l:csslintrc) \ : '' return 'csslint --format=compact ' . l:config_option . ' %t' diff --git a/ale_linters/d/dmd.vim b/ale_linters/d/dmd.vim index 7068681..bd3f9d5 100644 --- a/ale_linters/d/dmd.vim +++ b/ale_linters/d/dmd.vim @@ -31,7 +31,7 @@ function! ale_linters#d#dmd#DUBCommand(buffer) abort " To support older dub versions, we just change the directory to " the directory where we found the dub config, and then run `dub describe` " from that directory. - return 'cd ' . shellescape(fnamemodify(l:dub_file, ':h')) + return 'cd ' . ale#Escape(fnamemodify(l:dub_file, ':h')) \ . ' && dub describe --import-paths' endfunction @@ -42,7 +42,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort for l:line in a:dub_output if !empty(l:line) " The arguments must be '-Ifilename', not '-I filename' - call add(l:import_list, '-I' . shellescape(l:line)) + call add(l:import_list, '-I' . ale#Escape(l:line)) endif endfor diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim index 75a124a..08bc24b 100644 --- a/ale_linters/elm/make.vim +++ b/ale_linters/elm/make.vim @@ -43,14 +43,14 @@ function! ale_linters#elm#make#GetCommand(buffer) abort let l:dir_set_cmd = '' else let l:root_dir = fnamemodify(l:elm_package, ':p:h') - let l:dir_set_cmd = 'cd ' . shellescape(l:root_dir) . ' && ' + let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && ' endif " The elm-make compiler, at the time of this writing, uses '/dev/null' as " a sort of flag to tell the compiler not to generate an output file, " which is why this is hard coded here. " Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs - let l:elm_cmd = 'elm-make --report=json --output='.shellescape('/dev/null') + let l:elm_cmd = 'elm-make --report=json --output='.ale#Escape('/dev/null') return l:dir_set_cmd . ' ' . l:elm_cmd . ' %t' endfunction diff --git a/ale_linters/erlang/erlc.vim b/ale_linters/erlang/erlc.vim index 1b0f16c..162c7ec 100644 --- a/ale_linters/erlang/erlc.vim +++ b/ale_linters/erlang/erlc.vim @@ -6,7 +6,7 @@ function! ale_linters#erlang#erlc#GetCommand(buffer) abort let l:output_file = tempname() call ale#engine#ManageFile(a:buffer, l:output_file) - return 'erlc -o ' . shellescape(l:output_file) + return 'erlc -o ' . ale#Escape(l:output_file) \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') \ . ' %t' endfunction diff --git a/ale_linters/go/gometalinter.vim b/ale_linters/go/gometalinter.vim index 9913f21..aa52401 100644 --- a/ale_linters/go/gometalinter.vim +++ b/ale_linters/go/gometalinter.vim @@ -8,7 +8,7 @@ endif function! ale_linters#go#gometalinter#GetCommand(buffer) abort return 'gometalinter ' \ . ale#Var(a:buffer, 'go_gometalinter_options') - \ . ' ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ' ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) endfunction function! ale_linters#go#gometalinter#GetMatches(lines) abort diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index 2966d06..038fa24 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -47,7 +47,7 @@ function! s:BuildClassPathOption(buffer, import_paths) abort \) return !empty(l:class_paths) - \ ? '-cp ' . shellescape(join(l:class_paths, s:classpath_sep)) + \ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep)) \ : '' endfunction @@ -64,7 +64,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java') if !empty(l:src_dir) - let l:sp_option = '-sourcepath ' . shellescape(l:src_dir) + let l:sp_option = '-sourcepath ' . ale#Escape(l:src_dir) endif " Create .class files in a temporary directory, which we will delete later. @@ -73,7 +73,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort return 'javac -Xlint' \ . ' ' . l:cp_option \ . ' ' . l:sp_option - \ . ' -d ' . shellescape(l:class_file_directory) + \ . ' -d ' . ale#Escape(l:class_file_directory) \ . ' ' . ale#Var(a:buffer, 'java_javac_options') \ . ' %t' endfunction diff --git a/ale_linters/javascript/eslint.vim b/ale_linters/javascript/eslint.vim index 7e4929b..d5e51ac 100644 --- a/ale_linters/javascript/eslint.vim +++ b/ale_linters/javascript/eslint.vim @@ -34,7 +34,7 @@ function! ale_linters#javascript#eslint#GetExecutable(buffer) abort endfunction function! ale_linters#javascript#eslint#GetCommand(buffer) abort - return shellescape(ale_linters#javascript#eslint#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#javascript#eslint#GetExecutable(a:buffer)) \ . ' ' . ale#Var(a:buffer, 'javascript_eslint_options') \ . ' -f unix --stdin --stdin-filename %s' endfunction diff --git a/ale_linters/javascript/flow.vim b/ale_linters/javascript/flow.vim index 36247cd..461dd86 100644 --- a/ale_linters/javascript/flow.vim +++ b/ale_linters/javascript/flow.vim @@ -27,7 +27,7 @@ function! ale_linters#javascript#flow#GetCommand(buffer) abort return '' endif - return shellescape(ale_linters#javascript#flow#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#javascript#flow#GetExecutable(a:buffer)) \ . ' check-contents --respect-pragma --json --from ale %s' endfunction diff --git a/ale_linters/javascript/jshint.vim b/ale_linters/javascript/jshint.vim index ec3c2c9..757d209 100644 --- a/ale_linters/javascript/jshint.vim +++ b/ale_linters/javascript/jshint.vim @@ -27,11 +27,11 @@ function! ale_linters#javascript#jshint#GetCommand(buffer) abort \ get(g:, 'ale_jshint_config_loc', '') \) - let l:command = shellescape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) + let l:command = ale#Escape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) let l:command .= ' --reporter unix --extract auto' if !empty(l:jshint_config) - let l:command .= ' --config ' . shellescape(l:jshint_config) + let l:command .= ' --config ' . ale#Escape(l:jshint_config) endif let l:command .= ' -' diff --git a/ale_linters/javascript/standard.vim b/ale_linters/javascript/standard.vim index 30ebae1..befb85f 100644 --- a/ale_linters/javascript/standard.vim +++ b/ale_linters/javascript/standard.vim @@ -23,7 +23,7 @@ function! ale_linters#javascript#standard#GetExecutable(buffer) abort endfunction function! ale_linters#javascript#standard#GetCommand(buffer) abort - return shellescape(ale_linters#javascript#standard#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#javascript#standard#GetExecutable(a:buffer)) \ . ' ' . ale#Var(a:buffer, 'javascript_standard_options') \ . ' --stdin %s' endfunction diff --git a/ale_linters/javascript/xo.vim b/ale_linters/javascript/xo.vim index b7a549f..0c6d91a 100644 --- a/ale_linters/javascript/xo.vim +++ b/ale_linters/javascript/xo.vim @@ -23,7 +23,7 @@ function! ale_linters#javascript#xo#GetExecutable(buffer) abort endfunction function! ale_linters#javascript#xo#GetCommand(buffer) abort - return shellescape(ale_linters#javascript#xo#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer)) \ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') \ . ' --reporter unix --stdin --stdin-filename %s' endfunction diff --git a/ale_linters/kotlin/kotlinc.vim b/ale_linters/kotlin/kotlinc.vim index 543c3a9..2009991 100644 --- a/ale_linters/kotlin/kotlinc.vim +++ b/ale_linters/kotlin/kotlinc.vim @@ -16,13 +16,13 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer) abort " If the config file is enabled and readable, source it if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config') if filereadable(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)) - execute 'source ' . shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)) + execute 'source ' . ale#Escape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)) endif endif " If use module and module file is readable use that and return if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file') - let l:module_filename = shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1)) + let l:module_filename = ale#Escape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1)) if filereadable(l:module_filename) let l:kotlinc_opts .= ' -module ' . l:module_filename @@ -42,7 +42,7 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer) abort if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') !=# '' let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' ' endif - let l:fname .= shellescape(expand('#' . a:buffer . ':p')) + let l:fname .= ale#Escape(expand('#' . a:buffer . ':p')) let l:command .= l:kotlinc_opts . ' ' . l:fname return l:command diff --git a/ale_linters/lua/luacheck.vim b/ale_linters/lua/luacheck.vim index 8e3e986..f375f88 100644 --- a/ale_linters/lua/luacheck.vim +++ b/ale_linters/lua/luacheck.vim @@ -12,7 +12,7 @@ function! ale_linters#lua#luacheck#GetExecutable(buffer) abort endfunction function! ale_linters#lua#luacheck#GetCommand(buffer) abort - return shellescape(ale_linters#lua#luacheck#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#lua#luacheck#GetExecutable(a:buffer)) \ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options') \ . ' --formatter plain --codes --filename %s -' endfunction diff --git a/ale_linters/nim/nimcheck.vim b/ale_linters/nim/nimcheck.vim index 9bd1972..76fbe47 100644 --- a/ale_linters/nim/nimcheck.vim +++ b/ale_linters/nim/nimcheck.vim @@ -44,7 +44,7 @@ endfunction function! ale_linters#nim#nimcheck#GetCommand(buffer) abort - let l:directory = shellescape(fnamemodify(bufname(a:buffer), ':p:h')) + let l:directory = ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) return 'nim check --path:' . l:directory \ . ' --threads:on --verbosity:0 --colors:off --listFullPaths %t' diff --git a/ale_linters/python/flake8.vim b/ale_linters/python/flake8.vim index 99e9372..1bed03b 100644 --- a/ale_linters/python/flake8.vim +++ b/ale_linters/python/flake8.vim @@ -48,7 +48,7 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort return '' endif - let l:executable = shellescape(ale_linters#python#flake8#GetExecutable(a:buffer)) + let l:executable = ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer)) let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : '' return l:executable . l:module_string . ' --version' @@ -89,7 +89,7 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort let l:options = ale#Var(a:buffer, 'python_flake8_options') - return shellescape(ale_linters#python#flake8#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#python#flake8#GetExecutable(a:buffer)) \ . (!empty(l:options) ? ' ' . l:options : '') \ . l:display_name_args . ' -' endfunction diff --git a/ale_linters/python/mypy.vim b/ale_linters/python/mypy.vim index 7275af3..3c8b181 100644 --- a/ale_linters/python/mypy.vim +++ b/ale_linters/python/mypy.vim @@ -30,7 +30,7 @@ function! ale_linters#python#mypy#GetCommand(buffer) abort let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer) return l:cd_command - \ . shellescape(l:executable) + \ . ale#Escape(l:executable) \ . ' --show-column-numbers ' \ . ale#Var(a:buffer, 'python_mypy_options') \ . ' %s' diff --git a/ale_linters/python/pylint.vim b/ale_linters/python/pylint.vim index cce2847..4275ada 100644 --- a/ale_linters/python/pylint.vim +++ b/ale_linters/python/pylint.vim @@ -26,7 +26,7 @@ function! ale_linters#python#pylint#GetExecutable(buffer) abort endfunction function! ale_linters#python#pylint#GetCommand(buffer) abort - return shellescape(ale_linters#python#pylint#GetExecutable(a:buffer)) + return ale#Escape(ale_linters#python#pylint#GetExecutable(a:buffer)) \ . ' ' . ale#Var(a:buffer, 'python_pylint_options') \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n' \ . ' %s' diff --git a/ale_linters/tex/chktex.vim b/ale_linters/tex/chktex.vim index 776974a..7f1b0c7 100644 --- a/ale_linters/tex/chktex.vim +++ b/ale_linters/tex/chktex.vim @@ -18,7 +18,7 @@ function! ale_linters#tex#chktex#GetCommand(buffer) abort let l:command .= ' -v0 -p stdin -q' if !empty(l:chktex_config) - let l:command .= ' -l ' . shellescape(l:chktex_config) + let l:command .= ' -l ' . ale#Escape(l:chktex_config) endif let l:command .= ' ' . ale#Var(a:buffer, 'tex_chktex_options') diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index 8ba99cc..c382ed2 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -55,7 +55,7 @@ function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort \) let l:tslint_config_option = !empty(l:tslint_config_path) - \ ? '-c ' . shellescape(l:tslint_config_path) + \ ? '-c ' . ale#Escape(l:tslint_config_path) \ : '' return ale_linters#typescript#tslint#GetExecutable(a:buffer) diff --git a/ale_linters/verilog/verilator.vim b/ale_linters/verilog/verilator.vim index ed26c1f..b44731c 100644 --- a/ale_linters/verilog/verilator.vim +++ b/ale_linters/verilog/verilator.vim @@ -8,7 +8,7 @@ function! ale_linters#verilog#verilator#GetCommand(buffer) abort call ale#engine#ManageFile(a:buffer, l:filename) call writefile(getbufline(a:buffer, 1, '$'), l:filename) - return 'verilator --lint-only -Wall -Wno-DECLFILENAME ' . shellescape(l:filename) + return 'verilator --lint-only -Wall -Wno-DECLFILENAME ' . ale#Escape(l:filename) endfunction function! ale_linters#verilog#verilator#Handle(buffer, lines) abort diff --git a/autoload/ale.vim b/autoload/ale.vim index c8fbfdf..189f1e4 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -123,3 +123,14 @@ function! ale#Var(buffer, variable_name) abort return getbufvar(str2nr(a:buffer), l:full_name, g:[l:full_name]) 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 + return shellescape(a:str) + endif +endfunction diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 339f7ee..486bdd4 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -480,14 +480,14 @@ function! ale#engine#FormatCommand(buffer, command) abort " file. if l:command =~# '%s' let l:filename = fnamemodify(bufname(a:buffer), ':p') - let l:command = substitute(l:command, '%s', '\=shellescape(l:filename)', 'g') + let l:command = substitute(l:command, '%s', '\=ale#Escape(l:filename)', 'g') endif if l:command =~# '%t' " Create a temporary filename, / " The file itself will not be created by this function. let l:temporary_file = s:TemporaryFilename(a:buffer) - let l:command = substitute(l:command, '%t', '\=shellescape(l:temporary_file)', 'g') + let l:command = substitute(l:command, '%t', '\=ale#Escape(l:temporary_file)', 'g') endif " Finish formatting so %% becomes %. @@ -529,7 +529,7 @@ function! s:RunJob(options) abort " in the shell. We'll write out the file to a temporary file, " and then read it back in, in the shell. let l:temporary_file = s:TemporaryFilename(l:buffer) - let l:command = l:command . ' < ' . shellescape(l:temporary_file) + let l:command = l:command . ' < ' . ale#Escape(l:temporary_file) endif if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) @@ -636,7 +636,7 @@ function! s:RunJob(options) abort " Run a command synchronously if this test option is set. let s:job_info_map[l:job_id].output = systemlist( \ type(l:command) == type([]) - \ ? join(l:command[0:1]) . ' ' . shellescape(l:command[2]) + \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2]) \ : l:command \) call s:HandleExit(l:job) diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim index 26da9e2..88aa482 100644 --- a/autoload/ale/path.vim +++ b/autoload/ale/path.vim @@ -47,7 +47,7 @@ endfunction " Output 'cd && ' " This function can be used changing the directory for a linter command. function! ale#path#CdString(directory) abort - return 'cd ' . shellescape(a:directory) . ' && ' + return 'cd ' . ale#Escape(a:directory) . ' && ' endfunction " Output 'cd && '