How to Upload Files to Github From Vim
Open Local Files and Line Numbers in GitHub and GitLab From Trounce or Vim
Table of Contents
- Problem
- Solution
- Git Subcommand
- Vim Control
- Conclusion
Trouble
I oftentimes demand to share links and URLs to files in GitHub/GitLab repositories with colleagues.
Traditionally, I did this manually past launching a browser, navigating to the repository and file, and then selecting the line numbers in question, and finally copying the permalink or the link of the electric current branch.
Because this procedure takes several minutes, it was enough to cause significant context switching and breaks me out of the flow, causing me to lose my railroad train of thought (relevant comic).
Ane feature I appreciated in vim-fugitive was the :Gbrowse command on a buffer or a range (i.e. :Gbrowse on a visual selection) that would open the electric current file and line number directly on GitHub.
I wanted to implement this feature in my minimal vim setup, simply I also wanted to be able to utilize this in a shell without vim.
In this blog postal service, I will walk you through the process of implementing this solution one building block at a time.
Solution
I had an idea of the experience I wanted.
I wanted to be able to call git commands from the beat out, like:
# open local repo in GitHub (GH) / GitLab (GL) $ git browse # open a file from local repo in GH/GL # $ git browse <filename> $ git browse README.md # open up a file & line number from local repo in GH/GL # $ git browse <filename> <line_number> $ git scan README.md one # open a file & select range of lines from local repo in GH/GL # $ git browse <filename> <line_from> <line_to> $ git browse README.md 1 5
And I wanted to exist able to call the same functionality within vim, like:
" open current file & line nether cursor in GH/GL :Gbrowse " open line range from vim in GH/GL : 1 , vGbrowse
With that rough specification in mind, let'south dive into the implementation.
Git Subcommand
If you didn't know, git allows you to define your own custom subcommands as long as the file name starts with git- prefix and the file is located in your $PATH.
With this data in listen, we can start by creating a file called git-browse located in ${HOME}/bin (bold ${HOME}/bin is in your $PATH)
git-browse file will be a straight forward shell script:
- Define shebang and expected inputs:
#!/usr/bin/env bash filename = " ${ one } " line1 = " ${ 2 } " line2 = " ${ 3 } "
- Get some additional data we will need, like branch name, remote name, and remote-url:
co-operative = $(git rev-parse --abbrev-ref HEAD ii> /dev/null) remote = $(git config branch." ${ co-operative } ".remote || repeat "origin" ) giturl = " $(git remote get-url " ${ remote } " ) "
- I ever apply HTTPS for git URLs, only if you apply SSH, and then you would want to convert
git@*tohttps://*. Besides, remove the trailing.gitin the HTTP URL:
if [[ $giturl = git@* ]] ; then giturl = $( echo $giturl | sed -E -e 's/:/\//' -due east 's/\.git$//' -e 's/.*@(.*)/http:\/\/\1/' ) fi url = " ${ giturl %.git } "
- At present we arts and crafts the URL with filenames and line numbers based on the domain (GH & GL have slight nuances):
# GitLab Case: https://gitlab.instance.com/group/repo/-/blob/commit_or_branch/path/to/filename#L1-ii if [[ " ${ giturl } " =~ gitlab ]] ; and then if [[ -northward " ${ filename } " ]] ; then commit_hash = " $(git log -n1 --format =format:"%H" " ${ filename } " two>/dev/aught) " # append '/-/hulk' + commit hash or co-operative proper name + '/<filename>' url = " ${ url } /-/blob/ ${ commit_hash :-${ branch }} / ${ filename } " if [[ -n " ${ line1 } " ]] ; then # append '#L<LINE1>' url = " ${ url } #L ${ line1 } " if [[ -due north " ${ line2 } " ]] ; then # suspend '-<LINE2>' url = " ${ url } - ${ line2 } " fi fi fi fi # GitHub Example: https://github.example.com/org/repo/blob/commit_or_branch/path/to/filename#L1-L2 # Mostly the same as above, except: # - no '/-/' # - '#L1-L2' instead of '#L1-2'
- Lastly, open the crafted URL:
hash open up 2>/dev/zip && open " ${ url } " hash xdg-open 2>/dev/null && xdg-open " ${ url } "
- Don't forget to
chmod +x ${HOME}/bin/git-browse
At present, these commands should work
$ git scan $ git browse README.physician $ git browse README.md ane $ git browse README.dr. ane v
And that is one-half the battle!
TLDR
#!/usr/bin/env bash filename = " ${ one } " line1 = " ${ 2 } " line2 = " ${ 3 } " branch = $(git rev-parse --abbrev-ref HEAD 2> /dev/null) remote = $(git config branch." ${ co-operative } ".remote || echo "origin" ) giturl = " $(git remote get-url " ${ remote } " ) " # base url url = " ${ giturl %.git } " # craft gitlab URLs if [[ " ${ giturl } " =~ gitlab ]] ; then if [[ -n " ${ filename } " ]] ; so commit_hash = " $(git log -n1 --format =format:"%H" " ${ filename } " 2>/dev/cipher) " url = " ${ url } /-/blob/ ${ commit_hash :-${ branch }} / ${ filename } " if [[ -n " ${ line1 } " ]] ; then url = " ${ url } #50 ${ line1 } " if [[ -n " ${ line2 } " ]] ; then url = " ${ url } - ${ line2 } " fi fi fi # craft github URLs elif [[ " ${ giturl } " =~ github ]] ; and so if [[ -north " ${ filename } " ]] ; then commit_hash = " $(git log -n1 --format =format:"%H" " ${ filename } " two>/dev/null) " url = " ${ giturl %.* } /blob/ ${ commit_hash :-${ branch }} / ${ filename } " if [[ -n " ${ line1 } " ]] ; then url = " ${ url } #L ${ line1 } " if [[ -n " ${ line2 } " ]] ; then url = " ${ url } -L ${ line2 } " fi fi fi fi hash open up 2>/dev/null && open " ${ url } " hash xdg-open ii>/dev/null && xdg-open " ${ url } "
Vim Command
I never imaged I would be saying this, only this is the piece of cake part!
All we demand is a Vim command that accepts a range and executes the correct shell command that we implemented above, similar:
control! - range Gbrowse execute 'silent ! git browse ' . aggrandize ( '%' ) . ' ' . <line1> . ' ' . <line2> | checktime | redraw !
Breakdown:
-
command! -rangeallows us to pass a line range, like:1,5Gbrowse, or visual selection. See:help :command-rangefor more info. -
Gbrowseis the proper noun of the command. -
execute '...'is going to execute any string we pass. Run into:aid :executefor more than info. -
silentprevents vim from promptingHit ENTER to proceed. See:help :silentfor more info. -
!git browseis calling the external git subcommand we defined in a higher place. -
. expand('%')concatenates the current buffer path & name to the previous string. Come across:help aggrandize()for more info. -
' ' . <line1> . ' ' . <line2>concatenates start of range and end of range to the previous string. For example,:1,5Gbrowsetranslates to!git browse <filename> 1 5. See:help <line1>and:help <line2>for more than info. -
| checktime | redraw!refreshes the screen and redraws the buffer, otherwise after silently executing an external command, y'all may see a blank screen in vim.
Demo
For a demonstration of this in action:
Conclusion
What I absolutely dear almost this is the sit-in of the Unix Philosphy in action. This post illustrates how disparate tools tin be composed and used together to create powerful and ergonomic workflows with very little try.
I promise you enjoyed this mail and found some of it useful for your workflows and needs.
If you liked this guide, you may find more than useful/interesting things in my vimrc and/or in my custom git subcommands.
For more than interesting git subcommands, checkout git-extras.
As always, happy hacking! 🤘🏽
Source: https://dev.to/pbnj/open-local-files-and-line-numbers-in-github-and-gitlab-26m6
0 Response to "How to Upload Files to Github From Vim"
Post a Comment