From bc2a10661783bbe38fe46c07559fc28bd5e94692 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Thu, 5 Mar 2026 11:24:43 -0500 Subject: [PATCH] docs: update vimdoc for sync refactor, remove demo scripts Problem: Docs still referenced openssl dependency, defaulting to `sync` action, and the `calendar` config field. Demo scripts used the old singleton `store` API. Solution: Update vimdoc and README to reflect explicit actions, per- category calendars, and pure-Lua PKCE. Remove stale demo scripts and update sync specs to match new behavior. --- .gitignore | 1 + README.md | 2 +- doc/pending.txt | 57 +++++++++++++++++-------------------------- scripts/demo-init.lua | 30 ----------------------- scripts/demo.tape | 28 --------------------- spec/sync_spec.lua | 34 +++++++++++++------------- 6 files changed, 42 insertions(+), 110 deletions(-) delete mode 100644 scripts/demo-init.lua delete mode 100644 scripts/demo.tape diff --git a/.gitignore b/.gitignore index 93ac2c5..7cdfb66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ doc/tags *.log +minimal_init.lua .*cache* CLAUDE.md diff --git a/README.md b/README.md index cb3d3eb..43c8447 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Edit tasks like text. `:w` saves them. ## Requirements - Neovim 0.10+ -- (Optionally) `curl` and `openssl` for Google Calendar and Google Task sync +- (Optionally) `curl` for Google Calendar and Google Task sync ## Installation diff --git a/doc/pending.txt b/doc/pending.txt index d3eb03b..914644e 100644 --- a/doc/pending.txt +++ b/doc/pending.txt @@ -73,7 +73,7 @@ REQUIREMENTS *pending-requirements* - Neovim 0.10+ - No external dependencies for local use -- `curl` and `openssl` are required for the `gcal` and `gtasks` sync backends +- `curl` is required for the `gcal` and `gtasks` sync backends ============================================================================== INSTALL *pending-install* @@ -149,17 +149,17 @@ COMMANDS *pending-commands* Open the list with |:copen| to navigate to each task's category. *:Pending-gtasks* -:Pending gtasks [{action}] - Run a Google Tasks sync action. {action} defaults to `sync` when omitted. +:Pending gtasks {action} + Run a Google Tasks action. An explicit action is required. Actions: ~ - `sync` Push local changes then pull remote changes (default). + `sync` Push local changes then pull remote changes. `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 gtasks " push then pull (default) + :Pending gtasks sync " push then pull :Pending gtasks push " push local → Google Tasks :Pending gtasks pull " pull Google Tasks → local :Pending gtasks auth " authorize @@ -169,16 +169,15 @@ COMMANDS *pending-commands* See |pending-gtasks| for full details. *:Pending-gcal* -:Pending gcal [{action}] - Run a Google Calendar sync action. {action} defaults to `sync` when - omitted. +:Pending gcal {action} + Run a Google Calendar action. An explicit action is required. Actions: ~ - `sync` Push tasks with due dates to Google Calendar (default). + `push` Push tasks with due dates to Google Calendar. `auth` Run the OAuth authorization flow. Examples: >vim - :Pending gcal " push to Google Calendar (default) + :Pending gcal push " push to Google Calendar :Pending gcal auth " authorize < @@ -606,9 +605,7 @@ loads: >lua prev_task = '[t', }, sync = { - gcal = { - calendar = 'Pendings', - }, + gcal = {}, gtasks = {}, }, } @@ -893,8 +890,8 @@ SYNC BACKENDS *pending-sync-backend* Sync backends are Lua modules under `lua/pending/sync/.lua`. Each backend is exposed as a top-level `:Pending` subcommand: >vim - :Pending gtasks [action] - :Pending gcal [action] + :Pending gtasks {action} + :Pending gcal {action} < Each module returns a table conforming to the backend interface: >lua @@ -902,9 +899,9 @@ 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 sync? fun(): nil ---@field health? fun(): nil < @@ -924,16 +921,15 @@ Backend-specific configuration goes under `sync.` in |pending-config|. ============================================================================== GOOGLE CALENDAR *pending-gcal* -pending.nvim can push tasks with due dates to a dedicated Google Calendar as -all-day events. This is a one-way push; changes made in Google Calendar are -not pulled back into pending.nvim. +pending.nvim can push tasks with due dates to Google Calendar as all-day +events. Each pending.nvim category maps to a Google Calendar of the same +name. Calendars are created automatically on first push. This is a one-way +push; changes made in Google Calendar are not pulled back. Configuration: >lua vim.g.pending = { sync = { - gcal = { - calendar = 'Pendings', - }, + gcal = {}, }, } < @@ -943,11 +939,6 @@ used by default. Run `:Pending gcal auth` and the browser opens immediately. *pending.GcalConfig* Fields: ~ - {calendar} (string, default: 'Pendings') - Name of the Google Calendar to sync to. If a calendar - with this name does not exist it is created - automatically on the first sync. - {client_id} (string, optional) OAuth client ID. When set together with {client_secret}, these take priority over the @@ -973,26 +964,24 @@ OAuth flow: ~ 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 — -`openssl` generates the code challenge. After the user grants consent, the +OAuth redirect. The PKCE (Proof Key for Code Exchange) flow is used. After +the user grants consent, the authorization code is exchanged for tokens and the refresh token is stored at `stdpath('data')/pending/gcal_tokens.json` with mode `600`. Subsequent syncs use the stored refresh token and refresh the access token automatically when it is about to expire. -`:Pending gcal` behavior: ~ +`:Pending gcal push` 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. + created in the calendar matching the task's category. The event ID and + calendar ID are stored in the task's `_extra` table. - A pending task with a due date and an existing event: the event summary and date are updated in place. - A done or deleted task with an existing event: the event is deleted. - A pending task with no due date that had an existing event: the event is deleted. -A summary notification is shown after sync: `created: N, updated: N, -deleted: N`. - ============================================================================== GOOGLE TASKS *pending-gtasks* diff --git a/scripts/demo-init.lua b/scripts/demo-init.lua deleted file mode 100644 index 57da080..0000000 --- a/scripts/demo-init.lua +++ /dev/null @@ -1,30 +0,0 @@ -vim.opt.runtimepath:prepend(vim.fn.getcwd()) -local tmpdir = vim.fn.tempname() -vim.fn.mkdir(tmpdir, 'p') - -vim.g.pending = { - data_path = tmpdir .. '/tasks.json', -} - -local store = require('pending.store') -store.load() - -local today = os.date('%Y-%m-%d') -local yesterday = os.date('%Y-%m-%d', os.time() - 86400) -local tomorrow = os.date('%Y-%m-%d', os.time() + 86400) - -store.add({ - description = 'Finish quarterly report', - category = 'Work', - due = tomorrow, - recur = 'monthly', - priority = 1, -}) -store.add({ description = 'Review pull requests', category = 'Work' }) -store.add({ description = 'Update deployment docs', category = 'Work', status = 'done' }) -store.add({ description = 'Buy groceries', category = 'Personal', due = today }) -store.add({ description = 'Call dentist', category = 'Personal', due = yesterday, priority = 1 }) -store.add({ description = 'Read chapter 5', category = 'Personal' }) -store.add({ description = 'Learn a new language', category = 'Someday' }) -store.add({ description = 'Plan hiking trip', category = 'Someday' }) -store.save() diff --git a/scripts/demo.tape b/scripts/demo.tape deleted file mode 100644 index 3a1eee5..0000000 --- a/scripts/demo.tape +++ /dev/null @@ -1,28 +0,0 @@ -Output assets/demo.gif - -Require nvim - -Set Shell "bash" -Set FontSize 14 -Set Width 900 -Set Height 450 - -Type "nvim -u scripts/demo-init.lua -c 'autocmd VimEnter * Pending'" -Enter - -Sleep 2s - -Down -Down -Sleep 300ms -Down -Sleep 300ms - -Enter -Sleep 500ms - -Tab -Sleep 1s - -Type "q" -Sleep 200ms diff --git a/spec/sync_spec.lua b/spec/sync_spec.lua index ce38635..93d3e2c 100644 --- a/spec/sync_spec.lua +++ b/spec/sync_spec.lua @@ -49,27 +49,27 @@ describe('sync', function() assert.are.equal("gcal backend has no 'notreal' action", msg) end) - it('defaults to sync action when action is omitted', function() - local called = false - local gcal = require('pending.sync.gcal') - local orig_sync = gcal.sync - gcal.sync = function() - called = true + it('lists actions when action is omitted', function() + local msg = nil + local orig = vim.notify + vim.notify = function(m) + msg = m end pending.command('gcal') - gcal.sync = orig_sync - assert.is_true(called) + vim.notify = orig + assert.is_not_nil(msg) + assert.is_truthy(msg:find('push')) end) - it('routes explicit sync action', function() + it('routes explicit push action', function() local called = false local gcal = require('pending.sync.gcal') - local orig_sync = gcal.sync - gcal.sync = function() + local orig_push = gcal.push + gcal.push = function() called = true end - pending.command('gcal sync') - gcal.sync = orig_sync + pending.command('gcal push') + gcal.push = orig_push assert.is_true(called) end) @@ -90,10 +90,10 @@ describe('sync', function() config.reset() vim.g.pending = { data_path = tmpdir .. '/tasks.json', - sync = { gcal = { calendar = 'NewStyle' } }, + sync = { gcal = { client_id = 'test-id' } }, } local cfg = config.get() - assert.are.equal('NewStyle', cfg.sync.gcal.calendar) + assert.are.equal('test-id', cfg.sync.gcal.client_id) end) describe('gcal module', function() @@ -107,9 +107,9 @@ describe('sync', function() assert.are.equal('function', type(gcal.auth)) end) - it('has sync function', function() + it('has push function', function() local gcal = require('pending.sync.gcal') - assert.are.equal('function', type(gcal.sync)) + assert.are.equal('function', type(gcal.push)) end) it('has health function', function()