docs(gtasks): document Google Tasks backend and CLI changes

Problem: vimdoc had no coverage for the gtasks backend and still
referenced the old `:Pending sync <backend>` command form.

Solution: add `:Pending-gtasks` and `:Pending-gcal` command sections
with per-action docs, update sync backend interface, and add gtasks
config example.
This commit is contained in:
Barrett Ruth 2026-03-05 00:59:08 -05:00
parent ffc588ccf9
commit e8894d7d8b

View file

@ -41,6 +41,7 @@ Features: ~
- Foldable category sections (`zc`/`zo`) in category view
- Omnifunc completion for `cat:`, `due:`, and `rec:` tokens (`<C-x><C-o>`)
- Google Calendar one-way push via OAuth PKCE
- Google Tasks bidirectional sync via OAuth PKCE
==============================================================================
CONTENTS *pending-contents*
@ -63,15 +64,16 @@ CONTENTS *pending-contents*
16. Recipes ............................................... |pending-recipes|
17. Sync Backends ................................... |pending-sync-backend|
18. Google Calendar .......................................... |pending-gcal|
19. Data Format .............................................. |pending-data|
20. Health Check ........................................... |pending-health|
19. Google Tasks ............................................ |pending-gtasks|
20. Data Format .............................................. |pending-data|
21. Health Check ........................................... |pending-health|
==============================================================================
REQUIREMENTS *pending-requirements*
- Neovim 0.10+
- No external dependencies for local use
- `curl` and `openssl` are required for the `gcal` sync backend
- `curl` and `openssl` are required for the `gcal` and `gtasks` sync backends
==============================================================================
INSTALL *pending-install*
@ -146,24 +148,42 @@ COMMANDS *pending-commands*
Populate the quickfix list with all tasks that are overdue or due today.
Open the list with |:copen| to navigate to each task's category.
*:Pending-sync*
:Pending sync {backend} [{action}]
Run a sync action against a named backend. {backend} is required — bare
`:Pending sync` prints a usage message. {action} defaults to `sync`
when omitted. Each backend lives at `lua/pending/sync/<name>.lua`.
*:Pending-gtasks*
:Pending gtasks [{action}]
Run a Google Tasks sync action. {action} defaults to `sync` when omitted.
Actions: ~
`sync` Push local changes then pull remote changes (default).
`push` Push local changes to Google Tasks only.
`pull` Pull remote changes from Google Tasks only.
`auth` Run the OAuth authorization flow.
Examples: >vim
:Pending sync gcal " runs gcal.sync()
:Pending sync gcal auth " runs gcal.auth()
:Pending sync gcal sync " explicit sync (same as bare)
:Pending gtasks " push then pull (default)
:Pending gtasks push " push local → Google Tasks
:Pending gtasks pull " pull Google Tasks → local
:Pending gtasks auth " authorize
<
Tab completion after `:Pending sync ` lists discovered backends.
Tab completion after `:Pending sync gcal ` lists available actions.
Tab completion after `:Pending gtasks ` lists available actions.
See |pending-gtasks| for full details.
Built-in backends: ~
*:Pending-gcal*
:Pending gcal [{action}]
Run a Google Calendar sync action. {action} defaults to `sync` when
omitted.
`gcal` Google Calendar one-way push. See |pending-gcal|.
Actions: ~
`sync` Push tasks with due dates to Google Calendar (default).
`auth` Run the OAuth authorization flow.
Examples: >vim
:Pending gcal " push to Google Calendar (default)
:Pending gcal auth " authorize
<
Tab completion after `:Pending gcal ` lists available actions.
See |pending-gcal| for full details.
*:Pending-filter*
:Pending filter {predicates}
@ -590,6 +610,9 @@ loads: >lua
calendar = 'Pendings',
credentials_path = '/path/to/client_secret.json',
},
gtasks = {
credentials_path = '/path/to/client_secret.json',
},
},
}
<
@ -870,21 +893,30 @@ Open tasks in a new tab on startup: >lua
SYNC BACKENDS *pending-sync-backend*
Sync backends are Lua modules under `lua/pending/sync/<name>.lua`. Each
module returns a table conforming to the backend interface: >lua
backend is exposed as a top-level `:Pending` subcommand: >vim
:Pending gtasks [action]
:Pending gcal [action]
<
Each module returns a table conforming to the backend interface: >lua
---@class pending.SyncBackend
---@field name string
---@field auth fun(): nil
---@field sync fun(): nil
---@field push? fun(): nil
---@field pull? fun(): nil
---@field health? fun(): nil
<
Required fields: ~
{name} Backend identifier (matches the filename).
{sync} Main sync action. Called by `:Pending sync <name>`.
{auth} Authorization flow. Called by `:Pending sync <name> auth`.
{sync} Main sync action. Called by `:Pending <name>`.
{auth} Authorization flow. Called by `:Pending <name> auth`.
Optional fields: ~
{push} Push-only action. Called by `:Pending <name> push`.
{pull} Pull-only action. Called by `:Pending <name> pull`.
{health} Called by `:checkhealth pending` to report backend-specific
diagnostics (e.g. checking for external tools).
@ -923,7 +955,7 @@ Fields: ~
that Google provides or as a bare credentials object.
OAuth flow: ~
On the first `:Pending sync gcal` call the plugin detects that no refresh token
On the first `:Pending gcal` call the plugin detects that no refresh token
exists and opens the Google authorization URL in the browser using
|vim.ui.open()|. A temporary local HTTP server listens on port 18392 for the
OAuth redirect. The PKCE (Proof Key for Code Exchange) flow is used —
@ -933,7 +965,7 @@ authorization code is exchanged for tokens and the refresh token is stored at
use the stored refresh token and refresh the access token automatically when
it is about to expire.
`:Pending sync gcal` behavior: ~
`:Pending gcal` behavior: ~
For each task in the store:
- A pending task with a due date and no existing event: a new all-day event is
created and the event ID is stored in the task's `_extra` table.
@ -946,6 +978,67 @@ For each task in the store:
A summary notification is shown after sync: `created: N, updated: N,
deleted: N`.
==============================================================================
GOOGLE TASKS *pending-gtasks*
pending.nvim can sync tasks bidirectionally with Google Tasks. Each
pending.nvim category maps to a Google Tasks list of the same name. Lists are
created automatically on first sync.
Configuration: >lua
vim.g.pending = {
sync = {
gtasks = {
credentials_path = '/path/to/client_secret.json',
},
},
}
<
*pending.GtasksConfig*
Fields: ~
{credentials_path} (string)
Path to the OAuth client secret JSON file downloaded
from the Google Cloud Console. Default:
`stdpath('data')..'/pending/gtasks_credentials.json'`.
Accepts the `installed` wrapper format or a bare
credentials object.
OAuth flow: ~
Same PKCE flow as the gcal backend; listens on port 18393. Tokens are stored
at `stdpath('data')/pending/gtasks_tokens.json`. Run `:Pending gtasks auth`
to authorize; subsequent syncs refresh the token automatically.
`:Pending gtasks` actions: ~
`:Pending gtasks` (or `:Pending gtasks sync`) runs push then pull. Use
`:Pending gtasks push` or `:Pending gtasks pull` to run only one direction.
Push (local → Google Tasks, `:Pending gtasks push`):
- Pending task with no `_gtasks_task_id`: created in the matching list.
- Pending task with an existing ID: updated in Google Tasks.
- Done task with an existing ID: marked `completed` in Google Tasks.
- Deleted task with an existing ID: deleted from Google Tasks.
Pull (Google Tasks → local, `:Pending gtasks pull`):
- GTasks task already known (matched by `_gtasks_task_id`): updated locally
if `gtasks.updated` timestamp is newer than `task.modified`.
- GTasks task not known locally: created as a new pending.nvim task in the
category matching the list name.
Field mapping: ~
{title} ↔ task description
{status} `needsAction` ↔ `pending`, `completed` ↔ `done`
{due} date-only; time component ignored (GTasks limitation)
{notes} serializes extra fields: `pri:1 rec:weekly`
The `notes` field is used exclusively for pending.nvim metadata. Any existing
notes on tasks created outside pending.nvim are parsed for known tokens and
the remainder is ignored.
Recurrence (`rec:`) is stored in notes for round-tripping but is not
expanded by Google Tasks (GTasks has no recurrence API).
==============================================================================
DATA FORMAT *pending-data*
@ -979,7 +1072,8 @@ Task fields: ~
Any field not in the list above is preserved in `_extra` and written back on
save. This is used internally to store the Google Calendar event ID
(`_gcal_event_id`) and allows third-party tooling to annotate tasks without
(`_gcal_event_id`) and Google Tasks IDs (`_gtasks_task_id`,
`_gtasks_list_id`), and allows third-party tooling to annotate tasks without
data loss.
The `version` field is checked on load. If the file version is newer than the