feat: update helpdocs

This commit is contained in:
Barrett Ruth 2026-03-28 12:43:55 -04:00
parent afb5d93853
commit 4ae7439a75
No known key found for this signature in database
GPG key ID: A6C96C9349D2FC81
4 changed files with 101 additions and 96 deletions

View file

@ -36,7 +36,7 @@ Top-level keys: ~
`ci.lines` `integer` (default `10000`) `ci.lines` `integer` (default `10000`)
Maximum number of log lines fetched for CI/check log output. Maximum number of log lines fetched for CI/check log output.
`sources` *forge-config-sources* `sources` *forge-config-sources*
`table<string, { hosts: string[] }>` (default `{}`) `table<string, { hosts: string[] }>` (default `{}`)
Per-source host overrides for forge detection. Keys are source names Per-source host overrides for forge detection. Keys are source names
(e.g. `"github"`, `"gitlab"`, or a custom name). Each value has a (e.g. `"github"`, `"gitlab"`, or a custom name). Each value has a
@ -49,7 +49,7 @@ Top-level keys: ~
} }
< <
`keys` *forge-config-keys* `keys` *forge-config-keys*
`table|false` (default shown below) `table|false` (default shown below)
Per-picker action bindings. Set to `false` to disable all picker-level Per-picker action bindings. Set to `false` to disable all picker-level
actions. Use `"<cr>"` to bind to enter. Values use vim keymap notation actions. Use `"<cr>"` to bind to enter. Values use vim keymap notation
@ -96,11 +96,11 @@ Top-level keys: ~
} }
< <
`display` *forge-config-display* `display` *forge-config-display*
Controls icons, column widths, and fetch limits used in picker Controls icons, column widths, and fetch limits used in picker
formatting. formatting.
`display.icons` *forge-config-display-icons* `display.icons` *forge-config-display-icons*
`table` Status icons used in picker lines. `table` Status icons used in picker lines.
Key Default Used for ~ Key Default Used for ~
@ -113,7 +113,7 @@ Top-level keys: ~
`skip` `"-"` Skipped/cancelled runs `skip` `"-"` Skipped/cancelled runs
`unknown` `"?"` Unknown status `unknown` `"?"` Unknown status
`display.widths` *forge-config-display-widths* `display.widths` *forge-config-display-widths*
`table` Column widths (characters) for picker formatting. `table` Column widths (characters) for picker formatting.
Key Default ~ Key Default ~
@ -122,7 +122,7 @@ Top-level keys: ~
`name` `35` `name` `35`
`branch` `25` `branch` `25`
`display.limits` *forge-config-display-limits* `display.limits` *forge-config-display-limits*
`table` Maximum items fetched per list API call. `table` Maximum items fetched per list API call.
Key Default ~ Key Default ~
@ -131,7 +131,7 @@ Top-level keys: ~
`runs` `30` `runs` `30`
============================================================================== ==============================================================================
COMMANDS *:Forge* COMMANDS *:Forge*
`:Forge` *:Forge-no-args* `:Forge` *:Forge-no-args*
Open the main forge picker (|forge-picker|). Open the main forge picker (|forge-picker|).
@ -203,13 +203,13 @@ COMMANDS *:Forge*
`:Forge branch` *:Forge-branch* `:Forge branch` *:Forge-branch*
Open the branch picker. Open the branch picker.
`:Forge branch diff` {name} *:Forge-branch-diff* `:Forge branch diff` {name} *:Forge-branch-diff*
Start a review diffing against `{name}`. Start a review diffing against `{name}`.
`:Forge branch browse` {name} *:Forge-branch-browse* `:Forge branch browse` {name} *:Forge-branch-browse*
Open branch `{name}` on the forge. Open branch `{name}` on the forge.
`:Forge worktree` *:Forge-worktree* `:Forge worktree` *:Forge-worktree*
Open fzf-lua's git worktree picker. Open fzf-lua's git worktree picker.
`:Forge browse` [{flags}] *:Forge-browse* `:Forge browse` [{flags}] *:Forge-browse*
@ -225,13 +225,13 @@ COMMANDS *:Forge*
`--commit` Yank a commit-pinned URL. `--commit` Yank a commit-pinned URL.
(no flags) Yank a branch-pinned URL. (no flags) Yank a branch-pinned URL.
`:Forge review end` *:Forge-review-end* `:Forge review end` *:Forge-review-end*
End the current review session. End the current review session.
`: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 clear` *:Forge-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.
@ -239,17 +239,15 @@ All subcommands support tab completion.
============================================================================== ==============================================================================
PICKERS *forge-pickers* PICKERS *forge-pickers*
*forge-picker* *forge-picker*
FORGE PICKER ~ FORGE PICKER ~ The main entry point. Adapts based on the detected forge and
The main entry point. Adapts based on the detected forge and current current buffer. Lists: PRs/MRs, Issues, CI/CD, Browse Remote, Open File, Yank
buffer. Lists: PRs/MRs, Issues, CI/CD, Browse Remote, Open File, Yank Commit URL, Yank Branch URL, Commits, Branches, Worktrees. Items that require
Commit URL, Yank Branch URL, Commits, Branches, Worktrees. Items that a forge are hidden when no forge is detected. "Open File" and yank entries
require a forge are hidden when no forge is detected. "Open File" and yank require a named buffer on a branch.
entries require a named buffer on a branch.
*forge-picker-pr* *forge-picker-pr*
PR PICKER ~ 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` `<cr>` Check out the PR branch `checkout` `<cr>` Check out the PR branch
@ -262,9 +260,8 @@ Lists PRs/MRs with number, title, author, and relative time.
`filter` `<c-o>` Cycle state: open -> closed -> all `filter` `<c-o>` Cycle state: open -> closed -> all
`refresh` `<c-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 ~ Action Default Key Description ~
`browse` `<cr>` Open issue in browser `browse` `<cr>` Open issue in browser
@ -272,10 +269,9 @@ Lists issues with number, title, author, and relative time.
`filter` `<c-o>` Cycle state: all -> open -> closed `filter` `<c-o>` Cycle state: all -> open -> closed
`refresh` `<c-r>` Clear cache and re-fetch `refresh` `<c-r>` Clear cache and re-fetch
*forge-picker-ci* *forge-picker-ci*
CI PICKER ~ CI PICKER ~ Used for both per-PR checks (`:Forge pr ci {num}`) and repo-wide
Used for both per-PR checks (`:Forge pr ci {num}`) and repo-wide CI runs CI runs (`:Forge ci`). Both share the `keys.ci` bindings.
(`:Forge ci`). Both share the `keys.ci` bindings.
Action Default Key Description ~ Action Default Key Description ~
`log` `<cr>` View log (tail for running, failed-only for `log` `<cr>` View log (tail for running, failed-only for
@ -287,9 +283,8 @@ Used for both per-PR checks (`:Forge pr ci {num}`) and repo-wide CI runs
`all` `<c-a>` Show all `all` `<c-a>` Show all
`refresh` `<c-r>` Re-fetch runs `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` `<cr>` Checkout commit (detached HEAD) `checkout` `<cr>` Checkout commit (detached HEAD)
@ -297,19 +292,17 @@ Git log with colored output and commit preview.
`browse` `<c-x>` Open commit on forge `browse` `<c-x>` Open commit on forge
`yank` `<c-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` `<c-d>` Review diff against branch `diff` `<c-d>` Review diff against branch
`browse` `<c-x>` Open branch on forge `browse` `<c-x>` Open branch on forge
*forge-picker-manage* *forge-picker-manage*
MANAGE PICKER ~ MANAGE PICKER ~ Contextual actions for a specific PR, shown based on
Contextual actions for a specific PR, shown based on permissions and permissions and state: Approve, Merge (per available method: squash, rebase,
state: Approve, Merge (per available method: squash, rebase, merge), merge), Close/Reopen, Mark as draft/Mark as ready.
Close/Reopen, Mark as draft/Mark as ready.
============================================================================== ==============================================================================
REVIEW *forge-review* REVIEW *forge-review*
@ -371,7 +364,15 @@ Template discovery: ~
Codeberg: `.gitea/pull_request_template.md`, Codeberg: `.gitea/pull_request_template.md`,
`.github/pull_request_template.md` `.github/pull_request_template.md`
Highlight groups: ~ See |forge-highlights| for compose buffer highlight groups.
==============================================================================
HIGHLIGHTS *forge-highlights*
All highlight groups are defined with `default = true`, so they can be
overridden by colorschemes or user config.
Compose buffer: ~
Group Default Link Description ~ Group Default Link Description ~
`ForgeComposeComment` `Comment` Comment block lines `ForgeComposeComment` `Comment` Comment block lines
@ -382,7 +383,19 @@ Highlight groups: ~
`ForgeComposeAdded` `Added` Addition indicators (+) `ForgeComposeAdded` `Added` Addition indicators (+)
`ForgeComposeRemoved` `Removed` Deletion indicators (-) `ForgeComposeRemoved` `Removed` Deletion indicators (-)
All groups are defined with `default = true`. Picker lines: ~
Group Default Link Description ~
`ForgeNumber` `Number` PR/issue number (#123)
`ForgeOpen` `DiagnosticInfo` Open status icon
`ForgeMerged` `Constant` Merged status icon
`ForgeClosed` `Comment` Closed status icon
`ForgePass` `DiagnosticOk` Passed CI status icon
`ForgeFail` `DiagnosticError` Failed CI status icon
`ForgePending` `DiagnosticWarn` In-progress CI status icon
`ForgeSkip` `Comment` Skipped/cancelled CI icon
`ForgeBranch` `Special` Branch name in CI runs
`ForgeDim` `Comment` Author, age, elapsed time
============================================================================== ==============================================================================
SOURCES *forge-sources* SOURCES *forge-sources*
@ -394,12 +407,12 @@ Built-in sources: ~
`gitlab` `glab` `gitlab` `gitlab` `glab` `gitlab`
`codeberg` `tea` `codeberg`, `gitea`, `forgejo` `codeberg` `tea` `codeberg`, `gitea`, `forgejo`
Sources are lazy-loaded the first time a matching remote is detected. Sources are lazy-loaded the first time a matching remote is detected. Built-in
Built-in host patterns are checked after user-configured `sources` hosts, host patterns are checked after user-configured `sources` hosts, so user
so user overrides take priority. overrides take priority.
HOST OVERRIDES ~ HOST OVERRIDES ~
*forge-sources-hosts* *forge-sources-hosts*
To route a self-hosted instance to a built-in source: >lua To route a self-hosted instance to a built-in source: >lua
vim.g.forge = { vim.g.forge = {
sources = { sources = {
@ -409,19 +422,18 @@ To route a self-hosted instance to a built-in source: >lua
< <
CUSTOM SOURCE REGISTRATION ~ CUSTOM SOURCE REGISTRATION ~
*forge-sources-register* *forge-sources-register*
Register a custom source with `require('forge').register()`: >lua Register a custom source with `require('forge').register()`: >lua
local my_source = { ... } local my_source = { ... }
require('forge').register('myforgejo', my_source) require('forge').register('myforgejo', my_source)
< < The name must match the key used in `sources` host config. The source module
The name must match the key used in `sources` host config. The source is also discoverable as `forge.<name>` (e.g. `require('forge.myforgejo')` if
module is also discoverable as `forge.<name>` (e.g. `require('forge.myforgejo')` placed at `lua/forge/myforgejo.lua`).
if placed at `lua/forge/myforgejo.lua`).
THE `forge.Forge` INTERFACE ~ THE `forge.Forge` INTERFACE ~
*forge-Forge-interface* *forge-Forge-interface*
A source must implement all methods in the `forge.Forge` class. Each A source must implement all methods in the `forge.Forge` class. Each source is
source is a table with these fields and methods: a table with these fields and methods:
Fields: ~ Fields: ~
`name` `string` Source name (e.g. `"github"`). `name` `string` Source name (e.g. `"github"`).
@ -580,7 +592,7 @@ PUBLIC API: `require('forge')` ~
line number(s). In visual mode, includes the selected line range line number(s). In visual mode, includes the selected line range
(e.g. `"src/foo.lua:10-20"`). (e.g. `"src/foo.lua:10-20"`).
*forge.remote_web_url()* *forge.remote_web_url()*
`remote_web_url()` `remote_web_url()`
Returns `string`. The HTTPS URL of the `origin` remote, normalized Returns `string`. The HTTPS URL of the `origin` remote, normalized
from SSH or git URLs. from SSH or git URLs.
@ -590,7 +602,7 @@ PUBLIC API: `require('forge')` ~
Runs `args` (string[]) asynchronously and copies stdout to the `+` Runs `args` (string[]) asynchronously and copies stdout to the `+`
register. register.
*forge.clear_list()* *forge.clear_list()*
`clear_list(key?)` `clear_list(key?)`
Clears cached list data. If `key` is given, clears only that key. Clears cached list data. If `key` is given, clears only that key.
If `nil`, clears all list caches. If `nil`, clears all list caches.
@ -616,81 +628,81 @@ PUBLIC API: `require('forge')` ~
Synchronous `vim.notify` with `[forge.nvim]:` prefix and redraw. Synchronous `vim.notify` with `[forge.nvim]:` prefix and redraw.
PUBLIC API: `require('forge.pickers')` ~ PUBLIC API: `require('forge.pickers')` ~
*forge.pickers.git()* *forge.pickers.git()*
`git()` `git()`
Opens the main forge picker. Requires a git repository. Opens the main forge picker. Requires a git repository.
*forge.pickers.pr()* *forge.pickers.pr()*
`pr(state, f)` `pr(state, f)`
Opens the PR list picker. `state`: `"open"`, `"closed"`, or `"all"`. Opens the PR list picker. `state`: `"open"`, `"closed"`, or `"all"`.
`f`: `forge.Forge`. `f`: `forge.Forge`.
*forge.pickers.issue()* *forge.pickers.issue()*
`issue(state, f)` `issue(state, f)`
Opens the issue list picker. `state`: `"open"`, `"closed"`, or Opens the issue list picker. `state`: `"open"`, `"closed"`, or
`"all"`. `f`: `forge.Forge`. `"all"`. `f`: `forge.Forge`.
*forge.pickers.checks()* *forge.pickers.checks()*
`checks(f, num, filter?, cached_checks?)` `checks(f, num, filter?, cached_checks?)`
Opens the checks picker for PR `num`. `filter`: `"all"`, `"fail"`, Opens the checks picker for PR `num`. `filter`: `"all"`, `"fail"`,
`"pass"`, or `"pending"`. `"pass"`, or `"pending"`.
*forge.pickers.ci()* *forge.pickers.ci()*
`ci(f, branch?)` `ci(f, branch?)`
Opens the CI runs picker. `nil` branch shows all. Opens the CI runs picker. `nil` branch shows all.
*forge.pickers.commits()* *forge.pickers.commits()*
`commits(f)` `commits(f)`
Opens the commit log picker. `f` may be `nil` (browse action Opens the commit log picker. `f` may be `nil` (browse action
requires a forge). requires a forge).
*forge.pickers.branches()* *forge.pickers.branches()*
`branches(f)` `branches(f)`
Opens the branch picker. `f` may be `nil`. Opens the branch picker. `f` may be `nil`.
*forge.pickers.pr_manage()* *forge.pickers.pr_manage()*
`pr_manage(f, num)` `pr_manage(f, num)`
Opens the management picker for PR `num`. Opens the management picker for PR `num`.
*forge.pickers.pr_actions()* *forge.pickers.pr_actions()*
`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"`, `"ci"`, name (`"checkout"`, `"diff"`, `"worktree"`, `"browse"`, `"ci"`,
`"manage"`). `"manage"`).
*forge.pickers.issue_close()* *forge.pickers.issue_close()*
`issue_close(f, num)` `issue_close(f, num)`
Closes issue `num`. Closes issue `num`.
*forge.pickers.issue_reopen()* *forge.pickers.issue_reopen()*
`issue_reopen(f, num)` `issue_reopen(f, num)`
Reopens issue `num`. Reopens issue `num`.
PUBLIC API: `require('forge.review')` ~ PUBLIC API: `require('forge.review')` ~
*forge.review.start()* *forge.review.start()*
`start(base, mode?)` `start(base, mode?)`
Starts a review session. `base` is the diff range (e.g. Starts a review session. `base` is the diff range (e.g.
`"origin/main"`, `"abc123^..abc123"`). `mode`: `"unified"` (default) `"origin/main"`, `"abc123^..abc123"`). `mode`: `"unified"` (default)
or `"split"`. or `"split"`.
*forge.review.stop()* *forge.review.stop()*
`stop()` `stop()`
Ends the current review session. Clears state. Ends the current review session. Clears state.
*forge.review.toggle()* *forge.review.toggle()*
`toggle()` `toggle()`
Toggles between unified and split view. No-op if no review is Toggles between unified and split view. No-op if no review is
active. active.
*forge.review.nav()* *forge.review.nav()*
`nav(nav_cmd)` `nav(nav_cmd)`
Returns `function`. Creates a navigation function for `nav_cmd` Returns `function`. Creates a navigation function for `nav_cmd`
(`"cnext"`, `"cprev"`, `"lnext"`, `"lprev"`). In split mode, (`"cnext"`, `"cprev"`, `"lnext"`, `"lprev"`). In split mode,
closes the split before navigating and reopens after. Wraps at closes the split before navigating and reopens after. Wraps at
list boundaries. list boundaries.
*forge.review.state* *forge.review.state*
`state` `state`
`table` with fields: `table` with fields:
`base` `string?` The current diff range, or `nil`. `base` `string?` The current diff range, or `nil`.

View file

@ -13,11 +13,11 @@ local M = {}
---@field hosts string[] ---@field hosts string[]
---@class forge.KeysConfig ---@class forge.KeysConfig
---@field pr forge.PRPickerKeys ---@field pr forge.PRPickerKeys?
---@field issue forge.IssuePickerKeys ---@field issue forge.IssuePickerKeys?
---@field ci forge.CIPickerKeys ---@field ci forge.CIPickerKeys?
---@field commits forge.CommitsPickerKeys ---@field commits forge.CommitsPickerKeys?
---@field branches forge.BranchesPickerKeys ---@field branches forge.BranchesPickerKeys?
---@class forge.PRPickerKeys ---@class forge.PRPickerKeys
---@field checkout string|false ---@field checkout string|false
@ -256,6 +256,7 @@ end
---@field create_pr_cmd fun(self: forge.Forge, title: string, body: string, base: string, draft: boolean, reviewers: string[]?): string[] ---@field create_pr_cmd fun(self: forge.Forge, title: string, body: string, base: string, draft: boolean, reviewers: string[]?): string[]
---@field create_pr_web_cmd fun(self: forge.Forge): string[]? ---@field create_pr_web_cmd fun(self: forge.Forge): string[]?
---@field default_branch_cmd fun(self: forge.Forge): string[] ---@field default_branch_cmd fun(self: forge.Forge): string[]
---@field checks_json_cmd (fun(self: forge.Forge, num: string): string[])?
---@field template_paths fun(self: forge.Forge): string[] ---@field template_paths fun(self: forge.Forge): string[]
---@type table<string, forge.Forge> ---@type table<string, forge.Forge>
@ -461,12 +462,12 @@ local function parse_iso(iso)
return nil return nil
end end
local ok, ts = pcall(os.time, { local ok, ts = pcall(os.time, {
year = tonumber(y), year = tonumber(y) --[[@as integer]],
month = tonumber(mo), month = tonumber(mo) --[[@as integer]],
day = tonumber(d), day = tonumber(d) --[[@as integer]],
hour = tonumber(h), hour = tonumber(h) --[[@as integer]],
min = tonumber(mi), min = tonumber(mi) --[[@as integer]],
sec = tonumber(s), sec = tonumber(s) --[[@as integer]],
}) })
if ok and ts then if ok and ts then
return ts return ts

View file

@ -1,6 +1,6 @@
local M = {} local M = {}
---@param result vim.SystemCompleted ---@param result { code: integer, stdout: string?, stderr: string? }
---@param fallback string ---@param fallback string
---@return string ---@return string
local function cmd_error(result, fallback) local function cmd_error(result, fallback)
@ -186,12 +186,14 @@ local function pr_actions(f, num)
}, },
} }
---@type table<string, function>
local name_to_fn = {} local name_to_fn = {}
for _, def in ipairs(defs) do for _, def in ipairs(defs) do
name_to_fn[def.name] = def.fn name_to_fn[def.name] = def.fn
end end
local actions = build_actions('pr', defs) local actions = build_actions('pr', defs)
---@type table<string, function>
actions._by_name = name_to_fn actions._by_name = name_to_fn
return actions return actions
end end
@ -522,7 +524,7 @@ function M.ci(f, branch)
end end
end end
---@param f forge.Forge ---@param f forge.Forge?
function M.commits(f) function M.commits(f)
local forge_mod = require('forge') local forge_mod = require('forge')
local review = require('forge.review') local review = require('forge.review')

View file

@ -19,11 +19,6 @@ end
function M.stop() function M.stop()
M.state.base = nil M.state.base = nil
M.state.mode = 'unified' M.state.mode = 'unified'
local cfg = require('forge').config()
local lhs = cfg.keys ~= false and cfg.keys.review_toggle
if lhs then
pcall(vim.keymap.del, 'n', lhs)
end
vim.api.nvim_clear_autocmds({ group = review_augroup }) vim.api.nvim_clear_autocmds({ group = review_augroup })
end end
@ -61,11 +56,6 @@ end
function M.start(base, mode) function M.start(base, mode)
M.state.base = base M.state.base = base
M.state.mode = mode or 'unified' M.state.mode = mode or 'unified'
local cfg = require('forge').config()
local lhs = cfg.keys ~= false and cfg.keys.review_toggle
if lhs then
vim.keymap.set('n', lhs, M.toggle, { desc = 'toggle review split/unified' })
end
vim.api.nvim_clear_autocmds({ group = review_augroup }) vim.api.nvim_clear_autocmds({ group = review_augroup })
vim.api.nvim_create_autocmd('BufWipeout', { vim.api.nvim_create_autocmd('BufWipeout', {
group = review_augroup, group = review_augroup,