mirror of
https://github.com/harivansh-afk/forge.nvim.git
synced 2026-04-15 08:03:44 +00:00
feat: expand cli
This commit is contained in:
parent
b4db29e77a
commit
c677feee2f
5 changed files with 142 additions and 387 deletions
|
|
@ -14,7 +14,7 @@ Requirements: ~
|
||||||
- `gh` for GitHub
|
- `gh` for GitHub
|
||||||
- `glab` for GitLab
|
- `glab` for GitLab
|
||||||
- `tea` for Codeberg/Gitea/Forgejo
|
- `tea` for Codeberg/Gitea/Forgejo
|
||||||
- vim-fugitive (optional, for fugitive keymaps and split review)
|
- vim-fugitive (optional, for split review)
|
||||||
- diffs.nvim (optional, for review mode)
|
- diffs.nvim (optional, for review mode)
|
||||||
|
|
||||||
Run |:checkhealth| forge to verify CLIs and dependencies.
|
Run |:checkhealth| forge to verify CLIs and dependencies.
|
||||||
|
|
@ -51,87 +51,47 @@ Top-level keys: ~
|
||||||
|
|
||||||
`keys` *forge-config-keys*
|
`keys` *forge-config-keys*
|
||||||
`table|false` (default shown below)
|
`table|false` (default shown below)
|
||||||
Global keymaps. Set to `false` to disable all global keymaps. Setting
|
Per-picker action bindings. Set to `false` to disable all picker-level
|
||||||
an individual key to `nil` or `false` disables that single keymap.
|
actions. Use `"<cr>"` to bind to enter. Values use vim keymap notation
|
||||||
|
(e.g. `"<c-d>"`), which is translated to fzf-lua format internally.
|
||||||
|
|
||||||
Defaults: >lua
|
Defaults: >lua
|
||||||
keys = {
|
keys = {
|
||||||
picker = '<c-g>',
|
|
||||||
next_qf = ']q',
|
|
||||||
prev_qf = '[q',
|
|
||||||
next_loc = ']l',
|
|
||||||
prev_loc = '[l',
|
|
||||||
review_toggle = 's',
|
|
||||||
terminal_open = 'gx',
|
|
||||||
fugitive = {
|
|
||||||
create = 'cpr',
|
|
||||||
create_draft = 'cpd',
|
|
||||||
create_fill = 'cpf',
|
|
||||||
create_web = 'cpw',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
<
|
|
||||||
`keys.picker` Open the main forge picker (|forge-picker|).
|
|
||||||
`keys.next_qf` Navigate to next quickfix entry (wraps).
|
|
||||||
`keys.prev_qf` Navigate to previous quickfix entry (wraps).
|
|
||||||
`keys.next_loc` Navigate to next loclist entry (wraps).
|
|
||||||
`keys.prev_loc` Navigate to previous loclist entry (wraps).
|
|
||||||
`keys.review_toggle` Toggle unified/split review (|forge-review|).
|
|
||||||
`keys.terminal_open` Open URL in browser from log terminal buffers.
|
|
||||||
`keys.fugitive.create` Create PR via compose buffer.
|
|
||||||
`keys.fugitive.create_draft` Create draft PR via compose buffer.
|
|
||||||
`keys.fugitive.create_fill` Create PR instantly (skip compose buffer).
|
|
||||||
`keys.fugitive.create_web` Push and open create-PR page in browser.
|
|
||||||
|
|
||||||
Set `keys.fugitive` to `false` to disable all fugitive-buffer keymaps.
|
|
||||||
|
|
||||||
`picker_keys` *forge-config-picker-keys*
|
|
||||||
`table|false` (default shown below)
|
|
||||||
Per-picker action bindings. Set to `false` to disable all picker-level
|
|
||||||
actions. Use `"default"` to bind to `<enter>`. Other values use fzf-lua
|
|
||||||
binding syntax (e.g. `"ctrl-d"`).
|
|
||||||
|
|
||||||
Defaults: >lua
|
|
||||||
picker_keys = {
|
|
||||||
pr = {
|
pr = {
|
||||||
checkout = 'default',
|
checkout = '<cr>',
|
||||||
diff = 'ctrl-d',
|
diff = '<c-d>',
|
||||||
worktree = 'ctrl-w',
|
worktree = '<c-w>',
|
||||||
checks = 'ctrl-t',
|
ci = '<c-t>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
manage = 'ctrl-e',
|
manage = '<c-e>',
|
||||||
create = 'ctrl-a',
|
create = '<c-a>',
|
||||||
toggle = 'ctrl-o',
|
filter = '<c-o>',
|
||||||
refresh = 'ctrl-r',
|
refresh = '<c-r>',
|
||||||
},
|
},
|
||||||
issue = {
|
issue = {
|
||||||
browse = 'default',
|
browse = '<cr>',
|
||||||
close_reopen = 'ctrl-s',
|
close = '<c-s>',
|
||||||
toggle = 'ctrl-o',
|
filter = '<c-o>',
|
||||||
refresh = 'ctrl-r',
|
refresh = '<c-r>',
|
||||||
},
|
|
||||||
checks = {
|
|
||||||
log = 'default',
|
|
||||||
browse = 'ctrl-x',
|
|
||||||
failed = 'ctrl-f',
|
|
||||||
passed = 'ctrl-p',
|
|
||||||
running = 'ctrl-n',
|
|
||||||
all = 'ctrl-a',
|
|
||||||
},
|
},
|
||||||
ci = {
|
ci = {
|
||||||
log = 'default',
|
log = '<cr>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
refresh = 'ctrl-r',
|
failed = '<c-f>',
|
||||||
|
passed = '<c-p>',
|
||||||
|
running = '<c-n>',
|
||||||
|
all = '<c-a>',
|
||||||
|
refresh = '<c-r>',
|
||||||
},
|
},
|
||||||
commits = {
|
commits = {
|
||||||
checkout = 'default',
|
checkout = '<cr>',
|
||||||
diff = 'ctrl-d',
|
diff = '<c-d>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
yank = 'ctrl-y',
|
yank = '<c-y>',
|
||||||
},
|
},
|
||||||
branches = {
|
branches = {
|
||||||
diff = 'ctrl-d',
|
diff = '<c-d>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
<
|
<
|
||||||
|
|
@ -174,8 +134,7 @@ Top-level keys: ~
|
||||||
COMMANDS *:Forge*
|
COMMANDS *:Forge*
|
||||||
|
|
||||||
`:Forge` *:Forge-no-args*
|
`:Forge` *:Forge-no-args*
|
||||||
Open the main forge picker (|forge-picker|). Same as pressing
|
Open the main forge picker (|forge-picker|).
|
||||||
`keys.picker`.
|
|
||||||
|
|
||||||
`:Forge pr` [{flags}] *:Forge-pr*
|
`:Forge pr` [{flags}] *:Forge-pr*
|
||||||
Open the PR list picker. Defaults to open PRs.
|
Open the PR list picker. Defaults to open PRs.
|
||||||
|
|
@ -200,8 +159,8 @@ COMMANDS *:Forge*
|
||||||
`:Forge pr worktree` {num} *:Forge-pr-worktree*
|
`:Forge pr worktree` {num} *:Forge-pr-worktree*
|
||||||
Fetch PR `{num}` and create a git worktree.
|
Fetch PR `{num}` and create a git worktree.
|
||||||
|
|
||||||
`:Forge pr checks` {num} *:Forge-pr-checks*
|
`:Forge pr ci` {num} *:Forge-pr-ci*
|
||||||
Open the checks picker for PR `{num}`.
|
Open the CI checks picker for PR `{num}`.
|
||||||
|
|
||||||
`:Forge pr browse` {num} *:Forge-pr-browse*
|
`:Forge pr browse` {num} *:Forge-pr-browse*
|
||||||
Open PR `{num}` in the browser.
|
Open PR `{num}` in the browser.
|
||||||
|
|
@ -272,50 +231,11 @@ COMMANDS *:Forge*
|
||||||
`:Forge review toggle` *:Forge-review-toggle*
|
`:Forge review toggle` *:Forge-review-toggle*
|
||||||
Toggle between unified and split view (|forge-review|).
|
Toggle between unified and split view (|forge-review|).
|
||||||
|
|
||||||
`:Forge cache clear` *:Forge-cache-clear*
|
`:Forge clear` *:Forge-clear*
|
||||||
Clear all internal caches (forge detection, repo info, list data).
|
Clear all internal caches (forge detection, repo info, list data).
|
||||||
|
|
||||||
All subcommands support tab completion.
|
All subcommands support tab completion.
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
KEYMAPS *forge-keymaps*
|
|
||||||
|
|
||||||
GLOBAL KEYMAPS ~
|
|
||||||
|
|
||||||
All global keymaps are configured via `keys` (|forge-config-keys|).
|
|
||||||
|
|
||||||
Default Mode Description ~
|
|
||||||
`<c-g>` n, v Open the main forge picker
|
|
||||||
`]q` n Next quickfix entry (wraps to first)
|
|
||||||
`[q` n Previous quickfix entry (wraps to last)
|
|
||||||
`]l` n Next loclist entry (wraps to first)
|
|
||||||
`[l` n Previous loclist entry (wraps to last)
|
|
||||||
|
|
||||||
FUGITIVE KEYMAPS ~
|
|
||||||
|
|
||||||
Active in `fugitive` filetype buffers when a forge is detected. Configured
|
|
||||||
via `keys.fugitive`. Set `keys.fugitive = false` to disable.
|
|
||||||
|
|
||||||
Default Description ~
|
|
||||||
`cpr` Create PR via compose buffer
|
|
||||||
`cpd` Create draft PR via compose buffer
|
|
||||||
`cpf` Create PR instantly (fill from commits)
|
|
||||||
`cpw` Push and open create-PR page in browser
|
|
||||||
|
|
||||||
REVIEW KEYMAPS ~
|
|
||||||
|
|
||||||
Active during a review session (|forge-review|).
|
|
||||||
|
|
||||||
Default Description ~
|
|
||||||
`s` Toggle unified/split view
|
|
||||||
|
|
||||||
TERMINAL KEYMAPS ~
|
|
||||||
|
|
||||||
Active in log terminal buffers opened by the checks or CI pickers.
|
|
||||||
|
|
||||||
Default Description ~
|
|
||||||
`gx` Open the associated check/run URL in the browser
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
PICKERS *forge-pickers*
|
PICKERS *forge-pickers*
|
||||||
|
|
||||||
|
|
@ -332,65 +252,58 @@ PR PICKER ~
|
||||||
Lists PRs/MRs with number, title, author, and relative time.
|
Lists PRs/MRs with number, title, author, and relative time.
|
||||||
|
|
||||||
Action Default Key Description ~
|
Action Default Key Description ~
|
||||||
`checkout` `<enter>` Check out the PR branch
|
`checkout` `<cr>` Check out the PR branch
|
||||||
`diff` `ctrl-d` Start review (|forge-review|)
|
`diff` `<c-d>` Start review (|forge-review|)
|
||||||
`worktree` `ctrl-w` Create worktree from PR
|
`worktree` `<c-w>` Create worktree from PR
|
||||||
`checks` `ctrl-t` Open checks picker for this PR
|
`ci` `<c-t>` Open CI checks picker for this PR
|
||||||
`browse` `ctrl-x` Open PR in browser
|
`browse` `<c-x>` Open PR in browser
|
||||||
`manage` `ctrl-e` Open management picker
|
`manage` `<c-e>` Open management picker
|
||||||
`create` `ctrl-a` Create new PR (|forge-compose|)
|
`create` `<c-a>` Create new PR (|forge-compose|)
|
||||||
`toggle` `ctrl-o` Cycle state: open -> closed -> all
|
`filter` `<c-o>` Cycle state: open -> closed -> all
|
||||||
`refresh` `ctrl-r` Clear cache and re-fetch
|
`refresh` `<c-r>` Clear cache and re-fetch
|
||||||
|
|
||||||
*forge-picker-issue*
|
*forge-picker-issue*
|
||||||
ISSUE PICKER ~
|
ISSUE PICKER ~
|
||||||
Lists issues with number, title, author, and relative time.
|
Lists issues with number, title, author, and relative time.
|
||||||
|
|
||||||
Action Default Key Description ~
|
|
||||||
`browse` `<enter>` Open issue in browser
|
|
||||||
`close_reopen` `ctrl-s` Close or reopen the issue
|
|
||||||
`toggle` `ctrl-o` Cycle state: all -> open -> closed
|
|
||||||
`refresh` `ctrl-r` Clear cache and re-fetch
|
|
||||||
|
|
||||||
*forge-picker-checks*
|
|
||||||
CHECKS PICKER ~
|
|
||||||
Lists PR check runs with status icon, name, and elapsed time.
|
|
||||||
|
|
||||||
Action Default Key Description ~
|
Action Default Key Description ~
|
||||||
`log` `<enter>` View log (tail for running, full otherwise)
|
`browse` `<cr>` Open issue in browser
|
||||||
`browse` `ctrl-x` Open check URL in browser
|
`close` `<c-s>` Close or reopen the issue
|
||||||
`failed` `ctrl-f` Filter to failed checks
|
`filter` `<c-o>` Cycle state: all -> open -> closed
|
||||||
`passed` `ctrl-p` Filter to passed checks
|
`refresh` `<c-r>` Clear cache and re-fetch
|
||||||
`running` `ctrl-n` Filter to running checks
|
|
||||||
`all` `ctrl-a` Show all checks
|
|
||||||
|
|
||||||
*forge-picker-ci*
|
*forge-picker-ci*
|
||||||
CI PICKER ~
|
CI PICKER ~
|
||||||
Lists CI/CD runs for the current branch (or all branches with `--all`).
|
Used for both per-PR checks (`:Forge pr ci {num}`) and repo-wide CI runs
|
||||||
|
(`:Forge ci`). Both share the `keys.ci` bindings.
|
||||||
|
|
||||||
Action Default Key Description ~
|
Action Default Key Description ~
|
||||||
`log` `<enter>` View log (tail for running, failed-only for
|
`log` `<cr>` View log (tail for running, failed-only for
|
||||||
failures, full otherwise)
|
failures, full otherwise)
|
||||||
`browse` `ctrl-x` Open run URL in browser
|
`browse` `<c-x>` Open run/check URL in browser
|
||||||
`refresh` `ctrl-r` Re-fetch runs
|
`failed` `<c-f>` Filter to failed
|
||||||
|
`passed` `<c-p>` Filter to passed
|
||||||
|
`running` `<c-n>` Filter to running
|
||||||
|
`all` `<c-a>` Show all
|
||||||
|
`refresh` `<c-r>` Re-fetch runs
|
||||||
|
|
||||||
*forge-picker-commits*
|
*forge-picker-commits*
|
||||||
COMMITS PICKER ~
|
COMMITS PICKER ~
|
||||||
Git log with colored output and commit preview.
|
Git log with colored output and commit preview.
|
||||||
|
|
||||||
Action Default Key Description ~
|
Action Default Key Description ~
|
||||||
`checkout` `<enter>` Checkout commit (detached HEAD)
|
`checkout` `<cr>` Checkout commit (detached HEAD)
|
||||||
`diff` `ctrl-d` Review the commit diff
|
`diff` `<c-d>` Review the commit diff
|
||||||
`browse` `ctrl-x` Open commit on forge
|
`browse` `<c-x>` Open commit on forge
|
||||||
`yank` `ctrl-y` Yank commit hash to `+` register
|
`yank` `<c-y>` Yank commit hash to `+` register
|
||||||
|
|
||||||
*forge-picker-branches*
|
*forge-picker-branches*
|
||||||
BRANCHES PICKER ~
|
BRANCHES PICKER ~
|
||||||
Uses fzf-lua's `git_branches` with additional actions.
|
Uses fzf-lua's `git_branches` with additional actions.
|
||||||
|
|
||||||
Action Default Key Description ~
|
Action Default Key Description ~
|
||||||
`diff` `ctrl-d` Review diff against branch
|
`diff` `<c-d>` Review diff against branch
|
||||||
`browse` `ctrl-x` Open branch on forge
|
`browse` `<c-x>` Open branch on forge
|
||||||
|
|
||||||
*forge-picker-manage*
|
*forge-picker-manage*
|
||||||
MANAGE PICKER ~
|
MANAGE PICKER ~
|
||||||
|
|
@ -405,8 +318,8 @@ Review mode provides unified and split diff viewing for PRs and commits.
|
||||||
Requires diffs.nvim for unified view and vim-fugitive for split view.
|
Requires diffs.nvim for unified view and vim-fugitive for split view.
|
||||||
|
|
||||||
Starting a review: ~
|
Starting a review: ~
|
||||||
- `ctrl-d` on a PR in the PR picker
|
- `<c-d>` on a PR in the PR picker
|
||||||
- `ctrl-d` on a commit in the commit picker
|
- `<c-d>` on a commit in the commit picker
|
||||||
- `:Forge pr diff {num}`
|
- `:Forge pr diff {num}`
|
||||||
- `:Forge commit diff {sha}`
|
- `:Forge commit diff {sha}`
|
||||||
- `:Forge branch diff {name}`
|
- `:Forge branch diff {name}`
|
||||||
|
|
@ -416,13 +329,8 @@ Unified view (default): ~
|
||||||
a quickfix list of changed files.
|
a quickfix list of changed files.
|
||||||
|
|
||||||
Split view: ~
|
Split view: ~
|
||||||
Press the `review_toggle` key (default `s`) to switch to a side-by-side
|
`:Forge review toggle` switches to a side-by-side fugitive split
|
||||||
fugitive split (`:Gvdiffsplit`). Press again to return to unified.
|
(`:Gvdiffsplit`). Run again to return to unified.
|
||||||
|
|
||||||
Navigation: ~
|
|
||||||
`]q` / `[q` navigate quickfix entries. In split mode, the split is
|
|
||||||
automatically closed and reopened around the new file. Navigation wraps
|
|
||||||
at list boundaries.
|
|
||||||
|
|
||||||
Ending a review: ~
|
Ending a review: ~
|
||||||
`:Forge review end` or wipe the `diffs://review:*` buffer.
|
`:Forge review end` or wipe the `diffs://review:*` buffer.
|
||||||
|
|
@ -622,7 +530,6 @@ Reports on: ~
|
||||||
- Forge CLI availability (`gh`, `glab`, `tea`)
|
- Forge CLI availability (`gh`, `glab`, `tea`)
|
||||||
- `fzf-lua` installation (required)
|
- `fzf-lua` installation (required)
|
||||||
- `diffs.nvim` installation (review mode)
|
- `diffs.nvim` installation (review mode)
|
||||||
- `vim-fugitive` availability (fugitive keymaps, split review)
|
|
||||||
- Custom registered sources and their CLI availability
|
- Custom registered sources and their CLI availability
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
@ -640,7 +547,7 @@ PUBLIC API: `require('forge')` ~
|
||||||
`config()`
|
`config()`
|
||||||
Returns `table`. The resolved configuration, merging `vim.g.forge`
|
Returns `table`. The resolved configuration, merging `vim.g.forge`
|
||||||
over defaults. If `vim.g.forge.keys` is `false`, `cfg.keys` is
|
over defaults. If `vim.g.forge.keys` is `false`, `cfg.keys` is
|
||||||
`false`. Same for `picker_keys`.
|
`false`.
|
||||||
|
|
||||||
*forge.register()*
|
*forge.register()*
|
||||||
`register(name, source)`
|
`register(name, source)`
|
||||||
|
|
@ -749,7 +656,7 @@ PUBLIC API: `require('forge.pickers')` ~
|
||||||
`pr_actions(f, num)`
|
`pr_actions(f, num)`
|
||||||
Returns `table<string, function>`. Action functions for PR `num`,
|
Returns `table<string, function>`. Action functions for PR `num`,
|
||||||
keyed by fzf binding. Also has `_by_name` table keyed by action
|
keyed by fzf binding. Also has `_by_name` table keyed by action
|
||||||
name (`"checkout"`, `"diff"`, `"worktree"`, `"browse"`, `"checks"`,
|
name (`"checkout"`, `"diff"`, `"worktree"`, `"browse"`, `"ci"`,
|
||||||
`"manage"`).
|
`"manage"`).
|
||||||
|
|
||||||
*forge.pickers.issue_close()*
|
*forge.pickers.issue_close()*
|
||||||
|
|
@ -769,8 +676,7 @@ PUBLIC API: `require('forge.review')` ~
|
||||||
|
|
||||||
*forge.review.stop()*
|
*forge.review.stop()*
|
||||||
`stop()`
|
`stop()`
|
||||||
Ends the current review session. Clears state and removes the
|
Ends the current review session. Clears state.
|
||||||
`review_toggle` keymap.
|
|
||||||
|
|
||||||
*forge.review.toggle()*
|
*forge.review.toggle()*
|
||||||
`toggle()`
|
`toggle()`
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,6 @@ function M.check()
|
||||||
vim.health.info('diffs.nvim not found (review mode disabled)')
|
vim.health.info('diffs.nvim not found (review mode disabled)')
|
||||||
end
|
end
|
||||||
|
|
||||||
local has_fugitive = vim.fn.exists(':Git') == 2
|
|
||||||
if has_fugitive then
|
|
||||||
vim.health.ok('vim-fugitive found (fugitive keymaps available)')
|
|
||||||
else
|
|
||||||
vim.health.info('vim-fugitive not found (fugitive keymaps disabled)')
|
|
||||||
end
|
|
||||||
|
|
||||||
local forge_mod = require('forge')
|
local forge_mod = require('forge')
|
||||||
for name, source in pairs(forge_mod.registered_sources()) do
|
for name, source in pairs(forge_mod.registered_sources()) do
|
||||||
if name ~= 'github' and name ~= 'gitlab' and name ~= 'codeberg' then
|
if name ~= 'github' and name ~= 'gitlab' and name ~= 'codeberg' then
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ local M = {}
|
||||||
---@field ci forge.CIConfig
|
---@field ci forge.CIConfig
|
||||||
---@field sources table<string, forge.SourceConfig>
|
---@field sources table<string, forge.SourceConfig>
|
||||||
---@field keys forge.KeysConfig|false
|
---@field keys forge.KeysConfig|false
|
||||||
---@field picker_keys forge.PickerKeysConfig|false
|
|
||||||
---@field display forge.DisplayConfig
|
---@field display forge.DisplayConfig
|
||||||
|
|
||||||
---@class forge.CIConfig
|
---@class forge.CIConfig
|
||||||
|
|
@ -14,25 +13,8 @@ local M = {}
|
||||||
---@field hosts string[]
|
---@field hosts string[]
|
||||||
|
|
||||||
---@class forge.KeysConfig
|
---@class forge.KeysConfig
|
||||||
---@field picker string|false
|
|
||||||
---@field next_qf string|false
|
|
||||||
---@field prev_qf string|false
|
|
||||||
---@field next_loc string|false
|
|
||||||
---@field prev_loc string|false
|
|
||||||
---@field review_toggle string|false
|
|
||||||
---@field terminal_open string|false
|
|
||||||
---@field fugitive forge.FugitiveKeysConfig|false
|
|
||||||
|
|
||||||
---@class forge.FugitiveKeysConfig
|
|
||||||
---@field create string|false
|
|
||||||
---@field create_draft string|false
|
|
||||||
---@field create_fill string|false
|
|
||||||
---@field create_web string|false
|
|
||||||
|
|
||||||
---@class forge.PickerKeysConfig
|
|
||||||
---@field pr forge.PRPickerKeys
|
---@field pr forge.PRPickerKeys
|
||||||
---@field issue forge.IssuePickerKeys
|
---@field issue forge.IssuePickerKeys
|
||||||
---@field checks forge.ChecksPickerKeys
|
|
||||||
---@field ci forge.CIPickerKeys
|
---@field ci forge.CIPickerKeys
|
||||||
---@field commits forge.CommitsPickerKeys
|
---@field commits forge.CommitsPickerKeys
|
||||||
---@field branches forge.BranchesPickerKeys
|
---@field branches forge.BranchesPickerKeys
|
||||||
|
|
@ -41,30 +23,26 @@ local M = {}
|
||||||
---@field checkout string|false
|
---@field checkout string|false
|
||||||
---@field diff string|false
|
---@field diff string|false
|
||||||
---@field worktree string|false
|
---@field worktree string|false
|
||||||
---@field checks string|false
|
---@field ci string|false
|
||||||
---@field browse string|false
|
---@field browse string|false
|
||||||
---@field manage string|false
|
---@field manage string|false
|
||||||
---@field create string|false
|
---@field create string|false
|
||||||
---@field toggle string|false
|
---@field filter string|false
|
||||||
---@field refresh string|false
|
---@field refresh string|false
|
||||||
|
|
||||||
---@class forge.IssuePickerKeys
|
---@class forge.IssuePickerKeys
|
||||||
---@field browse string|false
|
---@field browse string|false
|
||||||
---@field close_reopen string|false
|
---@field close string|false
|
||||||
---@field toggle string|false
|
---@field filter string|false
|
||||||
---@field refresh string|false
|
---@field refresh string|false
|
||||||
|
|
||||||
---@class forge.ChecksPickerKeys
|
---@class forge.CIPickerKeys
|
||||||
---@field log string|false
|
---@field log string|false
|
||||||
---@field browse string|false
|
---@field browse string|false
|
||||||
---@field failed string|false
|
---@field failed string|false
|
||||||
---@field passed string|false
|
---@field passed string|false
|
||||||
---@field running string|false
|
---@field running string|false
|
||||||
---@field all string|false
|
---@field all string|false
|
||||||
|
|
||||||
---@class forge.CIPickerKeys
|
|
||||||
---@field log string|false
|
|
||||||
---@field browse string|false
|
|
||||||
---@field refresh string|false
|
---@field refresh string|false
|
||||||
|
|
||||||
---@class forge.CommitsPickerKeys
|
---@class forge.CommitsPickerKeys
|
||||||
|
|
@ -108,44 +86,29 @@ local DEFAULTS = {
|
||||||
ci = { lines = 10000 },
|
ci = { lines = 10000 },
|
||||||
sources = {},
|
sources = {},
|
||||||
keys = {
|
keys = {
|
||||||
picker = '<c-g>',
|
|
||||||
next_qf = ']q',
|
|
||||||
prev_qf = '[q',
|
|
||||||
next_loc = ']l',
|
|
||||||
prev_loc = '[l',
|
|
||||||
review_toggle = 's',
|
|
||||||
terminal_open = 'gx',
|
|
||||||
fugitive = {
|
|
||||||
create = 'cpr',
|
|
||||||
create_draft = 'cpd',
|
|
||||||
create_fill = 'cpf',
|
|
||||||
create_web = 'cpw',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
picker_keys = {
|
|
||||||
pr = {
|
pr = {
|
||||||
checkout = 'default',
|
checkout = '<cr>',
|
||||||
diff = 'ctrl-d',
|
diff = '<c-d>',
|
||||||
worktree = 'ctrl-w',
|
worktree = '<c-w>',
|
||||||
checks = 'ctrl-t',
|
ci = '<c-t>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
manage = 'ctrl-e',
|
manage = '<c-e>',
|
||||||
create = 'ctrl-a',
|
create = '<c-a>',
|
||||||
toggle = 'ctrl-o',
|
filter = '<c-o>',
|
||||||
refresh = 'ctrl-r',
|
refresh = '<c-r>',
|
||||||
},
|
},
|
||||||
issue = { browse = 'default', close_reopen = 'ctrl-s', toggle = 'ctrl-o', refresh = 'ctrl-r' },
|
issue = { browse = '<cr>', close = '<c-s>', filter = '<c-o>', refresh = '<c-r>' },
|
||||||
checks = {
|
ci = {
|
||||||
log = 'default',
|
log = '<cr>',
|
||||||
browse = 'ctrl-x',
|
browse = '<c-x>',
|
||||||
failed = 'ctrl-f',
|
failed = '<c-f>',
|
||||||
passed = 'ctrl-p',
|
passed = '<c-p>',
|
||||||
running = 'ctrl-n',
|
running = '<c-n>',
|
||||||
all = 'ctrl-a',
|
all = '<c-a>',
|
||||||
|
refresh = '<c-r>',
|
||||||
},
|
},
|
||||||
ci = { log = 'default', browse = 'ctrl-x', refresh = 'ctrl-r' },
|
commits = { checkout = '<cr>', diff = '<c-d>', browse = '<c-x>', yank = '<c-y>' },
|
||||||
commits = { checkout = 'default', diff = 'ctrl-d', browse = 'ctrl-x', yank = 'ctrl-y' },
|
branches = { diff = '<c-d>', browse = '<c-x>' },
|
||||||
branches = { diff = 'ctrl-d', browse = 'ctrl-x' },
|
|
||||||
},
|
},
|
||||||
display = {
|
display = {
|
||||||
icons = {
|
icons = {
|
||||||
|
|
@ -749,9 +712,6 @@ function M.config()
|
||||||
if user.keys == false then
|
if user.keys == false then
|
||||||
cfg.keys = false
|
cfg.keys = false
|
||||||
end
|
end
|
||||||
if user.picker_keys == false then
|
|
||||||
cfg.picker_keys = false
|
|
||||||
end
|
|
||||||
return cfg
|
return cfg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,20 @@ local fzf_args = (vim.env.FZF_DEFAULT_OPTS or '')
|
||||||
:gsub('%-%-bind=[^%s]+', '')
|
:gsub('%-%-bind=[^%s]+', '')
|
||||||
:gsub('%-%-color=[^%s]+', '')
|
:gsub('%-%-color=[^%s]+', '')
|
||||||
|
|
||||||
|
local function to_fzf_key(key)
|
||||||
|
if key == '<cr>' then
|
||||||
|
return 'default'
|
||||||
|
end
|
||||||
|
return key:gsub('<c%-(%a)>', function(ch)
|
||||||
|
return 'ctrl-' .. ch:lower()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
local function make_header(bindings)
|
local function make_header(bindings)
|
||||||
local utils = require('fzf-lua.utils')
|
local utils = require('fzf-lua.utils')
|
||||||
local parts = {}
|
local parts = {}
|
||||||
for _, b in ipairs(bindings) do
|
for _, b in ipairs(bindings) do
|
||||||
local key = utils.ansi_from_hl('FzfLuaHeaderBind', '<' .. b[1] .. '>')
|
local key = utils.ansi_from_hl('FzfLuaHeaderBind', b[1])
|
||||||
local desc = utils.ansi_from_hl('FzfLuaHeaderText', b[2])
|
local desc = utils.ansi_from_hl('FzfLuaHeaderText', b[2])
|
||||||
table.insert(parts, key .. ' to ' .. desc)
|
table.insert(parts, key .. ' to ' .. desc)
|
||||||
end
|
end
|
||||||
|
|
@ -32,34 +41,26 @@ end
|
||||||
|
|
||||||
local function build_actions(picker_name, action_defs)
|
local function build_actions(picker_name, action_defs)
|
||||||
local cfg = require('forge').config()
|
local cfg = require('forge').config()
|
||||||
local pk = cfg.picker_keys
|
local keys = cfg.keys
|
||||||
if pk == false then
|
if keys == false then
|
||||||
pk = {}
|
keys = {}
|
||||||
end
|
end
|
||||||
local bindings = pk[picker_name] or {}
|
local bindings = keys[picker_name] or {}
|
||||||
local actions = {}
|
local actions = {}
|
||||||
local header_entries = {}
|
local header_entries = {}
|
||||||
for _, def in ipairs(action_defs) do
|
for _, def in ipairs(action_defs) do
|
||||||
local key = bindings[def.name]
|
local key = bindings[def.name]
|
||||||
if key then
|
if key then
|
||||||
actions[key] = def.fn
|
local fzf_key = to_fzf_key(key)
|
||||||
|
actions[fzf_key] = def.fn
|
||||||
if def.label then
|
if def.label then
|
||||||
local display_key = key == 'default' and 'enter' or key:gsub('ctrl%-', 'ctrl-')
|
table.insert(header_entries, { key, def.label })
|
||||||
table.insert(header_entries, { display_key, def.label })
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return actions, make_header(header_entries)
|
return actions, make_header(header_entries)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function terminal_open_key()
|
|
||||||
local cfg = require('forge').config()
|
|
||||||
if cfg.keys == false then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
return cfg.keys.terminal_open
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param kind string
|
---@param kind string
|
||||||
---@param num string
|
---@param num string
|
||||||
---@param label string
|
---@param label string
|
||||||
|
|
@ -188,7 +189,7 @@ local function pr_actions(f, num)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = 'checks',
|
name = 'ci',
|
||||||
fn = function()
|
fn = function()
|
||||||
M.checks(f, num)
|
M.checks(f, num)
|
||||||
end,
|
end,
|
||||||
|
|
@ -318,7 +319,7 @@ function M.checks(f, num, filter, cached_checks)
|
||||||
pending = 'running',
|
pending = 'running',
|
||||||
}
|
}
|
||||||
|
|
||||||
local check_actions, check_header = build_actions('checks', {
|
local check_actions, check_header = build_actions('ci', {
|
||||||
{
|
{
|
||||||
name = 'log',
|
name = 'log',
|
||||||
label = 'log',
|
label = 'log',
|
||||||
|
|
@ -346,15 +347,8 @@ function M.checks(f, num, filter, cached_checks)
|
||||||
'n',
|
'n',
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
local to_key = terminal_open_key()
|
if c.link then
|
||||||
if c.link and to_key then
|
|
||||||
vim.b.forge_check_url = c.link
|
vim.b.forge_check_url = c.link
|
||||||
vim.keymap.set('n', to_key, function()
|
|
||||||
vim.ui.open(vim.b.forge_check_url)
|
|
||||||
end, {
|
|
||||||
buffer = true,
|
|
||||||
desc = 'open check in browser',
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
@ -495,15 +489,8 @@ function M.ci(f, branch)
|
||||||
'n',
|
'n',
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
local to_key = terminal_open_key()
|
if run.url ~= '' then
|
||||||
if run.url ~= '' and to_key then
|
|
||||||
vim.b.forge_run_url = run.url
|
vim.b.forge_run_url = run.url
|
||||||
vim.keymap.set('n', to_key, function()
|
|
||||||
vim.ui.open(vim.b.forge_run_url)
|
|
||||||
end, {
|
|
||||||
buffer = true,
|
|
||||||
desc = 'open run in browser',
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
@ -745,11 +732,11 @@ function M.pr(state, f)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = 'checks',
|
name = 'ci',
|
||||||
label = 'checks',
|
label = 'ci',
|
||||||
fn = function(selected)
|
fn = function(selected)
|
||||||
with_pr_num(selected, function(num)
|
with_pr_num(selected, function(num)
|
||||||
pr_actions(f, num)._by_name.checks()
|
pr_actions(f, num)._by_name.ci()
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
@ -779,8 +766,8 @@ function M.pr(state, f)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = 'toggle',
|
name = 'filter',
|
||||||
label = 'toggle',
|
label = 'filter',
|
||||||
fn = function()
|
fn = function()
|
||||||
M.pr(next_state, f)
|
M.pr(next_state, f)
|
||||||
end,
|
end,
|
||||||
|
|
@ -865,7 +852,7 @@ function M.issue(state, f)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = 'close_reopen',
|
name = 'close',
|
||||||
label = 'close/reopen',
|
label = 'close/reopen',
|
||||||
fn = function(selected)
|
fn = function(selected)
|
||||||
with_issue_num(selected, function(num)
|
with_issue_num(selected, function(num)
|
||||||
|
|
@ -874,8 +861,8 @@ function M.issue(state, f)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = 'toggle',
|
name = 'filter',
|
||||||
label = 'toggle',
|
label = 'filter',
|
||||||
fn = function()
|
fn = function()
|
||||||
M.issue(next_state, f)
|
M.issue(next_state, f)
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
129
plugin/forge.lua
129
plugin/forge.lua
|
|
@ -1,86 +1,3 @@
|
||||||
local cfg = require('forge').config()
|
|
||||||
|
|
||||||
if cfg.keys ~= false then
|
|
||||||
local k = cfg.keys
|
|
||||||
|
|
||||||
if k.picker then
|
|
||||||
vim.keymap.set({ 'n', 'v' }, k.picker, function()
|
|
||||||
require('forge.pickers').git()
|
|
||||||
end, { desc = 'forge git picker' })
|
|
||||||
end
|
|
||||||
|
|
||||||
if k.next_qf then
|
|
||||||
vim.keymap.set(
|
|
||||||
'n',
|
|
||||||
k.next_qf,
|
|
||||||
require('forge.review').nav('cnext'),
|
|
||||||
{ desc = 'next quickfix entry' }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if k.prev_qf then
|
|
||||||
vim.keymap.set(
|
|
||||||
'n',
|
|
||||||
k.prev_qf,
|
|
||||||
require('forge.review').nav('cprev'),
|
|
||||||
{ desc = 'prev quickfix entry' }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if k.next_loc then
|
|
||||||
vim.keymap.set(
|
|
||||||
'n',
|
|
||||||
k.next_loc,
|
|
||||||
require('forge.review').nav('lnext'),
|
|
||||||
{ desc = 'next loclist entry' }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if k.prev_loc then
|
|
||||||
vim.keymap.set(
|
|
||||||
'n',
|
|
||||||
k.prev_loc,
|
|
||||||
require('forge.review').nav('lprev'),
|
|
||||||
{ desc = 'prev loclist entry' }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
if k.fugitive ~= false then
|
|
||||||
vim.api.nvim_create_autocmd('FileType', {
|
|
||||||
pattern = 'fugitive',
|
|
||||||
callback = function(args)
|
|
||||||
local forge_mod = require('forge')
|
|
||||||
local f = forge_mod.detect()
|
|
||||||
if not f then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local fk = k.fugitive
|
|
||||||
local buf = args.buf
|
|
||||||
if fk.create then
|
|
||||||
vim.keymap.set('n', fk.create, function()
|
|
||||||
forge_mod.create_pr({ draft = false })
|
|
||||||
end, { buffer = buf, desc = 'create PR' })
|
|
||||||
end
|
|
||||||
if fk.create_draft then
|
|
||||||
vim.keymap.set('n', fk.create_draft, function()
|
|
||||||
forge_mod.create_pr({ draft = true })
|
|
||||||
end, { buffer = buf, desc = 'create draft PR' })
|
|
||||||
end
|
|
||||||
if fk.create_fill then
|
|
||||||
vim.keymap.set('n', fk.create_fill, function()
|
|
||||||
forge_mod.create_pr({ instant = true })
|
|
||||||
end, { buffer = buf, desc = 'create PR (fill)' })
|
|
||||||
end
|
|
||||||
if fk.create_web then
|
|
||||||
vim.keymap.set('n', fk.create_web, function()
|
|
||||||
forge_mod.create_pr({ web = true })
|
|
||||||
end, { buffer = buf, desc = 'create PR (web)' })
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd('FileType', {
|
vim.api.nvim_create_autocmd('FileType', {
|
||||||
pattern = 'qf',
|
pattern = 'qf',
|
||||||
callback = function()
|
callback = function()
|
||||||
|
|
@ -188,7 +105,7 @@ local function dispatch(args)
|
||||||
pickers.pr_actions(f, num)._by_name.diff()
|
pickers.pr_actions(f, num)._by_name.diff()
|
||||||
elseif action == 'worktree' then
|
elseif action == 'worktree' then
|
||||||
pickers.pr_actions(f, num)._by_name.worktree()
|
pickers.pr_actions(f, num)._by_name.worktree()
|
||||||
elseif action == 'checks' then
|
elseif action == 'ci' then
|
||||||
pickers.checks(f, num)
|
pickers.checks(f, num)
|
||||||
elseif action == 'browse' then
|
elseif action == 'browse' then
|
||||||
f:view_web(f.kinds.pr, num)
|
f:view_web(f.kinds.pr, num)
|
||||||
|
|
@ -424,17 +341,9 @@ local function dispatch(args)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if sub == 'cache' then
|
if sub == 'clear' then
|
||||||
if #args < 2 then
|
require('forge').clear_cache()
|
||||||
vim.notify('[forge]: missing cache action (clear)', vim.log.levels.WARN)
|
vim.notify('[forge]: cache cleared')
|
||||||
return
|
|
||||||
end
|
|
||||||
if args[2] == 'clear' then
|
|
||||||
require('forge').clear_cache()
|
|
||||||
vim.notify('[forge]: cache cleared')
|
|
||||||
else
|
|
||||||
vim.notify('[forge]: unknown cache action: ' .. args[2], vim.log.levels.WARN)
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -449,29 +358,20 @@ local function complete(arglead, cmdline, _)
|
||||||
local arg_idx = arglead == '' and #words or #words - 1
|
local arg_idx = arglead == '' and #words or #words - 1
|
||||||
|
|
||||||
local subcmds =
|
local subcmds =
|
||||||
{ 'pr', 'issue', 'ci', 'commit', 'branch', 'worktree', 'browse', 'yank', 'review', 'cache' }
|
{ 'pr', 'issue', 'ci', 'commit', 'branch', 'worktree', 'browse', 'yank', 'review', 'clear' }
|
||||||
local sub_actions = {
|
local sub_actions = {
|
||||||
pr = {
|
pr = { 'checkout', 'diff', 'worktree', 'ci', 'browse', 'manage', 'create', '--state=' },
|
||||||
'checkout',
|
issue = { 'browse', 'close', 'reopen', '--state=' },
|
||||||
'diff',
|
|
||||||
'worktree',
|
|
||||||
'checks',
|
|
||||||
'browse',
|
|
||||||
'manage',
|
|
||||||
'create',
|
|
||||||
'--state=open',
|
|
||||||
'--state=closed',
|
|
||||||
'--state=all',
|
|
||||||
},
|
|
||||||
issue = { 'browse', 'close', 'reopen', '--state=open', '--state=closed', '--state=all' },
|
|
||||||
ci = { '--all' },
|
ci = { '--all' },
|
||||||
commit = { 'checkout', 'diff', 'browse' },
|
commit = { 'checkout', 'diff', 'browse' },
|
||||||
branch = { 'diff', 'browse' },
|
branch = { 'diff', 'browse' },
|
||||||
review = { 'end', 'toggle' },
|
review = { 'end', 'toggle' },
|
||||||
cache = { 'clear' },
|
|
||||||
browse = { '--root', '--commit' },
|
browse = { '--root', '--commit' },
|
||||||
yank = { '--commit' },
|
yank = { '--commit' },
|
||||||
}
|
}
|
||||||
|
local flag_values = {
|
||||||
|
['--state'] = { 'open', 'closed', 'all' },
|
||||||
|
}
|
||||||
local create_flags = { '--draft', '--fill', '--web' }
|
local create_flags = { '--draft', '--fill', '--web' }
|
||||||
|
|
||||||
local function filter(candidates)
|
local function filter(candidates)
|
||||||
|
|
@ -480,6 +380,15 @@ local function complete(arglead, cmdline, _)
|
||||||
end, candidates)
|
end, candidates)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local flag, value_prefix = arglead:match('^(%-%-[^=]+)=(.*)$')
|
||||||
|
if flag and flag_values[flag] then
|
||||||
|
return vim.tbl_map(function(v)
|
||||||
|
return flag .. '=' .. v
|
||||||
|
end, vim.tbl_filter(function(v)
|
||||||
|
return v:find(value_prefix, 1, true) == 1
|
||||||
|
end, flag_values[flag]))
|
||||||
|
end
|
||||||
|
|
||||||
if arg_idx == 1 then
|
if arg_idx == 1 then
|
||||||
return filter(subcmds)
|
return filter(subcmds)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue