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
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
- [ ] Copy git link in a symlink directory of git repo.
- [ ] Copy git link in an un-pushed git branch, and receive an expected error.
- [ ] Copy git link in a pushed git branch but edited file, and receive a warning says the git link could be wrong.
- [ ] Copy git link with 'file' and 'rev' parameters.
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
version: latest
args: --config-path .stylua.toml ./lua ./spec
- uses: stevearc/nvim-typecheck-action@v1
- uses: mrcjkb/lua-typecheck-action@v0
with:
path: lua
level: Warning
directories: lua
configpath: ".luarc.json"
neodev-version: stable
- uses: cargo-bins/cargo-binstall@main
- name: Selene
run: |
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.luacheckcache
service.log
stderr.txt
stdout.txt
*nvim_gitlinker.nvim_lua.log
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,25 @@ There're several **router types**:

To specify the remote when there're multiple git remotes, add `remote=xxx` parameter, for example:

- `GitLink remote=upstream`: copy `blob` url to clipboard for the `upstream` remote.
- `GitLink! blame remote=upstream`: open `blame` url in browser for the `upstream` remote.
- `GitLink remote=upstream`: copy url for the `upstream` remote.
- `GitLink! blame remote=upstream`: open blame url for the `upstream` remote.

> By default `GitLink` will use the first detected remote (usually it's `origin`).

To specify the relative file path when current buffer's file path is not a normal file name, add `file=xxx` parameter, for example:

- `GitLink file=lua/gitlinker.lua`: copy url for the `lua/gitlinker.lua` file.
- `GitLink! blame file=README.md`: open blame url for the `README.md` file.

> By default `GitLink` will use the current buffer's file name.

To specify the git commit ID when current repository's commit ID is not on your needs, add `rev=xxx` parameter, for example:

- `GitLink rev=00b3f9a1`: copy url for the `00b3f9a1` commit ID.
- `GitLink! blame rev=00b3f9a1`: open blame url for the `00b3f9a1` commit ID.

> By default `GitLink` will use the current repository's commit ID.

### API

> [!NOTE]
Expand All @@ -155,7 +169,7 @@ You can also use the `link` API to generate git permlink:
--- @alias gitlinker.Linker {remote_url:string,protocol:string?,username:string?,password:string?,host:string,port:string?,org:string?,user:string?,repo:string,rev:string,file:string,lstart:integer,lend:integer,file_changed:boolean,default_branch:string?,current_branch:string?}
--- @alias gitlinker.Router fun(lk:gitlinker.Linker):string?
--- @alias gitlinker.Action fun(url:string):any
--- @param opts {router_type:string?,router:gitlinker.Router?,action:gitlinker.Action?,lstart:integer?,lend:integer?,message:boolean?,highlight_duration:integer?,remote:string?}?
--- @param opts {router_type:string?,router:gitlinker.Router?,action:gitlinker.Action?,lstart:integer?,lend:integer?,message:boolean?,highlight_duration:integer?,remote:string?,file:string?,rev:string?}?
require("gitlinker").link(opts)
```

Expand Down Expand Up @@ -187,6 +201,8 @@ require("gitlinker").link(opts)
- `message`: Whether print message in nvim command line. By default it uses the configured value while this plugin is been setup (see [Configuration](#configuration)). You can also overwrite this field to change the configured behavior.
- `highlight_duration`: How long (milliseconds) to highlight the line range. By default it uses the configured value while this plugin is been setup (see [Configuration](#configuration)). You can also overwrite this field to change the configured behavior.
- `remote`: Specify the git remote. By default is `nil`, it uses the first detected git remote (usually it's `origin`).
- `file`: Specify the relative file path. By default is `nil`, it uses the current buffer's file name.
- `rev`: Specify the git commit ID. By default is `nil`, it uses the current repository's git commit ID.

##### `gitlinker.Router`

Expand Down
30 changes: 24 additions & 6 deletions lua/gitlinker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ local function _blame(lk)
return _router("blame", lk)
end

--- @param opts {action:gitlinker.Action|boolean,router:gitlinker.Router,lstart:integer,lend:integer,message:boolean?,highlight_duration:integer?,remote:string?}
--- @param opts {action:gitlinker.Action|boolean,router:gitlinker.Router,lstart:integer,lend:integer,message:boolean?,highlight_duration:integer?,remote:string?,file:string?,rev:string?}
local _link = function(opts)
local confs = configs.get()
local logger = logging.get("gitlinker")
Expand All @@ -213,6 +213,14 @@ local _link = function(opts)
lk.lstart = opts.lstart
lk.lend = opts.lend

if str.not_empty(opts.file) then
lk.file = opts.file
lk.file_changed = false
end
if str.not_empty(opts.rev) then
lk.rev = opts.rev
end

async.scheduler()
local ok, url = pcall(opts.router, lk, true)
-- logger:debug(
Expand Down Expand Up @@ -264,30 +272,36 @@ local _link = function(opts)
return url
end

--- @type fun(opts:{action:gitlinker.Action?,router:gitlinker.Router,lstart:integer,lend:integer,remote:string?}):string?
--- @type fun(opts:{action:gitlinker.Action?,router:gitlinker.Router,lstart:integer,lend:integer,remote:string?,file:string?,rev:string?}):string?
local _void_link = async.void(_link)

--- @param args string?
--- @return {router_type:string,remote:string?}
--- @return {router_type:string,remote:string?,file:string?,rev:string?}
local function _parse_args(args)
args = args or ""

local router_type = "browse"
local remote = nil
local file = nil
local rev = nil
if string.len(args) == 0 then
return { router_type = router_type, remote = remote }
return { router_type = router_type, remote = remote, file = file, rev = rev }
end
local args_splits = vim.split(args, " ", { plain = true, trimempty = true })
for _, a in ipairs(args_splits) do
if string.len(a) > 0 then
if str.startswith(a, "remote=") then
remote = a:sub(8)
elseif str.startswith(a, "file=") then
file = a:sub(6)
elseif str.startswith(a, "rev=") then
rev = a:sub(5)
else
router_type = a
end
end
end
return { router_type = router_type, remote = remote }
return { router_type = router_type, remote = remote, file = file, rev = rev }
end

--- @param opts gitlinker.Options?
Expand Down Expand Up @@ -327,6 +341,8 @@ local function setup(opts)
lstart = lstart,
lend = lend,
remote = parsed.remote,
file = parsed.file,
rev = parsed.rev,
})
end, {
nargs = "*",
Expand Down Expand Up @@ -354,7 +370,7 @@ local function setup(opts)
end
end

--- @param opts {router_type:string?,router:gitlinker.Router?,action:gitlinker.Action?,lstart:integer?,lend:integer?,message:boolean?,highlight_duration:integer?,remote:string?}?
--- @param opts {router_type:string?,router:gitlinker.Router?,action:gitlinker.Action?,lstart:integer?,lend:integer?,message:boolean?,highlight_duration:integer?,remote:string?,file:string?,rev:string?}?
local function link_api(opts)
opts = opts
or {
Expand Down Expand Up @@ -384,6 +400,8 @@ local function link_api(opts)
message = opts.message,
highlight_duration = opts.highlight_duration,
remote = opts.remote,
file = opts.file,
rev = opts.rev,
})
end

Expand Down
3 changes: 3 additions & 0 deletions lua/gitlinker/commons/_system.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ local uv = vim.uv or vim.loop
--- @field stderr? string

--- @class vim.SystemState
--- @field cmd string[]
--- @field handle? uv.uv_process_t
--- @field timer? uv.uv_timer_t
--- @field pid? integer
Expand Down Expand Up @@ -57,6 +58,7 @@ local function close_handles(state)
end

--- @class vim.SystemObj
--- @field cmd string[]
--- @field pid integer
--- @field private _state vim.SystemState
--- @field wait fun(self: vim.SystemObj, timeout?: integer): vim.SystemCompleted
Expand All @@ -69,6 +71,7 @@ local SystemObj = {}
--- @return vim.SystemObj
local function new_systemobj(state)
return setmetatable({
cmd = state.cmd,
pid = state.pid,
_state = state,
}, { __index = SystemObj })
Expand Down