@@ -53,11 +53,12 @@ function! s:shellesc(arg) abort
5353 endif
5454endfunction
5555
56+ let s: fnameescape = " \t \n *?[{`$\\ %#'\" |!<"
5657function ! s: fnameescape (file ) abort
5758 if exists (' *fnameescape' )
5859 return fnameescape (a: file )
5960 else
60- return escape (a: file ," \t \n *?[{`$ \\ %#' \" |!< " )
61+ return escape (a: file , s: fnameescape )
6162 endif
6263endfunction
6364
@@ -641,18 +642,13 @@ function! s:Generate(rev, ...) abort
641642 return fugitive#Route (object, dir )
642643endfunction
643644
644- function ! s: RemoveDot (path , ... ) abort
645- if a: path !~# ' ^\./'
646- return a: path
647- endif
648- let dir = a: 0 ? a: 1 : get (b: , ' git_dir' , ' ' )
649- let cdir = fugitive#CommonDir (dir )
650- if len (filter ([' ' , ' /tags' , ' /heads' , ' /remotes' ], ' getftime(cdir . "/refs" . v:val . a:path[1:-1]) >= 0' )) ||
651- \ a: path = ~# ' HEAD$' && filereadable (dir . a: path [1 :-1 ]) ||
652- \ a: path = ~# ' ^\./refs/' && filereadable (cdir . a: path [1 :-1 ])
653- return a: path
645+ function ! s: DotRelative (path ) abort
646+ let cwd = getcwd ()
647+ let path = substitute (a: path , ' ^[~$]\i*' , ' \=expand(submatch(0))' , ' ' )
648+ if s: cpath (cwd . ' /' , (path . ' /' )[0 : len (cwd)])
649+ return ' .' . strpart (path , len (cwd))
654650 endif
655- return a: path[ 2 : -1 ]
651+ return a: path
656652endfunction
657653
658654function ! fugitive#Object (... ) abort
@@ -681,26 +677,71 @@ function! fugitive#Object(...) abort
681677 endif
682678endfunction
683679
680+ let s: var = ' \%(%\|#<\=\d\+\|##\=\)'
681+ let s: flag = ' \%(:[p8~.htre]\|:g\=s\(.\).\{-\}\1.\{-\}\1\)'
682+ let s: expand = ' \%(\(' . s: var . ' \)\(' . s: flag . ' *\)\(:S\)\=\)'
683+
684+ function ! s: BufName (var ) abort
685+ if a: var == # ' %'
686+ return bufname (get (b: , ' fugitive_blamed_bufnr' , ' ' ))
687+ elseif a: var = ~# ' ^#\d*$'
688+ let nr = getbufvar (+ a: var [1 :-1 ], ' fugitive_blamed_bufnr' , ' ' )
689+ return bufname (nr ? nr : + a: var [1 :-1 ])
690+ else
691+ return expand (a: var )
692+ endif
693+ endfunction
694+
695+ function ! s: ExpandVar (other, var , flags, esc) abort
696+ if a: other = ~# ' ^\'
697+ return a: other [1 :-1 ]
698+ elseif a: other = ~# ' ^!'
699+ let buffer = s: BufName (len (a: other ) > 1 ? ' #' . a: other [1 :-1 ] : ' %' )
700+ let owner = s: Owner (buffer )
701+ return len (owner) ? owner : ' @'
702+ endif
703+ let flags = a: flags
704+ let file = s: DotRelative (fugitive#Real (s: BufName (a: var )))
705+ while len (flags)
706+ let flag = matchstr (flags, s: flag )
707+ let flags = strpart (flags, len (flag))
708+ if flag == # ' :.'
709+ let file = s: DotRelative (file )
710+ else
711+ let file = fnamemodify (file , flag)
712+ endif
713+ endwhile
714+ let file = s: Slash (file )
715+ return (len (a: esc ) ? shellescape (file ) : file )
716+ endfunction
717+
684718function ! s: Expand (rev) abort
685719 if a: rev = ~# ' ^:[0-3]$'
686720 let file = a: rev . s: Relative (' :' )
687721 elseif a: rev = ~# ' ^-'
688722 let file = ' HEAD^{}' . a: rev [1 :-1 ] . s: Relative (' :' )
689723 elseif a: rev = ~# ' ^@{'
690724 let file = ' HEAD' . a: rev . s: Relative (' :' )
691- elseif a: rev = ~# ' ^[~^]/\@! '
725+ elseif a: rev = ~# ' ^\^[0-9~^{]\|^\~[0-9~^] '
692726 let commit = substitute (s: DirCommitFile (@% )[1 ], ' ^\d\=$' , ' HEAD' , ' ' )
693727 let file = commit . a: rev . s: Relative (' :' )
694728 else
695729 let file = a: rev
696730 endif
697- return s: sub (substitute (file ,
698- \ ' \([%#]\)$\|\\\([[:punct:]]\)' ,' \=len(submatch(2)) ? submatch(2) : fugitive#Path(expand(submatch(1)))' ,' g' ),
699- \ ' \.\@<=/$' ,' ' )
731+ return substitute (file ,
732+ \ ' \(\\[' . s: fnameescape . ' ]\|^\\[>+-]\|!\d*\)\|' . s: expand ,
733+ \ ' \=s:ExpandVar(submatch(1),submatch(2),submatch(3),"")' , ' g' )
734+ endfunction
735+
736+ function ! fugitive#Expand (object) abort
737+ return substitute (a: object ,
738+ \ ' \(\\[' . s: fnameescape . ' ]\|^\\[>+-]\|!\d*\)\|' . s: expand ,
739+ \ ' \=s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5))' , ' g' )
700740endfunction
701741
702742function ! s: ShellExpand (cmd) abort
703- return substitute (a: cmd , ' \\\@<![%#]:\@!' , ' \=s:RemoveDot(fugitive#Path(expand(submatch(0)), "./"))' , ' g' )
743+ return substitute (a: cmd , ' \(\\[!#%]\|!\d*\)\|' . s: expand ,
744+ \ ' \=s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5))' , ' g' )
704745endfunction
705746
706747let s: trees = {}
0 commit comments