diff --git a/README.md b/README.md index cff442d..1780cab 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ https://github.com/user-attachments/assets/f3898ecb-ec95-43fe-a71f-9c9f49628ba9 - Google Tasks bidirectional sync via OAuth PKCE - S3 whole-store sync via AWS CLI with cross-device merge - Auto-authentication: sync actions trigger auth flows automatically +- Forge links: reference GitHub/GitLab/Codeberg issues and PRs inline ## Requirements diff --git a/doc/pending.txt b/doc/pending.txt index f79961e..0b4b249 100644 --- a/doc/pending.txt +++ b/doc/pending.txt @@ -43,6 +43,7 @@ Features: ~ - Google Calendar one-way push via OAuth PKCE - Google Tasks bidirectional sync via OAuth PKCE - S3 whole-store sync via AWS CLI +- Forge links: reference GitHub/GitLab/Codeberg issues and PRs inline ============================================================================== CONTENTS *pending-contents* @@ -68,8 +69,9 @@ CONTENTS *pending-contents* 19. Google Tasks ............................................ |pending-gtasks| 20. Google Authentication ......................... |pending-google-auth| 21. S3 Sync ................................................... |pending-s3| - 22. Data Format .............................................. |pending-data| - 23. Health Check ........................................... |pending-health| + 22. Forge Links ........................................... |pending-forge| + 23. Data Format .............................................. |pending-data| + 24. Health Check ........................................... |pending-health| ============================================================================== REQUIREMENTS *pending-requirements* @@ -738,7 +740,7 @@ loads: >lua max_priority = 3, view = { default = 'category', - eol_format = '%c %r %d', + eol_format = '%l %c %r %d', category = { order = {}, folding = true, @@ -837,9 +839,10 @@ Fields: ~ The view to use when the buffer is opened for the first time in a session. - {eol_format} (string, default: '%c %r %d') + {eol_format} (string, default: '%l %c %r %d') Format string for end-of-line virtual text. Specifiers: + `%l` forge link label (`PendingForge`) `%c` category icon + name (`PendingHeader`) `%r` recurrence icon + pattern (`PendingRecur`) `%d` due icon + date (`PendingDue`/`PendingOverdue`) @@ -1009,6 +1012,15 @@ PendingFilter Applied to the `FILTER:` header line shown at the top of the buffer when a filter is active. Default: links to `DiagnosticWarn`. + *PendingForge* +PendingForge Applied to forge link virtual text (issue/PR reference). + Default: links to `DiagnosticInfo`. + + *PendingForgeClosed* +PendingForgeClosed Applied to forge link virtual text when the remote + issue/PR is closed or merged. + Default: links to `Comment`. + To override a group in your colorscheme or config: >lua vim.api.nvim_set_hl(0, 'PendingDue', { fg = '#aaaaaa', italic = true }) < @@ -1443,6 +1455,108 @@ Downloads the remote store from S3, then merges per-task by `_s3_sync_id`: `:Pending s3 sync` behavior: ~ Pulls first (merge), then pushes the merged result. +============================================================================== +FORGE LINKS *pending-forge* + +Tasks can reference remote issues, pull requests, and merge requests from +GitHub, GitLab, and Codeberg (or Gitea). References are parsed from inline +tokens, concealed in the buffer, and rendered as configurable virtual text. + +Inline syntax: ~ + +Two input forms, both parsed on `:w`: + + Shorthand: ~ + `gh:user/repo#42` GitHub issue or PR + `gl:group/project#15` GitLab issue or MR + `cb:user/repo#3` Codeberg issue or PR + + Full URL: ~ + `https://github.com/user/repo/issues/42` + `https://gitlab.com/group/project/-/merge_requests/15` + `https://codeberg.org/user/repo/issues/3` + +Example: > + Fix login bug gh:user/repo#42 due:friday +< + +On `:w`, the forge reference is stripped from the description, stored in the +task's `_extra._forge_ref` field, and rendered as right-aligned virtual text +alongside the due date and other metadata. + +Only one forge reference per task. The `%l` specifier in `eol_format` +controls where the link label appears in the virtual text line. The default +`eol_format` is `'%l %c %r %d'` (link first). + +Format string: ~ + *pending-forge-format* +Each forge has a configurable `issue_format` string with these placeholders: + `%i` Forge icon (nerd font) + `%o` Repository owner + `%r` Repository name + `%n` Issue/PR number + +Default: `'%i %o/%r#%n'` (e.g. ` user/repo#42`). + +Configuration: ~ + *pending.ForgeConfig* +>lua + vim.g.pending = { + forge = { + github = { + token = nil, + icon = '', + issue_format = '%i %o/%r#%n', + instances = {}, + }, + gitlab = { + token = nil, + icon = '', + issue_format = '%i %o/%r#%n', + instances = {}, + }, + codeberg = { + token = nil, + icon = '', + issue_format = '%i %o/%r#%n', + instances = {}, + }, + }, + } +< + +Fields (per forge): ~ + {token} (string, optional) API token for authenticated requests. + Falls back to CLI: `gh auth token` (GitHub), `glab auth + token` (GitLab). Codeberg uses token only. + {icon} (string) Nerd font icon used in virtual text. + {issue_format} (string) Format string for the EOL label. + {instances} (string[]) Additional hostnames for self-hosted instances + (e.g. `{ 'github.company.com' }`). + +Authentication: ~ +Token retrieval is CLI-preferred, config fallback: +1. GitHub: `gh auth token` stdout. Falls back to `forge.github.token`. +2. GitLab: `glab auth token` stdout. Falls back to `forge.gitlab.token`. +3. Codeberg: `forge.codeberg.token` only (no standard CLI). + +Unauthenticated requests work for public repositories. Private repositories +require a token. + +Metadata fetching: ~ +On buffer open, tasks with a `_forge_ref` whose cached metadata is older +than 5 minutes are re-fetched asynchronously. The buffer renders immediately +with cached data and updates extmarks when the fetch completes. + +State pull: ~ +After fetching, if the remote issue/PR is closed or merged and the local +task is pending/wip/blocked, the task is automatically marked as done. This +is one-way: local status changes do not push back to the forge. + +Highlight groups: ~ + |PendingForge| Open issue/PR link label + |PendingForgeClosed| Closed/merged issue/PR link label + ============================================================================== DATA FORMAT *pending-data* @@ -1481,6 +1595,7 @@ save. This is used internally to store sync backend metadata: - Google Calendar: `_gcal_event_id`, `_gcal_calendar_id` - Google Tasks: `_gtasks_task_id`, `_gtasks_list_id` - S3: `_s3_sync_id` (UUID for cross-device merge) +- Forge links: `_forge_ref` (parsed reference), `_forge_cache` (fetched state) Third-party tooling can annotate tasks via `_extra` without data loss. The `version` field is checked on load. If the file version is newer than the