feat: rename

This commit is contained in:
Barrett Ruth 2026-02-24 15:21:44 -05:00
parent c69a3957c8
commit 78a275d096
No known key found for this signature in database
GPG key ID: A6C96C9349D2FC81
21 changed files with 191 additions and 191 deletions

View file

@ -4,8 +4,8 @@ body:
- type: markdown
attributes:
value: |
Use this space for questions, ideas, and general discussion about todo.nvim.
For bug reports, please [open an issue](https://github.com/barrettruth/todo.nvim/issues/new/choose) instead.
Use this space for questions, ideas, and general discussion about pending.nvim.
For bug reports, please [open an issue](https://github.com/barrettruth/pending.nvim/issues/new/choose) instead.
- type: textarea
attributes:
label: Question or topic

View file

@ -9,7 +9,7 @@ body:
options:
- label:
I have searched [existing
issues](https://github.com/barrettruth/todo.nvim/issues)
issues](https://github.com/barrettruth/pending.nvim/issues)
required: true
- label: I have updated to the latest version
required: true
@ -69,7 +69,7 @@ body:
require('lazy.nvim').setup({
spec = {
{
'barrettruth/todo.nvim',
'barrettruth/pending.nvim',
opts = {},
},
},

View file

@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Questions
url: https://github.com/barrettruth/todo.nvim/discussions
url: https://github.com/barrettruth/pending.nvim/discussions
about: Ask questions and discuss ideas

View file

@ -9,7 +9,7 @@ body:
options:
- label:
I have searched [existing
issues](https://github.com/barrettruth/todo.nvim/issues)
issues](https://github.com/barrettruth/pending.nvim/issues)
required: true
- type: textarea

View file

@ -1,4 +1,4 @@
# todo.nvim
# pending.nvim
Edit tasks like text. `:w` saves them.
@ -27,13 +27,13 @@ concealed, and metadata is parsed from inline syntax on save.
## Install
```
luarocks install todo.nvim
luarocks install pending.nvim
```
**lazy.nvim:**
```lua
{ 'barrettruth/todo.nvim' }
{ 'barrettruth/pending.nvim' }
```
Requires Neovim 0.10+. No external dependencies for local use. Google Calendar
@ -41,7 +41,7 @@ sync requires `curl` and `openssl`.
## Usage
`:Todo` opens the task buffer. From there, it's just vim:
`:Pending` opens the task buffer. From there, it's just vim:
| Key | Action |
| --------- | ------------------------------- |
@ -68,24 +68,24 @@ header.
### Quick add
```vim
:Todo add Buy groceries due:2026-03-15
:Todo add School: Submit homework
:Pending add Buy groceries due:2026-03-15
:Pending add School: Submit homework
```
### Archive
```vim
:Todo archive " purge done tasks older than 30 days
:Todo archive 7 " purge done tasks older than 7 days
:Pending archive " purge done tasks older than 30 days
:Pending archive 7 " purge done tasks older than 7 days
```
## Configuration
No `setup()` call required. Set `vim.g.todo` before the plugin loads:
No `setup()` call required. Set `vim.g.pending` before the plugin loads:
```lua
vim.g.todo = {
data_path = vim.fn.stdpath('data') .. '/todo/tasks.json',
vim.g.pending = {
data_path = vim.fn.stdpath('data') .. '/pending/tasks.json',
default_view = 'category', -- 'category' or 'priority'
default_category = 'Inbox',
date_format = '%b %d', -- strftime format for virtual text
@ -101,7 +101,7 @@ One-way push of tasks with due dates to a dedicated Google Calendar as all-day
events.
```lua
vim.g.todo = {
vim.g.pending = {
gcal = {
calendar = 'Tasks',
credentials_path = '/path/to/client_secret.json',
@ -110,11 +110,11 @@ vim.g.todo = {
```
```vim
:Todo sync
:Pending sync
```
On first run, a browser window opens for OAuth consent. The refresh token is
stored at `stdpath('data')/todo/gcal_tokens.json`. Completed or deleted tasks
stored at `stdpath('data')/pending/gcal_tokens.json`. Completed or deleted tasks
have their calendar events removed. Due date changes update events in place.
## Mappings
@ -122,25 +122,25 @@ have their calendar events removed. Due date changes update events in place.
The plugin defines `<Plug>` mappings for custom keybinds:
```lua
vim.keymap.set('n', '<leader>t', '<Plug>(todo-open)')
vim.keymap.set('n', '<leader>T', '<Plug>(todo-toggle)')
vim.keymap.set('n', '<leader>t', '<Plug>(pending-open)')
vim.keymap.set('n', '<leader>T', '<Plug>(pending-toggle)')
```
| Plug mapping | Action |
| ---------------------- | --------------------- |
| `<Plug>(todo-open)` | Open task buffer |
| `<Plug>(todo-toggle)` | Toggle complete |
| `<Plug>(todo-view)` | Switch view |
| `<Plug>(todo-priority)`| Toggle priority flag |
| `<Plug>(todo-date)` | Prompt for due date |
| `<Plug>(pending-open)` | Open task buffer |
| `<Plug>(pending-toggle)` | Toggle complete |
| `<Plug>(pending-view)` | Switch view |
| `<Plug>(pending-priority)`| Toggle priority flag |
| `<Plug>(pending-date)` | Prompt for due date |
## Data format
Tasks are stored as JSON at `stdpath('data')/todo/tasks.json`. The schema is
Tasks are stored as JSON at `stdpath('data')/pending/tasks.json`. The schema is
versioned and forward-compatible — unknown fields are preserved on round-trip.
## Documentation
```vim
:checkhealth todo
:checkhealth pending
```

View file

@ -1,19 +1,19 @@
local config = require('todo.config')
local store = require('todo.store')
local views = require('todo.views')
local config = require('pending.config')
local store = require('pending.store')
local views = require('pending.views')
---@class todo.buffer
---@class pending.buffer
local M = {}
---@type integer?
local task_bufnr = nil
local task_ns = vim.api.nvim_create_namespace('todo')
local task_ns = vim.api.nvim_create_namespace('pending')
---@type 'category'|'priority'|nil
local current_view = nil
---@type todo.LineMeta[]
---@type pending.LineMeta[]
local _meta = {}
---@return todo.LineMeta[]
---@return pending.LineMeta[]
function M.meta()
return _meta
end
@ -33,7 +33,7 @@ local function set_buf_options(bufnr)
vim.bo[bufnr].buftype = 'acwrite'
vim.bo[bufnr].bufhidden = 'hide'
vim.bo[bufnr].swapfile = false
vim.bo[bufnr].filetype = 'todo'
vim.bo[bufnr].filetype = 'pending'
vim.bo[bufnr].modifiable = true
end
@ -65,7 +65,7 @@ end
---@param bufnr integer
local function setup_indentexpr(bufnr)
vim.bo[bufnr].indentexpr = 'v:lua.require("todo.buffer").get_indent()'
vim.bo[bufnr].indentexpr = 'v:lua.require("pending.buffer").get_indent()'
end
---@return integer
@ -82,7 +82,7 @@ function M.get_indent()
end
---@param bufnr integer
---@param line_meta todo.LineMeta[]
---@param line_meta pending.LineMeta[]
local function apply_extmarks(bufnr, line_meta)
vim.api.nvim_buf_clear_namespace(bufnr, task_ns, 0, -1)
for i, m in ipairs(line_meta) do
@ -90,7 +90,7 @@ local function apply_extmarks(bufnr, line_meta)
if m.type == 'task' then
if m.due then
vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, 0, {
virt_text = { { m.due, 'TodoDue' } },
virt_text = { { m.due, 'PendingDue' } },
virt_text_pos = 'right_align',
})
end
@ -99,14 +99,14 @@ local function apply_extmarks(bufnr, line_meta)
local col_start = line:find('/%d+/') and select(2, line:find('/%d+/')) + 2 or 0
vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, col_start, {
end_col = #line,
hl_group = 'TodoDone',
hl_group = 'PendingDone',
})
end
elseif m.type == 'header' then
local line = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ''
vim.api.nvim_buf_set_extmark(bufnr, task_ns, row, 0, {
end_col = #line,
hl_group = 'TodoHeader',
hl_group = 'PendingHeader',
})
end
end
@ -118,10 +118,10 @@ local function setup_highlights()
vim.api.nvim_set_hl(0, name, opts)
end
end
hl('TodoHeader', { bold = true })
hl('TodoDue', { fg = '#888888', italic = true })
hl('TodoDone', { strikethrough = true, fg = '#666666' })
hl('TodoPriority', { fg = '#e06c75', bold = true })
hl('PendingHeader', { bold = true })
hl('PendingDue', { fg = '#888888', italic = true })
hl('PendingDone', { strikethrough = true, fg = '#666666' })
hl('PendingPriority', { fg = '#e06c75', bold = true })
end
---@param bufnr? integer
@ -179,7 +179,7 @@ function M.open()
end
task_bufnr = vim.api.nvim_create_buf(true, false)
vim.api.nvim_buf_set_name(task_bufnr, 'todo://')
vim.api.nvim_buf_set_name(task_bufnr, 'pending://')
set_buf_options(task_bufnr)
setup_indentexpr(task_bufnr)

View file

@ -1,8 +1,8 @@
---@class todo.GcalConfig
---@class pending.GcalConfig
---@field calendar? string
---@field credentials_path? string
---@class todo.Config
---@class pending.Config
---@field data_path string
---@field default_view 'category'|'priority'
---@field default_category string
@ -10,27 +10,27 @@
---@field date_syntax string
---@field gcal? task.GcalConfig
---@class todo.config
---@class pending.config
local M = {}
---@type todo.Config
---@type pending.Config
local defaults = {
data_path = vim.fn.stdpath('data') .. '/todo/tasks.json',
data_path = vim.fn.stdpath('data') .. '/pending/tasks.json',
default_view = 'category',
default_category = 'Inbox',
date_format = '%b %d',
date_syntax = 'due',
}
---@type todo.Config?
---@type pending.Config?
local _resolved = nil
---@return todo.Config
---@return pending.Config
function M.get()
if _resolved then
return _resolved
end
local user = vim.g.todo or {}
local user = vim.g.pending or {}
_resolved = vim.tbl_deep_extend('force', defaults, user)
return _resolved
end

View file

@ -1,8 +1,8 @@
local config = require('todo.config')
local parse = require('todo.parse')
local store = require('todo.store')
local config = require('pending.config')
local parse = require('pending.parse')
local store = require('pending.store')
---@class todo.ParsedEntry
---@class pending.ParsedEntry
---@field type 'task'|'header'|'blank'
---@field id? integer
---@field description? string
@ -11,7 +11,7 @@ local store = require('todo.store')
---@field due? string
---@field lnum integer
---@class todo.diff
---@class pending.diff
local M = {}
---@return string
@ -20,7 +20,7 @@ local function timestamp()
end
---@param lines string[]
---@return todo.ParsedEntry[]
---@return pending.ParsedEntry[]
function M.parse_buffer(lines)
local result = {}
local current_category = nil

View file

@ -1,11 +1,11 @@
local M = {}
function M.check()
vim.health.start('todo.nvim')
vim.health.start('pending.nvim')
local ok, config = pcall(require, 'todo.config')
local ok, config = pcall(require, 'pending.config')
if not ok then
vim.health.error('Failed to load todo.config')
vim.health.error('Failed to load pending.config')
return
end
@ -25,7 +25,7 @@ function M.check()
end
if vim.fn.filereadable(cfg.data_path) == 1 then
local store_ok, store = pcall(require, 'todo.store')
local store_ok, store = pcall(require, 'pending.store')
if store_ok then
local load_ok, err = pcall(store.load)
if load_ok then

View file

@ -1,12 +1,12 @@
local buffer = require('todo.buffer')
local diff = require('todo.diff')
local parse = require('todo.parse')
local store = require('todo.store')
local buffer = require('pending.buffer')
local diff = require('pending.diff')
local parse = require('pending.parse')
local store = require('pending.store')
---@class task
local M = {}
---@type todo.Task[]?
---@type pending.Task[]?
local _undo_state = nil
---@return integer bufnr
@ -19,7 +19,7 @@ end
---@param bufnr integer
function M._setup_autocmds(bufnr)
local group = vim.api.nvim_create_augroup('TodoBuffer', { clear = true })
local group = vim.api.nvim_create_augroup('PendingBuffer', { clear = true })
vim.api.nvim_create_autocmd('BufWriteCmd', {
group = group,
buffer = bufnr,
@ -127,13 +127,13 @@ end
---@param text string
function M.add(text)
if not text or text == '' then
vim.notify('Usage: :Todo add <description>', vim.log.levels.ERROR)
vim.notify('Usage: :Pending add <description>', vim.log.levels.ERROR)
return
end
store.load()
local description, metadata = parse.command_add(text)
if not description or description == '' then
vim.notify('Todo must have a description.', vim.log.levels.ERROR)
vim.notify('Pending must have a description.', vim.log.levels.ERROR)
return
end
store.add({
@ -146,11 +146,11 @@ function M.add(text)
if bufnr and vim.api.nvim_buf_is_valid(bufnr) then
buffer.render(bufnr)
end
vim.notify('Todo added: ' .. description)
vim.notify('Pending added: ' .. description)
end
function M.sync()
local ok, gcal = pcall(require, 'todo.sync.gcal')
local ok, gcal = pcall(require, 'pending.sync.gcal')
if not ok then
vim.notify('Google Calendar sync module not available.', vim.log.levels.ERROR)
return
@ -196,10 +196,10 @@ function M.archive(days)
end
function M.show_help()
local cfg = require('todo.config').get()
local cfg = require('pending.config').get()
local dk = cfg.date_syntax or 'due'
local lines = {
'todo.nvim keybindings',
'pending.nvim keybindings',
'',
'<CR> Toggle complete/uncomplete',
'<Tab> Switch category/priority view',
@ -208,10 +208,10 @@ function M.show_help()
'p / P Paste (duplicates get new IDs)',
':w Save all changes',
'',
':Todo add <text> Quick-add task',
':Todo add Cat: <text> Quick-add with category',
':Todo sync Push to Google Calendar',
':Todo archive [days] Purge old done tasks',
':Pending add <text> Quick-add task',
':Pending add Cat: <text> Quick-add with category',
':Pending sync Push to Google Calendar',
':Pending archive [days] Purge old done tasks',
'',
'Inline metadata (on new lines before :w):',
' ' .. dk .. ':YYYY-MM-DD Set due date',
@ -257,7 +257,7 @@ function M.command(args)
local d = rest ~= '' and tonumber(rest) or nil
M.archive(d)
else
vim.notify('Unknown Todo subcommand: ' .. cmd, vim.log.levels.ERROR)
vim.notify('Unknown Pending subcommand: ' .. cmd, vim.log.levels.ERROR)
end
end

View file

@ -1,6 +1,6 @@
local config = require('todo.config')
local config = require('pending.config')
---@class todo.parse
---@class pending.parse
local M = {}
---@param s string

View file

@ -1,6 +1,6 @@
local config = require('todo.config')
local config = require('pending.config')
---@class todo.Task
---@class pending.Task
---@field id integer
---@field description string
---@field status 'pending'|'done'|'deleted'
@ -13,20 +13,20 @@ local config = require('todo.config')
---@field order integer
---@field _extra? table<string, any>
---@class todo.Data
---@class pending.Data
---@field version integer
---@field next_id integer
---@field tasks task.Task[]
---@class todo.store
---@class pending.store
local M = {}
local SUPPORTED_VERSION = 1
---@type todo.Data?
---@type pending.Data?
local _data = nil
---@return todo.Data
---@return pending.Data
local function empty_data()
return {
version = SUPPORTED_VERSION,
@ -62,7 +62,7 @@ local known_fields = {
order = true,
}
---@param task todo.Task
---@param task pending.Task
---@return table
local function task_to_table(task)
local t = {
@ -96,7 +96,7 @@ local function task_to_table(task)
end
---@param t table
---@return todo.Task
---@return pending.Task
local function table_to_task(t)
local task = {
id = t.id,
@ -122,7 +122,7 @@ local function table_to_task(t)
return task
end
---@return todo.Data
---@return pending.Data
function M.load()
local path = config.get().data_path
local f = io.open(path, 'r')
@ -138,11 +138,11 @@ function M.load()
end
local ok, decoded = pcall(vim.json.decode, content)
if not ok then
error('todo.nvim: failed to parse ' .. path .. ': ' .. tostring(decoded))
error('pending.nvim: failed to parse ' .. path .. ': ' .. tostring(decoded))
end
if decoded.version and decoded.version > SUPPORTED_VERSION then
error(
'todo.nvim: data file version '
'pending.nvim: data file version '
.. decoded.version
.. ' is newer than supported version '
.. SUPPORTED_VERSION
@ -177,13 +177,13 @@ function M.save()
local encoded = vim.json.encode(out)
local f = io.open(path, 'w')
if not f then
error('todo.nvim: cannot write to ' .. path)
error('pending.nvim: cannot write to ' .. path)
end
f:write(encoded)
f:close()
end
---@return todo.Data
---@return pending.Data
function M.data()
if not _data then
M.load()
@ -191,12 +191,12 @@ function M.data()
return _data
end
---@return todo.Task[]
---@return pending.Task[]
function M.tasks()
return M.data().tasks
end
---@return todo.Task[]
---@return pending.Task[]
function M.active_tasks()
local result = {}
for _, task in ipairs(M.tasks()) do
@ -208,7 +208,7 @@ function M.active_tasks()
end
---@param id integer
---@return todo.Task?
---@return pending.Task?
function M.get(id)
for _, task in ipairs(M.tasks()) do
if task.id == id then
@ -219,7 +219,7 @@ function M.get(id)
end
---@param fields { description: string, status?: string, category?: string, priority?: integer, due?: string, order?: integer, _extra?: table }
---@return todo.Task
---@return pending.Task
function M.add(fields)
local data = M.data()
local now = timestamp()
@ -243,7 +243,7 @@ end
---@param id integer
---@param fields table<string, any>
---@return todo.Task?
---@return pending.Task?
function M.update(id, fields)
local task = M.get(id)
if not task then
@ -263,7 +263,7 @@ function M.update(id, fields)
end
---@param id integer
---@return todo.Task?
---@return pending.Task?
function M.delete(id)
return M.update(id, { status = 'deleted', ['end'] = timestamp() })
end
@ -279,7 +279,7 @@ function M.find_index(id)
return nil
end
---@param tasks todo.Task[]
---@param tasks pending.Task[]
function M.replace_tasks(tasks)
M.data().tasks = tasks
end

View file

@ -1,5 +1,5 @@
local config = require('todo.config')
local store = require('todo.store')
local config = require('pending.config')
local store = require('pending.store')
local M = {}
@ -14,12 +14,12 @@ local function gcal_config()
end
local function token_path()
return vim.fn.stdpath('data') .. '/todo/gcal_tokens.json'
return vim.fn.stdpath('data') .. '/pending/gcal_tokens.json'
end
local function credentials_path()
local gc = gcal_config()
return gc.credentials_path or (vim.fn.stdpath('data') .. '/todo/gcal_credentials.json')
return gc.credentials_path or (vim.fn.stdpath('data') .. '/pending/gcal_credentials.json')
end
local function load_json_file(path)
@ -153,7 +153,7 @@ local function get_access_token()
local creds = load_credentials()
if not creds then
vim.notify(
'todo.nvim: No Google Calendar credentials found at ' .. credentials_path(),
'pending.nvim: No Google Calendar credentials found at ' .. credentials_path(),
vim.log.levels.ERROR
)
return nil
@ -172,7 +172,7 @@ local function get_access_token()
if now - obtained > expires - 60 then
tokens = refresh_access_token(creds, tokens)
if not tokens then
vim.notify('todo.nvim: Failed to refresh access token.', vim.log.levels.ERROR)
vim.notify('pending.nvim: Failed to refresh access token.', vim.log.levels.ERROR)
return nil
end
end
@ -183,7 +183,7 @@ function M.authorize()
local creds = load_credentials()
if not creds then
vim.notify(
'todo.nvim: No Google Calendar credentials found at ' .. credentials_path(),
'pending.nvim: No Google Calendar credentials found at ' .. credentials_path(),
vim.log.levels.ERROR
)
return
@ -225,7 +225,7 @@ function M.authorize()
.. '&code_challenge_method=S256'
vim.ui.open(auth_url)
vim.notify('todo.nvim: Opening browser for Google authorization...')
vim.notify('pending.nvim: Opening browser for Google authorization...')
local server = vim.uv.new_tcp()
server:bind('127.0.0.1', port)
@ -288,24 +288,24 @@ function M._exchange_code(creds, code, code_verifier, port)
:wait()
if result.code ~= 0 then
vim.notify('todo.nvim: Token exchange failed.', vim.log.levels.ERROR)
vim.notify('pending.nvim: Token exchange failed.', vim.log.levels.ERROR)
return
end
local ok, decoded = pcall(vim.json.decode, result.stdout or '')
if not ok or not decoded.access_token then
vim.notify('todo.nvim: Invalid token response.', vim.log.levels.ERROR)
vim.notify('pending.nvim: Invalid token response.', vim.log.levels.ERROR)
return
end
decoded.obtained_at = os.time()
save_tokens(decoded)
vim.notify('todo.nvim: Google Calendar authorized successfully.')
vim.notify('pending.nvim: Google Calendar authorized successfully.')
end
local function find_or_create_calendar(access_token)
local gc = gcal_config()
local cal_name = gc.calendar or 'Todos'
local cal_name = gc.calendar or 'Pendings'
local data, err =
curl_request('GET', BASE_URL .. '/users/me/calendarList', auth_headers(access_token))
@ -389,7 +389,7 @@ function M.sync()
local calendar_id, err = find_or_create_calendar(access_token)
if err then
vim.notify('todo.nvim: ' .. err, vim.log.levels.ERROR)
vim.notify('pending.nvim: ' .. err, vim.log.levels.ERROR)
return
end
@ -442,7 +442,7 @@ function M.sync()
store.save()
vim.notify(
string.format(
'todo.nvim: Synced to Google Calendar (created: %d, updated: %d, deleted: %d)',
'pending.nvim: Synced to Google Calendar (created: %d, updated: %d, deleted: %d)',
created,
updated,
deleted

View file

@ -1,6 +1,6 @@
local config = require('todo.config')
local config = require('pending.config')
---@class todo.LineMeta
---@class pending.LineMeta
---@field type 'task'|'header'|'blank'
---@field id? integer
---@field due? string
@ -8,7 +8,7 @@ local config = require('todo.config')
---@field status? string
---@field category? string
---@class todo.views
---@class pending.views
local M = {}
---@param due? string
@ -25,7 +25,7 @@ local function format_due(due)
return os.date(config.get().date_format, t)
end
---@param tasks todo.Task[]
---@param tasks pending.Task[]
local function sort_tasks(tasks)
table.sort(tasks, function(a, b)
if a.priority ~= b.priority then
@ -38,7 +38,7 @@ local function sort_tasks(tasks)
end)
end
---@param tasks todo.Task[]
---@param tasks pending.Task[]
local function sort_tasks_priority(tasks)
table.sort(tasks, function(a, b)
if a.priority ~= b.priority then
@ -62,9 +62,9 @@ local function sort_tasks_priority(tasks)
end)
end
---@param tasks todo.Task[]
---@param tasks pending.Task[]
---@return string[] lines
---@return todo.LineMeta[] meta
---@return pending.LineMeta[] meta
function M.category_view(tasks)
local by_cat = {}
local cat_order = {}
@ -130,9 +130,9 @@ function M.category_view(tasks)
return lines, meta
end
---@param tasks todo.Task[]
---@param tasks pending.Task[]
---@return string[] lines
---@return todo.LineMeta[] meta
---@return pending.LineMeta[] meta
function M.priority_view(tasks)
local pending = {}
local done = {}

View file

@ -1,14 +1,14 @@
rockspec_format = '3.0'
package = 'todo.nvim'
package = 'pending.nvim'
version = 'scm-1'
source = {
url = 'git+https://github.com/barrettruth/todo.nvim.git',
url = 'git+https://github.com/barrettruth/pending.nvim.git',
}
description = {
summary = 'Oil-like task management for Neovim',
homepage = 'https://github.com/barrettruth/todo.nvim',
homepage = 'https://github.com/barrettruth/pending.nvim',
license = 'MIT',
}

39
plugin/pending.lua Normal file
View file

@ -0,0 +1,39 @@
if vim.g.loaded_pending then
return
end
vim.g.loaded_pending = true
vim.api.nvim_create_user_command('Pending', function(opts)
require('pending').command(opts.args)
end, {
nargs = '*',
complete = function(arg_lead, cmd_line)
local subcmds = { 'add', 'sync', 'archive' }
if not cmd_line:match('^Pending%s+%S') then
return vim.tbl_filter(function(s)
return s:find(arg_lead, 1, true) == 1
end, subcmds)
end
return {}
end,
})
vim.keymap.set('n', '<Plug>(pending-open)', function()
require('pending').open()
end)
vim.keymap.set('n', '<Plug>(pending-toggle)', function()
require('pending').toggle_complete()
end)
vim.keymap.set('n', '<Plug>(pending-view)', function()
require('pending.buffer').toggle_view()
end)
vim.keymap.set('n', '<Plug>(pending-priority)', function()
require('pending').toggle_priority()
end)
vim.keymap.set('n', '<Plug>(pending-date)', function()
require('pending').prompt_date()
end)

View file

@ -1,39 +0,0 @@
if vim.g.loaded_todo then
return
end
vim.g.loaded_todo = true
vim.api.nvim_create_user_command('Todo', function(opts)
require('todo').command(opts.args)
end, {
nargs = '*',
complete = function(arg_lead, cmd_line)
local subcmds = { 'add', 'sync', 'archive' }
if not cmd_line:match('^Todo%s+%S') then
return vim.tbl_filter(function(s)
return s:find(arg_lead, 1, true) == 1
end, subcmds)
end
return {}
end,
})
vim.keymap.set('n', '<Plug>(todo-open)', function()
require('todo').open()
end)
vim.keymap.set('n', '<Plug>(todo-toggle)', function()
require('todo').toggle_complete()
end)
vim.keymap.set('n', '<Plug>(todo-view)', function()
require('todo.buffer').toggle_view()
end)
vim.keymap.set('n', '<Plug>(todo-priority)', function()
require('todo').toggle_priority()
end)
vim.keymap.set('n', '<Plug>(todo-date)', function()
require('todo').prompt_date()
end)

View file

@ -1,16 +1,16 @@
require('spec.helpers')
local config = require('todo.config')
local store = require('todo.store')
local config = require('pending.config')
local store = require('pending.store')
describe('diff', function()
local tmpdir
local diff = require('todo.diff')
local diff = require('pending.diff')
before_each(function()
tmpdir = vim.fn.tempname()
vim.fn.mkdir(tmpdir, 'p')
vim.g.todo = { data_path = tmpdir .. '/tasks.json' }
vim.g.pending = { data_path = tmpdir .. '/tasks.json' }
config.reset()
store.unload()
store.load()
@ -18,7 +18,7 @@ describe('diff', function()
after_each(function()
vim.fn.delete(tmpdir, 'rf')
vim.g.todo = nil
vim.g.pending = nil
config.reset()
end)

View file

@ -1,19 +1,19 @@
require('spec.helpers')
local config = require('todo.config')
local config = require('pending.config')
describe('parse', function()
before_each(function()
vim.g.todo = nil
vim.g.pending = nil
config.reset()
end)
after_each(function()
vim.g.todo = nil
vim.g.pending = nil
config.reset()
end)
local parse = require('todo.parse')
local parse = require('pending.parse')
describe('body', function()
it('returns plain description when no metadata', function()
@ -73,7 +73,7 @@ describe('parse', function()
end)
it('uses configurable date syntax', function()
vim.g.todo = { date_syntax = 'by' }
vim.g.pending = { date_syntax = 'by' }
config.reset()
local desc, meta = parse.body('Buy milk by:2026-03-15')
assert.are.equal('Buy milk', desc)
@ -81,7 +81,7 @@ describe('parse', function()
end)
it('ignores old syntax when date_syntax is changed', function()
vim.g.todo = { date_syntax = 'by' }
vim.g.pending = { date_syntax = 'by' }
config.reset()
local desc, meta = parse.body('Buy milk due:2026-03-15')
assert.are.equal('Buy milk due:2026-03-15', desc)

View file

@ -1,7 +1,7 @@
require('spec.helpers')
local config = require('todo.config')
local store = require('todo.store')
local config = require('pending.config')
local store = require('pending.store')
describe('store', function()
local tmpdir
@ -9,14 +9,14 @@ describe('store', function()
before_each(function()
tmpdir = vim.fn.tempname()
vim.fn.mkdir(tmpdir, 'p')
vim.g.todo = { data_path = tmpdir .. '/tasks.json' }
vim.g.pending = { data_path = tmpdir .. '/tasks.json' }
config.reset()
store.unload()
end)
after_each(function()
vim.fn.delete(tmpdir, 'rf')
vim.g.todo = nil
vim.g.pending = nil
config.reset()
end)
@ -37,14 +37,14 @@ describe('store', function()
tasks = {
{
id = 1,
description = 'Todo one',
description = 'Pending one',
status = 'pending',
entry = '2026-01-01T00:00:00Z',
modified = '2026-01-01T00:00:00Z',
},
{
id = 2,
description = 'Todo two',
description = 'Pending two',
status = 'done',
entry = '2026-01-01T00:00:00Z',
modified = '2026-01-01T00:00:00Z',
@ -55,7 +55,7 @@ describe('store', function()
local data = store.load()
assert.are.equal(3, data.next_id)
assert.are.equal(2, #data.tasks)
assert.are.equal('Todo one', data.tasks[1].description)
assert.are.equal('Pending one', data.tasks[1].description)
assert.are.equal('done', data.tasks[2].status)
end)
@ -68,7 +68,7 @@ describe('store', function()
tasks = {
{
id = 1,
description = 'Todo',
description = 'Pending',
status = 'pending',
entry = '2026-01-01T00:00:00Z',
modified = '2026-01-01T00:00:00Z',
@ -157,7 +157,7 @@ describe('store', function()
tasks = {
{
id = 1,
description = 'Todo',
description = 'Pending',
status = 'pending',
entry = '2026-01-01T00:00:00Z',
modified = '2026-01-01T00:00:00Z',

View file

@ -7,8 +7,8 @@ syntax match taskHeader /^\S.*$/ contains=taskId
syntax match taskPriority /!\ze / contained
syntax match taskLine /^\/\d\+\/ .*$/ contains=taskId,taskPriority
highlight default link taskHeader TodoHeader
highlight default link taskPriority TodoPriority
highlight default link taskHeader PendingHeader
highlight default link taskPriority PendingPriority
highlight default link taskLine Normal
let b:current_syntax = 'task'