async.vim 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. let s:available = has('nvim') || (
  2. \ has('job') && (
  3. \ (has('patch-7.4.1826') && !has('gui_running')) ||
  4. \ (has('patch-7.4.1850') && has('gui_running')) ||
  5. \ (has('patch-7.4.1832') && has('gui_macvim'))
  6. \ )
  7. \ )
  8. let s:jobs = {}
  9. function! gitgutter#async#available()
  10. return s:available
  11. endfunction
  12. function! gitgutter#async#execute(cmd, bufnr, handler) abort
  13. call gitgutter#debug#log('[async] '.a:cmd)
  14. let options = {
  15. \ 'stdoutbuffer': [],
  16. \ 'buffer': a:bufnr,
  17. \ 'handler': a:handler
  18. \ }
  19. let command = s:build_command(a:cmd)
  20. if has('nvim')
  21. call jobstart(command, extend(options, {
  22. \ 'on_stdout': function('s:on_stdout_nvim'),
  23. \ 'on_stderr': function('s:on_stderr_nvim'),
  24. \ 'on_exit': function('s:on_exit_nvim')
  25. \ }))
  26. else
  27. let job = job_start(command, {
  28. \ 'out_cb': function('s:on_stdout_vim', options),
  29. \ 'err_cb': function('s:on_stderr_vim', options),
  30. \ 'close_cb': function('s:on_exit_vim', options)
  31. \ })
  32. let s:jobs[s:job_id(job)] = 1
  33. endif
  34. endfunction
  35. function! s:build_command(cmd)
  36. if has('unix')
  37. return ['sh', '-c', a:cmd]
  38. endif
  39. if has('win32')
  40. return has('nvim') ? ['cmd.exe', '/c', a:cmd] : 'cmd.exe /c '.a:cmd
  41. endif
  42. throw 'unknown os'
  43. endfunction
  44. function! s:on_stdout_nvim(_job_id, data, _event) dict abort
  45. if empty(self.stdoutbuffer)
  46. let self.stdoutbuffer = a:data
  47. else
  48. let self.stdoutbuffer = self.stdoutbuffer[:-2] +
  49. \ [self.stdoutbuffer[-1] . a:data[0]] +
  50. \ a:data[1:]
  51. endif
  52. endfunction
  53. function! s:on_stderr_nvim(_job_id, data, _event) dict abort
  54. if a:data != [''] " With Neovim there is always [''] reported on stderr.
  55. call self.handler.err(self.buffer)
  56. endif
  57. endfunction
  58. function! s:on_exit_nvim(_job_id, exit_code, _event) dict abort
  59. if !a:exit_code
  60. call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
  61. endif
  62. endfunction
  63. function! s:on_stdout_vim(_channel, data) dict abort
  64. call add(self.stdoutbuffer, a:data)
  65. endfunction
  66. function! s:on_stderr_vim(channel, _data) dict abort
  67. call self.handler.err(self.buffer)
  68. endfunction
  69. function! s:on_exit_vim(channel) dict abort
  70. let job = ch_getjob(a:channel)
  71. let jobid = s:job_id(job)
  72. if has_key(s:jobs, jobid) | unlet s:jobs[jobid] | endif
  73. while 1
  74. if job_status(job) == 'dead'
  75. let exit_code = job_info(job).exitval
  76. break
  77. endif
  78. sleep 5m
  79. endwhile
  80. if !exit_code
  81. call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
  82. endif
  83. endfunction
  84. function! s:job_id(job)
  85. " Vim
  86. return job_info(a:job).process
  87. endfunction