From 88f50bba604f353c21dea554bf9932ad5c76265e Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Mon, 29 Mar 2021 20:05:00 -0400 Subject: [PATCH] Press escape to background :Git to preview window This can one day hopefully be generalized to handle --paginate, but for now, leave it as undocumented experiment. --- autoload/fugitive.vim | 97 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index 8a8949a..7bae666 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -2365,7 +2365,9 @@ endfunction function! s:TempReadPost(file) abort if has_key(s:temp_files, s:cpath(a:file)) let dict = s:temp_files[s:cpath(a:file)] - setlocal nobuflisted + if !has_key(dict, 'job') + setlocal nobuflisted + endif if get(dict, 'filetype', '') ==# 'git' call fugitive#MapJumps() endif @@ -2414,7 +2416,7 @@ function! s:AskPassArgs(dir) abort endfunction function! s:RunJobs() abort - return exists('*job_start') || exists('*jobstart') + return (exists('*job_start') || exists('*jobstart')) && exists('*bufwinid') endfunction function! s:RunSave(state) abort @@ -2430,6 +2432,10 @@ function! s:RunFinished(state, ...) abort if get(a:state, 'filetype', '') ==# 'git' && first =~# '\<\([[:upper:][:digit:]_-]\+(\d\+)\).*\1' let a:state.filetype = 'man' endif + if !has_key(a:state, 'capture_bufnr') + return + endif + call fugitive#ReloadStatus(a:state, 1) endfunction function! s:RunEdit(state, tmp, job) abort @@ -2479,6 +2485,38 @@ function! s:RunReceive(state, tmp, type, job, data, ...) abort endif let a:tmp.echo .= data endif + let line_count = a:tmp.line_count + let a:tmp.line_count += len(lines) - 1 + if !has_key(a:state, 'capture_bufnr') || !bufloaded(a:state.capture_bufnr) + return + endif + call remove(lines, -1) + try + call setbufvar(a:state.capture_bufnr, '&modifiable', 1) + if !line_count && len(lines) > 1000 + let first = remove(lines, 0, 999) + call setbufline(a:state.capture_bufnr, 1, first) + redraw + call setbufline(a:state.capture_bufnr, 1001, lines) + else + call setbufline(a:state.capture_bufnr, line_count + 1, lines) + endif + call setbufvar(a:state.capture_bufnr, '&modifiable', 0) + if !getwinvar(bufwinid(a:state.capture_bufnr), '&previewwindow') + " no-op + elseif exists('*win_execute') + call win_execute(bufwinid(a:state.capture_bufnr), '$') + else + let winnr = bufwinnr(a:state.capture_bufnr) + if winnr > 0 + let old_winnr = winnr() + exe 'noautocmd' winnr.'wincmd w' + $ + exe 'noautocmd' old_winnr.'wincmd w' + endif + endif + catch + endtry endfunction function! s:RunExit(state, tmp, job, exit_status) abort @@ -2496,6 +2534,19 @@ function! s:RunClose(state, tmp, job, ...) abort let noeol = substitute(substitute(a:tmp.err, "\r$", '', ''), ".*\r", '', '') . a:tmp.out call writefile([noeol], a:state.file, 'ba') call remove(a:state, 'job') + if has_key(a:state, 'capture_bufnr') && bufloaded(a:state.capture_bufnr) + if len(noeol) + call setbufvar(a:state.capture_bufnr, '&modifiable', 1) + call setbufline(a:state.capture_bufnr, a:tmp.line_count + 1, [noeol]) + call setbufvar(a:state.capture_bufnr, '&eol', 0) + call setbufvar(a:state.capture_bufnr, '&modifiable', 0) + endif + call setbufvar(a:state.capture_bufnr, '&modified', 0) + call setbufvar(a:state.capture_bufnr, '&buflisted', 0) + if a:state.filetype !=# getbufvar(a:state.capture_bufnr, '&filetype', '') + call setbufvar(a:state.capture_bufnr, '&filetype', a:state.filetype) + endif + endif if !has_key(a:state, 'exit_status') return endif @@ -2552,13 +2603,31 @@ function! s:RunWait(state, tmp, job, ...) abort if peek != 0 && !(has('win32') && peek == 128) let c = getchar() let c = type(c) == type(0) ? nr2char(c) : c - if c ==# "\" + if c ==# "\" || c ==# "\" let a:state.closed_in = 1 if type(a:job) ==# type(0) call chanclose(a:job, 'stdin') else call ch_close_in(a:job) endif + let can_pedit = exists('*setbufline') + for winnr in range(1, winnr('$')) + if getwinvar(winnr, '&previewwindow') && getbufvar(winbufnr(winnr), '&modified') + let can_pedit = 0 + endif + endfor + if can_pedit + if has_key(a:tmp, 'echo') + call remove(a:tmp, 'echo') + endif + call writefile(['fugitive: aborting edit due to background operation.'], a:state.file . '.exit') + exe (&splitbelow ? 'botright' : 'topleft') 'silent pedit ++ff=unix' fnameescape(a:state.file) + let a:state.capture_bufnr = bufnr(a:state.file) + call setbufvar(a:state.capture_bufnr, '&modified', 1) + let finished = 0 + redraw! + return '' + endif else call s:RunSend(a:job, c) if !a:state.pty @@ -2601,13 +2670,26 @@ if !exists('s:resume_queue') endif function! fugitive#Resume() abort while len(s:resume_queue) - try - call call('s:RunWait', remove(s:resume_queue, 0)) - endtry + if s:resume_queue[0][2] isnot# '' + try + call call('s:RunWait', remove(s:resume_queue, 0)) + endtry + endif endwhile endfunction function! s:RunBufDelete(bufnr) abort + let state = s:TempState(bufname(+a:bufnr)) + if has_key(state, 'job') + try + if type(state.job) == type(0) + call jobstop(state.job) + else + call job_stop(state.job) + endif + catch + endtry + endif if has_key(s:edit_jobs, a:bufnr) | call add(s:resume_queue, remove(s:edit_jobs, a:bufnr)) call feedkeys(":redraw!|call delete(" . string(s:resume_queue[-1][0].file . '.edit') . @@ -2617,7 +2699,7 @@ endfunction augroup fugitive_job autocmd! - autocmd BufDelete * call s:RunBufDelete(expand('')) + autocmd BufDelete * call s:RunBufDelete(+expand('')) autocmd VimLeave * \ for s:jobbuf in keys(s:edit_jobs) | \ call writefile(['Aborting edit due to Vim exit.'], s:edit_jobs[s:jobbuf][0].file . '.exit') | @@ -2782,6 +2864,7 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort let args = s:AskPassArgs(dir) + args endif let tmp = { + \ 'line_count': 0, \ 'err': '', \ 'out': '', \ 'echo': '',