Compare commits

..

2 commits

Author SHA1 Message Date
baa5444a7e fix(buffer): default to natural split height like fugitive
Problem: hardcoded drawer_height=15 was too small and diverged from
fugitive's model. Fugitive issues a plain botright split and lets Vim's
own split rules (equalalways, winheight) divide the available space.

Solution: remove the default height so the split sizes naturally. Only
call nvim_win_set_height when the user sets drawer_height to a positive
value, preserving the opt-in customization path.
2026-02-25 09:32:00 -05:00
b379b3cf13 feat(buffer): open as bottom-drawer split like fugitive
Problem: :Pending replaced the current buffer, making it impossible to
view tasks alongside the file being edited. No way to close the drawer
without :q or switching buffers manually.

Solution: open the task buffer in a botright horizontal split instead of
replacing the current buffer. Track the drawer window ID so re-opening
focuses it rather than creating a second split. Set winfixheight so the
drawer keeps its height when other windows open or close. Add q/<Esc>
mappings to close the drawer, and a WinClosed autocmd to clear the
tracked window ID when the user closes it manually. Add drawer_height
config option (default 15).
2026-02-25 09:24:04 -05:00
5 changed files with 143 additions and 26 deletions

View file

@ -1,4 +1,4 @@
title: "Q&A" title: 'Q&A'
labels: [] labels: []
body: body:
- type: markdown - type: markdown

View file

@ -1,13 +1,14 @@
name: Bug Report name: Bug Report
description: Report a bug description: Report a bug
title: "bug: " title: 'bug: '
labels: [bug] labels: [bug]
body: body:
- type: checkboxes - type: checkboxes
attributes: attributes:
label: Prerequisites label: Prerequisites
options: options:
- label: I have searched [existing - label:
I have searched [existing
issues](https://github.com/barrettruth/pending.nvim/issues) issues](https://github.com/barrettruth/pending.nvim/issues)
required: true required: true
- label: I have updated to the latest version - label: I have updated to the latest version
@ -15,16 +16,16 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: "Neovim version" label: 'Neovim version'
description: "Output of `nvim --version`" description: 'Output of `nvim --version`'
render: text render: text
validations: validations:
required: true required: true
- type: input - type: input
attributes: attributes:
label: "Operating system" label: 'Operating system'
placeholder: "e.g. Arch Linux, macOS 15, Ubuntu 24.04" placeholder: 'e.g. Arch Linux, macOS 15, Ubuntu 24.04'
validations: validations:
required: true required: true
@ -48,8 +49,8 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: "Health check" label: 'Health check'
description: "Output of `:checkhealth task`" description: 'Output of `:checkhealth task`'
render: text render: text
- type: textarea - type: textarea

View file

@ -1,13 +1,14 @@
name: Feature Request name: Feature Request
description: Suggest a feature description: Suggest a feature
title: "feat: " title: 'feat: '
labels: [enhancement] labels: [enhancement]
body: body:
- type: checkboxes - type: checkboxes
attributes: attributes:
label: Prerequisites label: Prerequisites
options: options:
- label: I have searched [existing - label:
I have searched [existing
issues](https://github.com/barrettruth/pending.nvim/issues) issues](https://github.com/barrettruth/pending.nvim/issues)
required: true required: true

View file

@ -3,7 +3,7 @@ name: luarocks
on: on:
push: push:
tags: tags:
- "v*" - 'v*'
jobs: jobs:
quality: quality:

143
README.md
View file

@ -2,30 +2,145 @@
Edit tasks like text. `:w` saves them. Edit tasks like text. `:w` saves them.
<!-- insert preview --> A buffer-centric task manager for Neovim. Tasks live in a plain buffer — add
with `o`, delete with `dd`, reorder with `dd`/`p`, rename by editing. Write the
buffer and the diff is computed against a JSON store. No UI chrome, no floating
windows, no abstractions between you and your tasks.
## Requirements ## How it works
- Neovim 0.10+ ```
- (Optionally) `curl` and `openssl` for Google Calendar and Google Task sync School
! Read chapter 5 Feb 28
Submit homework Feb 25
## Installation Errands
Buy groceries Mar 01
Clean apartment
```
Install with your package manager of choice or via Category headers sit at column 0. Tasks are indented below them. `!` marks
[luarocks](https://luarocks.org/modules/barrettruth/pending.nvim): priority. Due dates appear as right-aligned virtual text. Done tasks get
strikethrough. Everything you see is editable buffer text — the IDs are
concealed, and metadata is parsed from inline syntax on save.
## Install
``` ```
luarocks install pending.nvim luarocks install pending.nvim
``` ```
**lazy.nvim:**
```lua
{ 'barrettruth/pending.nvim' }
```
Requires Neovim 0.10+. No external dependencies for local use. Google Calendar
sync requires `curl` and `openssl`.
## Usage
`:Pending` opens the task buffer. From there, it's just vim:
| Key | Action |
| --------- | ------------------------------- |
| `o` / `O` | Add a new task |
| `dd` | Delete a task (on `:w`) |
| `p` | Paste (duplicates get new IDs) |
| `:w` | Save all changes |
| `<CR>` | Toggle complete (immediate) |
| `<Tab>` | Switch category / priority view |
| `g?` | Show keybind help |
### Inline metadata
Type metadata tokens at the end of a task line before saving:
```
Buy milk due:2026-03-15 cat:Errands
```
On `:w`, the date and category are extracted. The description becomes `Buy milk`,
the due date renders as virtual text, and the task moves under the `Errands`
header.
### Quick add
```vim
:Pending add Buy groceries due:2026-03-15
:Pending add School: Submit homework
```
### Archive
```vim
: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.pending` before the plugin loads:
```lua
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
date_syntax = 'due', -- inline token name (e.g. 'by' for by:2026-03-15)
}
```
All fields are optional. Absent keys use the defaults shown above.
## Google Calendar sync
One-way push of tasks with due dates to a dedicated Google Calendar as all-day
events.
```lua
vim.g.pending = {
gcal = {
calendar = 'Tasks',
credentials_path = '/path/to/client_secret.json',
},
}
```
```vim
:Pending sync
```
On first run, a browser window opens for OAuth consent. The refresh token is
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
The plugin defines `<Plug>` mappings for custom keybinds:
```lua
vim.keymap.set('n', '<leader>t', '<Plug>(pending-open)')
vim.keymap.set('n', '<leader>T', '<Plug>(pending-toggle)')
```
| Plug mapping | Action |
| -------------------------- | -------------------- |
| `<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')/pending/tasks.json`. The schema is
versioned and forward-compatible — unknown fields are preserved on round-trip.
## Documentation ## Documentation
```vim ```vim
:help pending.nvim :checkhealth pending
``` ```
## Acknowledgements
- [dooing](https://github.com/atiladefreitas/dooing)
- [todo-comments.nvim](https://github.com/folke/todo-comments.nvim)
- [todotxt.nvim](https://github.com/arnarg/todotxt.nvim)