commit 2e67f82b79dac66fb7eea1ed2ca4881a5f265568 (tree)
parent a81ba999e8a48e4b86beef84714ad4ad3dd1ff84
Author: Tim Pope <code@tpope.net>
Date: Tue, 18 Feb 2020 19:44:49 -0500
Refine handling of pagination via temp buffer
Use temp buffer for output of any command for which the Git
configuration option of pager.<command> is true. Avoid using a temp
buffer if the value is false, even for commands like "show" where we
normally would. If the configuration value is present and can't be
interpreted as a Boolean, punt to a :terminal where Git will invoke it
directly.
Generate and use custom config dictionary that includes -c values passed
to :Git. This enables `:Git -c pager.status status` to correctly use a
pager.
Paginate "config", "branch", and "tag" for certain argument lists,
matching the logic found in the Git source code as closely as possible.
These 3 commands were identified as having special pagination logic by
the presence of the DELAY_PAGER_CONFIG flag on their definitions in
git.c.
Paginate "am --show-current-patch".
References https://github.com/tpope/vim-fugitive/issues/1415
Diffstat:
2 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim
@@ -2356,6 +2356,37 @@ augroup fugitive_job
\ endfor
augroup END
+function! fugitive#PagerFor(argv, ...) abort
+ let args = a:argv
+ if empty(args)
+ return 0
+ elseif (args[0] ==# 'help' || get(args, 1, '') ==# '--help') && !s:HasOpt(args, '--web')
+ return 1
+ endif
+ if args[0] ==# 'config' && (s:HasOpt(args, '-e', '--edit') ||
+ \ !s:HasOpt(args, '--list', '--get-all', '--get-regexp', '--get-urlmatch')) ||
+ \ args[0] =~# '^\%(tag\|branch\)$' && (s:HasOpt(args, '--edit-description', '--unset-upstream') ||
+ \ len(filter(args[1:-1], 'v:val =~# "^[^-]\|^--set-upstream-to="')) &&
+ \ !s:HasOpt(args, '--contains', '--no-contains', '--merged', '--no-merged', '--points-at'))
+ return 0
+ endif
+ let config = a:0 ? a:1 : fugitive#Config()
+ let value = get(FugitiveConfigGetAll('pager.' . args[0], config), 0, -1)
+ if value =~# '^\%(true\|yes\|on\|1\)$'
+ return 1
+ elseif value =~# '^\%(false\|no|off\|0\|\)$'
+ return 0
+ elseif type(value) == type('')
+ return value
+ elseif args[0] =~# 'diff\%(tool\)\@!\|log\|^show$\|^config$\|^branch$\|^tag$' ||
+ \ (args[0] ==# 'stash' && get(args, 1, '') ==# 'show') ||
+ \ (args[0] ==# 'am' && s:HasOpt(args, '--show-current-patch'))
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
let s:disable_colors = []
for s:colortype in ['advice', 'branch', 'diff', 'grep', 'interactive', 'pager', 'push', 'remote', 'showBranch', 'status', 'transport', 'ui']
call extend(s:disable_colors, ['-c', 'color.' . s:colortype . '=false'])
@@ -2363,6 +2394,7 @@ endfor
unlet s:colortype
function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
let dir = s:Dir()
+ let config = copy(fugitive#Config(dir))
let [args, after] = s:SplitExpandChain(a:arg, s:Tree(dir))
let flags = []
while len(args) > 1
@@ -2403,23 +2435,33 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
while i < len(flags) - 1
if flags[i] ==# '-c'
let i += 1
- let config_name = matchstr(flags[i], '^[^=]\+\ze=')
- if has_key(s:prepare_env, config_name)
+ let config_name = tolower(matchstr(flags[i], '^[^=]\+'))
+ if has_key(s:prepare_env, config_name) && flags[i] =~# '=.'
let env[s:prepare_env[config_name]] = matchstr(flags[i], '=\zs.*')
endif
+ if !has_key(config, config_name)
+ let config[config_name] = []
+ endif
+ if flags[i] =~# '='
+ let config[config_name] = [matchstr(flags[i], '=\zs.*')] + config[config_name]
+ else
+ let config[config_name] = [1] + config[config_name]
+ endif
endif
let i += 1
endwhile
- if a:bang || args[0] =~# '^-p$\|^--paginate$\|diff\%(tool\)\@!\|log\|^show$' ||
- \ (args[0] ==# 'stash' && get(args, 1, '') ==# 'show') ||
- \ (args[0] ==# 'help' || get(args, 1, '') ==# '--help') && !s:HasOpt(args, '--web')
- if args[0] =~# '^-p$\|^--paginate$'
- call remove(args, 0)
- endif
+ if args[0] =~# '^-p$\|^--paginate$'
+ call remove(args, 0)
+ let pager = 1
+ else
+ let pager = fugitive#PagerFor(args, config)
+ endif
+ if a:bang || pager is# 1
return s:OpenExec((a:line2 > 0 ? a:line2 : '') . (a:line2 ? 'split' : 'edit'), a:mods, env, flags + args, dir) . after
endif
if s:HasOpt(args, ['add', 'checkout', 'commit', 'stage', 'stash', 'reset'], '-p', '--patch') ||
- \ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive')
+ \ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive') ||
+ \ type(pager) == type('')
let mods = substitute(s:Mods(a:mods), '\<tab\>', '-tab', 'g')
let assign = len(dir) ? '|let b:git_dir = ' . string(dir) : ''
if has('nvim')
diff --git a/doc/fugitive.txt b/doc/fugitive.txt
@@ -25,10 +25,12 @@ that are part of Git repositories).
resume running the command. A few Git subcommands
have different behavior; these are documented below.
-:Git! {args} Run an arbitrary git command, capture output to a temp
-:Git --paginate {args} file, and |:split| that temp file. Use :0Git to
-:Git -p {args} |:edit| the temp file instead. A temp file is always
-:G ... used for diff and log commands.
+:Git --paginate {args} Run an arbitrary git command, capture output to a temp
+:Git -p {args} file, and |:split| that temp file. Use :0Git to
+:G --paginate {args} |:edit| the temp file instead. A temp file is always
+:G -p {args} used for commands like diff and log that typically
+ user a pager, and for any command that has the
+ pager.<cmd> Git configuration option set.
*fugitive-summary*
:Git With no arguments, bring up a summary window vaguely
@@ -630,6 +632,7 @@ just one space character longer than the legacy version.
*:Gfetch* Superseded by |:Git-fetch|.
*:Glog* Superseded by |:Gclog|.
*:Gstatus* Superseded by |:Git| (with no arguments).
+*:Git!* Superseded by |:Git| --paginate.
*:Gsplit!* Superseded by |:Git| --paginate.
*:Gvsplit!* Superseded by |:vert| |:Git| --paginate.
*:Gtabsplit!* Superseded by |:tab| |:Git| --paginate.