linrongbin16/gitlinker.nvim

github github
plugingit
stars 23
issues 0
subscribers 1
forks 1
CREATED

2023-02-18

UPDATED

23 days ago


gitlinker.nvim

A fork of ruifm's gitlinker, refactored with pattern based rule engine, Windows support and other enhancements.

A lua plugin for Neovim to generate sharable file permalinks (with line ranges) for git host websites. Inspired by tpope/vim-fugitive's :GBrowse.

An example of git permalink: https://github.com/neovim/neovim/blob/2e156a3b7d7e25e56b03683cc6228c531f4c91ef/src/nvim/main.c#L137-L156

Personally, I use this all the time to easily share code locations with my co-workers.

Break Changes & Features

  1. Bug fix: you can disable/custom default key mappings.
  2. Windows support: you can use it on Windows.
  3. Url mapping engine changed: pattern based rules instead of hard coding.
  4. Refactor: use git error message instead of self-defined error, drop off plenary library.
  5. Rewrittens: API re-designed, logger added, code base re-structured.

Lua pattern based rules

Lua pattern is introduced to map git remote url to host url. The lua pattern has many limitations compared with the standard regex expression, but it's still the best solution in this scenario.

For now supported platforms are:

  • github.com
  • gitlab.com

PRs are welcomed for other git host websites!

Installation

Requirement:

  • git
  • neovim 0.8

packer.nvim

use {
    'linrongbin16/gitlinker.nvim',
    config = function()
        require('gitlinker').setup()
    end,
}

vim-plug

call plug#begin()

Plug 'linrongbin16/gitlinker.nvim'

call plug#end()

lua<<EOF
require('gitlinker').setup()
EOF

lazy.nvim

{
    'linrongbin16/gitlinker.nvim',
    config = function()
        require('gitlinker').setup()
    end,
},

Usage

Action

  • require('gitlinker.actions').clipboard: copy git link to clipboard.
  • require('gitlinker.actions').system: open git link in browser.

API

  • require('gitlinker').link(option): the main API that generate the git permalink, the option is a lua table that has below fields:

    {
        action = ..., -- gitlinker actions: clipboard/system
        lstart = ..., -- selected line start, please see in [Customization](#customization).
        lend = ..., -- selected line end, please see in [Customization](#customization).
    }
    

There're no pre-defined vim command, you need to use:

  • require('gitlinker').link({ action = require('gitlinker.actions').clipboard }) to copy git link.
  • require('gitlinker').link({ action = require('gitlinker.actions').system }) to open git link.

Key Mappings

The above two operations are already defined with two default key mappings:

  • <leader>gl (normal/visual mode): copy git link to clipboard.
  • <leader>gL (normal/visual mode): open git link in browser.

Customization

To disable the default key mappings, set mapping = false in setup() function (see Configuration).

To create your own key mappings, please specify the mapping option in setup() function.

To create your own vim command, please use:

For vim:

command! -range GitLink lua require('gitlinker').link({ action = require('gitlinker.actions').system, lstart = vim.api.nvim_buf_get_mark(0, '<')[1], lend = vim.api.nvim_buf_get_mark(0, '>')[1] })

For lua:

vim.api.nvim_create_user_command("GitLink", function()
    require("gitlinker").link({
        action = require("gitlinker.actions").system,
        lstart = vim.api.nvim_buf_get_mark(0, '<')[1],
        lend = vim.api.nvim_buf_get_mark(0, '>')[1]
    })
end, {
    range = true,
})

Support command range is a little bit tricky, please read https://github.com/linrongbin16/gitlinker.nvim/discussions/38 and https://github.com/linrongbin16/gitlinker.nvim/issues/47.

Configuration

require('gitlinker').setup({
  -- print message in command line
  message = true,

  -- key mapping
  mapping = {
    ["<leader>gl"] = {
      -- copy git link to clipboard
      action = require("gitlinker.actions").clipboard,
      desc = "Copy git link to clipboard",
    },
    ["<leader>gL"] = {
      -- open git link in browser
      action = require("gitlinker.actions").system,
      desc = "Open git link in browser",
    },
  },

  -- regex pattern based rules
  pattern_rules = {
    {
      ["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
      ["^https?://github%.([_%.%-%w]+)/([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
      ["^git@gitlab%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://gitlab.%1/%2/%3/blob/",
      ["^https?://gitlab%.([_%.%-%w]+)/([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://gitlab.%1/%2/%3/blob/",
    },
    {
      ["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)$"] = "https://github.%1/%2/%3/blob/",
      ["^https?://github%.([_%.%-%w]+)/([%.%-%w]+)/([_%.%-%w]+)$"] = "https://github.%1/%2/%3/blob/",
      ["^git@gitlab%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)$"] = "https://gitlab.%1/%2/%3/blob/",
      ["^https?://gitlab%.([_%.%-%w]+)/([%.%-%w]+)/([_%.%-%w]+)$"] = "https://gitlab.%1/%2/%3/blob/",
    },
  },

  -- function based rules: function(remote_url) => host_url.
  -- this function will override the `pattern_rules`.
  -- here's an example of custom_rules:
  --
  -- ```
  -- custom_rules = function(remote_url)
  --   local pattern_rules = {
  --     {
  --       ["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
  --       ["^https://github%.([_%.%-%w]+)/([%.%-%w]+)/([%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
  --     },
  --     -- http(s)://github.(com|*)/linrongbin16/gitlinker.nvim(.git)? -> https://github.com/linrongbin16/gitlinker.nvim(.git)?
  --     {
  --       ["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([%.%-%w]+)$"] = "https://github.%1/%2/%3/blob/",
  --       ["^https://github%.([_%.%-%w]+)/([%.%-%w]+)/([%.%-%w]+)$"] = "https://github.%1/%2/%3/blob/",
  --     },
  --   }
  --   for _, group in ipairs(pattern_rules) do
  --     for pattern, replace in pairs(group) do
  --       if string.match(remote_url, pattern) then
  --         local result = string.gsub(remote_url, pattern, replace)
  --         return result
  --       end
  --     end
  --   end
  --   return nil
  -- end,
  -- ```
  --
  --- @overload fun(remote_url:string):string|nil
  custom_rules = nil,


  -- enable debug
  debug = false,

  -- write logs to console(command line)
  console_log = true,

  -- write logs to file
  file_log = false,
})

Contribute

For developing:

  1. Use lua-language-server for code lint.
  2. Use stylua for code formatting.
  3. Start neovim and run unit test: lua require('gitlinker.test.test_rules')

Please also open issue/PR for anything about gitlinker.nvim.

Like gitlinker.nvim? Consider

Github Sponsor Wechat Pay Alipay