" ============================================================================ " File: autoload/gitstatus/job.vim " Description: async-jobs " Maintainer: Xuyuan Pang " 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, ' ')), "\", "\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