Problem: The S3 backend had no `:Pending s3` entry in the COMMANDS
section, `:Pending auth` only mentioned Google, the `sync` config
field omitted `s3`, `_s3_sync_id` was missing from the data format
section, `:Pending done` was implemented but undocumented, and the
README lacked a features overview.
Solution: Add `:Pending s3` and `:Pending done` command docs, rewrite
`:Pending auth` to cover all backends and sub-actions, update config
and data format references, add `aws` CLI to requirements, and add a
Features section to `README.md`.
* feat(sync): add `setup` command to configure credentials interactively
Problem: users had to manually create a JSON credentials file at the
correct path before authenticating, with no guidance from the plugin.
Solution: add `OAuthClient:setup()` that prompts for client ID and
secret via `vim.ui.input`, writes to the shared
`google_credentials.json`, then immediately starts the OAuth flow.
Expose as `:Pending {gtasks,gcal} setup`. Also extend
`resolve_credentials()` to fall back to a shared `google_credentials.json`
so one file covers both backends.
* fix(sync): improve `setup` input loop with validation and masking
Problem: `setup()` used async `vim.ui.input` for both prompts, causing
newline and re-prompt issues when validation failed. The secret was also
echoed in plain text.
Solution: switch to synchronous `vim.fn.input` / `vim.fn.inputsecret`
loops with `vim.cmd.redraw()` + `nvim_echo` for inline error display and
re-prompting. Validate client ID format and `GOCSPX-` secret prefix
before saving.
* fix(oauth): fix `ipairs` nil truncation in `resolve_credentials` and add file-path setup option
Problem: `resolve_credentials` built `cred_paths` with a potentially nil
first element (`credentials_path`), causing `ipairs` to stop immediately
and always fall through to bundled placeholder credentials.
Solution: build `cred_paths` without nil entries using `table.insert`.
Also add a `2. Load from JSON file path` option to `setup()` via
`vim.fn.inputlist`, with `vim.fn.expand` for `~`/`$HOME` support and
the `installed` wrapper unwrap.
* doc: cleanup
* ci: format
* refactor(oauth): async coroutine support, pure-Lua PKCE, server hardening
Problem: OAuth module shelled out to openssl for PKCE, used blocking
`vim.system():wait()`, had a weak `os.time()` PRNG seed, and the TCP
callback server leaked on read errors with no timeout.
Solution: Add `M.system()` coroutine wrapper and `M.async()` helper,
replace openssl with `vim.fn.sha256` + `vim.base64.encode`, seed from
`vim.uv.hrtime()`, add `close_server()` guard with 120s timeout, and
close the server on read errors.
* fix(gtasks): async operations, error notifications, buffer refresh
Problem: Sync operations blocked the editor, `push_pass` silently
dropped delete/update/create API errors, and the buffer was not
re-rendered after push/pull/sync.
Solution: Wrap `push`, `pull`, `sync` in `oauth.async()`, add
`vim.notify` for all `push_pass` failure paths, and re-render the
pending buffer after each operation.
* fix(init): edit recompute, filter predicates, sync action listing
Problem: `M.edit()` skipped `_recompute_counts()` after saving,
`compute_hidden_ids` lacked `done`/`pending` predicates, and
`run_sync` defaulted to `sync` instead of listing available actions.
Solution: Replace `s:save()` with `_save_and_notify()` in `M.edit()`,
add `done` and `pending` filter predicates, and list backend actions
when no action is specified.
* refactor(gcal): per-category calendars, async push, error notifications
Problem: gcal used a single hardcoded calendar name, ran synchronously
blocking the editor, and silently dropped some API errors.
Solution: Fetch all calendars and map categories to calendars (creating
on demand), wrap push in `oauth.async()`, notify on individual API
failures, track `_gcal_calendar_id` in `_extra`, and remove the `$`
anchor from `next_day` pattern.
* refactor: formatting fixes, config cleanup, health simplification
Problem: Formatter disagreements in `init.lua` and `gtasks.lua`,
stale `calendar` field in gcal config, and redundant health checks
for data directory existence.
Solution: Apply stylua formatting, remove `calendar` field from
`pending.GcalConfig`, drop data-dir and no-file health messages,
add `done`/`pending` to filter tab-completion candidates.
* 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.
* fix(types): correct LuaLS annotations in oauth and gcal
* docs: remove unnecessary mini.ai recipe from vimdoc
Problem: the `*pending-mini-ai*` section assumed mini.ai intercepts
buffer-local `at`/`it`/`aC`/`iC` mappings, requiring a manual
`vim.b.miniai_config` workaround.
Solution: remove the section. Neovim's keymap resolver already
prioritizes longer buffer-local mappings over mini.ai's global
`a`/`i` handlers — no recipe needed.
* refactor(icons): unify category/header icon and use checkbox overlays
Problem: `header` and `category` were separate icons for the same
concept. The icon overlay replaced `[ ]` with a bare character,
hiding the markdown checkbox syntax. Header format `## ` produced
a double-space with single-char icons.
Solution: merge `header` into `category` (one icon for both header
lines and EOL labels). Overlay renders `[icon]` preserving bracket
syntax. Change header line format from `## ` to `# ` so the
2-char overlay (`# `) maps cleanly.
* ci: remove empty `assets/` placeholder
* refactor(config): default icons to ascii
Problem: default icons used unicode characters (○, ✓, ●, ▸, ·, ↺)
which render poorly in some terminals and font configurations.
Solution: replace defaults with ascii equivalents (-, x, !, >, ., ~).
Users can still override to unicode or nerd font icons via config.
* ci: ignore library type checking
* feat(config): add icons table with unicode defaults
* feat(buffer): render icon overlays from config.icons
Problem: status characters ([ ], [x], [!]) and metadata prefixes are
hardcoded literals with no user customization.
Solution: read config.icons in apply_extmarks and apply overlay
extmarks for checkboxes/headers, replace hardcoded recur ↺ with
icons.recur, and prefix due/category virt_text with configurable
icon characters.
* feat(plugin): add PendingTab command and <Plug>(pending-tab)
* docs: add icons config, PendingTab recipes, and demo infrastructure
Problem: icon customization and auto-start workflow are undocumented;
no demo asset exists for the README.
Solution: document pending.Icons in vimdoc with nerd font and ASCII
recipes, add PendingTab to commands and mappings, add open-on-startup
recipe, add demo-init.lua and demo.tape for VHS screenshot generation,
add assets/ directory, add README icons section and demo placeholder.
* ci: format
Problem: repo had no documentation for users.
Solution: add README covering usage, configuration, inline
metadata syntax, Google Calendar sync, mappings, and data
format.