Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Here's an example of git permalink: https://github.com/neovim/neovim/blob/2e156a
## Table of Contents

- [Break Changes & Updates](#break-changes--updates)
- [Lua pattern based rules](#lua-pattern-based-rules)
- [Lua pattern based mapping engine](#lua-pattern-based-mapping-engine)
- [Installation](#installation)
- [packer.nvim](#packernvim)
- [vim-plug](#vim-plug)
Expand Down Expand Up @@ -102,6 +102,8 @@ require("lazy").setup({

## Usage

There's no pre-defined vim command, this plugin provides two actions and one API to achieve the goal.

### Action

- `require('gitlinker.actions').clipboard`: copy git link to clipboard.
Expand All @@ -114,12 +116,12 @@ require("lazy").setup({
```lua
{
action = ..., -- gitlinker actions: clipboard/system
lstart = ..., -- selected line start, please see in [Customization](#customization).
lend = ..., -- selected line end, please see in [Customization](#customization).
lstart = ..., -- (optional) line range start, please see in [Customization](#customization).
lend = ..., -- (optional) line range end, please see in [Customization](#customization).
}
```

There're no pre-defined vim command, you need to use:
You could use below two lua code to copy/open git link:

- `require('gitlinker').link({ action = require('gitlinker.actions').clipboard })` to copy git link.
- `require('gitlinker').link({ action = require('gitlinker.actions').system })` to open git link.
Expand All @@ -133,11 +135,9 @@ The above two operations are already defined with two default key mappings:

## Customization

To disable the default key mappings, set `mapping = false` in `setup()` function
(see [Configuration](#configuration)).
To disable the default key mappings, set `mapping = false` in `setup()` function (see [Configuration](#configuration)).

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

To create your own vim command, please use:

Expand All @@ -151,17 +151,17 @@ For lua:

```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]
})
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,
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.
> Support command range is a little bit tricky, since you need to pass line range from to `link` API.

## Configuration

Expand Down
171 changes: 38 additions & 133 deletions lua/gitlinker.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
local git = require("gitlinker.git")
local util = require("gitlinker.util")
local logger = require("gitlinker.logger")
local Linker = require("gitlinker.linker").Linker

--- @alias Options table<any, any>
--- @type Options
Expand All @@ -26,7 +25,8 @@ local Defaults = {
},

-- pattern based rules
--- @type {[1]:table<string,string>,[2]:table<string,string>}
--
--- @type table<string,string>[]
pattern_rules = {
{
["^git@github%.([_%.%-%w]+):([%.%-%w]+)/([_%.%-%w]+)%.git$"] = "https://github.%1/%2/%3/blob/",
Expand Down Expand Up @@ -72,29 +72,31 @@ local Defaults = {
-- end,
-- ```
--
--- @alias CustomRules fun(remote_url:string):string?
--- @type CustomRules?
--- @type fun(remote_url:string):string?|nil
custom_rules = nil,

-- enable debug
--
--- @type boolean
debug = false,

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

-- write logs to file
--
--- @type boolean
file_log = false,
}

--- @type Options
local Configs = {}

--- @param option Options?
local function setup(option)
Configs = vim.tbl_deep_extend("force", Defaults, option or {})
--- @param opts Options?
local function setup(opts)
Configs = vim.tbl_deep_extend("force", vim.deepcopy(Defaults), opts or {})

-- logger
logger.setup({
Expand All @@ -104,9 +106,9 @@ local function setup(option)
})

local key_mappings = nil
if type(option) == "table" and option["mapping"] ~= nil then
if type(option["mapping"]) == "table" then
key_mappings = option["mapping"]
if type(opts) == "table" and opts["mapping"] ~= nil then
if type(opts["mapping"]) == "table" then
key_mappings = opts["mapping"]
end
else
key_mappings = Defaults.mapping
Expand All @@ -131,101 +133,6 @@ local function setup(option)
-- logger.debug("|setup| Configs:%s", vim.inspect(Configs))
end

--- @class Linker
--- @field remote_url string
--- @field rev string
--- @field file string
--- @field lstart integer
--- @field lend integer
--- @field file_changed boolean
local Linker = {}

--- @param remote_url string
--- @param rev string
--- @param file string
--- @param lstart integer
--- @param lend integer
--- @param file_changed boolean
--- @return Linker
local function new_linker(remote_url, rev, file, lstart, lend, file_changed)
local linker = vim.tbl_extend("force", vim.deepcopy(Linker), {
remote_url = remote_url,
rev = rev,
file = file,
lstart = lstart,
lend = lend,
file_changed = file_changed,
})
return linker
end

--- @return Linker?
local function make_link_data(range)
local root = git.get_root()
if not root then
return nil
end

--- @type string|nil
local remote = git.get_branch_remote()
if not remote then
return nil
end
logger.debug("|make_link_data| remote:%s", vim.inspect(remote))

local remote_url_result = git.get_remote_url(remote)
if not remote_url_result then
return nil
end
logger.debug(
"|make_link_data| remote_url_result:%s",
vim.inspect(remote_url_result)
)

--- @type string|nil
local rev = git.get_closest_remote_compatible_rev(remote)
if not rev then
return nil
end
logger.debug("|make_link_data| rev:%s", vim.inspect(rev))

local buf_path_on_root = util.path_relative(root) --[[@as string]]
logger.debug(
"|make_link_data| root:%s, buf_path_on_root:%s",
vim.inspect(root),
vim.inspect(buf_path_on_root)
)

local file_in_rev_result = git.is_file_in_rev(buf_path_on_root, rev)
if not file_in_rev_result then
return nil
end
logger.debug(
"|make_link_data| file_in_rev_result:%s",
vim.inspect(file_in_rev_result)
)

local buf_path_on_cwd = util.path_relative() --[[@as string]]
logger.debug(
"|make_link_data| buf_path_on_cwd:%s",
vim.inspect(buf_path_on_cwd)
)

if range == nil or range["lstart"] == nil or range["lend"] == nil then
range = util.line_range()
logger.debug("[make_link_data] range:%s", vim.inspect(range))
end

return new_linker(
remote_url_result,
rev,
buf_path_on_root,
range.lstart,
range.lend,
git.has_file_changed(buf_path_on_cwd, rev)
)
end

--- @package
--- @param remote_url string
--- @return string?
Expand Down Expand Up @@ -263,52 +170,49 @@ local function _map_remote_to_host(remote_url)
end

--- @param host_url string
--- @param linker Linker
--- @param lk Linker
--- @return string
local function make_sharable_permalinks(host_url, linker)
local url = host_url .. linker.rev .. "/" .. linker.file
if not linker.lstart then
local function _make_sharable_permalinks(host_url, lk)
local url = string.format([[%s%s/%s]], host_url, lk.rev, lk.file)
if not lk.lstart then
return url
end
url = url .. "#L" .. linker.lstart
if linker.lend and linker.lend ~= linker.lstart then
url = url .. "-L" .. linker.lend
url = string.format([[%s#L%d]], url, lk.lstart)
if lk.lend and lk.lend ~= lk.lstart then
url = string.format([[%s-L%d]], url, lk.lend)
end
return url
end

--- @param opts Options
--- @param opts Options?
--- @return string?
local function link(opts)
opts = vim.tbl_deep_extend("force", Configs, opts or {})
opts = vim.tbl_deep_extend("force", vim.deepcopy(Configs), opts or {})
logger.debug("[link] merged opts: %s", vim.inspect(opts))

local range = nil
if opts["lstart"] ~= nil and opts["lend"] ~= nil then
range = { lstart = opts["lstart"], lend = opts["lend"] }
end
local linker = make_link_data(range)
if not linker then
return nil
end

local host_url = _map_remote_to_host(linker.remote_url)

if type(host_url) ~= "string" or string.len(host_url) <= 0 then
logger.err(
"Error! Cannot generate git link from remote url:%s",
linker.remote_url
)
local range = (
type(opts.lstart) == "number" and type(opts.lend) == "number"
)
and { lstart = opts.lstart, lend = opts.lend }
or nil
local lk = Linker:make(range)
if not lk then
return nil
end

local url = make_sharable_permalinks(host_url, linker)
local host_url = _map_remote_to_host(lk.remote_url) --[[@as string]]
logger.ensure(
type(host_url) == "string" and string.len(host_url) > 0,
"fatal: failed to generate permanent url from remote url:%s",
lk.remote_url
)

local url = _make_sharable_permalinks(host_url, lk)
if opts.action then
opts.action(url)
end
if opts.message then
local msg = linker.file_changed
local msg = lk.file_changed
and string.format(
"%s (lines can be wrong due to file change)",
url
Expand All @@ -323,6 +227,7 @@ end
local M = {
setup = setup,
link = link,
_make_sharable_permalinks = _make_sharable_permalinks,
_map_remote_to_host = _map_remote_to_host,
}

Expand Down
22 changes: 11 additions & 11 deletions lua/gitlinker/git.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
local logger = require("gitlinker.logger")
local spawn = require("gitlinker.spawn")

--- @class JobResult
--- @class CmdResult
--- @field stdout string[]
--- @field stderr string[]
local JobResult = {}
local CmdResult = {}

--- @return JobResult
function JobResult:new()
--- @return CmdResult
function CmdResult:new()
local o = {
stdout = {},
stderr = {},
Expand All @@ -18,17 +18,17 @@ function JobResult:new()
end

--- @return boolean
function JobResult:has_out()
function CmdResult:has_out()
return type(self.stdout) == "table" and #self.stdout > 0
end

--- @return boolean
function JobResult:has_err()
function CmdResult:has_err()
return type(self.stderr) == "table" and #self.stderr > 0
end

--- @param default string
function JobResult:print_err(default)
function CmdResult:print_err(default)
if self:has_err() then
for _, e in ipairs(self.stderr) do
logger.err("%s", e)
Expand All @@ -42,9 +42,9 @@ end
--- @package
--- @param args string[]
--- @param cwd string?
--- @return JobResult
--- @return CmdResult
local function cmd(args, cwd)
local result = JobResult:new()
local result = CmdResult:new()

local sp = spawn.Spawn:make(args, {
cwd = cwd or vim.fn.getcwd(),
Expand All @@ -71,7 +71,7 @@ local function cmd(args, cwd)
end

--- @package
--- @return JobResult
--- @return CmdResult
local function _get_remote()
local result = cmd({ "git", "remote" })
logger.debug("|git._get_remote| result:%s", vim.inspect(result))
Expand Down Expand Up @@ -246,7 +246,7 @@ end
--- @return string?
local function get_branch_remote()
-- origin/upstream
--- @type JobResult
--- @type CmdResult
local remote_result = _get_remote()

if type(remote_result.stdout) ~= "table" or #remote_result.stdout == 0 then
Expand Down
Loading