Last active
March 9, 2016 22:58
-
-
Save AndrewRadev/1478115 to your computer and use it in GitHub Desktop.
Start a github pull request from Vim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" Usage: | |
" | |
" :Ginitpull [remote-name] [branch-name] | |
" | |
" Initiates a github pull request in the default browser, from the given | |
" branch name to master, on the given remote. Tab-completes both arguments. | |
" | |
" If called without any arguments, defaults to the "origin" remote and the | |
" current branch name, which is probably what you usually want. | |
" | |
command! -complete=custom,s:GinitpullComplete -nargs=* Ginitpull call s:Ginitpull(<f-args>) | |
function! s:Ginitpull(...) | |
let remote_name = get(a:000, 0, 'origin') | |
let branch_name = get(a:000, 1, '') | |
try | |
if branch_name == '' | |
let branch_name = s:CurrentGitBranch() | |
endif | |
let github_path = s:GithubPath(remote_name) | |
catch /./ | |
echoerr v:exception | |
endtry | |
call s:OpenURL('https://github.com/'.github_path.'/pull/new/'.branch_name) | |
endfunction | |
function! s:GithubPath(remote_name) | |
for remote in split(system('git remote -v'), "\n") | |
if remote =~ '^'.a:remote_name | |
if remote =~ '[email protected]' | |
return substitute(remote, '.*[email protected]:\(.*\)\.git.*', '\1', '') | |
elseif remote =~ 'https\?://github\.com' | |
return substitute(remote, '.*https\?://github\.com/\(.*\)\.git.*', '\1', '') | |
endif | |
endif | |
endfor | |
throw 'No remote "'.a:remote_name.'" was found, or remote is not from github.' | |
endfunction | |
function! s:CurrentGitBranch() | |
" Search upwards for relevant files | |
let head_file = findfile('.git/HEAD', ';') | |
let dot_git_file = findfile('.git', ';') | |
if filereadable(head_file) | |
let head_ref = readfile(head_file)[0] | |
elseif filereadable(dot_git_file) | |
let module_file = readfile(dot_git_file)[0] | |
let module_file = substitute(module_file, 'gitdir: \(.*\)', '\1/HEAD', '') | |
let head_ref = readfile(module_file)[0] | |
else | |
throw 'This doesn''t look like a git repository, neither .git/HEAD nor .git were found.' | |
endif | |
return substitute(head_ref, 'ref: refs/heads/\(.*\)', '\1', '') | |
endfunction | |
function! s:GinitpullComplete(argument_lead, command_line, cursor_position) | |
if a:argument_lead != '' | |
" then we're in the middle of an argument, remove it from the command-line | |
let start_of_line = substitute(a:command_line, a:argument_lead.'$', '', '') | |
else | |
" just take the entire command-line | |
let start_of_line = a:command_line | |
end | |
let arg_count = len(split(start_of_line, '\s\+')) | |
if arg_count <= 1 | |
" first argument: remote | |
let completions = s:TrimLines(system('git remote')) | |
elseif arg_count == 2 | |
" second argument: branch | |
let completions = substitute(system('git branch'), '\*\s*', '', 'g') | |
let completions = s:TrimLines(completions) | |
else | |
" can't handle more than 2 arguments | |
let completions = '' | |
endif | |
return completions | |
endfunction | |
function! s:OpenURL(url) | |
let url = shellescape(a:url) | |
if has('mac') | |
silent call system('open '.url) | |
elseif has('unix') | |
if executable('xdg-open') | |
silent call system('xdg-open '.url.' 2>&1 > /dev/null &') | |
else | |
echoerr "You need to install xdg-open to be able to open urls" | |
return | |
end | |
else | |
echoerr "Don't know how to open a URL on this system" | |
return | |
end | |
echo "Opening ".url | |
endfunction | |
function! s:Trim(s) | |
let s = a:s | |
let s = substitute(s, '^\_s\+', '', '') | |
let s = substitute(s, '\_s\+$', '', '') | |
return s | |
endfunction | |
" Trim a list of items | |
function! s:TrimList(ss) | |
return map(a:ss, 's:Trim(v:val)') | |
endfunction | |
" Trim each line in the given string | |
function! s:TrimLines(s) | |
return join(s:TrimList(split(a:s, "\n")), "\n") | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment