From 2e67f82b79dac66fb7eea1ed2ca4881a5f265568 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Tue, 18 Feb 2020 19:44:49 -0500 Subject: [PATCH] Refine handling of pagination via temp buffer Use temp buffer for output of any command for which the Git configuration option of pager. 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 --- autoload/fugitive.vim | 60 ++++++++++++++++++++++++++++++++++++------- doc/fugitive.txt | 11 +++++--- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index a8d8a75..d2c04ce 100644 --- 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', 'g') let assign = len(dir) ? '|let b:git_dir = ' . string(dir) : '' if has('nvim') diff --git a/doc/fugitive.txt b/doc/fugitive.txt index 224b14d..0baa1e3 100644 --- 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. 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.