37 Commits

Author SHA1 Message Date
Tim Pope
f61beed747 Add packed-ref handling 2015-12-01 04:04:55 -05:00
Tim Pope
d854197c03 Open release page for tags on GitHub 2015-12-01 04:04:55 -05:00
Tim Pope
d8ce8d1d03 Document transition to rhubarb.vim 2015-11-30 22:25:50 -05:00
Tim Pope
23faeadc7c Revert "Show all untracked files in :Gstatus window"
This reverts commit 21b6dd7aee.

Closes https://github.com/tpope/vim-fugitive/issues/726
2015-11-30 19:38:48 -05:00
Andy Russell
1ecd12d523 Add support for fish shell syntax
Closes #626.
2015-11-06 15:54:34 -05:00
Jerome Reybert
f8aa87a4b5 Fix when $GIT_DIR is set and is not an absolute path 2015-11-03 09:52:22 -05:00
Jacob Niehus
dba8a0705d Fix diff sometimes opening in preview window
If the previous window no longer exists when Gedit is called, the
attempt to change windows with 'wincmd p' fails and 'wincmd w' should be
used instead.
2015-10-16 23:48:38 -04:00
Tim Pope
8cf3d94a3a Support gf in git filetypes
Closes https://github.com/tpope/vim-fugitive/issues/697
2015-10-07 00:21:49 -04:00
Tim Pope
28de2a1ddd Enable jumping on @@ hunk header 2015-10-07 00:21:49 -04:00
Tim Pope
01cda4d443 :Gdiff! keeps window focus 2015-10-07 00:21:35 -04:00
Tim Pope
b5188a1b4f Accept +cmd with :Gdiff 2015-10-07 00:05:07 -04:00
Tim Pope
8e63140181 Resplit when :Gstatus is final window 2015-10-07 00:05:07 -04:00
Tim Pope
cec56ef5ff Extract current file logic from s:GF 2015-10-06 21:45:40 -04:00
Tim Pope
1e755064e9 Better error on :Gwrite failure
References https://github.com/tpope/vim-fugitive/issues/696
2015-10-06 20:33:41 -04:00
Daniel Hahler
0b43b51d77 Expand % instead of <amatch> in the Buf* autocommands
This is relevant in case a previous BufReadPost autocmd changes the file
name using `:file` - fugitive should use the new/current name then.
2015-10-02 19:40:37 -04:00
Daniel Hahler
5dcf8a0175 ReplaceCmd: redirect stderr to tmp file / buffer
The option `status.showUntrackedFiles=all` used with `git status` for
`:Gstatus` might cause an error, which then causes fugitive to display an
empty status window / index file.

Redirecting the stderr output is useful in this case.

The generated command was:

    git --git-dir=/home/user/.dotfiles/.git -c 'status.displayCommentPrefix=true' -c 'color.status=false' -c 'status.short=false' -c 'status.showUntrackedFiles=all' status

The error from git is related to submodules being moved to another
subdirectory, where the relative "gitdir" now does not exist anymore:

    fatal: Not a git repository: vim/bundle.old.nobackup/CLEAN/colorscheme-base16/../../../.git/modules/vim/bundle/colorscheme-base16

While that's a Git / user error after all, fugitive should be more
helpful in that case by displaying the error.

It uses the 'shellpipe' setting to detect if '2>&1' is supported (Ref:
https://github.com/tpope/vim-fugitive/pull/661#issuecomment-120438667).

Closes #661.
2015-10-02 19:39:07 -04:00
Daniel Hahler
2509641eac Add "stash" and stash refs in repo.superglob
This looks for `refs/stash` and calls `git stash list` to get all of
them in case it exists.
2015-10-02 19:27:35 -04:00
Tim Pope
073f3a37b9 Short circuit when jumping too far in blame history
References https://github.com/tpope/vim-fugitive/issues/607
2015-09-30 18:49:56 -04:00
David Elentok
b7b23001de Allow using the "%" variable in git commands
Closes https://github.com/tpope/vim-fugitive/issues/686

For example, when running:

  :Git add %

neovim throws the following exception:

  E499: Empty file name for '%' or '#',
  only works with ":p:h": terminal git add %

It is a result of the tabnew command, it creates a new blank tab where
"%" is empty.

This commit changes "tabnew" to "tabedit %" so you're still working on
the same file.

Once the command is done running the tab closes.
2015-09-10 15:32:35 -04:00
Patrick Davey
b319b69453 Add the "L" prefix which github requires for highlighting ranges now
Fixes https://github.com/tpope/vim-fugitive/issues/669
2015-08-02 15:26:14 -04:00
Pieter-Jan Van de Maele
03cc95cc19 Support for Ggrep when only %f is available 2015-07-20 15:06:06 -04:00
Tim Pope
7c4a906147 Support Vim without 'wildignorecase'
Closes #659.
2015-07-01 10:55:35 -04:00
Tim Pope
b5b2548a87 Support older Vim without 'fileignorecase' 2015-06-30 20:39:54 -04:00
Tim Pope
ca727b07f1 Better support for case insensitive file systems
Closes #451.
2015-06-30 17:43:16 -04:00
Tim Pope
0fbbe0b3a4 Open :Gcommit tab before current
Pretty ridiculous, but this seems to be the only way to return to the
right tab after closing the commit message.
2015-06-29 17:52:39 -04:00
Tim Pope
1c844375fa Add support for flagship.vim 2015-06-14 20:06:38 -04:00
Daniel Hahler
e065e4f841 (Re)store the current window in s:diffoff_all
This is required to make Vim execute the "Enter" autocommands when
closing the fugitive window.

Fixes: https://github.com/tpope/vim-fugitive/issues/421
2015-05-31 12:14:23 -04:00
Eli Young
21b6dd7aee Show all untracked files in :Gstatus window
Previously, if there were untracked files inside an untracked folder,
:Gstatus would only show the new folder. Attempting to run a diff on the
folder would pass the directory name, which would result in Vim opening
a directory listing. This makes :Gstatus list all untracked files, even
if they're inside untracked folders. This requires Git >=1.4, and will
silently fall back to the old behavior on earlier versions.

Closes #605.
2015-05-22 17:50:42 -04:00
Tim Pope
935a2cccd3 Don't close window after :Gremove
This is nothing more than a change in personal preference on my part.
It's particularly annoying when :Gstatus or the quickfix window is the
only other window open.
2015-05-19 12:27:22 -04:00
Tim Pope
c2908b174d Support older Git in :Gpull
Closes #645.
2015-05-19 11:15:30 -04:00
Diego Vera
b0e38f08dc Make Ggrep to work properly on Mac
- Color were causing to appear strange characters in the result.
- These characters made impossible to navigate the results
- The solution was to disable colors while executing git grep
2015-05-16 10:12:41 -04:00
Ole Reifschneider
4cc201cbe3 Use the neovim terminal emulator for :Git 2015-03-31 13:40:01 -04:00
Tim Pope
baa05dcfda Pass correct files to git reset --patch 2015-03-29 16:29:18 -04:00
Fedor Gusev
0095769029 Provide g:fugitive_no_maps to disable key maps
Add variable g:fugitive_no_maps. If set y<C-G> and <C-R><C-G> are not
mapped.

Resolves tpope/vim-fugitive#394
2015-02-20 15:50:02 -05:00
Eli Young
e8b94098bb Support browsing with new netrw.vim
The previous fix for #594 didn't handle the case in which the net netrw
was installed on older versions of Vim.
2015-02-20 15:49:36 -05:00
Tim Pope
eb8eb1850a Support for browsing with recent Vim
Closes #594.
2015-02-08 22:31:37 -05:00
Daniel Hahler
933f6a1e1d s:Diff: use winnr with <C-W>w instead of <C-W>p
This is more reliable and fixes an issue where the syntastic location
list of the original file would be focused after `:Gdiff`.

Ref: c99f0ff06b (commitcomment-9434351)
2015-01-25 19:23:45 -05:00
2 changed files with 287 additions and 130 deletions

View File

@@ -220,32 +220,38 @@ that are part of Git repositories).
:[range]Gblame [flags] Run git-blame on the given range. :[range]Gblame [flags] Run git-blame on the given range.
*fugitive-:Gbrowse* *fugitive-:Gbrowse*
:[range]Gbrowse If the remote for the current branch is on GitHub, :Gbrowse Open the current file, blob, tree, commit, or tag
open the current file, blob, tree, commit, or tag in your browser at the upstream hosting provider
(with git-web--browse) on GitHub. Otherwise, open the indicated by the "origin" remote. If a range is
current file, blob, tree, commit, or tag in given, it is appropriately appended to the URL as an
git-instaweb (if you have issues, verify you can run anchor.
"git instaweb" from a terminal). If a range is given,
it is appropriately appended to the URL as an anchor.
To use with GitHub FI, point g:fugitive_github_domains Upstream providers can be added by installing an
at a list of domains: appropriate Vim plugin. For example, GitHub can be
> supported by installing rhubarb.vim, available at
let g:fugitive_github_domains = ['https://example.com'] <https://github.com/tpope/vim-rhubarb>. (Native
~ support for GitHub is currently included, but that is
:[range]Gbrowse! Like :Gbrowse, but put the URL on the clipboard rather slated to be removed.)
than opening it.
:[range]Gbrowse {revision} If no upstream support is available, a local instance
Like :Gbrowse, but for a given |fugitive-revision|. A of git-instaweb will be started and used instead.
:Gbrowse {revision} Like :Gbrowse, but for a given |fugitive-revision|. A
useful value here is -, which ties the URL to the useful value here is -, which ties the URL to the
latest commit rather than a volatile branch. latest commit rather than a volatile branch.
:[range]Gbrowse [...]@{remote} :Gbrowse [...]@{remote} Force using the given remote rather than the remote
Force using the given remote rather than the remote
for the current branch. The remote is used to for the current branch. The remote is used to
determine which GitHub repository to link to. determine which GitHub repository to link to.
:{range}Gbrowse [args] Appends an anchor to the URL that emphasizes the
selected lines. You almost certainly want to give a
"-" argument in this case to force the URL to include
an exact revision.
:[range]Gbrowse! [args] Like :Gbrowse, but put the URL on the clipboard rather
than opening it.
MAPPINGS *fugitive-mappings* MAPPINGS *fugitive-mappings*
These maps are available everywhere. These maps are available everywhere.

View File

@@ -143,11 +143,11 @@ function! fugitive#extract_git_dir(path) abort
break break
endif endif
if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR) if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR)
return $GIT_DIR return simplify(fnamemodify(expand($GIT_DIR), ':p:s?[\/]$??'))
endif endif
if fugitive#is_git_dir($GIT_DIR) if fugitive#is_git_dir($GIT_DIR)
" Ensure that we've cached the worktree " Ensure that we've cached the worktree
call s:configured_tree($GIT_DIR) call s:configured_tree(simplify(fnamemodify(expand($GIT_DIR), ':p:s?[\/]$??')))
if has_key(s:dir_for_worktree, root) if has_key(s:dir_for_worktree, root)
return s:dir_for_worktree[root] return s:dir_for_worktree[root]
endif endif
@@ -193,8 +193,10 @@ function! fugitive#detect(path) abort
let &mls = save_mls let &mls = save_mls
endtry endtry
endif endif
cnoremap <buffer> <expr> <C-R><C-G> fnameescape(<SID>recall()) if !exists('g:fugitive_no_maps')
nnoremap <buffer> <silent> y<C-G> :call setreg(v:register, <SID>recall())<CR> cnoremap <buffer> <expr> <C-R><C-G> fnameescape(<SID>recall())
nnoremap <buffer> <silent> y<C-G> :call setreg(v:register, <SID>recall())<CR>
endif
let buffer = fugitive#buffer() let buffer = fugitive#buffer()
if expand('%:p') =~# '//' if expand('%:p') =~# '//'
call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', '')) call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', ''))
@@ -218,7 +220,7 @@ endfunction
augroup fugitive augroup fugitive
autocmd! autocmd!
autocmd BufNewFile,BufReadPost * call fugitive#detect(expand('<amatch>:p')) autocmd BufNewFile,BufReadPost * call fugitive#detect(expand('%:p'))
autocmd FileType netrw call fugitive#detect(expand('%:p')) autocmd FileType netrw call fugitive#detect(expand('%:p'))
autocmd User NERDTreeInit,NERDTreeNewRoot call fugitive#detect(b:NERDTreeRoot.path.str()) autocmd User NERDTreeInit,NERDTreeNewRoot call fugitive#detect(b:NERDTreeRoot.path.str())
autocmd VimEnter * if expand('<amatch>')==''|call fugitive#detect(getcwd())|endif autocmd VimEnter * if expand('<amatch>')==''|call fugitive#detect(getcwd())|endif
@@ -296,49 +298,86 @@ function! s:repo_bare() dict abort
endif endif
endfunction endfunction
function! s:repo_disambiguate(spec) dict abort
if a:spec =~# '^:[0-3]:\|^:\=/\|^:\=$\|^\x\{40\}$'
return a:spec
elseif a:spec =~# '^:'
return ':0' . a:spec
elseif a:spec ==# '^\.'
return '/' . a:spec
elseif a:spec =~# '^[^:~^]*\.\.'
let before = self.qualify_ref(matchstr(a:spec, '.\{-\}\ze\.\.'))
let after = self.qualify_ref(matchstr(a:spec, '\.\.\.\=\zs.*'))
if before =~# '^/' || after =~# '^/'
return '/' . a:spec
else
return before . matchstr(a:spec, '\.\.\.\=') . after
endif
endif
let head = s:sub(a:spec, '[:~^].*|\@\{.*', '')
let rest = strpart(a:spec, len(head))
if head ==# '@'
return 'HEAD'.rest
endif
if head =~# "[[?*\001-\037\177]".'\|\%([./]\|\.lock\)\%(/\|$\)'
return '/' . a:spec
endif
let packed = {}
if filereadable(self.dir('packed-refs'))
for [v, k] in map(readfile(self.dir('packed-refs')), 'split(v:val, " ")')
let packed[k] = v
endfor
endif
for pattern in ['%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s', 'refs/remotes/%s', 'refs/remotes/%s/HEAD']
let ref = printf(pattern, head)
if filereadable(self.dir(ref)) || has_key(packed, ref)
return ref . rest
endif
endfor
let tag = matchstr(head, '.*\ze-\d\+-g\x\+$')
if !empty(tag) && (filereadable(self.dir('refs/tags/'.tag)) || has_key(packed, ref))
return head . rest
endif
if head =~# '^\x\{4,40\}$'
try
return self.rev_parse(head) . rest
catch /^fugitive:/
endtry
endif
return '/' . a:spec
endfunction
function! s:repo_translate(spec) dict abort function! s:repo_translate(spec) dict abort
if a:spec ==# '.' || a:spec ==# '/.' let spec = self.disambiguate(a:spec)
return self.bare() ? self.dir() : self.tree() if spec =~# '^/\=\.git$' && self.bare()
elseif a:spec =~# '^/\=\.git$' && self.bare()
return self.dir() return self.dir()
elseif a:spec =~# '^/\=\.git/' elseif spec =~# '^/\=\.git/'
return self.dir(s:sub(a:spec, '^/=\.git/', '')) return self.dir(s:sub(spec, '^/=\.git/', ''))
elseif a:spec =~# '^/' elseif spec =~# '^/'
return self.tree().a:spec return self.tree().spec
elseif a:spec =~# '^:[0-3]:' elseif spec =~# '^:[0-3]:'
return 'fugitive://'.self.dir().'//'.a:spec[1].'/'.a:spec[3:-1] return 'fugitive://'.self.dir().'//'.spec[1].'/'.spec[3:-1]
elseif a:spec ==# ':' elseif spec ==# ':'
if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(self.dir())] ==# self.dir('') && filereadable($GIT_INDEX_FILE) if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(self.dir())] ==# self.dir('') && filereadable($GIT_INDEX_FILE)
return fnamemodify($GIT_INDEX_FILE,':p') return fnamemodify($GIT_INDEX_FILE,':p')
else else
return self.dir('index') return self.dir('index')
endif endif
elseif a:spec =~# '^:/' elseif spec =~# '^:/'
let ref = self.rev_parse(matchstr(a:spec,'.[^:]*')) let ref = self.rev_parse(matchstr(spec,'.[^:]*'))
return 'fugitive://'.self.dir().'//'.ref return 'fugitive://'.self.dir().'//'.ref
elseif a:spec =~# '^:'
return 'fugitive://'.self.dir().'//0/'.a:spec[1:-1]
elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(self.dir(a:spec))
return self.dir(a:spec)
elseif filereadable(self.dir('refs/'.a:spec))
return self.dir('refs/'.a:spec)
elseif filereadable(self.dir('refs/tags/'.a:spec))
return self.dir('refs/tags/'.a:spec)
elseif filereadable(self.dir('refs/heads/'.a:spec))
return self.dir('refs/heads/'.a:spec)
elseif filereadable(self.dir('refs/remotes/'.a:spec))
return self.dir('refs/remotes/'.a:spec)
elseif filereadable(self.dir('refs/remotes/'.a:spec.'/HEAD'))
return self.dir('refs/remotes/'.a:spec,'/HEAD')
else
try
let ref = self.rev_parse(matchstr(a:spec,'[^:]*'))
let path = s:sub(matchstr(a:spec,':.*'),'^:','/')
return 'fugitive://'.self.dir().'//'.ref.path
catch /^fugitive:/
return self.tree(a:spec)
endtry
endif endif
let ref = matchstr(spec,'[^:]*')
let path = s:sub(matchstr(spec,':.*'),'^:','/')
if empty(path) && ref !~# '[~^]'
if filereadable(self.dir(ref))
return self.dir(ref)
else
return self.dir('packed-refs')
endif
endif
return 'fugitive://'.self.dir().'//'.self.rev_parse(ref).path
endfunction endfunction
function! s:repo_head(...) dict abort function! s:repo_head(...) dict abort
@@ -357,7 +396,7 @@ function! s:repo_head(...) dict abort
return branch return branch
endfunction endfunction
call s:add_methods('repo',['dir','tree','bare','translate','head']) call s:add_methods('repo',['dir','tree','bare','disambiguate','translate','head'])
function! s:repo_git_command(...) dict abort function! s:repo_git_command(...) dict abort
let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)
@@ -402,6 +441,11 @@ function! s:repo_superglob(base) dict abort
if a:base !~# '^/' if a:base !~# '^/'
let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"] let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"]
let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n")) let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n"))
" Add any stashes.
if filereadable(s:repo().dir('refs/stash'))
let heads += ["stash"]
let heads += sort(split(s:repo().git_chomp("stash","list","--pretty=format:%gd"),"\n"))
endif
call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base') call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
let results += heads let results += heads
endif endif
@@ -555,13 +599,24 @@ function! s:buffer_commit() dict abort
return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*') return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*')
endfunction endfunction
function! s:cpath(path) abort
if exists('+fileignorecase') && &fileignorecase
return tolower(a:path)
else
return a:path
endif
endfunction
function! s:buffer_path(...) dict abort function! s:buffer_path(...) dict abort
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*') let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
if rev != '' if rev != ''
let rev = s:sub(rev,'\w*','') let rev = s:sub(rev,'\w*','')
elseif self.spec()[0 : len(self.repo().dir())] ==# self.repo().dir() . '/' elseif s:cpath(self.spec()[0 : len(self.repo().dir())]) ==#
\ s:cpath(self.repo().dir() . '/')
let rev = '/.git'.self.spec()[strlen(self.repo().dir()) : -1] let rev = '/.git'.self.spec()[strlen(self.repo().dir()) : -1]
elseif !self.repo().bare() && self.spec()[0 : len(self.repo().tree())] ==# self.repo().tree() . '/' elseif !self.repo().bare() &&
\ s:cpath(self.spec()[0 : len(self.repo().tree())]) ==#
\ s:cpath(self.repo().tree() . '/')
let rev = self.spec()[strlen(self.repo().tree()) : -1] let rev = self.spec()[strlen(self.repo().tree()) : -1]
endif endif
return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '') return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '')
@@ -668,8 +723,17 @@ function! s:Git(bang, args) abort
let git .= ' --no-pager' let git .= ' --no-pager'
endif endif
let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=') let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
call s:ExecuteInTree('!'.git.' '.args) if exists(':terminal')
call fugitive#reload_status() let dir = s:repo().tree()
tabedit %
execute 'lcd' fnameescape(dir)
execute 'terminal' git args
else
call s:ExecuteInTree('!'.git.' '.args)
if has('win32')
call fugitive#reload_status()
endif
endif
return matchstr(a:args, '\v\C\\@<!%(\\\\)*\|\zs.*') return matchstr(a:args, '\v\C\\@<!%(\\\\)*\|\zs.*')
endfunction endfunction
@@ -706,6 +770,7 @@ augroup fugitive_status
autocmd! autocmd!
if !has('win32') if !has('win32')
autocmd FocusGained,ShellCmdPost * call fugitive#reload_status() autocmd FocusGained,ShellCmdPost * call fugitive#reload_status()
autocmd BufDelete term://* call fugitive#reload_status()
endif endif
augroup END augroup END
@@ -971,7 +1036,7 @@ function! s:StagePatch(lnum1,lnum2) abort
execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)')) execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)'))
endif endif
if !empty(reset) if !empty(reset)
execute "Git reset --patch -- ".join(map(add,'s:shellesc(v:val)')) execute "Git reset --patch -- ".join(map(reset,'s:shellesc(v:val)'))
endif endif
if exists('first_filename') if exists('first_filename')
silent! edit! silent! edit!
@@ -1043,7 +1108,7 @@ function! s:Commit(args, ...) abort
if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod
execute 'keepalt edit '.s:fnameescape(msgfile) execute 'keepalt edit '.s:fnameescape(msgfile)
elseif a:args =~# '\%(^\| \)-\%(-verbose\|\w*v\)\>' elseif a:args =~# '\%(^\| \)-\%(-verbose\|\w*v\)\>'
execute 'keepalt tabedit '.s:fnameescape(msgfile) execute 'keepalt '.(tabpagenr()-1).'tabedit '.s:fnameescape(msgfile)
elseif s:buffer().type() ==# 'index' elseif s:buffer().type() ==# 'index'
execute 'keepalt edit '.s:fnameescape(msgfile) execute 'keepalt edit '.s:fnameescape(msgfile)
execute (search('^#','n')+1).'wincmd+' execute (search('^#','n')+1).'wincmd+'
@@ -1164,13 +1229,15 @@ function! s:Merge(cmd, bang, args) abort
\ !empty(s:repo().git_chomp('diff-files', '--diff-filter=U'))) \ !empty(s:repo().git_chomp('diff-files', '--diff-filter=U')))
let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U' let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U'
else else
let &l:makeprg = s:sub(g:fugitive_git_executable.' -c core.editor=false '. let &l:makeprg = s:sub(g:fugitive_git_executable . ' ' . a:cmd .
\ a:cmd . (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') . ' ' . a:args, \ (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') .
\ ' *$', '') \ ' ' . a:args, ' *$', '')
endif endif
if !empty($GIT_EDITOR) if !empty($GIT_EDITOR) || has('win32')
let old_editor = $GIT_EDITOR let old_editor = $GIT_EDITOR
let $GIT_EDITOR = 'false' let $GIT_EDITOR = 'false'
else
let &l:makeprg = 'env GIT_EDITOR=false ' . &l:makeprg
endif endif
execute cd fnameescape(s:repo().tree()) execute cd fnameescape(s:repo().tree())
silent noautocmd make! silent noautocmd make!
@@ -1227,8 +1294,8 @@ function! s:Grep(cmd,bang,arg) abort
let dir = getcwd() let dir = getcwd()
try try
execute cd.'`=s:repo().tree()`' execute cd.'`=s:repo().tree()`'
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n') let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color')
let &grepformat = '%f:%l:%m' let &grepformat = '%f:%l:%m,%f'
exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|') exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
let list = a:cmd =~# '^l' ? getloclist(0) : getqflist() let list = a:cmd =~# '^l' ? getloclist(0) : getqflist()
for entry in list for entry in list
@@ -1303,7 +1370,14 @@ function! s:Edit(cmd,bang,...) abort
let buffer = s:buffer() let buffer = s:buffer()
if a:cmd !~# 'read' if a:cmd !~# 'read'
if &previewwindow && getbufvar('','fugitive_type') ==# 'index' if &previewwindow && getbufvar('','fugitive_type') ==# 'index'
wincmd p if winnr('$') == 1
let tabs = (&go =~# 'e' || !has('gui_running')) && &stal && (tabpagenr('$') >= &stal)
execute 'rightbelow' (&lines - &previewheight - &cmdheight - tabs - 1 - !!&laststatus).'new'
elseif winnr('#')
wincmd p
else
wincmd w
endif
if &diff if &diff
let mywinnr = winnr() let mywinnr = winnr()
for winnr in range(winnr('$'),1,-1) for winnr in range(winnr('$'),1,-1)
@@ -1334,7 +1408,7 @@ function! s:Edit(cmd,bang,...) abort
return 'redraw|echo '.string(':!'.git.' '.args) return 'redraw|echo '.string(':!'.git.' '.args)
else else
let temp = resolve(tempname()) let temp = resolve(tempname())
let s:temp_files[tolower(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist } let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist }
silent execute a:cmd.' '.temp silent execute a:cmd.' '.temp
if a:cmd =~# 'pedit' if a:cmd =~# 'pedit'
wincmd P wincmd P
@@ -1431,6 +1505,9 @@ function! s:Write(force,...) abort
let mytab = tabpagenr() let mytab = tabpagenr()
let mybufnr = bufnr('') let mybufnr = bufnr('')
let path = a:0 ? join(a:000, ' ') : s:buffer().path() let path = a:0 ? join(a:000, ' ') : s:buffer().path()
if empty(path)
return 'echoerr '.string('fugitive: cannot determine file path')
endif
if path =~# '^:\d\>' if path =~# '^:\d\>'
return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path))) return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path)))
endif endif
@@ -1588,9 +1665,9 @@ endfunction
" Section: Gdiff " Section: Gdiff
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',<f-args>)") call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',<bang>0,<f-args>)")
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gvdiff :execute s:Diff('keepalt vert ',<f-args>)") call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gvdiff :execute s:Diff('keepalt vert ',<bang>0,<f-args>)")
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gsdiff :execute s:Diff('keepalt ',<f-args>)") call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gsdiff :execute s:Diff('keepalt ',<bang>0,<f-args>)")
augroup fugitive_diff augroup fugitive_diff
autocmd! autocmd!
@@ -1667,6 +1744,7 @@ function! s:diffoff() abort
endfunction endfunction
function! s:diffoff_all(dir) abort function! s:diffoff_all(dir) abort
let curwin = winnr()
for nr in range(1,winnr('$')) for nr in range(1,winnr('$'))
if getwinvar(nr,'&diff') if getwinvar(nr,'&diff')
if nr != winnr() if nr != winnr()
@@ -1678,6 +1756,7 @@ function! s:diffoff_all(dir) abort
endif endif
endif endif
endfor endfor
execute curwin.'wincmd w'
endfunction endfunction
function! s:buffer_compare_age(commit) dict abort function! s:buffer_compare_age(commit) dict abort
@@ -1702,11 +1781,16 @@ endfunction
call s:add_methods('buffer',['compare_age']) call s:add_methods('buffer',['compare_age'])
function! s:Diff(vert,...) abort function! s:Diff(vert,keepfocus,...) abort
let args = copy(a:000)
let post = ''
if get(args, 0) =~# '^+'
let post = remove(args, 0)[1:-1]
endif
let vert = empty(a:vert) ? s:diff_modifier(2) : a:vert let vert = empty(a:vert) ? s:diff_modifier(2) : a:vert
if exists(':DiffGitCached') if exists(':DiffGitCached')
return 'DiffGitCached' return 'DiffGitCached'
elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# '' elseif (empty(args) || args[0] == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
let nr = bufnr('') let nr = bufnr('')
execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`' execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
@@ -1718,11 +1802,11 @@ function! s:Diff(vert,...) abort
call s:diffthis() call s:diffthis()
wincmd p wincmd p
call s:diffthis() call s:diffthis()
return '' return post
elseif a:0 elseif len(args)
let arg = join(a:000, ' ') let arg = join(args, ' ')
if arg ==# '' if arg ==# ''
return '' return post
elseif arg ==# '/' elseif arg ==# '/'
let file = s:buffer().path('/') let file = s:buffer().path('/')
elseif arg ==# ':' elseif arg ==# ':'
@@ -1755,13 +1839,17 @@ function! s:Diff(vert,...) abort
else else
execute 'leftabove '.vert.'diffsplit '.s:fnameescape(spec) execute 'leftabove '.vert.'diffsplit '.s:fnameescape(spec)
endif endif
let &l:readonly = &l:readonly
redraw
let w:fugitive_diff_restore = restore let w:fugitive_diff_restore = restore
let winnr = winnr() let winnr = winnr()
if getwinvar('#', '&diff') if getwinvar('#', '&diff')
wincmd p wincmd p
call feedkeys("\<C-W>p", 'n') if !a:keepfocus
call feedkeys(winnr."\<C-W>w", 'n')
endif
endif endif
return '' return post
catch /^fugitive:/ catch /^fugitive:/
return 'echoerr v:errmsg' return 'echoerr v:errmsg'
endtry endtry
@@ -1831,7 +1919,7 @@ function! s:Remove(force) abort
return 'echoerr '.string(v:errmsg) return 'echoerr '.string(v:errmsg)
else else
call fugitive#reload_status() call fugitive#reload_status()
return 'bdelete'.(a:force ? '!' : '') return 'edit'.(a:force ? '!' : '')
endif endif
endfunction endfunction
@@ -1933,7 +2021,7 @@ function! s:Blame(bang,line1,line2,count,args) abort
endif endif
let top = line('w0') + &scrolloff let top = line('w0') + &scrolloff
let current = line('.') let current = line('.')
let s:temp_files[tolower(temp)] = { 'dir': s:repo().dir(), 'args': cmd } let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd }
exe 'keepalt leftabove vsplit '.temp exe 'keepalt leftabove vsplit '.temp
let b:fugitive_blamed_bufnr = bufnr let b:fugitive_blamed_bufnr = bufnr
let w:fugitive_leave = restore let w:fugitive_leave = restore
@@ -2043,15 +2131,17 @@ function! s:BlameJump(suffix) abort
if winnr > 0 if winnr > 0
exe bufnr.'bdelete' exe bufnr.'bdelete'
endif endif
execute 'Gblame '.args if exists(':Gblame')
execute lnum execute 'Gblame '.args
let delta = line('.') - line('w0') - offset execute lnum
if delta > 0 let delta = line('.') - line('w0') - offset
execute 'normal! '.delta."\<C-E>" if delta > 0
elseif delta < 0 execute 'normal! '.delta."\<C-E>"
execute 'normal! '.(-delta)."\<C-Y>" elseif delta < 0
execute 'normal! '.(-delta)."\<C-Y>"
endif
syncbind
endif endif
syncbind
return '' return ''
endfunction endfunction
@@ -2225,7 +2315,14 @@ function! s:Browse(bang,line1,count,...) abort
elseif exists(':Browse') == 2 elseif exists(':Browse') == 2
return 'echomsg '.string(url).'|Browse '.url return 'echomsg '.string(url).'|Browse '.url
else else
return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)' if !exists('g:loaded_netrw')
runtime! autoload/netrw.vim
endif
if exists('*netrw#BrowseX')
return 'echomsg '.string(url).'|call netrw#BrowseX('.string(url).', 0)'
else
return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)'
endif
endif endif
catch /^fugitive:/ catch /^fugitive:/
return 'echoerr v:errmsg' return 'echoerr v:errmsg'
@@ -2258,6 +2355,8 @@ function! s:github_url(opts, ...) abort
else else
return root . '/commits/' . branch return root . '/commits/' . branch
endif endif
elseif path =~# '^\.git/refs/tags/'
return root . '/releases/tag/' . matchstr(path,'[^/]\+$')
elseif path =~# '^\.git/refs/.' elseif path =~# '^\.git/refs/.'
return root . '/commits/' . matchstr(path,'[^/]\+$') return root . '/commits/' . matchstr(path,'[^/]\+$')
elseif path =~# '.git/\%(config$\|hooks\>\)' elseif path =~# '.git/\%(config$\|hooks\>\)'
@@ -2283,11 +2382,8 @@ function! s:github_url(opts, ...) abort
if get(a:opts, 'line2') && a:opts.line1 == a:opts.line2 if get(a:opts, 'line2') && a:opts.line1 == a:opts.line2
let url .= '#L' . a:opts.line1 let url .= '#L' . a:opts.line1
elseif get(a:opts, 'line2') elseif get(a:opts, 'line2')
let url .= '#L' . a:opts.line1 . '-' . a:opts.line2 let url .= '#L' . a:opts.line1 . '-L' . a:opts.line2
endif endif
elseif a:opts.type == 'tag'
let commit = matchstr(getline(3),'^tag \zs.*')
let url = root . '/tree/' . commit
else else
let url = root . '/commit/' . commit let url = root . '/commit/' . commit
endif endif
@@ -2357,11 +2453,17 @@ function! s:ReplaceCmd(cmd,...) abort
let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' ' let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' '
endif endif
endif endif
let redir = ' > '.tmp
if &shellpipe =~ '2>&1'
let redir .= ' 2>&1'
endif
if s:winshell() if s:winshell()
let cmd_escape_char = &shellxquote == '(' ? '^' : '^^^' let cmd_escape_char = &shellxquote == '(' ? '^' : '^^^'
call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').' > '.tmp.'"') call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').redir.'"')
elseif &shell =~# 'fish'
call system(' begin;'.prefix.a:cmd.redir.';end ')
else else
call system(' ('.prefix.a:cmd.' > '.tmp.') ') call system(' ('.prefix.a:cmd.redir.') ')
endif endif
finally finally
if exists('old_index') if exists('old_index')
@@ -2631,6 +2733,10 @@ augroup fugitive_files
\ if exists('b:git_dir') | \ if exists('b:git_dir') |
\ call s:JumpInit() | \ call s:JumpInit() |
\ endif \ endif
autocmd FileType git,gitcommit,gitrebase
\ if exists('b:git_dir') |
\ call s:GFInit() |
\ endif
augroup END augroup END
" Section: Temp files " Section: Temp files
@@ -2642,10 +2748,10 @@ endif
augroup fugitive_temp augroup fugitive_temp
autocmd! autocmd!
autocmd BufNewFile,BufReadPost * autocmd BufNewFile,BufReadPost *
\ if has_key(s:temp_files,tolower(expand('<afile>:p'))) | \ if has_key(s:temp_files,s:cpath(expand('<afile>:p'))) |
\ let b:git_dir = s:temp_files[tolower(expand('<afile>:p'))].dir | \ let b:git_dir = s:temp_files[s:cpath(expand('<afile>:p'))].dir |
\ let b:git_type = 'temp' | \ let b:git_type = 'temp' |
\ let b:git_args = s:temp_files[tolower(expand('<afile>:p'))].args | \ let b:git_args = s:temp_files[s:cpath(expand('<afile>:p'))].args |
\ call fugitive#detect(expand('<afile>:p')) | \ call fugitive#detect(expand('<afile>:p')) |
\ setlocal bufhidden=delete nobuflisted | \ setlocal bufhidden=delete nobuflisted |
\ nnoremap <buffer> <silent> q :<C-U>bdelete<CR>| \ nnoremap <buffer> <silent> q :<C-U>bdelete<CR>|
@@ -2654,7 +2760,18 @@ augroup END
" Section: Go to file " Section: Go to file
function! s:JumpInit() abort nnoremap <SID>: :<C-U><C-R>=v:count ? v:count : ''<CR>
function! s:GFInit(...) abort
cnoremap <buffer> <expr> <Plug><cfile> fugitive#cfile()
if !exists('g:fugitive_no_maps') && empty(mapcheck('gf', 'n'))
nmap <buffer> <silent> gf <SID>:find <Plug><cfile><CR>
nmap <buffer> <silent> <C-W>f <SID>:sfind <Plug><cfile><CR>
nmap <buffer> <silent> <C-W><C-F> <SID>:sfind <Plug><cfile><CR>
nmap <buffer> <silent> <C-W>gf <SID>:tabfind <Plug><cfile><CR>
endif
endfunction
function! s:JumpInit(...) abort
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>GF("edit")<CR> nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>GF("edit")<CR>
if !&modifiable if !&modifiable
nnoremap <buffer> <silent> o :<C-U>exe <SID>GF("split")<CR> nnoremap <buffer> <silent> o :<C-U>exe <SID>GF("split")<CR>
@@ -2673,7 +2790,7 @@ function! s:JumpInit() abort
endif endif
endfunction endfunction
function! s:GF(mode) abort function! s:cfile() abort
try try
let buffer = s:buffer() let buffer = s:buffer()
let myhash = buffer.sha1() let myhash = buffer.sha1()
@@ -2683,12 +2800,10 @@ function! s:GF(mode) abort
if buffer.type('tree') if buffer.type('tree')
let showtree = (getline(1) =~# '^tree ' && getline(2) == "") let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
if showtree && line('.') == 1 if showtree && line('.') > 2
return "" return [buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$','')]
elseif showtree && line('.') > 2
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$',''))
elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t' elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$','')) return [buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$','')]
endif endif
elseif buffer.type('blob') elseif buffer.type('blob')
@@ -2698,38 +2813,40 @@ function! s:GF(mode) abort
catch /^fugitive:/ catch /^fugitive:/
endtry endtry
if exists('sha1') if exists('sha1')
return s:Edit(a:mode,0,ref) return [ref]
endif endif
else else
let dcmds = []
" Index " Index
if getline('.') =~# '^\d\{6\} \x\{40\} \d\t' if getline('.') =~# '^\d\{6\} \x\{40\} \d\t'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':') let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':')
return s:Edit(a:mode,0,file) return [file]
elseif getline('.') =~# '^#\trenamed:.* -> ' elseif getline('.') =~# '^#\trenamed:.* -> '
let file = '/'.matchstr(getline('.'),' -> \zs.*') let file = '/'.matchstr(getline('.'),' -> \zs.*')
return s:Edit(a:mode,0,file) return [file]
elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.' elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.'
let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$') let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$')
return s:Edit(a:mode,0,file) return [file]
elseif getline('.') =~# '^#\t.' elseif getline('.') =~# '^#\t.'
let file = '/'.matchstr(getline('.'),'#\t\zs.*') let file = '/'.matchstr(getline('.'),'#\t\zs.*')
return s:Edit(a:mode,0,file) return [file]
elseif getline('.') =~# ': needs merge$' elseif getline('.') =~# ': needs merge$'
let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$') let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$')
return s:Edit(a:mode,0,file).'|Gdiff' return [file, 'Gdiff!']
elseif getline('.') ==# '# Not currently on any branch.' elseif getline('.') ==# '# Not currently on any branch.'
return s:Edit(a:mode,0,'HEAD') return ['HEAD']
elseif getline('.') =~# '^# On branch ' elseif getline('.') =~# '^# On branch '
let file = 'refs/heads/'.getline('.')[12:] let file = 'refs/heads/'.getline('.')[12:]
return s:Edit(a:mode,0,file) return [file]
elseif getline('.') =~# "^# Your branch .*'" elseif getline('.') =~# "^# Your branch .*'"
let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'") let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'")
return s:Edit(a:mode,0,file) return [file]
endif endif
let showtree = (getline(1) =~# '^tree ' && getline(2) == "") let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
@@ -2739,7 +2856,7 @@ function! s:GF(mode) abort
elseif getline('.') =~# '^commit \x\{40\}\>' elseif getline('.') =~# '^commit \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
return s:Edit(a:mode,0,ref) return [ref]
elseif getline('.') =~# '^parent \x\{40\}\>' elseif getline('.') =~# '^parent \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
@@ -2749,21 +2866,21 @@ function! s:GF(mode) abort
let parent += 1 let parent += 1
let line -= 1 let line -= 1
endwhile endwhile
return s:Edit(a:mode,0,ref) return [ref]
elseif getline('.') =~ '^tree \x\{40\}$' elseif getline('.') =~ '^tree \x\{40\}$'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
if s:repo().rev_parse(myhash.':') == ref if s:repo().rev_parse(myhash.':') == ref
let ref = myhash.':' let ref = myhash.':'
endif endif
return s:Edit(a:mode,0,ref) return [ref]
elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$' elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
let type = matchstr(getline(line('.')+1),'type \zs.*') let type = matchstr(getline(line('.')+1),'type \zs.*')
elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$' elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$'
return '' let ref = buffer.rev()
elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>' elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}') let ref = matchstr(getline('.'),'\x\{40\}')
@@ -2784,18 +2901,25 @@ function! s:GF(mode) abort
endwhile endwhile
let offset += matchstr(getline(lnum), type.'\zs\d\+') let offset += matchstr(getline(lnum), type.'\zs\d\+')
let ref = getline(search('^'.type.'\{3\} [ab]/','bnW'))[4:-1] let ref = getline(search('^'.type.'\{3\} [ab]/','bnW'))[4:-1]
let dcmd = '+'.offset.'|normal! zv' let dcmds = [offset, 'normal!zv']
let dref = ''
elseif getline('.') =~# '^rename from ' elseif getline('.') =~# '^rename from '
let ref = 'a/'.getline('.')[12:] let ref = 'a/'.getline('.')[12:]
elseif getline('.') =~# '^rename to ' elseif getline('.') =~# '^rename to '
let ref = 'b/'.getline('.')[10:] let ref = 'b/'.getline('.')[10:]
elseif getline('.') =~# '^@@ -\d\+,\d\+ +\d\+,'
let diff = getline(search('^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)', 'bcnW'))
let offset = matchstr(getline('.'), '+\zs\d\+')
let dref = matchstr(diff, '\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
let ref = matchstr(diff, '\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
let dcmd = 'Gdiff! +'.offset
elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)') let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)') let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
let dcmd = 'Gdiff' let dcmd = 'Gdiff!'
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)' elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
let line = getline(line('.')-1) let line = getline(line('.')-1)
@@ -2807,7 +2931,7 @@ function! s:GF(mode) abort
let ref = getline('.') let ref = getline('.')
elseif expand('<cword>') =~# '^\x\{7,40\}\>' elseif expand('<cword>') =~# '^\x\{7,40\}\>'
return s:Edit(a:mode,0,expand('<cword>')) return [expand('<cword>')]
else else
let ref = '' let ref = ''
@@ -2833,16 +2957,38 @@ function! s:GF(mode) abort
endif endif
if exists('dref') if exists('dref')
return s:Edit(a:mode,0,ref) . '|'.dcmd.' '.s:fnameescape(dref) return [ref, dcmd . ' ' . s:fnameescape(dref)] + dcmds
elseif ref != "" elseif ref != ""
return s:Edit(a:mode,0,ref) return [ref] + dcmds
endif endif
endif endif
return '' return []
endtry
endfunction
function! s:GF(mode) abort
try
let results = s:cfile()
catch /^fugitive:/ catch /^fugitive:/
return 'echoerr v:errmsg' return 'echoerr v:errmsg'
endtry endtry
if len(results)
return s:Edit(a:mode, 0, results[0]).join(map(results[1:-1], '"|".v:val'), '')
else
return ''
endif
endfunction
function! fugitive#cfile() abort
let pre = ''
let results = s:cfile()
if empty(results)
return expand('<cfile>')
elseif len(results) > 1
let pre = '+' . join(map(results[1:-1], 'escape(v:val, " ")'), '\|') . ' '
endif
return pre . s:fnameescape(fugitive#repo().translate(results[0]))
endfunction endfunction
" Section: Statusline " Section: Statusline
@@ -2880,6 +3026,11 @@ function! fugitive#head(...) abort
return s:repo().head(a:0 ? a:1 : 0) return s:repo().head(a:0 ? a:1 : 0)
endfunction endfunction
augroup fugitive_statusline
autocmd!
autocmd User Flags call Hoist('buffer', function('fugitive#statusline'))
augroup END
" Section: Folding " Section: Folding
function! fugitive#foldtext() abort function! fugitive#foldtext() abort