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.
This commit is contained in:
Barrett Ruth 2026-02-26 18:23:50 -05:00
parent 9fc24f5239
commit cd96a269a4
6 changed files with 188 additions and 1 deletions

View file

@ -2,7 +2,7 @@
Edit tasks like text. `:w` saves them.
<!-- insert preview -->
![demo](assets/demo.gif)
## Requirements
@ -24,6 +24,21 @@ luarocks install pending.nvim
:help pending.nvim
```
## Icons
pending.nvim renders task status and metadata using configurable icon characters. The defaults use plain unicode (no nerd font required):
```lua
vim.g.pending = {
icons = {
pending = '○', done = '✓', priority = '●',
header = '▸', due = '·', recur = '↺', category = '#',
},
}
```
See `:help pending.Icons` for nerd font examples.
## Acknowledgements
- [dooing](https://github.com/atiladefreitas/dooing)

0
assets/.gitkeep Normal file
View file

View file

@ -356,6 +356,10 @@ COMMANDS *pending-commands*
Equivalent to the `U` buffer-local key (see |pending-mappings|). Up to 20
levels of undo are persisted across sessions.
*:PendingTab*
:PendingTab
Open the task buffer in a new tab.
==============================================================================
MAPPINGS *pending-mappings*
@ -494,6 +498,9 @@ All motions support count: `3]]` jumps three headers forward. `]]` and
to the current buffer's file and the cursor's line number.
See |pending-file-token|.
<Plug>(pending-tab) *<Plug>(pending-tab)*
Open the task buffer in a new tab. See |:PendingTab|.
Example configuration: >lua
vim.keymap.set('n', '<leader>t', '<Plug>(pending-open)')
vim.keymap.set('n', '<leader>T', '<Plug>(pending-toggle)')
@ -679,6 +686,16 @@ Fields: ~
automatically. New configs should use `sync.gcal`
instead. See |pending.GcalConfig|.
{icons} (table) *pending.Icons*
Icon characters displayed in the buffer. Fields:
{pending} Uncompleted task icon. Default: '○'
{done} Completed task icon. Default: '✓'
{priority} Priority task icon. Default: '●'
{header} Category header prefix. Default: '▸'
{due} Due date prefix. Default: '·'
{recur} Recurrence prefix. Default: '↺'
{category} Category label prefix. Default: '#'
==============================================================================
LUA API *pending-api*
@ -860,6 +877,41 @@ directly, or disable `a_category` in `keymaps` and handle it via a
`vim.b.miniai_config` entry that returns a linewise region if mini.ai's
spec allows it in your version.
Nerd font icons: >lua
vim.g.pending = {
icons = {
pending = '',
done = '',
priority = '',
header = '',
due = '',
recur = '󰁯',
category = '',
},
}
<
ASCII fallback icons: >lua
vim.g.pending = {
icons = {
pending = '-',
done = 'x',
priority = '!',
header = '>',
due = '@',
recur = '~',
category = '+',
},
}
<
Open tasks in a new tab on startup: >lua
vim.api.nvim_create_autocmd('VimEnter', {
callback = function()
vim.cmd.PendingTab()
end,
})
<
==============================================================================
GOOGLE CALENDAR *pending-gcal*

33
scripts/demo-init.lua Normal file
View file

@ -0,0 +1,33 @@
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',
icons = {
pending = '',
done = '',
priority = '',
header = '',
due = '·',
recur = '',
category = '#',
},
}
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()

28
scripts/demo.tape Normal file
View file

@ -0,0 +1,28 @@
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

59
spec/icons_spec.lua Normal file
View file

@ -0,0 +1,59 @@
require('spec.helpers')
local config = require('pending.config')
describe('icons', function()
before_each(function()
vim.g.pending = nil
config.reset()
end)
after_each(function()
vim.g.pending = nil
config.reset()
end)
it('has default icon values', function()
local icons = config.get().icons
assert.equals('', icons.pending)
assert.equals('', icons.done)
assert.equals('', icons.priority)
assert.equals('', icons.header)
assert.equals('·', icons.due)
assert.equals('', icons.recur)
assert.equals('#', icons.category)
end)
it('allows overriding individual icons', function()
vim.g.pending = { icons = { pending = '-', done = 'x' } }
config.reset()
local icons = config.get().icons
assert.equals('-', icons.pending)
assert.equals('x', icons.done)
assert.equals('', icons.priority)
assert.equals('', icons.header)
end)
it('allows overriding all icons', function()
vim.g.pending = {
icons = {
pending = '-',
done = 'x',
priority = '!',
header = '>',
due = '@',
recur = '~',
category = '+',
},
}
config.reset()
local icons = config.get().icons
assert.equals('-', icons.pending)
assert.equals('x', icons.done)
assert.equals('!', icons.priority)
assert.equals('>', icons.header)
assert.equals('@', icons.due)
assert.equals('~', icons.recur)
assert.equals('+', icons.category)
end)
end)