From 4ae7439a7590e9b1f19abc925539e23a421b152f Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Sat, 28 Mar 2026 12:43:55 -0400 Subject: [PATCH] feat: update helpdocs --- doc/forge.nvim.txt | 158 +++++++++++++++++++++++------------------- lua/forge/init.lua | 23 +++--- lua/forge/pickers.lua | 6 +- lua/forge/review.lua | 10 --- 4 files changed, 101 insertions(+), 96 deletions(-) diff --git a/doc/forge.nvim.txt b/doc/forge.nvim.txt index b4d882b..6db4e3d 100644 --- a/doc/forge.nvim.txt +++ b/doc/forge.nvim.txt @@ -36,7 +36,7 @@ Top-level keys: ~ `ci.lines` `integer` (default `10000`) Maximum number of log lines fetched for CI/check log output. -`sources` *forge-config-sources* +`sources` *forge-config-sources* `table` (default `{}`) Per-source host overrides for forge detection. Keys are source names (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) Per-picker action bindings. Set to `false` to disable all picker-level actions. Use `""` 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 formatting. - `display.icons` *forge-config-display-icons* + `display.icons` *forge-config-display-icons* `table` Status icons used in picker lines. Key Default Used for ~ @@ -113,7 +113,7 @@ Top-level keys: ~ `skip` `"-"` Skipped/cancelled runs `unknown` `"?"` Unknown status - `display.widths` *forge-config-display-widths* + `display.widths` *forge-config-display-widths* `table` Column widths (characters) for picker formatting. Key Default ~ @@ -122,7 +122,7 @@ Top-level keys: ~ `name` `35` `branch` `25` - `display.limits` *forge-config-display-limits* + `display.limits` *forge-config-display-limits* `table` Maximum items fetched per list API call. Key Default ~ @@ -131,7 +131,7 @@ Top-level keys: ~ `runs` `30` ============================================================================== -COMMANDS *:Forge* +COMMANDS *:Forge* `:Forge` *:Forge-no-args* Open the main forge picker (|forge-picker|). @@ -203,13 +203,13 @@ COMMANDS *:Forge* `:Forge branch` *:Forge-branch* Open the branch picker. -`:Forge branch diff` {name} *:Forge-branch-diff* +`:Forge branch diff` {name} *:Forge-branch-diff* 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. -`:Forge worktree` *:Forge-worktree* +`:Forge worktree` *:Forge-worktree* Open fzf-lua's git worktree picker. `:Forge browse` [{flags}] *:Forge-browse* @@ -225,13 +225,13 @@ COMMANDS *:Forge* `--commit` Yank a commit-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. -`:Forge review toggle` *:Forge-review-toggle* +`:Forge review toggle` *:Forge-review-toggle* 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). All subcommands support tab completion. @@ -239,17 +239,15 @@ All subcommands support tab completion. ============================================================================== PICKERS *forge-pickers* - *forge-picker* -FORGE PICKER ~ -The main entry point. Adapts based on the detected forge and current -buffer. Lists: PRs/MRs, Issues, CI/CD, Browse Remote, Open File, Yank -Commit URL, Yank Branch URL, Commits, Branches, Worktrees. Items that -require a forge are hidden when no forge is detected. "Open File" and yank -entries require a named buffer on a branch. + *forge-picker* +FORGE PICKER ~ The main entry point. Adapts based on the detected forge and +current buffer. Lists: PRs/MRs, Issues, CI/CD, Browse Remote, Open File, Yank +Commit URL, Yank Branch URL, Commits, Branches, Worktrees. Items that require +a forge are hidden when no forge is detected. "Open File" and yank entries +require a named buffer on a branch. - *forge-picker-pr* -PR PICKER ~ -Lists PRs/MRs with number, title, author, and relative time. + *forge-picker-pr* +PR PICKER ~ Lists PRs/MRs with number, title, author, and relative time. Action Default Key Description ~ `checkout` `` Check out the PR branch @@ -262,9 +260,8 @@ Lists PRs/MRs with number, title, author, and relative time. `filter` `` Cycle state: open -> closed -> all `refresh` `` Clear cache and re-fetch - *forge-picker-issue* -ISSUE PICKER ~ -Lists issues with number, title, author, and relative time. + *forge-picker-issue* +ISSUE PICKER ~ Lists issues with number, title, author, and relative time. Action Default Key Description ~ `browse` `` Open issue in browser @@ -272,10 +269,9 @@ Lists issues with number, title, author, and relative time. `filter` `` Cycle state: all -> open -> closed `refresh` `` Clear cache and re-fetch - *forge-picker-ci* -CI PICKER ~ -Used for both per-PR checks (`:Forge pr ci {num}`) and repo-wide CI runs -(`:Forge ci`). Both share the `keys.ci` bindings. + *forge-picker-ci* +CI PICKER ~ 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 ~ `log` `` 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` `` Show all `refresh` `` Re-fetch runs - *forge-picker-commits* -COMMITS PICKER ~ -Git log with colored output and commit preview. + *forge-picker-commits* +COMMITS PICKER ~ Git log with colored output and commit preview. Action Default Key Description ~ `checkout` `` Checkout commit (detached HEAD) @@ -297,19 +292,17 @@ Git log with colored output and commit preview. `browse` `` Open commit on forge `yank` `` Yank commit hash to `+` register - *forge-picker-branches* -BRANCHES PICKER ~ -Uses fzf-lua's `git_branches` with additional actions. + *forge-picker-branches* +BRANCHES PICKER ~ Uses fzf-lua's `git_branches` with additional actions. Action Default Key Description ~ `diff` `` Review diff against branch `browse` `` Open branch on forge - *forge-picker-manage* -MANAGE PICKER ~ -Contextual actions for a specific PR, shown based on permissions and -state: Approve, Merge (per available method: squash, rebase, merge), -Close/Reopen, Mark as draft/Mark as ready. + *forge-picker-manage* +MANAGE PICKER ~ Contextual actions for a specific PR, shown based on +permissions and state: Approve, Merge (per available method: squash, rebase, +merge), Close/Reopen, Mark as draft/Mark as ready. ============================================================================== REVIEW *forge-review* @@ -371,7 +364,15 @@ Template discovery: ~ Codeberg: `.gitea/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 ~ `ForgeComposeComment` `Comment` Comment block lines @@ -382,7 +383,19 @@ Highlight groups: ~ `ForgeComposeAdded` `Added` Addition 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* @@ -394,12 +407,12 @@ Built-in sources: ~ `gitlab` `glab` `gitlab` `codeberg` `tea` `codeberg`, `gitea`, `forgejo` -Sources are lazy-loaded the first time a matching remote is detected. -Built-in host patterns are checked after user-configured `sources` hosts, -so user overrides take priority. +Sources are lazy-loaded the first time a matching remote is detected. Built-in +host patterns are checked after user-configured `sources` hosts, so user +overrides take priority. HOST OVERRIDES ~ - *forge-sources-hosts* + *forge-sources-hosts* To route a self-hosted instance to a built-in source: >lua vim.g.forge = { sources = { @@ -409,19 +422,18 @@ To route a self-hosted instance to a built-in source: >lua < CUSTOM SOURCE REGISTRATION ~ - *forge-sources-register* + *forge-sources-register* Register a custom source with `require('forge').register()`: >lua local my_source = { ... } require('forge').register('myforgejo', my_source) -< -The name must match the key used in `sources` host config. The source -module is also discoverable as `forge.` (e.g. `require('forge.myforgejo')` -if placed at `lua/forge/myforgejo.lua`). +< The name must match the key used in `sources` host config. The source module +is also discoverable as `forge.` (e.g. `require('forge.myforgejo')` if +placed at `lua/forge/myforgejo.lua`). THE `forge.Forge` INTERFACE ~ - *forge-Forge-interface* -A source must implement all methods in the `forge.Forge` class. Each -source is a table with these fields and methods: + *forge-Forge-interface* +A source must implement all methods in the `forge.Forge` class. Each source is +a table with these fields and methods: Fields: ~ `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 (e.g. `"src/foo.lua:10-20"`). - *forge.remote_web_url()* + *forge.remote_web_url()* `remote_web_url()` Returns `string`. The HTTPS URL of the `origin` remote, normalized from SSH or git URLs. @@ -590,7 +602,7 @@ PUBLIC API: `require('forge')` ~ Runs `args` (string[]) asynchronously and copies stdout to the `+` register. - *forge.clear_list()* + *forge.clear_list()* `clear_list(key?)` Clears cached list data. If `key` is given, clears only that key. If `nil`, clears all list caches. @@ -616,81 +628,81 @@ PUBLIC API: `require('forge')` ~ Synchronous `vim.notify` with `[forge.nvim]:` prefix and redraw. PUBLIC API: `require('forge.pickers')` ~ - *forge.pickers.git()* + *forge.pickers.git()* `git()` Opens the main forge picker. Requires a git repository. - *forge.pickers.pr()* + *forge.pickers.pr()* `pr(state, f)` Opens the PR list picker. `state`: `"open"`, `"closed"`, or `"all"`. `f`: `forge.Forge`. - *forge.pickers.issue()* + *forge.pickers.issue()* `issue(state, f)` Opens the issue list picker. `state`: `"open"`, `"closed"`, or `"all"`. `f`: `forge.Forge`. - *forge.pickers.checks()* + *forge.pickers.checks()* `checks(f, num, filter?, cached_checks?)` Opens the checks picker for PR `num`. `filter`: `"all"`, `"fail"`, `"pass"`, or `"pending"`. - *forge.pickers.ci()* + *forge.pickers.ci()* `ci(f, branch?)` Opens the CI runs picker. `nil` branch shows all. - *forge.pickers.commits()* + *forge.pickers.commits()* `commits(f)` Opens the commit log picker. `f` may be `nil` (browse action requires a forge). - *forge.pickers.branches()* + *forge.pickers.branches()* `branches(f)` Opens the branch picker. `f` may be `nil`. - *forge.pickers.pr_manage()* + *forge.pickers.pr_manage()* `pr_manage(f, num)` Opens the management picker for PR `num`. - *forge.pickers.pr_actions()* + *forge.pickers.pr_actions()* `pr_actions(f, num)` Returns `table`. Action functions for PR `num`, keyed by fzf binding. Also has `_by_name` table keyed by action name (`"checkout"`, `"diff"`, `"worktree"`, `"browse"`, `"ci"`, `"manage"`). - *forge.pickers.issue_close()* + *forge.pickers.issue_close()* `issue_close(f, num)` Closes issue `num`. - *forge.pickers.issue_reopen()* + *forge.pickers.issue_reopen()* `issue_reopen(f, num)` Reopens issue `num`. PUBLIC API: `require('forge.review')` ~ - *forge.review.start()* + *forge.review.start()* `start(base, mode?)` Starts a review session. `base` is the diff range (e.g. `"origin/main"`, `"abc123^..abc123"`). `mode`: `"unified"` (default) or `"split"`. - *forge.review.stop()* + *forge.review.stop()* `stop()` Ends the current review session. Clears state. - *forge.review.toggle()* + *forge.review.toggle()* `toggle()` Toggles between unified and split view. No-op if no review is active. - *forge.review.nav()* + *forge.review.nav()* `nav(nav_cmd)` Returns `function`. Creates a navigation function for `nav_cmd` (`"cnext"`, `"cprev"`, `"lnext"`, `"lprev"`). In split mode, closes the split before navigating and reopens after. Wraps at list boundaries. - *forge.review.state* + *forge.review.state* `state` `table` with fields: `base` `string?` The current diff range, or `nil`. diff --git a/lua/forge/init.lua b/lua/forge/init.lua index 0e76536..4b2771d 100644 --- a/lua/forge/init.lua +++ b/lua/forge/init.lua @@ -13,11 +13,11 @@ local M = {} ---@field hosts string[] ---@class forge.KeysConfig ----@field pr forge.PRPickerKeys ----@field issue forge.IssuePickerKeys ----@field ci forge.CIPickerKeys ----@field commits forge.CommitsPickerKeys ----@field branches forge.BranchesPickerKeys +---@field pr forge.PRPickerKeys? +---@field issue forge.IssuePickerKeys? +---@field ci forge.CIPickerKeys? +---@field commits forge.CommitsPickerKeys? +---@field branches forge.BranchesPickerKeys? ---@class forge.PRPickerKeys ---@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_web_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[] ---@type table @@ -461,12 +462,12 @@ local function parse_iso(iso) return nil end local ok, ts = pcall(os.time, { - year = tonumber(y), - month = tonumber(mo), - day = tonumber(d), - hour = tonumber(h), - min = tonumber(mi), - sec = tonumber(s), + year = tonumber(y) --[[@as integer]], + month = tonumber(mo) --[[@as integer]], + day = tonumber(d) --[[@as integer]], + hour = tonumber(h) --[[@as integer]], + min = tonumber(mi) --[[@as integer]], + sec = tonumber(s) --[[@as integer]], }) if ok and ts then return ts diff --git a/lua/forge/pickers.lua b/lua/forge/pickers.lua index 29bb132..d31486b 100644 --- a/lua/forge/pickers.lua +++ b/lua/forge/pickers.lua @@ -1,6 +1,6 @@ local M = {} ----@param result vim.SystemCompleted +---@param result { code: integer, stdout: string?, stderr: string? } ---@param fallback string ---@return string local function cmd_error(result, fallback) @@ -186,12 +186,14 @@ local function pr_actions(f, num) }, } + ---@type table local name_to_fn = {} for _, def in ipairs(defs) do name_to_fn[def.name] = def.fn end local actions = build_actions('pr', defs) + ---@type table actions._by_name = name_to_fn return actions end @@ -522,7 +524,7 @@ function M.ci(f, branch) end end ----@param f forge.Forge +---@param f forge.Forge? function M.commits(f) local forge_mod = require('forge') local review = require('forge.review') diff --git a/lua/forge/review.lua b/lua/forge/review.lua index 5c6ef8a..af9db6b 100644 --- a/lua/forge/review.lua +++ b/lua/forge/review.lua @@ -19,11 +19,6 @@ end function M.stop() M.state.base = nil 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 }) end @@ -61,11 +56,6 @@ end function M.start(base, mode) M.state.base = base 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_create_autocmd('BufWipeout', { group = review_augroup,