Skip to content

Commit

Permalink
feat(api): add 'link' api (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
linrongbin16 committed Mar 7, 2024
1 parent 38b508e commit 46dcc5d
Show file tree
Hide file tree
Showing 16 changed files with 528 additions and 145 deletions.
193 changes: 182 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ PRs are welcomed for other git host websites!
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Command](#command)
- [API](#api)
- [Recommended Key Mappings](#recommended-key-mappings)
- [Configuration](#configuration)
- [Customize Urls](#customize-urls)
- [String Template](#string-template)
Expand All @@ -60,7 +63,7 @@ PRs are welcomed for other git host websites!

## Requirements

- Neovim ≥ v0.7.
- Neovim ≥ 0.7.
- [git](https://git-scm.com/).
- [ssh](https://www.openssh.com/) (optional for resolve ssh host alias).
- [wslview](https://github.com/wslutilities/wslu) (optional for open browser from Windows wsl2).
Expand Down Expand Up @@ -101,36 +104,134 @@ return require('pckr').add(

## Usage

You could use below command:
### Command

You can use the user command `GitLink` to generate git permlink:

- `GitLink(!)`: copy the `/blob` url to clipboard (use `!` to open in browser).
- `GitLink(!) blame`: copy the `/blame` url to clipboard (use `!` to open in browser).
- `GitLink(!) default_branch`: copy the `/main` or `/master` url to clipboard (use `!` to open in browser).

There're **3 routers** provided:
There're several **router types**:

- `browse`: generate the `/blob` url (default).
- `blame`: generate the `/blame` url.
- `default_branch`: generate the `/main` or `/master` url.

> [!NOTE]
>
> Routers can work for any git hosts, for example for bitbucket.org.
> A router type is a general collection of router implementations binding on different git hosts, thus it can work for any git hosts, for example for [bitbucket.org](https://bitbucket.org/):
>
> - `browse` generate the `/src` url (default): https://bitbucket.org/gitlinkernvim/gitlinker.nvim/src/dbf3922382576391fbe50b36c55066c1768b08b6/.gitignore#lines-9:14.
> - `blame` generate the `/annotate` url: https://bitbucket.org/gitlinkernvim/gitlinker.nvim/annotate/dbf3922382576391fbe50b36c55066c1768b08b6/.gitignore#lines-9:14.
> - `default_branch` generate the `/main` or `/master` url based on actual project: https://bitbucket.org/gitlinkernvim/gitlinker.nvim/src/master/.gitignore#lines-9:14.
There're several arguments:

- `remote`: by default `GitLink` will use the first detected remote (usually it's `origin`), but if you need to specify other remotes, please use `remote=xxx`. For example:
- `GitLink remote=upstream`: copy `blob` url to clipboard for `upstream`.
- `GitLink! blame remote=upstream`: open `blame` url in browser for `upstream`.

### API

> [!NOTE]
>
> - `browse`: generate the `/src` url (default).
> - `blame`: generate the `/annotate` url.
> - `default_branch`: generate the `/main` or `/master` url based on actual project.
> Highly recommend reading [Customize Urls](#customize-urls) before this section, which helps understanding the router design of this plugin.
You can also use the `link` API to generate git permlink:

```lua
--- @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?}?
require("gitlinker").link(opts)
```

#### Parameters:

- `opts`: (Optional) lua table that contains below fields:

- `router_type`: Which router type should this API use. By default is `nil`, means `browse`. It has below builtin options:

- `browse`
- `blame`
- `default_branch`

- `router`: Which router implementation should this API use. By default is `nil`, it uses the configured router implementations while this plugin is been setup (see [Configuration](#configuration)). You can **_dynamically_** overwrite the generate behavior by pass a router in this field.

> Once set this field, you will get full control of generating the url, and `router_type` field will no longer take effect.
>
> Please refer to [`gitlinker.Router`](#gitlinkerrouter) for more details.
- `action`: What action should this API behave. By default is `nil`, this API will copy the generated link to clipboard. It has below builtin options:

- `require("gitlinker.actions").clipboard`: Copy generated link to clipboard.
- `require("gitlinker.actions").system`: Open generated link in browser.

> Please refer to [`gitlinker.Action`](#gitlinkeraction) for more details.
- `lstart`/`lend`: Visual selected line range, e.g. start & end line numbers. By default both are `nil`, it will automatically try to find user selected line range. You can also overwrite these two fields to force the line numbers in generated url.
- `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`).

##### `gitlinker.Router`

`gitlinker.Router` is a lua function that implements a router for a git host. It use below function signature:

```lua
function(lk:gitlinker.Linker):string?
```

**Parameters:**

- `lk`: Lua table that presents the `gitlinker.Linker` data type. It contains all the information (fields) you need to generate a git link, e.g. the `protocol`, `host`, `username`, `path`, `rev`, etc.

> Please refer to [Customize Urls - Lua Function](#lua-function) for more details.
**Returns:**

- It returns the generated link as a `string` type, if success.
- It returns `nil`, if failed.

##### `gitlinker.Action`

`gitlinker.Action` is a lua function that do some operations with a generated git link. It use below function signature:

```lua
function(url:string):any
```

**Parameters:**

- `url`: The generated git link. For example: https://codeberg.org/linrongbin16/gitlinker.nvim/src/commit/a570f22ff833447ee0c58268b3bae4f7197a8ad8/LICENSE#L4-L7.

By default `GitLink` will use the first detected remote (`origin`), but if you need to specify other remotes, please use `remote=xxx` arguments. For example:
For now we have below builtin actions:

- `GitLink remote=upstream`: copy `upstream` url to clipboard.
- `GitLink! remote=upstream`: open `upstream` url in browser.
- `require("gitlinker.actions").clipboard`: Copy url to clipboard.
- `require("gitlinker.actions").system`: Open url in browser.

If you only need to get the generated url, instead of do some actions, you can pass a callback function to accept the url:

```lua
require("gitlinker").link({
action = function(url)
print("generated url:" .. vim.inspect(url))
end,
})
```

> The `link` API is running in async way because it uses lua coroutine to avoid editor blocking.
### Recommended Key Mappings

<details>
<summary><i>Click here to see recommended key mappings</i></summary>
<summary><i>Click here to see lua scripts</i></summary>
<br/>

```lua
-- with command:
-- browse
vim.keymap.set(
{"n", 'v'},
Expand All @@ -157,6 +258,76 @@ vim.keymap.set(
"<cmd>GitLink! blame<cr>",
{ silent = true, noremap = true, desc = "Open git blame link in browser" }
)
-- default branch
vim.keymap.set(
{"n", 'v'},
"<leader>gd",
"<cmd>GitLink default_branch<cr>",
{ silent = true, noremap = true, desc = "Copy default branch link to clipboard" }
)
vim.keymap.set(
{"n", 'v'},
"<leader>gD",
"<cmd>GitLink! default_branch<cr>",
{ silent = true, noremap = true, desc = "Open default branch link in browser" }
)

-- with api:
-- browse
vim.keymap.set(
{"n", 'v'},
"<leader>gl",
require("gitlinker").link,
{ silent = true, noremap = true, desc = "GitLink" }
)
vim.keymap.set(
{"n", 'v'},
"<leader>gL",
function()
require("gitlinker").link({ action = require("gitlinker.actions").system })
end,
{ silent = true, noremap = true, desc = "GitLink!" }
)
-- blame
vim.keymap.set(
{"n", 'v'},
"<leader>gb",
function()
require("gitlinker").link({ router_type = "blame" })
end,
{ silent = true, noremap = true, desc = "GitLink blame" }
)
vim.keymap.set(
{"n", 'v'},
"<leader>gB",
function()
require("gitlinker").link({
router_type = "blame",
action = require("gitlinker.actions").system,
})
end,
{ silent = true, noremap = true, desc = "GitLink! blame" }
)
-- default branch
vim.keymap.set(
{"n", 'v'},
"<leader>gd",
function()
require("gitlinker").link({ router_type = "default_branch" })
end,
{ silent = true, noremap = true, desc = "GitLink default_branch" }
)
vim.keymap.set(
{"n", 'v'},
"<leader>gD",
function()
require("gitlinker").link({
router_type = "default_branch",
action = require("gitlinker.actions").system,
})
end,
{ silent = true, noremap = true, desc = "GitLink! default_branch" }
)
```

</details>
Expand Down
Loading

0 comments on commit 46dcc5d

Please sign in to comment.