Merge remote-tracking branch 'origin/main' into docs/sync-s3-auto-auth
# Conflicts: # doc/pending.txt # lua/pending/config.lua # lua/pending/forge.lua # spec/forge_spec.lua
This commit is contained in:
commit
d043c6aaee
5 changed files with 113 additions and 15 deletions
|
|
@ -1500,7 +1500,7 @@ Configuration: ~
|
|||
>lua
|
||||
vim.g.pending = {
|
||||
forge = {
|
||||
auto_close = false,
|
||||
close = false,
|
||||
warn_missing_cli = true,
|
||||
github = {
|
||||
icon = '',
|
||||
|
|
@ -1522,7 +1522,7 @@ Configuration: ~
|
|||
<
|
||||
|
||||
Top-level fields: ~
|
||||
{auto_close} (boolean, default: false) When true, tasks linked to
|
||||
{close} (boolean, default: false) When true, tasks linked to
|
||||
closed/merged remote issues are automatically marked
|
||||
done on buffer open.
|
||||
{warn_missing_cli} (boolean, default: true) When true, warns once per
|
||||
|
|
@ -1550,7 +1550,7 @@ than 5 minutes are re-fetched asynchronously. The buffer renders immediately
|
|||
with cached data and updates extmarks when the fetch completes.
|
||||
|
||||
State pull: ~
|
||||
Requires `forge.auto_close = true`. After fetching, if the remote issue/PR
|
||||
Requires `forge.close = true`. After fetching, if the remote issue/PR
|
||||
is closed or merged and the local task is pending/wip/blocked, the task is
|
||||
automatically marked as done. Disabled by default. One-way: local status
|
||||
changes do not push back to the forge.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
local config = require('pending.config')
|
||||
local forge = require('pending.forge')
|
||||
|
||||
---@class pending.CompletionItem
|
||||
---@field word string
|
||||
|
|
@ -109,6 +110,17 @@ local function recur_completions()
|
|||
return result
|
||||
end
|
||||
|
||||
---@param source string
|
||||
---@return boolean
|
||||
function M._is_forge_source(source)
|
||||
for _, b in ipairs(forge.backends()) do
|
||||
if b.shorthand == source then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@type string?
|
||||
local _complete_source = nil
|
||||
|
||||
|
|
@ -128,10 +140,10 @@ function M.omnifunc(findstart, base)
|
|||
{ vim.pesc(dk) .. ':([%S]*)$', dk },
|
||||
{ 'cat:([%S]*)$', 'cat' },
|
||||
{ vim.pesc(rk) .. ':([%S]*)$', rk },
|
||||
{ 'gh:([%S]*)$', 'gh' },
|
||||
{ 'gl:([%S]*)$', 'gl' },
|
||||
{ 'cb:([%S]*)$', 'cb' },
|
||||
}
|
||||
for _, b in ipairs(forge.backends()) do
|
||||
table.insert(checks, { vim.pesc(b.shorthand) .. ':([%S]*)$', b.shorthand })
|
||||
end
|
||||
|
||||
for _, check in ipairs(checks) do
|
||||
local start = before:find(check[1])
|
||||
|
|
@ -172,7 +184,7 @@ function M.omnifunc(findstart, base)
|
|||
table.insert(matches, { word = c.word, menu = '[' .. source .. ']', info = c.info })
|
||||
end
|
||||
end
|
||||
elseif source == 'gh' or source == 'gl' or source == 'cb' then
|
||||
elseif M._is_forge_source(source) then
|
||||
local s = require('pending.buffer').store()
|
||||
if s then
|
||||
local seen = {}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,10 @@
|
|||
---@field icon? string
|
||||
---@field issue_format? string
|
||||
---@field instances? string[]
|
||||
---@field shorthand? string
|
||||
|
||||
---@class pending.ForgeConfig
|
||||
---@field auto_close? boolean
|
||||
---@field close? boolean
|
||||
---@field warn_missing_cli? boolean
|
||||
---@field [string] pending.ForgeInstanceConfig
|
||||
|
||||
|
|
@ -153,7 +154,7 @@ local defaults = {
|
|||
},
|
||||
sync = {},
|
||||
forge = {
|
||||
auto_close = false,
|
||||
close = false,
|
||||
warn_missing_cli = true,
|
||||
github = {
|
||||
icon = '',
|
||||
|
|
|
|||
|
|
@ -63,6 +63,14 @@ function M.backends()
|
|||
return _backends
|
||||
end
|
||||
|
||||
function M._reset_instances()
|
||||
_instances_resolved = false
|
||||
_by_shorthand = {}
|
||||
for _, b in ipairs(_backends) do
|
||||
_by_shorthand[b.shorthand] = b
|
||||
end
|
||||
end
|
||||
|
||||
local function _ensure_instances()
|
||||
if _instances_resolved then
|
||||
return
|
||||
|
|
@ -74,17 +82,27 @@ local function _ensure_instances()
|
|||
for _, inst in ipairs(forge_cfg.instances or {}) do
|
||||
_by_host[inst] = backend
|
||||
end
|
||||
if forge_cfg.shorthand and forge_cfg.shorthand ~= backend.shorthand then
|
||||
_by_shorthand[backend.shorthand] = nil
|
||||
backend.shorthand = forge_cfg.shorthand
|
||||
_by_shorthand[backend.shorthand] = backend
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param token string
|
||||
---@return pending.ForgeRef?
|
||||
function M._parse_shorthand(token)
|
||||
local prefix, rest = token:match('^(%l%l):(.+)$')
|
||||
if not prefix then
|
||||
return nil
|
||||
_ensure_instances()
|
||||
local backend, rest
|
||||
for prefix, b in pairs(_by_shorthand) do
|
||||
local candidate = token:match('^' .. vim.pesc(prefix) .. ':(.+)$')
|
||||
if candidate then
|
||||
backend = b
|
||||
rest = candidate
|
||||
break
|
||||
end
|
||||
end
|
||||
local backend = _by_shorthand[prefix]
|
||||
if not backend then
|
||||
return nil
|
||||
end
|
||||
|
|
@ -291,7 +309,7 @@ end
|
|||
---@param s pending.Store
|
||||
function M.refresh(s)
|
||||
local forge_cfg = config.get().forge or {}
|
||||
if not forge_cfg.auto_close then
|
||||
if not forge_cfg.close then
|
||||
return
|
||||
end
|
||||
local tasks = s:tasks()
|
||||
|
|
@ -309,7 +327,7 @@ function M.refresh(s)
|
|||
any_fetched = true
|
||||
local forge_cfg = config.get().forge or {}
|
||||
if
|
||||
forge_cfg.auto_close
|
||||
forge_cfg.close
|
||||
and (cache.state == 'closed' or cache.state == 'merged')
|
||||
and (task.status == 'pending' or task.status == 'wip' or task.status == 'blocked')
|
||||
then
|
||||
|
|
|
|||
|
|
@ -391,6 +391,73 @@ describe('forge registry', function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe('custom forge prefixes', function()
|
||||
local config = require('pending.config')
|
||||
local complete = require('pending.complete')
|
||||
|
||||
it('parses custom-length shorthand (3+ chars)', function()
|
||||
local custom = forge.gitea_backend({
|
||||
name = 'customforge',
|
||||
shorthand = 'cgf',
|
||||
default_host = 'custom.example.com',
|
||||
})
|
||||
forge.register(custom)
|
||||
|
||||
local ref = forge._parse_shorthand('cgf:alice/proj#99')
|
||||
assert.is_not_nil(ref)
|
||||
assert.equals('customforge', ref.forge)
|
||||
assert.equals('alice', ref.owner)
|
||||
assert.equals('proj', ref.repo)
|
||||
assert.equals(99, ref.number)
|
||||
end)
|
||||
|
||||
it('parse_ref dispatches custom-length shorthand', function()
|
||||
local ref = forge.parse_ref('cgf:alice/proj#5')
|
||||
assert.is_not_nil(ref)
|
||||
assert.equals('customforge', ref.forge)
|
||||
assert.equals(5, ref.number)
|
||||
end)
|
||||
|
||||
it('find_refs finds custom-length shorthand', function()
|
||||
local refs = forge.find_refs('Fix cgf:alice/proj#12')
|
||||
assert.equals(1, #refs)
|
||||
assert.equals('customforge', refs[1].ref.forge)
|
||||
assert.equals(12, refs[1].ref.number)
|
||||
end)
|
||||
|
||||
it('completion returns entries for custom backends', function()
|
||||
assert.is_true(complete._is_forge_source('cgf'))
|
||||
end)
|
||||
|
||||
it('config shorthand override re-registers backend', function()
|
||||
vim.g.pending = {
|
||||
forge = {
|
||||
github = { shorthand = 'github' },
|
||||
},
|
||||
}
|
||||
config.reset()
|
||||
forge._reset_instances()
|
||||
|
||||
local ref = forge._parse_shorthand('github:user/repo#1')
|
||||
assert.is_not_nil(ref)
|
||||
assert.equals('github', ref.forge)
|
||||
assert.equals('user', ref.owner)
|
||||
assert.equals('repo', ref.repo)
|
||||
assert.equals(1, ref.number)
|
||||
|
||||
assert.is_nil(forge._parse_shorthand('gh:user/repo#1'))
|
||||
|
||||
vim.g.pending = nil
|
||||
config.reset()
|
||||
for _, b in ipairs(forge.backends()) do
|
||||
if b.name == 'github' then
|
||||
b.shorthand = 'gh'
|
||||
end
|
||||
end
|
||||
forge._reset_instances()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('forge diff integration', function()
|
||||
local store = require('pending.store')
|
||||
local diff = require('pending.diff')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue