How to Upload Files to Github From Vim

Peter Benjamin (he/they)

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                      

Enter fullscreen style Exit fullscreen mode

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                      

Enter fullscreen style Leave fullscreen mode

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              }              "                      

Enter fullscreen style Exit fullscreen way

  • 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              }              "              )              "                      

Enter fullscreen style Exit fullscreen fashion

  • I ever apply HTTPS for git URLs, only if you apply SSH, and then you would want to convert git@* to https://*. Besides, remove the trailing .git in 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              }              "                      

Enter fullscreen style Leave fullscreen mode

  • 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'                      

Enter fullscreen mode Exit fullscreen mode

  • Lastly, open the crafted URL:
                          hash              open up 2>/dev/zip              &&              open              "              ${              url              }              "              hash              xdg-open 2>/dev/null              &&              xdg-open              "              ${              url              }              "                      

Enter fullscreen mode Exit fullscreen mode

  • 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                      

Enter fullscreen manner Exit fullscreen manner

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              }              "                      

Enter fullscreen mode Get out fullscreen way

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              !                      

Enter fullscreen mode Exit fullscreen mode

Breakdown:

  • command! -range allows us to pass a line range, like :1,5Gbrowse, or visual selection. See :help :command-range for more info.
  • Gbrowse is the proper noun of the command.
  • execute '...' is going to execute any string we pass. Run into :aid :execute for more than info.
  • silent prevents vim from prompting Hit ENTER to proceed. See :help :silent for more info.
  • !git browse is 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,5Gbrowse translates 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! 🤘🏽

brenanfoody1997.blogspot.com

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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel