Support expansion flags

This commit is contained in:
Tim Pope
2018-08-28 00:35:06 -04:00
parent 1e3786734b
commit fd83fcaf90
2 changed files with 69 additions and 27 deletions

View File

@@ -53,11 +53,12 @@ function! s:shellesc(arg) abort
endif
endfunction
let s:fnameescape = " \t\n*?[{`$\\%#'\"|!<"
function! s:fnameescape(file) abort
if exists('*fnameescape')
return fnameescape(a:file)
else
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
return escape(a:file, s:fnameescape)
endif
endfunction
@@ -641,18 +642,13 @@ function! s:Generate(rev, ...) abort
return fugitive#Route(object, dir)
endfunction
function! s:RemoveDot(path, ...) abort
if a:path !~# '^\./'
return a:path
function! s:DotRelative(path) abort
let cwd = getcwd()
let path = substitute(a:path, '^[~$]\i*', '\=expand(submatch(0))', '')
if s:cpath(cwd . '/', (path . '/')[0 : len(cwd)])
return '.' . strpart(path, len(cwd))
endif
let dir = a:0 ? a:1 : get(b:, 'git_dir', '')
let cdir = fugitive#CommonDir(dir)
if len(filter(['', '/tags', '/heads', '/remotes'], 'getftime(cdir . "/refs" . v:val . a:path[1:-1]) >= 0')) ||
\ a:path =~# 'HEAD$' && filereadable(dir . a:path[1:-1]) ||
\ a:path =~# '^\./refs/' && filereadable(cdir . a:path[1:-1])
return a:path
endif
return a:path[2:-1]
return a:path
endfunction
function! fugitive#Object(...) abort
@@ -681,6 +677,44 @@ function! fugitive#Object(...) abort
endif
endfunction
let s:var = '\%(%\|#<\=\d\+\|##\=\)'
let s:flag = '\%(:[p8~.htre]\|:g\=s\(.\).\{-\}\1.\{-\}\1\)'
let s:expand = '\%(\(' . s:var . '\)\(' . s:flag . '*\)\(:S\)\=\)'
function! s:BufName(var) abort
if a:var ==# '%'
return bufname(get(b:, 'fugitive_blamed_bufnr', ''))
elseif a:var =~# '^#\d*$'
let nr = getbufvar(+a:var[1:-1], 'fugitive_blamed_bufnr', '')
return bufname(nr ? nr : +a:var[1:-1])
else
return expand(a:var)
endif
endfunction
function! s:ExpandVar(other, var, flags, esc) abort
if a:other =~# '^\'
return a:other[1:-1]
elseif a:other =~# '^!'
let buffer = s:BufName(len(a:other) > 1 ? '#'. a:other[1:-1] : '%')
let owner = s:Owner(buffer)
return len(owner) ? owner : '@'
endif
let flags = a:flags
let file = s:DotRelative(fugitive#Real(s:BufName(a:var)))
while len(flags)
let flag = matchstr(flags, s:flag)
let flags = strpart(flags, len(flag))
if flag ==# ':.'
let file = s:DotRelative(file)
else
let file = fnamemodify(file, flag)
endif
endwhile
let file = s:Slash(file)
return (len(a:esc) ? shellescape(file) : file)
endfunction
function! s:Expand(rev) abort
if a:rev =~# '^:[0-3]$'
let file = a:rev . s:Relative(':')
@@ -688,19 +722,26 @@ function! s:Expand(rev) abort
let file = 'HEAD^{}' . a:rev[1:-1] . s:Relative(':')
elseif a:rev =~# '^@{'
let file = 'HEAD' . a:rev. s:Relative(':')
elseif a:rev =~# '^[~^]/\@!'
elseif a:rev =~# '^\^[0-9~^{]\|^\~[0-9~^]'
let commit = substitute(s:DirCommitFile(@%)[1], '^\d\=$', 'HEAD', '')
let file = commit . a:rev . s:Relative(':')
else
let file = a:rev
endif
return s:sub(substitute(file,
\ '\([%#]\)$\|\\\([[:punct:]]\)','\=len(submatch(2)) ? submatch(2) : fugitive#Path(expand(submatch(1)))','g'),
\ '\.\@<=/$','')
return substitute(file,
\ '\(\\[' . s:fnameescape . ']\|^\\[>+-]\|!\d*\)\|' . s:expand,
\ '\=s:ExpandVar(submatch(1),submatch(2),submatch(3),"")', 'g')
endfunction
function! fugitive#Expand(object) abort
return substitute(a:object,
\ '\(\\[' . s:fnameescape . ']\|^\\[>+-]\|!\d*\)\|' . s:expand,
\ '\=s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5))', 'g')
endfunction
function! s:ShellExpand(cmd) abort
return substitute(a:cmd, '\\\@<![%#]:\@!', '\=s:RemoveDot(fugitive#Path(expand(submatch(0)), "./"))', 'g')
return substitute(a:cmd, '\(\\[!#%]\|!\d*\)\|' . s:expand,
\ '\=s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5))', 'g')
endfunction
let s:trees = {}