feat(nvim): support glab, gh in forge picker
This commit is contained in:
parent
8ed4522da2
commit
597f98d65b
2 changed files with 124 additions and 23 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
---@return string
|
---@return string
|
||||||
local function gh_file_loc()
|
local function file_loc()
|
||||||
local root = vim.trim(vim.fn.system('git rev-parse --show-toplevel'))
|
local root = vim.trim(vim.fn.system('git rev-parse --show-toplevel'))
|
||||||
local file = vim.api.nvim_buf_get_name(0):sub(#root + 2)
|
local file = vim.api.nvim_buf_get_name(0):sub(#root + 2)
|
||||||
local mode = vim.fn.mode()
|
local mode = vim.fn.mode()
|
||||||
|
|
@ -18,7 +18,7 @@ local function gh_file_loc()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param args string[]
|
---@param args string[]
|
||||||
local function gh_yank(args)
|
local function yank_url(args)
|
||||||
vim.system(args, { text = true }, function(result)
|
vim.system(args, { text = true }, function(result)
|
||||||
if result.code == 0 then
|
if result.code == 0 then
|
||||||
local url = vim.trim(result.stdout or '')
|
local url = vim.trim(result.stdout or '')
|
||||||
|
|
@ -31,28 +31,128 @@ local function gh_yank(args)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function remote_web_url()
|
||||||
|
local url = vim.trim(vim.fn.system('git remote get-url origin'))
|
||||||
|
url = url:gsub('%.git$', '')
|
||||||
|
url = url:gsub('^ssh://git@', 'https://')
|
||||||
|
url = url:gsub('^git@([^:]+):', 'https://%1/')
|
||||||
|
return url
|
||||||
|
end
|
||||||
|
|
||||||
|
local function gitlab_file_url(loc, ref)
|
||||||
|
local base = remote_web_url()
|
||||||
|
local file, lines = loc:match('^(.+):(.+)$')
|
||||||
|
return ('%s/-/blob/%s/%s#L%s'):format(base, ref, file, lines)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function detect_forge()
|
||||||
|
local url = vim.trim(vim.fn.system('git remote get-url origin'))
|
||||||
|
if vim.v.shell_error ~= 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if url:find('github') and vim.fn.executable('gh') == 1 then
|
||||||
|
return 'github'
|
||||||
|
end
|
||||||
|
if url:find('gitlab') and vim.fn.executable('glab') == 1 then
|
||||||
|
return 'gitlab'
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local forges = {
|
||||||
|
github = {
|
||||||
|
kinds = { issue = 'issue', pr = 'pr' },
|
||||||
|
labels = { issue = 'Issues', pr = 'PRs' },
|
||||||
|
list_cmd = function(kind, state)
|
||||||
|
return ('gh %s list --limit 100 --state %s'):format(kind, state)
|
||||||
|
end,
|
||||||
|
view_cmd = function(kind, num)
|
||||||
|
return { 'gh', kind, 'view', num, '--web' }
|
||||||
|
end,
|
||||||
|
browse = function(loc, branch)
|
||||||
|
vim.system({ 'gh', 'browse', loc, '--branch', branch })
|
||||||
|
end,
|
||||||
|
browse_root = function()
|
||||||
|
vim.system({ 'gh', 'browse' })
|
||||||
|
end,
|
||||||
|
yank_branch = function(loc)
|
||||||
|
yank_url({ 'gh', 'browse', loc, '-n' })
|
||||||
|
end,
|
||||||
|
yank_commit = function(loc)
|
||||||
|
yank_url({ 'gh', 'browse', loc, '--commit=last', '-n' })
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
gitlab = {
|
||||||
|
kinds = { issue = 'issue', pr = 'mr' },
|
||||||
|
labels = { issue = 'Issues', pr = 'MRs' },
|
||||||
|
list_cmd = function(kind, state)
|
||||||
|
local cmd = ('glab %s list --per-page 100'):format(kind)
|
||||||
|
if state == 'closed' then
|
||||||
|
cmd = cmd .. ' --closed'
|
||||||
|
elseif state == 'all' then
|
||||||
|
cmd = cmd .. ' --all'
|
||||||
|
end
|
||||||
|
return cmd
|
||||||
|
end,
|
||||||
|
view_cmd = function(kind, num)
|
||||||
|
return { 'glab', kind, 'view', num, '--web' }
|
||||||
|
end,
|
||||||
|
browse = function(loc, branch)
|
||||||
|
vim.ui.open(gitlab_file_url(loc, branch))
|
||||||
|
end,
|
||||||
|
browse_root = function()
|
||||||
|
vim.system({ 'glab', 'repo', 'view', '--web' })
|
||||||
|
end,
|
||||||
|
yank_branch = function(loc)
|
||||||
|
local branch = vim.trim(vim.fn.system('git branch --show-current'))
|
||||||
|
vim.fn.setreg('+', gitlab_file_url(loc, branch))
|
||||||
|
end,
|
||||||
|
yank_commit = function(loc)
|
||||||
|
local commit = vim.trim(vim.fn.system('git rev-parse HEAD'))
|
||||||
|
vim.fn.setreg('+', gitlab_file_url(loc, commit))
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
---@param kind 'issue'|'pr'
|
---@param kind 'issue'|'pr'
|
||||||
---@param state 'all'|'open'|'closed'
|
---@param state 'all'|'open'|'closed'
|
||||||
local function gh_picker(kind, state)
|
local function forge_picker(kind, state)
|
||||||
|
local forge_name = detect_forge()
|
||||||
|
if not forge_name then
|
||||||
|
vim.notify('No supported forge detected', vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local forge = forges[forge_name]
|
||||||
|
local cli_kind = forge.kinds[kind]
|
||||||
local next_state = ({ all = 'open', open = 'closed', closed = 'all' })[state]
|
local next_state = ({ all = 'open', open = 'closed', closed = 'all' })[state]
|
||||||
local label = kind == 'pr' and 'PRs' or 'Issues'
|
require('fzf-lua').fzf_exec(forge.list_cmd(cli_kind, state), {
|
||||||
require('fzf-lua').fzf_exec(('gh %s list --limit 100 --state %s'):format(kind, state), {
|
prompt = ('%s (%s)> '):format(forge.labels[kind], state),
|
||||||
prompt = ('%s (%s)> '):format(label, state),
|
|
||||||
header = ':: <c-o> to toggle all/open/closed',
|
header = ':: <c-o> to toggle all/open/closed',
|
||||||
actions = {
|
actions = {
|
||||||
['default'] = function(selected)
|
['default'] = function(selected)
|
||||||
local num = selected[1]:match('^(%d+)')
|
local num = selected[1]:match('^[#!]?(%d+)')
|
||||||
if num then
|
if num then
|
||||||
vim.system({ 'gh', kind, 'view', num, '--web' })
|
vim.system(forge.view_cmd(cli_kind, num))
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
['ctrl-o'] = function()
|
['ctrl-o'] = function()
|
||||||
gh_picker(kind, next_state)
|
forge_picker(kind, next_state)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function with_forge(fn)
|
||||||
|
return function()
|
||||||
|
local forge_name = detect_forge()
|
||||||
|
if not forge_name then
|
||||||
|
vim.notify('No supported forge detected', vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
fn(forges[forge_name])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
{
|
{
|
||||||
'tpope/vim-fugitive',
|
'tpope/vim-fugitive',
|
||||||
|
|
@ -84,42 +184,42 @@ return {
|
||||||
keys = {
|
keys = {
|
||||||
{
|
{
|
||||||
'<leader>go',
|
'<leader>go',
|
||||||
function()
|
with_forge(function(forge)
|
||||||
local branch = vim.trim(vim.fn.system('git branch --show-current'))
|
local branch = vim.trim(vim.fn.system('git branch --show-current'))
|
||||||
vim.system({ 'gh', 'browse', gh_file_loc(), '--branch', branch })
|
forge.browse(file_loc(), branch)
|
||||||
end,
|
end),
|
||||||
mode = { 'n', 'v' },
|
mode = { 'n', 'v' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'<leader>gy',
|
'<leader>gy',
|
||||||
function()
|
with_forge(function(forge)
|
||||||
gh_yank({ 'gh', 'browse', gh_file_loc(), '--commit=last', '-n' })
|
forge.yank_commit(file_loc())
|
||||||
end,
|
end),
|
||||||
mode = { 'n', 'v' },
|
mode = { 'n', 'v' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'<leader>gl',
|
'<leader>gl',
|
||||||
function()
|
with_forge(function(forge)
|
||||||
gh_yank({ 'gh', 'browse', gh_file_loc(), '-n' })
|
forge.yank_branch(file_loc())
|
||||||
end,
|
end),
|
||||||
mode = { 'n', 'v' },
|
mode = { 'n', 'v' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'<leader>gx',
|
'<leader>gx',
|
||||||
function()
|
with_forge(function(forge)
|
||||||
vim.system({ 'gh', 'browse' })
|
forge.browse_root()
|
||||||
end,
|
end),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'<leader>gi',
|
'<leader>gi',
|
||||||
function()
|
function()
|
||||||
gh_picker('issue', 'all')
|
forge_picker('issue', 'all')
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'<leader>gp',
|
'<leader>gp',
|
||||||
function()
|
function()
|
||||||
gh_picker('pr', 'all')
|
forge_picker('pr', 'all')
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ in
|
||||||
poppler-utils
|
poppler-utils
|
||||||
librsvg
|
librsvg
|
||||||
imagemagick
|
imagemagick
|
||||||
|
graphite-cli
|
||||||
]
|
]
|
||||||
++ lib.optionals hostConfig.isLinux [ xclip ]
|
++ lib.optionals hostConfig.isLinux [ xclip ]
|
||||||
++ lib.optionals rust [ rustup ];
|
++ lib.optionals rust [ rustup ];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue