Echo from wait loop, not job callback

This makes the pager behave a better, allowing the -- More -- prompt to
actually display and not dropping output if the process exits while
there's a backlog.  An additional benefit is if Git for some reason
produces additional output while GIT_EDITOR is running, that output will
be buffered rather than interrupting the user.

The extracted s:RunTick() helper changes the Vim behavior to check the
process status after waiting as well as before.  This brings it in line
with how Neovim's jobwait() appears to work.

The zero argument :echo after the final s:RunEcho() clears up some weird
draw issues with `:Git command|someothercommand`.

References https://github.com/tpope/vim-fugitive/issues/1717
This commit is contained in:
Tim Pope
2021-03-25 22:40:32 -04:00
parent af1a46edb7
commit 00cb68e627

View File

@@ -2421,8 +2421,8 @@ function! s:RunEdit(state, tmp, job) abort
endfunction endfunction
function! s:RunReceive(state, tmp, type, job, data, ...) abort function! s:RunReceive(state, tmp, type, job, data, ...) abort
let data = type(a:data) == type([]) ? join(a:data, "\n") : a:data
if a:type ==# 'err' || a:state.pty if a:type ==# 'err' || a:state.pty
let data = type(a:data) == type([]) ? join(a:data, "\n") : a:data
let data = a:tmp.escape . data let data = a:tmp.escape . data
let escape = "\033]51;[^\007]*" let escape = "\033]51;[^\007]*"
let a:tmp.escape = matchstr(data, escape . '$') let a:tmp.escape = matchstr(data, escape . '$')
@@ -2447,12 +2447,12 @@ function! s:RunReceive(state, tmp, type, job, data, ...) abort
let lines[-1] = '' let lines[-1] = ''
endif endif
call writefile(lines, a:state.file, 'ba') call writefile(lines, a:state.file, 'ba')
let data = a:tmp.echo . data if has_key(a:tmp, 'echo')
let a:tmp.echo = matchstr(data, "[\r\n]\\+$") if !exists('l:data')
if len(a:tmp.echo) let data = type(a:data) == type([]) ? join(a:data, "\n") : a:data
let data = strpart(data, 0, len(data) - len(a:tmp.echo)) endif
let a:tmp.echo .= data
endif endif
echon substitute(data, "\r\\ze\n", '', 'g')
endfunction endfunction
function! s:RunExit(state, tmp, job, exit_status) abort function! s:RunExit(state, tmp, job, exit_status) abort
@@ -2489,16 +2489,32 @@ function! s:RunSend(job, str) abort
endtry endtry
endfunction endfunction
function! s:RunEcho(tmp) abort
let data = a:tmp.echo
let a:tmp.echo = matchstr(data, "[\r\n]\\+$")
if len(a:tmp.echo)
let data = strpart(data, 0, len(data) - len(a:tmp.echo))
endif
echon substitute(data, "\r\\ze\n", '', 'g')
endfunction
function! s:RunTick(job) abort
if type(a:job) == v:t_number
return jobwait([a:job], 1)[0] == -1
elseif type(a:job) == v:t_job && (ch_status(a:job) !=# 'closed' || job_status(a:job) ==# 'run')
sleep 1m
return ch_status(a:job) !=# 'closed' || job_status(a:job) ==# 'run'
endif
endfunction
if !exists('s:edit_jobs') if !exists('s:edit_jobs')
let s:edit_jobs = {} let s:edit_jobs = {}
endif endif
function! s:RunWait(state, tmp, job) abort function! s:RunWait(state, tmp, job) abort
let finished = 0 let finished = 0
try try
while get(a:state, 'request', '') !=# 'edit' && (type(a:job) == type(0) ? jobwait([a:job], 1)[0] == -1 : ch_status(a:job) !=# 'closed' || job_status(a:job) ==# 'run') while get(a:state, 'request', '') !=# 'edit' && s:RunTick(a:job)
if !exists('*jobwait') call s:RunEcho(a:tmp)
sleep 1m
endif
if !get(a:state, 'closed_in') if !get(a:state, 'closed_in')
let peek = getchar(1) let peek = getchar(1)
if peek != 0 && !(has('win32') && peek == 128) if peek != 0 && !(has('win32') && peek == 128)
@@ -2520,7 +2536,7 @@ function! s:RunWait(state, tmp, job) abort
endif endif
endif endif
endwhile endwhile
sleep 1m call s:RunEcho(a:tmp)
echo echo
call s:RunEdit(a:state, a:tmp, a:job) call s:RunEdit(a:state, a:tmp, a:job)
let finished = 1 let finished = 1