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.
This commit is contained in:
parent
9a762a5320
commit
bc2a106617
6 changed files with 42 additions and 110 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
|||
doc/tags
|
||||
*.log
|
||||
minimal_init.lua
|
||||
|
||||
.*cache*
|
||||
CLAUDE.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
|
||||
|
||||
|
|
|
|||
|
|
@ -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/<name>.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.<name>` 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*
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue