1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 18:10:05 +08:00
SpaceVim/bundle/nerdtree-git-plugin/autoload/gitstatus/job.vim
2021-09-12 23:45:01 +08:00

137 lines
4.5 KiB
VimL

" ============================================================================
" File: autoload/gitstatus/job.vim
" Description: async-jobs
" Maintainer: Xuyuan Pang <xuyuanp at gmail dot com>
" License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
" ============================================================================
if exists('g:loaded_nerdtree_git_status_job')
finish
endif
let g:loaded_nerdtree_git_status_job = 1
" stolen from vim-plug
let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait'))
let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
let s:Job = {
\ 'running': 0,
\ 'failed': 0,
\ 'chunks': [''],
\ 'err_chunks': [''],
\ }
" disabled ProhibitImplicitScopeVariable because we will use lots of `self`
" disabled ProhibitUnusedVariable because lambda
" vint: -ProhibitImplicitScopeVariable -ProhibitUnusedVariable
function! s:newJob(name, opts) abort
return extend(deepcopy(s:Job), {
\ 'name': a:name,
\ 'opts': a:opts
\ })
endfunction
function! s:Job.onStdoutCB(data) abort
let self.chunks[-1] .= a:data[0]
call extend(self.chunks, a:data[1:])
endfunction
function! s:Job.onStderrCB(data) abort
let self.failed = self.failed || !s:isEOF(a:data)
let self.err_chunks[-1] .= a:data[0]
call extend(self.err_chunks, a:data[1:])
endfunction
function! s:Job.onExitCB() abort
let self.running = 0
if self.failed
call self.onFailed()
else
call self.onSuccess()
endif
endfunction
function! s:Job.onFailed() abort
if has_key(self.opts, 'on_failed_cb')
call call(self.opts.on_failed_cb, [self])
endif
endfunction
function! s:Job.onSuccess() abort
if has_key(self.opts, 'on_success_cb')
call call(self.opts.on_success_cb, [self])
endif
endfunction
if s:nvim
function! s:Job.run(cmd) abort
let jid = jobstart(a:cmd, {
\ 'on_stdout': {_job_id, data, _event -> self.onStdoutCB(data)},
\ 'on_stderr': {_job_id, data, _event -> self.onStderrCB(data)},
\ 'on_exit': {_job_id, _data, _event -> self.onExitCB()},
\ 'env': {'GIT_OPTIONAL_LOCKS': '0'},
\ })
let self.id = jid
let self.running = jid > 0
if jid <= 0
let self.failed = 1
let self.err_chunks = jid == 0 ?
\ ['invalid arguments'] :
\ ['command is not executable']
call self.onExitCB()
endif
endfunction
elseif s:vim8
function! s:Job.run(cmd) abort
let options = {
\ 'out_cb': { _ch, data -> self.onStdoutCB([data]) },
\ 'err_cb': { _ch, data -> self.onStderrCB([data]) },
\ 'close_cb': { _ch -> self.onExitCB() },
\ 'out_mode': 'nl',
\ 'err_mode': 'nl',
\ 'env': {'GIT_OPTIONAL_LOCKS': '0'},
\ }
if has('patch-8.1.350')
let options['noblock'] = 1
endif
let jid = job_start(a:cmd, options)
if job_status(jid) ==# 'run'
let self.id = jid
let self.running = 1
else
let self.running = 0
let self.failed = 1
let self.err_chunks = ['failed to start job']
call self.onExitCB()
endif
endfunction
else
function! s:Job.run(cmd) abort
let bak = $GIT_OPTIONAL_LOCKS
let $GIT_OPTIONAL_LOCKS = 0
let output = substitute(system(join(a:cmd, ' ')), "\<C-A>", "\n", 'g')
let $GIT_OPTIONAL_LOCKS = bak
let self.failed = v:shell_error isnot# 0
if self.failed
let self.err_chunks = [output]
else
let self.chunks = [output]
endif
call self.onExitCB()
endfunction
endif
" vint: +ProhibitImplicitScopeVariable +ProhibitUnusedVariable
function! s:isEOF(data) abort
return len(a:data) == 1 && a:data[0] is# ''
endfunction
function! gitstatus#job#Spawn(name, cmd, opts) abort
let l:job = s:newJob(a:name, a:opts)
call l:job.run(a:cmd)
return l:job
endfunction