From 72f3455214c6345047b43273f3d90d39234b3fd0 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 8 Jul 2024 23:33:19 +0900 Subject: [PATCH] Allow pressing 'q' to abort the process; and 'R' to retry If you press 'q' while `PlugInstall` or `PlugUpdate` is in progress, the current version of vim-plug immediately closes its window and aborts all the running processes. This commit enhances the 'q' map so that it doesn't close the window, but instead displays aborted tasks so that the user can press 'R' to retry aborted/skipped tasks. Fix #1285 --- plug.vim | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/plug.vim b/plug.vim index 6296f8b..66f4cf6 100644 --- a/plug.vim +++ b/plug.vim @@ -783,10 +783,11 @@ endfunction function! s:syntax() syntax clear syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber - syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX + syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX,plugAbort syn match plugNumber /[0-9]\+[0-9.]*/ contained syn match plugBracket /[[\]]/ contained syn match plugX /x/ contained + syn match plugAbort /\~/ contained syn match plugDash /^-\{1}\ / syn match plugPlus /^+/ syn match plugStar /^*/ @@ -811,6 +812,7 @@ function! s:syntax() hi def link plug2 Repeat hi def link plugH2 Type hi def link plugX Exception + hi def link plugAbort Ignore hi def link plugBracket Structure hi def link plugNumber Number @@ -908,7 +910,7 @@ function! s:prepare(...) endif endfor - call s:job_abort() + call s:job_abort(0) if s:switch_in() if b:plug_preview == 1 pc @@ -944,6 +946,8 @@ function! s:close_pane() if b:plug_preview == 1 pc let b:plug_preview = -1 + elseif exists('s:jobs') && !empty(s:jobs) + call s:job_abort(1) else bd endif @@ -1326,7 +1330,7 @@ function! s:update_finish() endif endfunction -function! s:job_abort() +function! s:job_abort(cancel) if (!s:nvim && !s:vim8) || !exists('s:jobs') return endif @@ -1340,8 +1344,16 @@ function! s:job_abort() if j.new call s:rm_rf(g:plugs[name].dir) endif + let s:jobs[name] = { 'running': 0, 'lines': ['Aborted'], 'error': 1, 'abort': 1 } endfor - let s:jobs = {} + + if a:cancel + for todo in values(s:update.todo) + let todo.abort = 1 + endfor + else + let s:jobs = {} + endif endfunction function! s:last_non_empty_line(lines) @@ -1355,6 +1367,16 @@ function! s:last_non_empty_line(lines) return '' endfunction +function! s:bullet_for(job, ...) + if a:job.running + return a:job.new ? '+' : '*' + endif + if get(a:job, 'abort', 0) + return '~' + endif + return a:job.error ? 'x' : get(a:000, 0, '-') +endfunction + function! s:job_out_cb(self, data) abort let self = a:self let data = remove(self.lines, -1) . a:data @@ -1363,10 +1385,9 @@ function! s:job_out_cb(self, data) abort " To reduce the number of buffer updates let self.tick = get(self, 'tick', -1) + 1 if !self.running || self.tick % len(s:jobs) == 0 - let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-') let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) if len(result) - call s:log(bullet, self.name, result) + call s:log(s:bullet_for(self), self.name, result) endif endif endfunction @@ -1380,7 +1401,7 @@ endfunction function! s:job_cb(fn, job, ch, data) if !s:plug_window_exists() " plug window closed - return s:job_abort() + return s:job_abort(0) endif call call(a:fn, [a:job, a:data]) endfunction @@ -1452,17 +1473,16 @@ function! s:reap(name) endif let more = len(get(job, 'queue', [])) - let bullet = job.error ? 'x' : more ? (job.new ? '+' : '*') : '-' let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) if len(result) - call s:log(bullet, a:name, result) + call s:log(s:bullet_for(job), a:name, result) endif if !job.error && more let job.spec.queue = job.queue let s:update.todo[a:name] = job.spec else - let s:update.bar .= job.error ? 'x' : '=' + let s:update.bar .= s:bullet_for(job, '=') call s:bar() endif endfunction @@ -1541,6 +1561,12 @@ while 1 " Without TCO, Vim stack is bound to explode let name = keys(s:update.todo)[0] let spec = remove(s:update.todo, name) + if get(spec, 'abort', 0) + let s:jobs[name] = { 'running': 0, 'lines': ['Skipped'], 'abort': 1, 'error': 1 } + call s:reap(name) + continue + endif + let queue = get(spec, 'queue', []) let new = empty(globpath(spec.dir, '.git', 1))