From cc139ae461fb7d00d2aa3171d443d4d52a037f85 Mon Sep 17 00:00:00 2001 From: Peter Lustig Date: Sat, 21 Feb 2026 00:26:36 -0500 Subject: [PATCH] Fix Support for PowerShell under Windows with VIM 8+ The following 'vim-plug' commands would fail and/or display errors when executed on 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. --- plug.vim | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plug.vim b/plug.vim index de5ae1fc..c878f751 100644 --- a/plug.vim +++ b/plug.vim @@ -1462,7 +1462,7 @@ function! s:spawn(name, spec, queue, opts) elseif s:vim8 let cmd = join(map(copy(argv), 'plug#shellescape(v:val, {"script": 0})')) if has_key(a:opts, 'dir') - let cmd = s:with_cd(cmd, a:opts.dir, 0) + let cmd = s:with_cd(cmd, a:opts.dir, {'shell': s:is_win ? 'cmd.exe' : 'sh', 'script': 0}) endif let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd] let jid = job_start(s:is_win ? join(argv, ' ') : argv, { @@ -2328,11 +2328,18 @@ function! s:format_message(bullet, name, message) endfunction function! s:with_cd(cmd, dir, ...) - let script = a:0 > 0 ? a:1 : 1 - let pwsh = s:is_powershell(&shell) + let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {} + let opts.shell = get(opts, 'shell', &shell) + let opts.script = get(opts, 'script', 1) + + let pwsh = s:is_powershell(opts.shell) let cd = s:is_win && !pwsh ? 'cd /d' : 'cd' let sep = pwsh ? ';' : '&&' - return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd) + let pwsh_block_required = pwsh && !has('patch-9.2.6') + let start = pwsh_block_required ? '& { ' : '' + let end = pwsh_block_required ? ' }' : '' + + return printf('%s%s %s %s %s%s', start, cd, plug#shellescape(a:dir, opts), sep, a:cmd, end) endfunction function! s:system_job(cmd) abort @@ -2372,7 +2379,7 @@ function! s:system(cmd, ...) let cmd = a:cmd endif if a:0 > 0 - let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list) + let cmd = s:with_cd(cmd, a:1, {'script': type(a:cmd) != s:TYPE.list}) endif if s:is_win && type(a:cmd) != s:TYPE.list let [batchfile, cmd] = s:batchfile(cmd)