ci: typgin,e tc

This commit is contained in:
Barrett Ruth 2026-03-28 00:47:59 -04:00
parent c9d271c7a6
commit f96eaf5938
No known key found for this signature in database
GPG key ID: A6C96C9349D2FC81
3 changed files with 1147 additions and 185 deletions

342
README.md
View file

@ -7,21 +7,19 @@ your editor.
## Features ## Features
- Forge detection from git remote (GitHub via `gh`, GitLab via `glab`, - Automatic forge detection from git remote (GitHub via `gh`, GitLab via `glab`,
Codeberg/Gitea/Forgejo via `tea`) Codeberg/Gitea/Forgejo via `tea`)
- PR lifecycle: list, create, checkout, review, merge, approve, close/reopen, - PR lifecycle: list, create (compose buffer with template discovery, diff stat,
reviewers), checkout, worktree, review diff, merge, approve, close/reopen,
draft toggle draft toggle
- Issue management: list, browse, close/reopen - Issue management: list, browse, close/reopen, state filtering
- CI/CD: view runs, stream logs, filter by status - CI/CD: view runs per-branch or repo-wide, stream logs, filter by status
- PR compose buffer with diff stat, template discovery, and syntax highlighting - Code review via [diffs.nvim](https://github.com/barrettruth/diffs.nvim) with
- Code review via [diffs.nvim](https://github.com/barrettruth/diffs.nvim) unified/split toggle and quickfix navigation
unified/split diff with quickfix navigation - Commit and branch browsing with checkout, diff, and URL generation
- Commit browsing with checkout, diff review, and URL yanking - File/line permalink generation and yanking (commit and branch URLs)
- Branch browsing with diff review and remote links - [fzf-lua](https://github.com/ibhagwan/fzf-lua) pickers with contextual keybinds
- Worktree creation from PRs - Pluggable source registration for custom or self-hosted forges
- File/line permalink generation (commit and branch URLs)
- [fzf-lua](https://github.com/ibhagwan/fzf-lua) pickers with contextual
keybinds throughout
## Dependencies ## Dependencies
@ -32,35 +30,327 @@ your editor.
- [`glab`](https://gitlab.com/gitlab-org/cli) for GitLab - [`glab`](https://gitlab.com/gitlab-org/cli) for GitLab
- [`tea`](https://gitea.com/gitea/tea) for Codeberg/Gitea/Forgejo - [`tea`](https://gitea.com/gitea/tea) for Codeberg/Gitea/Forgejo
- [vim-fugitive](https://github.com/tpope/vim-fugitive) (optional, for fugitive - [vim-fugitive](https://github.com/tpope/vim-fugitive) (optional, for fugitive
keymaps) keymaps and split diff)
- [diffs.nvim](https://github.com/barrettruth/diffs.nvim) (optional, for review - [diffs.nvim](https://github.com/barrettruth/diffs.nvim) (optional, for review
mode) mode)
## Installation ## Installation
Install with your package manager of choice or via ### [lazy.nvim](https://github.com/folke/lazy.nvim)
[luarocks](https://luarocks.org/modules/barrettruth/forge.nvim):
```lua
{
'barrettruth/forge.nvim',
dependencies = { 'ibhagwan/fzf-lua' },
}
```
### [mini.deps](https://github.com/echasnovski/mini.deps)
```lua
MiniDeps.add({
source = 'barrettruth/forge.nvim',
depends = { 'ibhagwan/fzf-lua' },
})
```
### [luarocks](https://luarocks.org/modules/barrettruth/forge.nvim)
``` ```
luarocks install forge.nvim luarocks install forge.nvim
``` ```
## Documentation ### Manual
```vim ```sh
:help forge.nvim git clone https://github.com/barrettruth/forge.nvim \
~/.local/share/nvim/site/pack/plugins/start/forge.nvim
``` ```
## Usage
forge.nvim works through two entry points: the `:Forge` command and the
`<c-g>` picker.
`:Forge` with no arguments (or `<c-g>`) opens the top-level picker — PRs,
issues, CI, commits, branches, worktrees, and browse actions. Each sub-picker
has contextual keybinds shown in the fzf header.
PR creation opens a compose buffer (markdown) pre-filled from commit messages
and repo templates. First line is the title, everything after the blank line is
the body. Draft, reviewers, and base branch are set in the HTML comment block
below. Write (`:w`) to push and create.
## Configuration
Configure via `vim.g.forge`. All fields are optional — defaults shown below.
```lua
vim.g.forge = {
ci = { lines = 10000 },
sources = {},
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 = {
checkout = 'default', diff = 'ctrl-d', worktree = 'ctrl-w',
checks = 'ctrl-t', browse = 'ctrl-x', manage = 'ctrl-e',
create = 'ctrl-a', toggle = 'ctrl-o', refresh = 'ctrl-r',
},
issue = { browse = 'default', close_reopen = 'ctrl-s', toggle = 'ctrl-o', refresh = 'ctrl-r' },
checks = { log = 'default', browse = 'ctrl-x', failed = 'ctrl-f', passed = 'ctrl-p', running = 'ctrl-n', all = 'ctrl-a' },
ci = { log = 'default', browse = 'ctrl-x', refresh = 'ctrl-r' },
commits = { checkout = 'default', diff = 'ctrl-d', browse = 'ctrl-x', yank = 'ctrl-y' },
branches = { diff = 'ctrl-d', browse = 'ctrl-x' },
},
display = {
icons = { open = '+', merged = 'm', closed = 'x', pass = '*', fail = 'x', pending = '~', skip = '-', unknown = '?' },
widths = { title = 45, author = 15, name = 35, branch = 25 },
limits = { pulls = 100, issues = 100, runs = 30 },
},
}
```
Set `keys = false` to disable all keymaps. Set `picker_keys = false` to disable
all picker keybinds. Set any individual key to `false` to disable it.
### Examples
Disable quickfix/loclist keymaps:
```lua
vim.g.forge = {
keys = { next_qf = false, prev_qf = false, next_loc = false, prev_loc = false },
}
```
Nerd font icons:
```lua
vim.g.forge = {
display = {
icons = { open = '', merged = '', closed = '', pass = '', fail = '', pending = '', skip = '', unknown = '' },
},
}
```
Self-hosted GitLab:
```lua
vim.g.forge = {
sources = { gitlab = { hosts = { 'gitlab.mycompany.com' } } },
}
```
Override PR picker bindings:
```lua
vim.g.forge = {
picker_keys = { pr = { checkout = 'ctrl-o', diff = 'default' } },
}
```
## Commands
`:Forge` with no arguments opens the top-level picker. Subcommands:
| Command | Description |
|---|---|
| `:Forge pr` | List open PRs |
| `:Forge pr --state={open,closed,all}` | List PRs by state |
| `:Forge pr create [--draft] [--fill] [--web]` | Create PR |
| `:Forge pr checkout {num}` | Checkout PR branch |
| `:Forge pr diff {num}` | Review PR diff |
| `:Forge pr worktree {num}` | Fetch PR into worktree |
| `:Forge pr checks {num}` | Show PR checks |
| `:Forge pr browse {num}` | Open PR in browser |
| `:Forge pr manage {num}` | Merge/approve/close/draft actions |
| `:Forge issue` | List all issues |
| `:Forge issue --state={open,closed,all}` | List issues by state |
| `:Forge issue browse {num}` | Open issue in browser |
| `:Forge issue close {num}` | Close issue |
| `:Forge issue reopen {num}` | Reopen issue |
| `:Forge ci` | CI runs for current branch |
| `:Forge ci --all` | CI runs for all branches |
| `:Forge commit` | Browse commits |
| `:Forge commit checkout {sha}` | Checkout commit |
| `:Forge commit diff {sha}` | Review commit diff |
| `:Forge commit browse {sha}` | Open commit in browser |
| `:Forge branch` | Browse branches |
| `:Forge branch diff {name}` | Review branch diff |
| `:Forge branch browse {name}` | Open branch in browser |
| `:Forge worktree` | List worktrees |
| `:Forge browse [--root] [--commit]` | Open file/repo/commit in browser |
| `:Forge yank [--commit]` | Yank permalink for file/line |
| `:Forge review end` | End review session |
| `:Forge review toggle` | Toggle split/unified review |
| `:Forge cache clear` | Clear all caches |
## Keymaps
### Global
| Key | Mode | Description |
|---|---|---|
| `<c-g>` | n, v | Open forge picker |
| `]q` / `[q` | n | Next/prev quickfix entry (wraps) |
| `]l` / `[l` | n | Next/prev loclist entry (wraps) |
### Fugitive buffer
Active in `fugitive` filetype buffers when a forge is detected.
| Key | Description |
|---|---|
| `cpr` | Create PR (compose buffer) |
| `cpd` | Create draft PR |
| `cpf` | Create PR from commits (no compose) |
| `cpw` | Push and open web creation |
### Review
Active during a review session.
| Key | Description |
|---|---|
| `s` | Toggle unified/split diff |
### Terminal (log buffers)
Active on CI/check log terminals when a URL is available.
| Key | Description |
|---|---|
| `gx` | Open run/check in browser |
## Picker Actions
Keybinds shown in the fzf header. `default` = `enter`.
| Picker | Key | Action |
|---|---|---|
| **PR** | `enter` | Checkout |
| | `ctrl-d` | Review diff |
| | `ctrl-w` | Worktree |
| | `ctrl-t` | Checks |
| | `ctrl-x` | Browse |
| | `ctrl-e` | Manage (merge/approve/close/draft) |
| | `ctrl-a` | Create new |
| | `ctrl-o` | Cycle state (open/closed/all) |
| | `ctrl-r` | Refresh |
| **Issue** | `enter` | Browse |
| | `ctrl-s` | Close/reopen |
| | `ctrl-o` | Cycle state |
| | `ctrl-r` | Refresh |
| **Checks** | `enter` | View log (tails if running) |
| | `ctrl-x` | Browse |
| | `ctrl-f` / `ctrl-p` / `ctrl-n` | Filter: failed / passed / running |
| | `ctrl-a` | Show all |
| **CI** | `enter` | View log (tails if running) |
| | `ctrl-x` | Browse |
| | `ctrl-r` | Refresh |
| **Commits** | `enter` | Checkout (detached) |
| | `ctrl-d` | Review diff |
| | `ctrl-x` | Browse |
| | `ctrl-y` | Yank hash |
| **Branches** | `ctrl-d` | Review diff |
| | `ctrl-x` | Browse |
## Custom Sources
Register a custom forge source for self-hosted or alternative platforms:
```lua
require('forge').register('mygitea', require('my_gitea_source'))
```
Route remotes to your source by host:
```lua
vim.g.forge = {
sources = { mygitea = { hosts = { 'gitea.internal.dev' } } },
}
```
A source is a table implementing the `forge.Forge` interface. Required fields:
`name` (string), `cli` (string, checked via `executable()`), `kinds` (`{ issue,
pr }`), and `labels` (`{ issue, pr, pr_one, pr_full, ci }`).
Required methods (all receive `self`): `list_pr_json_cmd`, `list_issue_json_cmd`,
`pr_json_fields`, `issue_json_fields`, `view_web`, `browse`, `browse_root`,
`browse_branch`, `browse_commit`, `checkout_cmd`, `yank_branch`, `yank_commit`,
`fetch_pr`, `pr_base_cmd`, `pr_for_branch_cmd`, `checks_cmd`, `check_log_cmd`,
`check_tail_cmd`, `list_runs_json_cmd`, `list_runs_cmd`, `normalize_run`,
`run_log_cmd`, `run_tail_cmd`, `merge_cmd`, `approve_cmd`, `repo_info`,
`pr_state`, `close_cmd`, `reopen_cmd`, `close_issue_cmd`, `reopen_issue_cmd`,
`draft_toggle_cmd`, `create_pr_cmd`, `create_pr_web_cmd`, `default_branch_cmd`,
`template_paths`.
See `lua/forge/github.lua`, `lua/forge/gitlab.lua`, or `lua/forge/codeberg.lua`
for complete implementations. The `forge.Forge` class definition with full type
annotations is in `lua/forge/init.lua`.
### Skeleton
```lua
local M = {
name = 'mygitea',
cli = 'tea',
kinds = { issue = 'issues', pr = 'pulls' },
labels = { issue = 'Issues', pr = 'PRs', pr_one = 'PR', pr_full = 'Pull Requests', ci = 'CI/CD' },
}
function M:list_pr_json_cmd(state)
return { 'tea', 'pr', 'list', '--state', state, '--output', 'json' }
end
function M:pr_json_fields()
return { number = 'number', title = 'title', branch = 'head', state = 'state', author = 'poster', created_at = 'created_at' }
end
return M
```
## Health
Run `:checkhealth forge` to verify your setup. Checks for `git`, forge CLIs
(`gh`, `glab`, `tea`), required plugins (`fzf-lua`), optional plugins
(`diffs.nvim`, `vim-fugitive`), and any registered custom sources.
## FAQ ## FAQ
**Q: How do I create a PR?** **Q: How do I create a PR?**
`<c-g>` -> Pull Requests -> `ctrl-a` to compose. Or from fugitive: `cpr`
(compose), `cpd` (draft), `cpf` (instant), `cpw` (web).
Press `<c-g>` to open the forge picker, select "Pull Requests", then `<ctrl-a>` **Q: Does review mode require diffs.nvim?**
to create. Or from a fugitive buffer: `cpr` (create), `cpd` (draft), `cpf` Yes. Without [diffs.nvim](https://github.com/barrettruth/diffs.nvim), the diff
(instant), `cpw` (web). action and review toggling are unavailable.
**Q: Does forge.nvim support review diffs?** **Q: How does forge detection work?**
forge.nvim reads the `origin` remote URL and matches against known hosts and
any custom `sources.<name>.hosts`. The first match wins, and the CLI must be in
`$PATH`.
Yes, with [diffs.nvim](https://github.com/barrettruth/diffs.nvim) installed. **Q: Can I use this with self-hosted GitLab/Gitea?**
Select a PR and press `<ctrl-d>` to enter review mode with unified diff. Press Yes. Add your host to `vim.g.forge.sources`. See the [examples](#examples).
`s` to toggle split/unified view. Navigate files with `]q`/`[q`.
**Q: What does `ctrl-o` do in pickers?**
Cycles the state filter: open -> closed -> all -> open.
**Q: How do I merge/approve/close a PR?**
`ctrl-e` on a PR in the picker opens the manage picker. Available actions depend
on your repository permissions.
**Q: Does this work without a forge remote?**
Partially. Commits, branches, and worktrees work in any git repo. PRs, issues,
CI, and browse require a detected forge.

View file

@ -1,7 +1,5 @@
*forge.nvim.txt* Forge-agnostic git workflow for Neovim *forge.nvim.txt* Forge-agnostic git workflow for Neovim
Author: Barrett Ruth <br.barrettruth@gmail.com> License: MIT
============================================================================== ==============================================================================
INTRODUCTION *forge.nvim* INTRODUCTION *forge.nvim*
@ -9,222 +7,788 @@ forge.nvim provides PR, issue, and CI workflows across GitHub, GitLab, and
Codeberg from inside Neovim. It detects the forge from your git remote and Codeberg from inside Neovim. It detects the forge from your git remote and
delegates to the appropriate CLI (`gh`, `glab`, or `tea`). delegates to the appropriate CLI (`gh`, `glab`, or `tea`).
Features: ~ Requirements: ~
- Forge detection from git remote URL
- PR lifecycle (list, create, checkout, review, merge, approve, draft toggle)
- Issue management (list, browse, close/reopen)
- CI/CD run viewing, log streaming, status filtering
- PR compose buffer with diff stat and template discovery
- Code review via diffs.nvim with unified/split toggle
- Commit and branch browsing with forge permalinks
- Worktree creation from PRs
- fzf-lua pickers with contextual keybinds
==============================================================================
CONTENTS *forge-contents*
1. Introduction ............................................... |forge.nvim|
2. Requirements ....................................... |forge-requirements|
3. Setup ..................................................... |forge-setup|
4. Configuration ............................................ |forge-config|
5. Forge Picker ............................................ |forge-picker|
6. Pull Requests ................................................. |forge-pr|
7. Issues .................................................. |forge-issues|
8. CI/CD ...................................................... |forge-ci|
9. Commits ............................................... |forge-commits|
10. Branches .............................................. |forge-branches|
11. Review ................................................ |forge-review|
12. Compose Buffer ........................................ |forge-compose|
13. Highlight Groups .................................... |forge-highlights|
14. Health Check ............................................ |forge-health|
==============================================================================
REQUIREMENTS *forge-requirements*
- Neovim 0.10.0+ - Neovim 0.10.0+
- fzf-lua (required) - fzf-lua (required)
- One or more forge CLIs: - One or more forge CLIs:
- `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) - vim-fugitive (optional, for fugitive keymaps and split review)
- diffs.nvim (optional, for review mode) - diffs.nvim (optional, for review mode)
============================================================================== Run |:checkhealth| forge to verify CLIs and dependencies.
SETUP *forge-setup*
Install with lazy.nvim: >lua
{
'barrettruth/forge.nvim',
keys = {
{ '<c-g>', mode = { 'n', 'v' } },
},
}
<
Run `:checkhealth forge` to verify CLIs and dependencies.
============================================================================== ==============================================================================
CONFIGURATION *forge-config* CONFIGURATION *forge-config*
Configuration is done via `vim.g.forge`: >lua Configuration is set via the `vim.g.forge` global. All keys are optional;
unset keys use defaults. >lua
vim.g.forge = { vim.g.forge = {
ci = { lines = 10000 }, ci = { lines = 5000 },
display = { icons = { open = '' } },
} }
< <
*forge-config-ci-lines* Top-level keys: ~
ci.lines ~
Number of log lines to fetch for CI runs. Default: `10000`. `ci` *forge-config-ci*
`ci.lines` `integer` (default `10000`)
Maximum number of log lines fetched for CI/check log output.
`sources` *forge-config-sources*
`table<string, { hosts: string[] }>` (default `{}`)
Per-source host overrides for forge detection. Keys are source names
(e.g. `"github"`, `"gitlab"`, or a custom name). Each value has a
`hosts` list of hostname substrings matched against the git remote. >lua
vim.g.forge = {
sources = {
gitlab = { hosts = { 'git.internal.co' } },
myforgejo = { hosts = { 'forgejo.example.com' } },
},
}
<
`keys` *forge-config-keys*
`table|false` (default shown below)
Global keymaps. Set to `false` to disable all global keymaps. Setting
an individual key to `nil` or `false` disables that single keymap.
Defaults: >lua
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 = {
checkout = 'default',
diff = 'ctrl-d',
worktree = 'ctrl-w',
checks = 'ctrl-t',
browse = 'ctrl-x',
manage = 'ctrl-e',
create = 'ctrl-a',
toggle = 'ctrl-o',
refresh = 'ctrl-r',
},
issue = {
browse = 'default',
close_reopen = 'ctrl-s',
toggle = 'ctrl-o',
refresh = 'ctrl-r',
},
checks = {
log = 'default',
browse = 'ctrl-x',
failed = 'ctrl-f',
passed = 'ctrl-p',
running = 'ctrl-n',
all = 'ctrl-a',
},
ci = {
log = 'default',
browse = 'ctrl-x',
refresh = 'ctrl-r',
},
commits = {
checkout = 'default',
diff = 'ctrl-d',
browse = 'ctrl-x',
yank = 'ctrl-y',
},
branches = {
diff = 'ctrl-d',
browse = 'ctrl-x',
},
}
<
`display` *forge-config-display*
Controls icons, column widths, and fetch limits used in picker
formatting.
`display.icons` *forge-config-display-icons*
`table` Status icons used in picker lines.
Key Default Used for ~
`open` `"+"` Open PRs/issues
`merged` `"m"` Merged PRs
`closed` `"x"` Closed PRs/issues
`pass` `"*"` Passed checks/runs
`fail` `"x"` Failed checks/runs
`pending` `"~"` In-progress checks/runs
`skip` `"-"` Skipped/cancelled runs
`unknown` `"?"` Unknown status
`display.widths` *forge-config-display-widths*
`table` Column widths (characters) for picker formatting.
Key Default ~
`title` `45`
`author` `15`
`name` `35`
`branch` `25`
`display.limits` *forge-config-display-limits*
`table` Maximum items fetched per list API call.
Key Default ~
`pulls` `100`
`issues` `100`
`runs` `30`
============================================================================== ==============================================================================
FORGE PICKER *forge-picker* COMMANDS *:Forge*
*<c-g>* `:Forge` *:Forge-no-args*
Press `<c-g>` in normal or visual mode to open the main forge picker. The Open the main forge picker (|forge-picker|). Same as pressing
picker adapts based on the detected forge and current buffer state. `keys.picker`.
Available entries: ~ `:Forge pr` [{flags}] *:Forge-pr*
- Pull Requests / Merge Requests Open the PR list picker. Defaults to open PRs.
- Issues `--state=open` Show open PRs (default).
- CI / Pipelines `--state=closed` Show closed PRs.
- Browse Remote `--state=all` Show all PRs.
- Open File (current file on remote)
- Yank Commit URL / Yank Branch URL `:Forge pr create` [{flags}] *:Forge-pr-create*
- Commits Create a new PR.
- Branches (no flags) Open the compose buffer (|forge-compose|).
- Worktrees `--draft` Open compose buffer with draft pre-set.
`--fill` Create instantly from commits (skip compose).
`--web` Push and open the forge's web create-PR page.
`--draft --fill` Create draft instantly.
`:Forge pr checkout` {num} *:Forge-pr-checkout*
Check out the branch for PR `{num}`.
`:Forge pr diff` {num} *:Forge-pr-diff*
Start a review for PR `{num}` (|forge-review|).
`:Forge pr worktree` {num} *:Forge-pr-worktree*
Fetch PR `{num}` and create a git worktree.
`:Forge pr checks` {num} *:Forge-pr-checks*
Open the checks picker for PR `{num}`.
`:Forge pr browse` {num} *:Forge-pr-browse*
Open PR `{num}` in the browser.
`:Forge pr manage` {num} *:Forge-pr-manage*
Open the management picker for PR `{num}` (approve, merge, close,
reopen, draft toggle).
`:Forge issue` [{flags}] *:Forge-issue*
Open the issue list picker. Defaults to all issues.
`--state=open` Show open issues.
`--state=closed` Show closed issues.
`--state=all` Show all issues (default).
`:Forge issue browse` {num} *:Forge-issue-browse*
Open issue `{num}` in the browser.
`:Forge issue close` {num} *:Forge-issue-close*
Close issue `{num}`.
`:Forge issue reopen` {num} *:Forge-issue-reopen*
Reopen issue `{num}`.
`:Forge ci` [{flags}] *:Forge-ci*
Open the CI runs picker. Defaults to current branch.
`--all` Show runs for all branches.
`:Forge commit` *:Forge-commit*
Open the commit log picker.
`:Forge commit checkout` {sha} *:Forge-commit-checkout*
Check out commit `{sha}` (detached HEAD).
`:Forge commit diff` {sha} *:Forge-commit-diff*
Start a review for commit `{sha}`.
`:Forge commit browse` {sha} *:Forge-commit-browse*
Open commit `{sha}` on the forge.
`:Forge branch` *:Forge-branch*
Open the branch picker.
`:Forge branch diff` {name} *:Forge-branch-diff*
Start a review diffing against `{name}`.
`:Forge branch browse` {name} *:Forge-branch-browse*
Open branch `{name}` on the forge.
`:Forge worktree` *:Forge-worktree*
Open fzf-lua's git worktree picker.
`:Forge browse` [{flags}] *:Forge-browse*
Open the current file location on the forge.
`--root` Open the repository root page.
`--commit` Open the current HEAD commit.
(no flags) Open the current file and line(s) on the current
branch. In visual mode, the selected line range is
included.
`:Forge yank` [{flags}] *:Forge-yank*
Yank a permalink URL to the `+` register.
`--commit` Yank a commit-pinned URL.
(no flags) Yank a branch-pinned URL.
`:Forge review end` *:Forge-review-end*
End the current review session.
`:Forge review toggle` *:Forge-review-toggle*
Toggle between unified and split view (|forge-review|).
`:Forge cache clear` *:Forge-cache-clear*
Clear all internal caches (forge detection, repo info, list data).
All subcommands support tab completion.
============================================================================== ==============================================================================
PULL REQUESTS *forge-pr* KEYMAPS *forge-keymaps*
The PR picker lists open PRs by default. Toggle state with `<ctrl-o>` to cycle GLOBAL KEYMAPS ~
through open/closed/all.
PR picker keybinds: ~ All global keymaps are configured via `keys` (|forge-config-keys|).
`<enter>` Checkout PR branch
`<ctrl-d>` Review diff (requires diffs.nvim)
`<ctrl-w>` Create worktree from PR
`<ctrl-t>` View checks/CI status
`<ctrl-x>` Open in browser
`<ctrl-e>` Manage (merge, approve, close, draft toggle)
`<ctrl-a>` Create new PR
`<ctrl-o>` Toggle state filter (open/closed/all)
`<ctrl-r>` Refresh list
PR management actions: ~ Default Mode Description ~
Approve, Merge (per available method), Close/Reopen, Draft toggle. `<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
============================================================================== ==============================================================================
ISSUES *forge-issues* PICKERS *forge-pickers*
Issue picker keybinds: ~ *forge-picker*
`<enter>` Open in browser FORGE PICKER ~
`<ctrl-s>` Close/reopen issue The main entry point. Adapts based on the detected forge and current
`<ctrl-o>` Toggle state filter buffer. Lists: PRs/MRs, Issues, CI/CD, Browse Remote, Open File, Yank
`<ctrl-r>` Refresh list 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*
CI/CD *forge-ci* PR PICKER ~
Lists PRs/MRs with number, title, author, and relative time.
CI picker shows workflow runs for the current branch. Action Default Key Description ~
`checkout` `<enter>` Check out the PR branch
`diff` `ctrl-d` Start review (|forge-review|)
`worktree` `ctrl-w` Create worktree from PR
`checks` `ctrl-t` Open checks picker for this PR
`browse` `ctrl-x` Open PR in browser
`manage` `ctrl-e` Open management picker
`create` `ctrl-a` Create new PR (|forge-compose|)
`toggle` `ctrl-o` Cycle state: open -> closed -> all
`refresh` `ctrl-r` Clear cache and re-fetch
CI picker keybinds: ~ *forge-picker-issue*
`<enter>` View logs (tail for in-progress, full for completed) ISSUE PICKER ~
`<ctrl-x>` Open in browser Lists issues with number, title, author, and relative time.
`<ctrl-r>` Refresh
Checks picker (from PR): ~ Action Default Key Description ~
`<enter>` View check logs `browse` `<enter>` Open issue in browser
`<ctrl-x>` Open in browser `close_reopen` `ctrl-s` Close or reopen the issue
`<ctrl-f>` Filter to failed `toggle` `ctrl-o` Cycle state: all -> open -> closed
`<ctrl-p>` Filter to passed `refresh` `ctrl-r` Clear cache and re-fetch
`<ctrl-n>` Filter to running
`<ctrl-a>` Show all
============================================================================== *forge-picker-checks*
COMMITS *forge-commits* CHECKS PICKER ~
Lists PR check runs with status icon, name, and elapsed time.
Commit picker keybinds: ~ Action Default Key Description ~
`<enter>` Checkout commit (detached HEAD) `log` `<enter>` View log (tail for running, full otherwise)
`<ctrl-d>` Review diff `browse` `ctrl-x` Open check URL in browser
`<ctrl-x>` Open in browser (requires forge) `failed` `ctrl-f` Filter to failed checks
`<ctrl-y>` Yank commit hash `passed` `ctrl-p` Filter to passed checks
`running` `ctrl-n` Filter to running checks
`all` `ctrl-a` Show all checks
============================================================================== *forge-picker-ci*
BRANCHES *forge-branches* CI PICKER ~
Lists CI/CD runs for the current branch (or all branches with `--all`).
Branch picker keybinds: ~ Action Default Key Description ~
`<ctrl-d>` Review diff against branch `log` `<enter>` View log (tail for running, failed-only for
`<ctrl-x>` Open branch on remote (requires forge) failures, full otherwise)
`browse` `ctrl-x` Open run URL in browser
`refresh` `ctrl-r` Re-fetch runs
*forge-picker-commits*
COMMITS PICKER ~
Git log with colored output and commit preview.
Action Default Key Description ~
`checkout` `<enter>` Checkout commit (detached HEAD)
`diff` `ctrl-d` Review the commit diff
`browse` `ctrl-x` Open commit on forge
`yank` `ctrl-y` Yank commit hash to `+` register
*forge-picker-branches*
BRANCHES PICKER ~
Uses fzf-lua's `git_branches` with additional actions.
Action Default Key Description ~
`diff` `ctrl-d` Review diff against branch
`browse` `ctrl-x` 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.
============================================================================== ==============================================================================
REVIEW *forge-review* REVIEW *forge-review*
Review mode requires diffs.nvim. Enter review via `<ctrl-d>` on a PR or Review mode provides unified and split diff viewing for PRs and commits.
commit. Requires diffs.nvim for unified view and vim-fugitive for split view.
Review keybinds: ~ Starting a review: ~
`s` Toggle unified/split view - `ctrl-d` on a PR in the PR picker
`]q` / `[q` Next/previous quickfix entry (file navigation) - `ctrl-d` on a commit in the commit picker
`]l` / `[l` Next/previous loclist entry - `:Forge pr diff {num}`
- `:Forge commit diff {sha}`
- `:Forge branch diff {name}`
Review mode ends automatically when the review buffer is wiped. Unified view (default): ~
diffs.nvim renders a combined diff in a `diffs://review:*` buffer with
a quickfix list of changed files.
Split view: ~
Press the `review_toggle` key (default `s`) to switch to a side-by-side
fugitive split (`:Gvdiffsplit`). Press 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: ~
`:Forge review end` or wipe the `diffs://review:*` buffer.
State: ~
`require('forge.review').state` holds: >lua
{ base = 'origin/main', mode = 'unified' }
<
`base` is `nil` when no review is active.
============================================================================== ==============================================================================
COMPOSE BUFFER *forge-compose* COMPOSE BUFFER *forge-compose*
Creating a PR opens a compose buffer (`forge://pr/new`) with: Creating a PR (without `--fill` or `--web`) opens a compose buffer at
`forge://pr/new` with filetype `markdown` and buftype `acwrite`.
- Line 1: PR title (pre-filled from commit subject or branch name) Layout: ~
- Line 3+: PR body (pre-filled from commit body or PR template) Line 1 PR title (pre-filled from single commit subject or branch)
- HTML comment block: metadata (branch info, draft, reviewers, diff stat) Line 2 Empty separator
Lines 3+ PR body (from commit body or discovered PR template)
`<!--` Metadata comment block (branch, forge, draft, reviewers,
diff stat). Editable.
`-->` End of metadata
The compose buffer is `filetype=markdown` with `buftype=acwrite`. Write the Write (`:w`) to push the branch and create the PR. An empty title or body
buffer (`:w`) to push and create the PR. An empty title or body aborts. aborts creation. The PR URL is copied to the `+` register on success.
Metadata fields (editable in the comment block): ~ Metadata fields: ~
`Draft:` Set to `yes` or `true` to create as draft `Draft: yes` Create as draft (also `true`). Empty = not draft.
`Reviewers:` Comma-separated list of reviewer usernames `Reviewers:` Comma or space separated usernames.
Template discovery: ~ forge.nvim searches for PR templates in the repository: Template discovery: ~
- `.github/pull_request_template.md` forge.nvim searches forge-specific template paths. If a template
- `.github/PULL_REQUEST_TEMPLATE/` (single file auto-selected, multiple directory contains multiple `.md` files, you are prompted to choose.
prompts for choice) GitHub: `.github/pull_request_template.md`,
- GitLab/Codeberg equivalents `.github/PULL_REQUEST_TEMPLATE/`
GitLab: `.gitlab/merge_request_templates/`
Codeberg: `.gitea/pull_request_template.md`,
`.github/pull_request_template.md`
Fugitive keymaps: ~ From a fugitive buffer, the following keymaps are Highlight groups: ~
available:
`cpr` Create PR Group Default Link Description ~
`cpd` Create draft PR `ForgeComposeComment` `Comment` Comment block lines
`cpf` Create PR instantly (skip compose buffer) `ForgeComposeBranch` `Special` Branch names
`cpw` Create PR via web browser `ForgeComposeForge` `Type` Forge name
`ForgeComposeDraft` `DiagnosticWarn` Draft status value
`ForgeComposeFile` `Directory` File paths in diff stat
`ForgeComposeAdded` `Added` Addition indicators (+)
`ForgeComposeRemoved` `Removed` Deletion indicators (-)
All groups are defined with `default = true`.
============================================================================== ==============================================================================
HIGHLIGHT GROUPS *forge-highlights* SOURCES *forge-sources*
The compose buffer uses the following highlight groups: Built-in sources: ~
`ForgeComposeComment` Entire comment block Links to `Comment` Name CLI Hosts matched ~
`ForgeComposeBranch` Branch names Links to `Special` `github` `gh` `github`
`ForgeComposeForge` Forge name Links to `Type` `gitlab` `glab` `gitlab`
`ForgeComposeDraft` Draft status value Links to `DiagnosticWarn` `codeberg` `tea` `codeberg`, `gitea`, `forgejo`
`ForgeComposeFile` File paths in diff stat Links to `Directory`
`ForgeComposeAdded` Addition indicators (+) Links to `Added`
`ForgeComposeRemoved` Deletion indicators (-) Links to `Removed`
All groups are defined with `default = true` so colorschemes can override Sources are lazy-loaded the first time a matching remote is detected.
them. Built-in host patterns are checked after user-configured `sources` hosts,
so user overrides take priority.
HOST OVERRIDES ~
*forge-sources-hosts*
To route a self-hosted instance to a built-in source: >lua
vim.g.forge = {
sources = {
gitlab = { hosts = { 'gitlab.corp.com' } },
},
}
<
CUSTOM SOURCE REGISTRATION ~
*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.<name>` (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:
Fields: ~
`name` `string` Source name (e.g. `"github"`).
`cli` `string` CLI executable name (e.g. `"gh"`).
`kinds` `table` `{ issue = string, pr = string }` -- CLI
subcommand names for issues and PRs.
`labels` `table` `{ issue = string, pr = string,`
`pr_one = string, pr_full = string,`
`ci = string }` -- display labels.
Required methods: ~
All methods receive `self` as the first argument (use `:` syntax).
Method Returns ~
`list_pr_json_cmd(state)` `string[]` cmd to list PRs as JSON.
`list_issue_json_cmd(state)` `string[]` cmd to list issues as JSON.
`pr_json_fields()` `table` field name mapping:
`{ number, title, branch, state,`
`author, created_at }`.
`issue_json_fields()` `table` field name mapping:
`{ number, title, state, author,`
`created_at }`.
`view_web(kind, num)` Opens PR/issue in browser.
`browse(loc, branch)` Opens file location on remote.
`browse_root()` Opens repo root in browser.
`browse_branch(branch)` Opens branch in browser.
`browse_commit(sha)` Opens commit in browser.
`checkout_cmd(num)` `string[]` cmd to checkout a PR.
`yank_branch(loc)` Yanks branch-pinned URL.
`yank_commit(loc)` Yanks commit-pinned URL.
`fetch_pr(num)` `string[]` git fetch refspec for PR.
`pr_base_cmd(num)` `string[]` cmd returning base branch.
`pr_for_branch_cmd(branch)` `string[]` cmd returning PR number
for a branch (empty = no PR).
`checks_cmd(num)` `string` shell command for checks.
`check_log_cmd(run_id, failed_only)` `string[]` cmd to view check log.
`check_tail_cmd(run_id)` `string[]` cmd to tail check log.
`list_runs_cmd(branch?)` `string` shell command for CI runs.
`normalize_run(entry)` `forge.CIRun` normalized run entry.
`run_log_cmd(id, failed_only)` `string[]` cmd to view run log.
`run_tail_cmd(id)` `string[]` cmd to tail run log.
`merge_cmd(num, method)` `string[]` cmd to merge PR.
`approve_cmd(num)` `string[]` cmd to approve PR.
`repo_info()` `forge.RepoInfo` with `permission`
(`"ADMIN"`, `"WRITE"`, `"READ"`)
and `merge_methods` (`string[]`).
`pr_state(num)` `forge.PRState` with `state`,
`mergeable`, `review_decision`,
`is_draft`.
`close_cmd(num)` `string[]` cmd to close PR.
`reopen_cmd(num)` `string[]` cmd to reopen PR.
`close_issue_cmd(num)` `string[]` cmd to close issue.
`reopen_issue_cmd(num)` `string[]` cmd to reopen issue.
`create_pr_cmd(title, body,` `string[]` cmd to create a PR.
`base, draft, reviewers?)`
`default_branch_cmd()` `string[]` cmd returning default
branch name.
`template_paths()` `string[]` repo-relative paths to
PR templates.
`draft_toggle_cmd(num, is_draft)` `string[]?` cmd to toggle draft.
Return `nil` if unsupported.
Optional methods: ~
Method Fallback ~
`list_runs_json_cmd(branch?)` `string[]` JSON CI list cmd.
If absent, `list_runs_cmd` is used
as a raw fzf-lua command source.
`checks_json_cmd(num)` `string[]` JSON checks cmd.
If absent, `checks_cmd` string is
used as a raw fzf-lua command.
`create_pr_web_cmd()` `string[]?` cmd to open web PR
creation. Return `nil` to no-op.
Skeleton: >lua
local M = {
name = 'myforgejo',
cli = 'tea',
kinds = { issue = 'issues', pr = 'pulls' },
labels = {
issue = 'Issues',
pr = 'PRs',
pr_one = 'PR',
pr_full = 'Pull Requests',
ci = 'CI/CD',
},
}
function M:list_pr_json_cmd(state)
return { 'tea', 'pulls', 'list', '--state', state, '--output', 'json' }
end
-- ... implement remaining methods ...
return M
<
============================================================================== ==============================================================================
HEALTH CHECK *forge-health* HEALTH *forge-health*
Run `:checkhealth forge` to verify: `:checkhealth forge`
- git is available
- Forge CLIs (`gh`, `glab`, `tea`) and their status Reports on: ~
- fzf-lua is installed - `git` availability
- diffs.nvim is available (for review mode) - Forge CLI availability (`gh`, `glab`, `tea`)
- vim-fugitive is available (for fugitive keymaps) - `fzf-lua` installation (required)
- `diffs.nvim` installation (review mode)
- `vim-fugitive` availability (fugitive keymaps, split review)
- Custom registered sources and their CLI availability
==============================================================================
API *forge-api*
PUBLIC API: `require('forge')` ~
*forge.detect()*
`detect()`
Returns `forge.Forge?`. Detects the forge for the current git
repository by inspecting the `origin` remote URL. Returns `nil` if
not in a git repo, no matching source, or the CLI is not installed.
Results are cached per git root.
*forge.config()*
`config()`
Returns `table`. The resolved configuration, merging `vim.g.forge`
over defaults. If `vim.g.forge.keys` is `false`, `cfg.keys` is
`false`. Same for `picker_keys`.
*forge.register()*
`register(name, source)`
Registers a custom `forge.Forge` source under `name`.
*forge.registered_sources()*
`registered_sources()`
Returns `table<string, forge.Forge>`. All registered sources.
*forge.create_pr()*
`create_pr(opts?)`
Creates a PR. `opts` is `forge.CreatePROpts?`:
`draft` `boolean?` Create as draft.
`instant` `boolean?` Skip compose buffer, fill from commits.
`web` `boolean?` Push and open web create page.
*forge.clear_cache()*
`clear_cache()`
Clears all internal caches (forge detection, repo info, git root,
list data).
*forge.repo_info()*
`repo_info(f)`
Returns `forge.RepoInfo`. Fetches and caches repository info
(permissions, merge methods) for forge `f`.
*forge.file_loc()*
`file_loc()`
Returns `string`. Current buffer file path relative to git root with
line number(s). In visual mode, includes the selected line range
(e.g. `"src/foo.lua:10-20"`).
*forge.remote_web_url()*
`remote_web_url()`
Returns `string`. The HTTPS URL of the `origin` remote, normalized
from SSH or git URLs.
*forge.yank_url()*
`yank_url(args)`
Runs `args` (string[]) asynchronously and copies stdout to the `+`
register.
*forge.clear_list()*
`clear_list(key?)`
Clears cached list data. If `key` is given, clears only that key.
If `nil`, clears all list caches.
*forge.list_key()*
`list_key(kind, state)`
Returns `string`. Cache key for list data, scoped to git root.
*forge.get_list()*
`get_list(key)`
Returns `table[]?`. Cached list data for `key`.
*forge.set_list()*
`set_list(key, data)`
Stores `data` in the list cache under `key`.
*forge.log()*
`log(msg, level?)`
Schedules a `vim.notify` with `[forge.nvim]:` prefix.
*forge.log_now()*
`log_now(msg, level?)`
Synchronous `vim.notify` with `[forge.nvim]:` prefix and redraw.
PUBLIC API: `require('forge.pickers')` ~
*forge.pickers.git()*
`git()`
Opens the main forge picker. Requires a git repository.
*forge.pickers.pr()*
`pr(state, f)`
Opens the PR list picker. `state`: `"open"`, `"closed"`, or `"all"`.
`f`: `forge.Forge`.
*forge.pickers.issue()*
`issue(state, f)`
Opens the issue list picker. `state`: `"open"`, `"closed"`, or
`"all"`. `f`: `forge.Forge`.
*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()*
`ci(f, branch?)`
Opens the CI runs picker. `nil` branch shows all.
*forge.pickers.commits()*
`commits(f)`
Opens the commit log picker. `f` may be `nil` (browse action
requires a forge).
*forge.pickers.branches()*
`branches(f)`
Opens the branch picker. `f` may be `nil`.
*forge.pickers.pr_manage()*
`pr_manage(f, num)`
Opens the management picker for PR `num`.
*forge.pickers.pr_actions()*
`pr_actions(f, num)`
Returns `table<string, function>`. Action functions for PR `num`,
keyed by fzf binding. Also has `_by_name` table keyed by action
name (`"checkout"`, `"diff"`, `"worktree"`, `"browse"`, `"checks"`,
`"manage"`).
*forge.pickers.issue_close()*
`issue_close(f, num)`
Closes issue `num`.
*forge.pickers.issue_reopen()*
`issue_reopen(f, num)`
Reopens issue `num`.
PUBLIC API: `require('forge.review')` ~
*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()*
`stop()`
Ends the current review session. Clears state and removes the
`review_toggle` keymap.
*forge.review.toggle()*
`toggle()`
Toggles between unified and split view. No-op if no review is
active.
*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*
`state`
`table` with fields:
`base` `string?` The current diff range, or `nil`.
`mode` `"unified"|"split"` Current view mode.
============================================================================== ==============================================================================
vim:tw=78:ts=8:ft=help:norl: vim:tw=78:ts=8:ft=help:norl:

View file

@ -1,5 +1,109 @@
local M = {} local M = {}
---@class forge.Config
---@field ci forge.CIConfig
---@field sources table<string, forge.SourceConfig>
---@field keys forge.KeysConfig|false
---@field picker_keys forge.PickerKeysConfig|false
---@field display forge.DisplayConfig
---@class forge.CIConfig
---@field lines integer
---@class forge.SourceConfig
---@field hosts string[]
---@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 issue forge.IssuePickerKeys
---@field checks forge.ChecksPickerKeys
---@field ci forge.CIPickerKeys
---@field commits forge.CommitsPickerKeys
---@field branches forge.BranchesPickerKeys
---@class forge.PRPickerKeys
---@field checkout string|false
---@field diff string|false
---@field worktree string|false
---@field checks string|false
---@field browse string|false
---@field manage string|false
---@field create string|false
---@field toggle string|false
---@field refresh string|false
---@class forge.IssuePickerKeys
---@field browse string|false
---@field close_reopen string|false
---@field toggle string|false
---@field refresh string|false
---@class forge.ChecksPickerKeys
---@field log string|false
---@field browse string|false
---@field failed string|false
---@field passed string|false
---@field running string|false
---@field all string|false
---@class forge.CIPickerKeys
---@field log string|false
---@field browse string|false
---@field refresh string|false
---@class forge.CommitsPickerKeys
---@field checkout string|false
---@field diff string|false
---@field browse string|false
---@field yank string|false
---@class forge.BranchesPickerKeys
---@field diff string|false
---@field browse string|false
---@class forge.DisplayConfig
---@field icons forge.IconsConfig
---@field widths forge.WidthsConfig
---@field limits forge.LimitsConfig
---@class forge.IconsConfig
---@field open string
---@field merged string
---@field closed string
---@field pass string
---@field fail string
---@field pending string
---@field skip string
---@field unknown string
---@class forge.WidthsConfig
---@field title integer
---@field author integer
---@field name integer
---@field branch integer
---@class forge.LimitsConfig
---@field pulls integer
---@field issues integer
---@field runs integer
---@type forge.Config
local DEFAULTS = { local DEFAULTS = {
ci = { lines = 10000 }, ci = { lines = 10000 },
sources = {}, sources = {},
@ -71,10 +175,13 @@ local DEFAULTS = {
---@type table<string, forge.Forge> ---@type table<string, forge.Forge>
local sources = {} local sources = {}
---@param name string
---@param source forge.Forge
function M.register(name, source) function M.register(name, source)
sources[name] = source sources[name] = source
end end
---@return table<string, forge.Forge>
function M.registered_sources() function M.registered_sources()
return sources return sources
end end
@ -635,6 +742,7 @@ function M.filter_checks(checks, filter)
return filtered return filtered
end end
---@return forge.Config
function M.config() function M.config()
local user = vim.g.forge or {} local user = vim.g.forge or {}
local cfg = vim.tbl_deep_extend('force', DEFAULTS, user) local cfg = vim.tbl_deep_extend('force', DEFAULTS, user)