mirror of
https://github.com/junegunn/vim-plug.git
synced 2026-09-10 07:16:19 -04:00
Use job API for system() calls in GUI Vim to avoid overhead
In GUI Vim (gvim, MacVim), each system() call incurs significant overhead due to command prompt window creation, making operations like PlugDiff ~5x slower than in terminal Vim or Neovim. Add s:system_job() which uses job_start with file-based output to run commands without that overhead, and use it in s:system() when running in GUI Vim with job support. Since v:shell_error is read-only in Vim 9, introduce s:shell_error which is set by both code paths and used at all call sites. Fixes #1312
This commit is contained in:
parent
d72ac8734f
commit
cf2d899500
45
plug.vim
45
plug.vim
|
|
@ -68,6 +68,7 @@ let s:mac_gui = has('gui_macvim') && has('gui_running')
|
|||
let s:is_win = has('win32')
|
||||
let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
|
||||
let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
|
||||
let s:shell_error = 0
|
||||
if s:is_win && &shellslash
|
||||
set noshellslash
|
||||
let s:me = resolve(expand('<sfile>:p'))
|
||||
|
|
@ -170,7 +171,7 @@ function! s:git_origin_branch(spec)
|
|||
|
||||
" The command may not return the name of a branch in detached HEAD state
|
||||
let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
|
||||
return v:shell_error ? '' : result[-1]
|
||||
return s:shell_error ? '' : result[-1]
|
||||
endfunction
|
||||
|
||||
if s:is_win
|
||||
|
|
@ -1097,7 +1098,7 @@ function! s:checkout(spec)
|
|||
let credential_helper = s:disable_credential_helper() ? '-c credential.helper= ' : ''
|
||||
let output = s:system(
|
||||
\ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
|
||||
let error = v:shell_error
|
||||
let error = s:shell_error
|
||||
endif
|
||||
return [output, error]
|
||||
endfunction
|
||||
|
|
@ -1303,7 +1304,7 @@ function! s:update_finish()
|
|||
let tag = spec.tag
|
||||
if tag =~ '\*'
|
||||
let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))
|
||||
if !v:shell_error && !empty(tags)
|
||||
if !s:shell_error && !empty(tags)
|
||||
let tag = tags[0]
|
||||
call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
|
||||
call append(3, '')
|
||||
|
|
@ -1311,7 +1312,7 @@ function! s:update_finish()
|
|||
endif
|
||||
call s:log4(name, 'Checking out '.tag)
|
||||
let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
|
||||
let error = v:shell_error
|
||||
let error = s:shell_error
|
||||
endif
|
||||
if !error && filereadable(spec.dir.'/.gitmodules') &&
|
||||
\ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
|
||||
|
|
@ -1319,7 +1320,7 @@ function! s:update_finish()
|
|||
let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)
|
||||
let error = v:shell_error
|
||||
endif
|
||||
let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
|
||||
let msg = s:format_message(error ? 'x': '-', name, out)
|
||||
if error
|
||||
call add(s:update.errors, name)
|
||||
call s:regress_bar()
|
||||
|
|
@ -1480,7 +1481,7 @@ function! s:spawn(name, spec, queue, opts)
|
|||
endif
|
||||
else
|
||||
let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [argv, a:opts.dir] : [argv]))
|
||||
let job.error = v:shell_error != 0
|
||||
let job.error = s:shell_error != 0
|
||||
let job.running = 0
|
||||
endif
|
||||
endfunction
|
||||
|
|
@ -2334,6 +2335,21 @@ function! s:with_cd(cmd, dir, ...)
|
|||
return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd)
|
||||
endfunction
|
||||
|
||||
function! s:system_job(cmd) abort
|
||||
let tmp = tempname()
|
||||
let job = job_start(['/bin/sh', '-c', a:cmd], {
|
||||
\ 'out_io': 'file',
|
||||
\ 'out_name': tmp,
|
||||
\ 'err_io': 'out',
|
||||
\})
|
||||
while job_status(job) ==# 'run'
|
||||
endwhile
|
||||
let s:shell_error = job_info(job).exitval
|
||||
let result = filereadable(tmp) ? join(readfile(tmp, 'b'), "\n") : ''
|
||||
silent! call delete(tmp)
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:system(cmd, ...)
|
||||
let batchfile = ''
|
||||
try
|
||||
|
|
@ -2343,7 +2359,9 @@ function! s:system(cmd, ...)
|
|||
" but it cannot set the working directory for the command.
|
||||
" Assume that the command does not rely on the shell.
|
||||
if has('nvim') && a:0 == 0
|
||||
return system(a:cmd)
|
||||
let ret = system(a:cmd)
|
||||
let s:shell_error = v:shell_error
|
||||
return ret
|
||||
endif
|
||||
let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
|
||||
if s:is_powershell(&shell)
|
||||
|
|
@ -2358,7 +2376,12 @@ function! s:system(cmd, ...)
|
|||
if s:is_win && type(a:cmd) != s:TYPE.list
|
||||
let [batchfile, cmd] = s:batchfile(cmd)
|
||||
endif
|
||||
return system(cmd)
|
||||
if s:vim8 && has('gui_running') && !s:is_win
|
||||
return s:system_job(cmd)
|
||||
endif
|
||||
let ret = system(cmd)
|
||||
let s:shell_error = v:shell_error
|
||||
return ret
|
||||
finally
|
||||
let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
|
||||
if s:is_win && filereadable(batchfile)
|
||||
|
|
@ -2369,7 +2392,7 @@ endfunction
|
|||
|
||||
function! s:system_chomp(...)
|
||||
let ret = call('s:system', a:000)
|
||||
return v:shell_error ? '' : substitute(ret, '\n$', '', '')
|
||||
return s:shell_error ? '' : substitute(ret, '\n$', '', '')
|
||||
endfunction
|
||||
|
||||
function! s:git_validate(spec, check_branch)
|
||||
|
|
@ -2412,7 +2435,7 @@ function! s:git_validate(spec, check_branch)
|
|||
\ 'git', 'rev-list', '--count', '--left-right',
|
||||
\ printf('HEAD...origin/%s', origin_branch)
|
||||
\ ], a:spec.dir)), '\t')
|
||||
if v:shell_error || len(ahead_behind) != 2
|
||||
if s:shell_error || len(ahead_behind) != 2
|
||||
let err = "Failed to compare with the origin. The default branch might have changed.\nPlugClean required."
|
||||
else
|
||||
let [ahead, behind] = ahead_behind
|
||||
|
|
@ -2562,7 +2585,7 @@ function! s:upgrade()
|
|||
|
||||
try
|
||||
let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
|
||||
if v:shell_error
|
||||
if s:shell_error
|
||||
return s:err('Error upgrading vim-plug: '. out)
|
||||
endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue