Skip to content

Commit d7db1b6

Browse files
authored
Fix Support for PowerShell under Windows with VIM 8+ (#1326)
The following 'vim-plug' commands would fail and/or display errors when executed by VIM 8+ on a Windows platform with the 'shell' option set to 'powershell' or 'pwsh': - PlugInstall - PlugUpdate - PlugClean - PlugStatus - PlugDiff There were two causes for these errors: - A bug in VIM itself (resolved by patch 9.2.6) with how compound PowerShell commands are handled by the 'system()' vimscript function. - A bug in the 's:vim8' branch of the private 'vim-plug' function 's:spawn()' where the actual command to be executed was escaped for 'cmd.exe' but the 'cd' prefix added by 's:with_cd()" was escaped for PowerShell.
1 parent 34467fc commit d7db1b6

1 file changed

Lines changed: 14 additions & 7 deletions

File tree

plug.vim

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ function! s:bang(cmd, ...)
997997
let [sh, shellcmdflag, shrd] = s:chsh(a:0)
998998
" FIXME: Escaping is incomplete. We could use shellescape with eval,
999999
" but it won't work on Windows.
1000-
let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
1000+
let cmd = a:0 ? s:with_cd(a:cmd, a:1, {'shell': s:is_win ? 'cmd.exe' : &shell}) : a:cmd
10011001
if s:is_win
10021002
let [batchfile, cmd] = s:batchfile(cmd)
10031003
endif
@@ -1462,7 +1462,7 @@ function! s:spawn(name, spec, queue, opts)
14621462
elseif s:vim8
14631463
let cmd = join(map(copy(argv), 'plug#shellescape(v:val, {"script": 0})'))
14641464
if has_key(a:opts, 'dir')
1465-
let cmd = s:with_cd(cmd, a:opts.dir, 0)
1465+
let cmd = s:with_cd(cmd, a:opts.dir, {'shell': s:is_win ? 'cmd.exe' : 'sh', 'script': 0})
14661466
endif
14671467
let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]
14681468
let jid = job_start(s:is_win ? join(argv, ' ') : argv, {
@@ -2328,11 +2328,18 @@ function! s:format_message(bullet, name, message)
23282328
endfunction
23292329

23302330
function! s:with_cd(cmd, dir, ...)
2331-
let script = a:0 > 0 ? a:1 : 1
2332-
let pwsh = s:is_powershell(&shell)
2331+
let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
2332+
let opts.shell = get(opts, 'shell', &shell)
2333+
let opts.script = get(opts, 'script', 1)
2334+
2335+
let pwsh = s:is_powershell(opts.shell)
23332336
let cd = s:is_win && !pwsh ? 'cd /d' : 'cd'
23342337
let sep = pwsh ? ';' : '&&'
2335-
return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd)
2338+
let pwsh_block_required = pwsh && !has('patch-9.2.6')
2339+
let start = pwsh_block_required ? '& { ' : ''
2340+
let end = pwsh_block_required ? ' }' : ''
2341+
2342+
return printf('%s%s %s %s %s%s', start, cd, plug#shellescape(a:dir, opts), sep, a:cmd, end)
23362343
endfunction
23372344

23382345
function! s:system_job(cmd) abort
@@ -2372,9 +2379,9 @@ function! s:system(cmd, ...)
23722379
let cmd = a:cmd
23732380
endif
23742381
if a:0 > 0
2375-
let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
2382+
let cmd = s:with_cd(cmd, a:1, {'script': type(a:cmd) != s:TYPE.list})
23762383
endif
2377-
if s:is_win && type(a:cmd) != s:TYPE.list
2384+
if s:is_win && type(a:cmd) != s:TYPE.list && !s:is_powershell(&shell)
23782385
let [batchfile, cmd] = s:batchfile(cmd)
23792386
endif
23802387
if s:vim8 && has('gui_running') && !s:is_win

0 commit comments

Comments
 (0)