diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index 5512ebf..5b30106 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -3371,44 +3371,66 @@ function! s:LogComplete(A, L, P) abort return s:CompleteSubcommand('log', a:A, a:L, a:P) endfunction -function! s:Grep(cmd,bang,arg) abort - let listnr = a:cmd =~# '^l' ? 0 : -1 - let grepprg = &grepprg - let grepformat = &grepformat - try - let cdback = s:Cd(s:Tree()) - let &grepprg = s:UserCommand() . ' --no-pager grep -n --no-color' - let &grepformat = '%f:%l:%c:%m,%f:%l:%m,%m %f match%ts,%f' - if fugitive#GitVersion(2, 19) - let &grepprg .= ' --column' +function! s:GrepParseLine(cached, name_only, dir, line) abort + if a:line =~# '^git: \|^usage: \|^error: \|^fatal: ' + return {'text': a:line} + endif + let entry = {'valid': 1} + let match = matchlist(a:line, '^\(.\{-\}\):\(\d\+\):\(\d\+:\)\=\(.*\)$') + if len(match) + let entry.module = match[1] + let entry.lnum = +match[2] + let entry.col = +match[3] + let entry.text = match[4] + else + let entry.module = matchstr(a:line, '\CBinary file \zs.*\ze matches$') + if len(entry.module) + let entry.text = 'Binary file' + let entry.valid = 0 endif - let args = s:SplitExpand(a:arg) - exe a:cmd.'! '.escape(s:shellesc(args), '|#%') - let list = s:GetLocList(listnr) - for entry in list - if bufname(entry.bufnr) =~ ':' - let entry.filename = s:Generate(bufname(entry.bufnr)) - unlet! entry.bufnr - let changed = 1 - elseif s:HasOpt(args, '--cached') - let entry.filename = s:Generate(':0:'.bufname(entry.bufnr)) - unlet! entry.bufnr - let changed = 1 - endif - endfor - if exists('changed') - call s:SetLocList(listnr, list, 'r') - endif - if !a:bang && !empty(list) - return (listnr < 0 ? 'c' : 'l').'first' - else - return '' - endif - finally - let &grepprg = grepprg - let &grepformat = grepformat - execute cdback - endtry + endif + if empty(entry.module) && a:name_only + let entry.module = a:line + endif + if empty(entry.module) + return {'text': a:line} + endif + if a:cached + let entry.module = ':0:' . entry.module + endif + if entry.module !~# ':' + let entry.filename = fugitive#Find(':(top)' . entry.module, a:dir) + else + let entry.filename = fugitive#Find(entry.module, a:dir) + endif + return entry +endfunction + +function! s:Grep(type, bang, arg) abort + let dir = s:Dir() + let listnr = a:type =~# '^l' ? 0 : -1 + let cmd = s:UserCommandList(dir) + ['--no-pager', 'grep', '-n', '--no-color', '--full-name'] + if fugitive#GitVersion(2, 19) + call add(cmd, '--column') + endif + let args = s:SplitExpand(a:arg, s:Tree(dir)) + if exists(':chistory') + call s:SetLocList(listnr, [], ' ', {'title': (listnr < 0 ? ':Ggrep ' : ':Glgrep ') . s:fnameescape(args)}) + else + call s:SetLocList(listnr, [], ' ') + endif + let tempfile = tempname() + exe '!' . s:shellesc(cmd + args) + \ printf(&shellpipe . (&shellpipe =~# '%s' ? '' : ' %s'), s:shellesc(tempfile)) + let cached = s:HasOpt(args, '--cached') + let name_only = s:HasOpt(args, '-l', '--files-with-matches', '--name-only', '-L', '--files-without-match') + let list = map(readfile(tempfile), 's:GrepParseLine(cached, name_only, dir, v:val)') + call s:SetLocList(listnr, list, 'a') + if !a:bang && !empty(list) + return (listnr < 0 ? 'c' : 'l').'first' + else + return '' + endif endfunction function! s:Log(type, bang, line1, count, args) abort @@ -3474,8 +3496,8 @@ function! s:Log(type, bang, line1, count, args) abort return '' endfunction -call s:command("-bar -bang -nargs=? -complete=customlist,s:GrepComplete Ggrep :execute s:Grep('grep',0,)") -call s:command("-bar -bang -nargs=? -complete=customlist,s:GrepComplete Glgrep :execute s:Grep('lgrep',0,)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:GrepComplete Ggrep :execute s:Grep('c',0,)") +call s:command("-bar -bang -nargs=? -complete=customlist,s:GrepComplete Glgrep :execute s:Grep('l',0,)") call s:command("-bar -bang -nargs=? -range=-1 -complete=customlist,s:LogComplete Glog :exe s:Log('c',0,,,)") call s:command("-bar -bang -nargs=? -range=-1 -complete=customlist,s:LogComplete Gllog :exe s:Log('l',0,,,)")