Provide :Gbrowse to open code in web browser
This commit is contained in:
parent
af9d44f91b
commit
d6615891c2
@ -17,7 +17,8 @@ mofo. And guess what `:Gcommit` does!
|
|||||||
|
|
||||||
`:Gblame` brings up an interactive vertical split with `git blame`
|
`:Gblame` brings up an interactive vertical split with `git blame`
|
||||||
output. Press enter on a line to reblame the file as it stood in that
|
output. Press enter on a line to reblame the file as it stood in that
|
||||||
commit, or `o` to open that commit in a split.
|
commit, or `o` to open that commit in a split. When you're done, use
|
||||||
|
`:Gedit` in the historic buffer to go back to the work tree version.
|
||||||
|
|
||||||
`:Gmove` does a `git mv` on a file and simultaneously renames the
|
`:Gmove` does a `git mv` on a file and simultaneously renames the
|
||||||
buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes
|
buffer. `:Gremove` does a `git rm` on a file and simultaneously deletes
|
||||||
@ -35,6 +36,10 @@ and you never get any warnings about the file changing outside Vim.
|
|||||||
making it like `git add` when called from a work tree file and like
|
making it like `git add` when called from a work tree file and like
|
||||||
`git checkout` when called from the index or a blob in history.
|
`git checkout` when called from the index or a blob in history.
|
||||||
|
|
||||||
|
Use `:Gbrowse` to open the current file on GitHub, with optional line
|
||||||
|
range (try it in visual mode!). If your current repository isn't on
|
||||||
|
GitHub, `git instaweb` will be spun up instead.
|
||||||
|
|
||||||
Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator
|
Add `%{fugitive#statusline()}` to `'statusline'` to get an indicator
|
||||||
with the current branch in (surprise!) your statusline.
|
with the current branch in (surprise!) your statusline.
|
||||||
|
|
||||||
|
@ -154,6 +154,33 @@ 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*
|
||||||
|
:[range]Gbrowse If the remote for the current branch is on GitHub,
|
||||||
|
open the current file, blob, tree, commit, or tag
|
||||||
|
(with git-web--browse) on GitHub. Otherwise, open the
|
||||||
|
current flie, blob, tree, commit, or tag in
|
||||||
|
git-instaweb (if you have issues, verify you can run
|
||||||
|
"git instaweb" from a terminal). If a range is given,
|
||||||
|
it is appropriately appended to the URL as an anchor.
|
||||||
|
|
||||||
|
:[range]Gbrowse! Like :Gbrowse, but put the URL on the clipboard rather
|
||||||
|
than opening it.
|
||||||
|
|
||||||
|
:[range]Gbrowse - Like :Gbrowse, but tie the URL to the current HEAD.
|
||||||
|
This is useful in a work tree file to ensure the link
|
||||||
|
always goes to the file as it currently stands, rather
|
||||||
|
than whatever the latest on master is. Note that
|
||||||
|
when editing a historical file, said link is tied by
|
||||||
|
default to the commit you're currently browsing. (The
|
||||||
|
intent is that ultimately, one will be able to specify
|
||||||
|
any |fugitive-revision| here, but the current
|
||||||
|
implementation is limited to this one special case.)
|
||||||
|
|
||||||
|
[range]Gbrowse [...]@{remote}
|
||||||
|
Force using the given remote rather than the remote
|
||||||
|
for the current branch. The remote is used to
|
||||||
|
determine which GitHub repository to link to.
|
||||||
|
|
||||||
MAPPINGS *fugitive-mappings*
|
MAPPINGS *fugitive-mappings*
|
||||||
|
|
||||||
These maps are available in Git objects.
|
These maps are available in Git objects.
|
||||||
|
@ -900,7 +900,7 @@ call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gtabedit
|
|||||||
call s:command("-bar -bang -nargs=? -count -complete=customlist,s:EditComplete Gread :execute s:Edit((!<count> && <line1> ? '' : <count>).'read<bang>',<f-args>)")
|
call s:command("-bar -bang -nargs=? -count -complete=customlist,s:EditComplete Gread :execute s:Edit((!<count> && <line1> ? '' : <count>).'read<bang>',<f-args>)")
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
" Gwrite {{{1
|
" Gwrite, Gwq {{{1
|
||||||
|
|
||||||
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwrite :execute s:Write(<bang>0,<f-args>)")
|
call s:command("-bar -bang -nargs=? -complete=customlist,s:EditComplete Gwrite :execute s:Write(<bang>0,<f-args>)")
|
||||||
|
|
||||||
@ -1367,6 +1367,127 @@ function! s:BlameSyntax() abort
|
|||||||
hi def link FugitiveblameNotCommittedYet Comment
|
hi def link FugitiveblameNotCommittedYet Comment
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" }}}1
|
||||||
|
" Gbrowse {{{1
|
||||||
|
|
||||||
|
call s:command("-bar -bang -count=0 -nargs=? Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
|
||||||
|
|
||||||
|
function! s:Browse(bang,line1,count,...) abort
|
||||||
|
try
|
||||||
|
let rev = a:0 ? substitute(a:1,'@[[:alnum:]_-]\+$','','') : ''
|
||||||
|
if a:0 && a:1 =~# '@[[:alnum:]_-]\+$'
|
||||||
|
let remote = matchstr(a:1,'@\zs[[:alnum:]_-]\+$')
|
||||||
|
elseif s:buffer().path() =~# '^\.git/refs/remotes/.'
|
||||||
|
let remote = matchstr(s:buffer().path(),'^\.git/refs/remotes/\zs[^/]\+')
|
||||||
|
else
|
||||||
|
let remote = 'origin'
|
||||||
|
let branch = matchstr(s:repo().head_ref(),'\<refs/heads/\zs.*')
|
||||||
|
if branch != ''
|
||||||
|
let remote = s:repo().git_chomp('config','branch.'.branch.'.remote')
|
||||||
|
if remote == ''
|
||||||
|
let remote = 'origin'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
let raw = s:repo().git_chomp('config','remote.'.remote.'.url')
|
||||||
|
let url = s:github_url(s:buffer(),raw,rev,a:line1,a:count)
|
||||||
|
if url == ''
|
||||||
|
let url = s:instaweb_url(s:buffer(),rev,a:count ? a:line1 : 0)
|
||||||
|
endif
|
||||||
|
if url == ''
|
||||||
|
call s:throw("Instaweb failed to start and '".remote."' is not a GitHub remote")
|
||||||
|
endif
|
||||||
|
if a:bang
|
||||||
|
let @* = url
|
||||||
|
return 'echomsg '.string(url)
|
||||||
|
else
|
||||||
|
return 'echomsg '.string(url).'|silent Git web--browse '.shellescape(url,1)
|
||||||
|
endif
|
||||||
|
catch /^fugitive:/
|
||||||
|
return 'echoerr v:errmsg'
|
||||||
|
endtry
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:github_url(buffer,url,rev,line1,line2) abort
|
||||||
|
let self = a:buffer
|
||||||
|
let path = self.path()
|
||||||
|
let repo = matchstr(a:url,'^\%(https\=://\|git://\|git@\)github\.com[/:]\zs.\{-\}\ze\%(\.git\)\=$')
|
||||||
|
if repo ==# ''
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
let root = 'http://github.com/' . repo
|
||||||
|
if path =~# '^\.git/refs/.'
|
||||||
|
return root . '/tree/' . matchstr(path,'[^/]\+$')
|
||||||
|
elseif path ==# '.git/config'
|
||||||
|
return root . '/admin'
|
||||||
|
elseif path =~# '^\.git\>'
|
||||||
|
return root
|
||||||
|
endif
|
||||||
|
if a:rev ==# '-'
|
||||||
|
let commit = self.repo().rev_parse('HEAD')
|
||||||
|
elseif self.commit() =~# '^\x\{40\}$'
|
||||||
|
let commit = self.commit()
|
||||||
|
else
|
||||||
|
let commit = matchstr(self.repo().head_ref(),'[^/]\+$')
|
||||||
|
endif
|
||||||
|
if self.type() ==# 'directory' || self.type() ==# 'tree'
|
||||||
|
let url = s:sub(root . '/tree/' . commit . '/' . path,'/$','')
|
||||||
|
elseif self.type() ==# 'file' || self.type() ==# 'blob'
|
||||||
|
let url = root . '/blob/' . commit . '/' . path
|
||||||
|
if a:line2 && a:line1 == a:line2
|
||||||
|
let url .= '#L' . a:line1
|
||||||
|
elseif a:line2
|
||||||
|
let url .= '#L' . a:line1 . '-' . a:line2
|
||||||
|
endif
|
||||||
|
elseif self.type() ==# 'tag'
|
||||||
|
let commit = matchstr(getline(3),'^tag \zs.*')
|
||||||
|
let url = root . '/tree/' . commit
|
||||||
|
else
|
||||||
|
let url = root . '/commit/' . commit
|
||||||
|
endif
|
||||||
|
return url
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:instaweb_url(buffer,rev,...) abort
|
||||||
|
let self = a:buffer
|
||||||
|
let path = self.path()
|
||||||
|
let output = self.repo().git_chomp('instaweb','-b','unknown')
|
||||||
|
if output =~# 'http://'
|
||||||
|
let root = matchstr(output,'http://.*').'/?p='.fnamemodify(self.repo().dir(),':t')
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
if path =~# '^\.git/refs/.'
|
||||||
|
return root . ';a=shortlog;h=' . matchstr(path,'^\.git/\zs.*')
|
||||||
|
elseif path =~# '^\.git\>'
|
||||||
|
return root
|
||||||
|
endif
|
||||||
|
let url = root
|
||||||
|
if self.commit() =~# '^\x\{40\}$' || a:rev ==# '-'
|
||||||
|
let ref = a:rev ==# '-' ? 'HEAD' : self.commit()
|
||||||
|
let url .= ';h=' . self.repo().rev_parse(ref . path)
|
||||||
|
else
|
||||||
|
if self.type() ==# 'file' || self.type() ==# 'blob'
|
||||||
|
let tmp = tempname()
|
||||||
|
silent execute 'write !'.self.repo().git_command('hash-object','-w','--stdin').' > '.tmp
|
||||||
|
let url .= ';h=' . readfile(tmp)[0]
|
||||||
|
else
|
||||||
|
try
|
||||||
|
let url .= ';h=' . self.repo().rev_parse(self.path((self.commit() == '' ? 'HEAD' : ':'.self.commit()).':'))
|
||||||
|
catch /^fugitive:/
|
||||||
|
endtry
|
||||||
|
endif
|
||||||
|
let root .= ';hb=' . matchstr(self.repo().head_ref(),'[^ ]\+$')
|
||||||
|
endif
|
||||||
|
if path !=# ''
|
||||||
|
let url .= ';f=' . path
|
||||||
|
endif
|
||||||
|
if a:0 && a:1
|
||||||
|
let url .= '#l' . a:1
|
||||||
|
endif
|
||||||
|
return url
|
||||||
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
" File access {{{1
|
" File access {{{1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user