TODO items, logging, repeaters and priorities
Table of Contents
- 1. How to use this file
- 2. Keys in this file
- 3. Keywords: the basics
- 4. Logging state changes
- 5. Repeating tasks
- 6. Dependencies
- 7. Progress: statistics cookies
- 8. Tags that follow the state (todo_state_tags_triggers)
- 9. Reacting to state changes (autocmds)
- 10. Priorities
- 11. Finding TODO items
- 12. Further reading
1. How to use this file
This file is a hands-on course on TODO items in org.nvim: keywords and states, logging, repeating tasks, habits, dependencies, progress cookies, tag triggers and priorities. Every top-level heading covers one topic and goes from simple to advanced.
Start Neovim from the root of the repository with the bundled init file, so nothing touches your own configuration or notes:
nvim -u examples/minimal_init.lua examples/04-todo.org
What that init file sets up (read examples/minimal_init.lua):
<leader>is<Space>, so<prefix>(the default<leader>o) is<Space>o. Everywhere below,<prefix>ameans<Space>oa.agenda_filesare all theexamples/*.orgfiles, so the entries of this file show up in the agenda (<prefix>a).enforce_todo_dependencies = true: a task can't be marked DONE while it has open subtasks (see Dependencies).- Captures go to a scratch directory, never into this folder.
How to move around:
- The file opens folded (
#+STARTUP: overview).<Tab>on a heading opens it,<S-Tab>cycles the whole buffer. uundoes anything.git checkout examples/04-todo.orgrestores the original file when you are done experimenting.g?lists every key of the buffer. The usual Emacs keys work too (C-c C-tis written<C-c><C-t>here).- Try: marks an exercise, Expect: says exactly what you should see.
Times like
[2026-09-28 Mon 15:08]stand for "the date and time when you press the key". - Lines starting with
#and a space are Org comments: notes for you, never exported.
Some options can only be set from Lua. Where an exercise needs one, there
is a small lua source block: put the cursor in it, press <C-c><C-c> and
answer y. Lua blocks run inside Neovim, so the change lasts until you quit
(restart Neovim to go back to the defaults).
1.1. The settings of this file
The lines at the very top of this file configure it:
#+STARTUP: overview logdone #+TODO: TODO(t) NEXT(n) WAITING(w@/!) | DONE(d!) CANCELLED(c@) #+SEQ_TODO: REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f!) #+PRIORITIES: A E C
logdoneadds aCLOSED:timestamp when a task is done.- Two keyword sequences: a GTD-style workflow and a bug-tracking workflow.
- Priorities go from
A(highest) toE(lowest);Cis the default.
Each of these is explained in its own section below.
2. Keys in this file
| Key | Emacs key | What it does |
|---|---|---|
cit / ciT |
next / previous TODO state | |
<S-Right> <S-Left> |
same | same, cursor on a headline |
<C-c><C-t>, <prefix>S |
C-c C-t |
pick a state (fast keys) |
4<C-c><C-t> |
C-u C-c C-t |
change state, force a note |
<C-S-Right> <C-S-Left> |
same | next / previous keyword set |
<M-S-CR>, <prefix>it |
<C-S-CR> |
insert a new TODO heading |
<C-c><C-z> |
C-c C-z |
add a note to the entry |
<C-c><C-x>o |
C-c C-x o |
toggle the ORDERED property |
<prefix># |
C-c # |
update statistics cookies |
<S-Up> <S-Down> |
same | raise / lower the priority |
<C-a> <C-x> |
same, cursor on [#A] |
|
<prefix>, |
C-c , |
set the priority with a key |
<prefix>/ then t |
C-c / t |
sparse tree of open TODOs |
<prefix>a then t |
C-c a t |
agenda: global TODO list |
In the *Org Note* window that opens for notes: <C-c><C-c> stores the
note, <C-c><C-k> cancels it.
3. Keywords: the basics
3.1. What makes a heading a TODO item
A heading is a TODO item when its first word is one of the file's TODO keywords. Keywords are case sensitive and must come right after the stars and a space.
Keywords after the | in the definition are "done" states (here DONE and
CANCELLED, FIXED), the others are "todo" (open) states. The agenda,
sparse trees and dependencies all use this distinction.
Try: put the cursor on "Todo lower-case keywords are just text" and press
<S-Right>.
Expect: the heading becomes TODO Todo lower-case keywords are just
text: the keyword is added in front, the old word stays part of the title.
3.1.1. TODO Buy printer paper
3.1.2. NEXT Call the plumber
3.1.3. WAITING Parts for the bike
3.1.4. DONE Renew the library card
3.1.5. Todo lower-case keywords are just text
3.1.6. Remember: TODO in the middle of a title is just text
3.1.7. TODOLIST is one word, not the keyword TODO
3.2. Cycling through states with cit / ciT and S-Right / S-Left
cit (or <S-Right> with the cursor on a headline) moves to the next
keyword, ciT (or <S-Left>) to the previous one. Like Emacs, these
walk every keyword of every sequence of the file in order, with "no
keyword" before the first and after the last:
(none) → TODO → NEXT → WAITING → DONE → CANCELLED
→ REPORT → BUG → KNOWNCAUSE → FIXED → (none)
Entering some states logs something (see 4):
- entering
WAITINGorCANCELLEDopens the*Org Note*window for a note. Type a note and press<C-c><C-c>, or press<C-c><C-k>to skip it (the state still changes, nothing is logged); - entering
DONEorFIXEDadds aCLOSED:line and a log line.
3.2.1. Cycle me
Try: on "Cycle me", press cit twice.
Expect: the heading reads NEXT Cycle me (first TODO, then NEXT).
Try: press ciT twice.
Expect: back to Cycle me with no keyword.
Try: press ciT once more.
Expect: FIXED Cycle me (going backwards from "no keyword" wraps to
the last keyword), with a CLOSED: [...] line and a line
- State "FIXED" from "" [2026-09-28 Mon 15:08] under it
("" because there was no previous keyword).
3.3. Fast selection with <prefix>S and C-c C-t
The letters in parentheses in #+TODO: TODO(t) NEXT(n) ... are fast
selection keys. <C-c><C-t> (or <prefix>S) opens a small menu with
the keywords of each sequence and their keys; press one key to jump
straight to that state, or <Space> to remove the keyword. <Esc>
cancels. The exercises below use <C-c><C-t>; <prefix>S works the same.
| Key | State | Key | State |
|---|---|---|---|
t |
TODO | r |
REPORT |
n |
NEXT | b |
BUG |
w |
WAITING | k |
KNOWNCAUSE |
d |
DONE | f |
FIXED |
c |
CANCELLED |
3.3.1. TODO Water the office plants
Try: on "Water the office plants", press <C-c><C-t> then n.
Expect: NEXT Water the office plants.
Try: press <C-c><C-t> then d.
Expect: DONE Water the office plants, followed by
CLOSED: [2026-09-28 Mon 15:08] and
- State "DONE" from "NEXT" [2026-09-28 Mon 15:08].
Try: press <C-c><C-t> then <Space>.
Expect: the keyword is gone and so is the CLOSED: line (the log line
stays: it is history).
3.3.2. A count picks the keyword by number
<C-c><C-t> takes a count like Emacs' prefix argument. A plain number
N jumps to the N-th keyword of the file (in the order shown above), but
4, 16 and 64 mean C-u, C-u C-u and C-u C-u C-u:
| Count | Emacs | Effect |
|---|---|---|
2 |
C-2 C-c C-t |
the 2nd keyword (NEXT) |
4 |
C-u C-c C-t |
change the state and always ask for a note |
16 |
C-u C-u ... |
switch to the first keyword of the next set |
64 |
C-u C-u C-u |
change the state even if the task is blocked |
3.3.3. Without fast keys, C-c C-t cycles inside one sequence
When no keyword has a key (or with use_fast_todo_selection = false),
<C-c><C-t> cycles within the current sequence only: after its last
keyword the heading has no keyword, and the next <C-c><C-t> starts that
same sequence again. Run this block to switch fast selection off for this
session:
require("org.config").opts.use_fast_todo_selection = false
- BUG The login page is slow
Try: run the block above (
<C-c><C-c>inside it, answery), then on "The login page is slow" press<C-c><C-t>three times. Expect:KNOWNCAUSE, thenFIXED(withCLOSED:and a log line), then no keyword at all. One more<C-c><C-t>givesREPORT: the bug sequence starts again, it does not jump toTODO.
3.4. Several keyword sequences
A file (or your config) can define several sequences. Here the first is a personal workflow and the second tracks bugs:
#+TODO: TODO(t) NEXT(n) WAITING(w@/!) | DONE(d!) CANCELLED(c@) #+SEQ_TODO: REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f!)
#+SEQ_TODO: is a synonym of #+TODO:. Each line is one sequence; you can
also put several on separate #+TODO: lines. <C-S-Right> /
<C-S-Left> jump to the first keyword of the next / previous sequence
(this switch is never logged).
3.4.1. REPORT Crash when saving an empty file
Try: on "Crash when saving an empty file", press <C-S-Right>.
Expect: TODO Crash when saving an empty file and the message
Keyword-Set 1/2: TODO NEXT WAITING DONE CANCELLED. Press it again to
get REPORT back.
3.4.2. The same sequences in your config
In Lua the same definition is a list of strings, one per sequence. File lines replace the configured keywords for that file.
require("org").setup({
todo_keywords = {
"TODO(t) NEXT(n) WAITING(w@/!) | DONE(d!) CANCELLED(c@)",
"REPORT(r) BUG(b) KNOWNCAUSE(k) | FIXED(f!)",
},
})
Without any |, the last keyword of a sequence is its done state:
#+TODO: TODO DOING DONE has DONE as done state.
3.5. Type keywords (#+TYP_TODO)
A type sequence lists kinds of tasks (often people) instead of steps:
#+TYP_TODO: FRED SARA LUCY | DELEGATED. Then <C-c><C-t> goes from no
keyword to FRED, from any person straight to DELEGATED (the task is
done, whoever did it), and from DELEGATED back to no keyword. Pressing
<C-c><C-t> several times in a row (without moving or editing in between)
walks the names instead: FRED, SARA, LUCY, …
Type sequences come first in the list of keywords (Emacs puts
#+TYP_TODO: before #+TODO: and #+SEQ_TODO:), and <C-c><C-t> only
cycles when no keyword has a fast key, so this exercise switches fast
selection off first.
require("org.config").opts.use_fast_todo_selection = false
3.5.1. Review the budget
Try: delete the # and the space in front of #+TYP_TODO: above,
press <C-c><C-c> on that line (message "Local setup has been
refreshed"), run the Lua block, then on "Review the budget" press
<C-c><C-t>.
Expect: FRED Review the budget.
Try: press $ (the cursor moves, so the next one is a new command), then
press <C-c><C-t> once.
Expect: DELEGATED Review the budget with a CLOSED: line: from a
type it jumps straight to the done state.
Try: press <C-c><C-t> to clear it, then <C-c><C-t> three times
without moving.
Expect: FRED, then SARA, then LUCY.
When you are done, put the # and a space back in front of the
#+TYP_TODO: line and press <C-c><C-c> on it again (or u until it is
back).
3.6. Inserting new TODO headings
<M-S-CR>(Emacs<C-S-CR>) on a heading inserts a sibling TODO heading after its subtree, using the first keyword of the first sequence (TODO).<prefix>itdoes the same from Normal mode.<M-CR>/<prefix>ihinsert a plain heading; add a keyword later.
3.6.1. TODO Pack the suitcase
Try: on "Pack the suitcase", press <M-S-CR> and type Book a taxi,
then <Esc>.
Expect: a new heading TODO Book a taxi after the text of "Pack the
suitcase" (a new heading always goes after the whole subtree).
4. Logging state changes
4.1. CLOSED timestamps (logdone)
With logdone (on the #+STARTUP: line of this file, or log_done =
"time" in your config), entering a done state adds a CLOSED: line right
under the heading. Going back to an open state removes it again.
4.1.1. TODO Send the invoice
Try: on "Send the invoice", press <C-c><C-t> then d.
Expect: three lines:
*** DONE Send the invoice CLOSED: [2026-09-28 Mon 15:08] - State "DONE" from "TODO" [2026-09-28 Mon 15:08]
The CLOSED: line comes from logdone; the - State line comes from the
! in DONE(d!), see the next section.
Try: press <C-c><C-t> then t.
Expect: TODO Send the invoice; the CLOSED: line is gone (the
state line stays).
4.1.2. DONE Archived last week
Other #+STARTUP: words for the same setting:
| Word | Effect when a task becomes done |
|---|---|
logdone |
add CLOSED: [timestamp] |
lognotedone |
add CLOSED: and ask for a closing note |
nologdone |
nothing (unless the keyword itself logs) |
Like Emacs, CLOSED: is only added when logdone (or log_done) is on:
a ! on the DONE keyword alone gives the - State line but no
CLOSED:. closed_keep_when_no_todo = true keeps CLOSED: when the
keyword is removed completely.
4.2. Timestamps (!) and notes (@) per keyword
In a keyword definition, the part in parentheses is (key enter/leave):
| Spec | Meaning |
|---|---|
DONE(d!) |
key d, log a timestamp when entering DONE |
CANCELLED(c@) |
key c, ask for a note when entering CANCELLED |
WAITING(w@/!) |
note when entering WAITING, timestamp when leaving it |
NEXT(n) |
key n, nothing logged |
X(/!) |
no key, only log the time when leaving X |
A logged state change is one list item under the heading:
- State "WAITING" from "TODO" [2026-09-22 Tue 09:12] \\ Emailed the landlord about the heating.
The \\ ends the heading of the item; the note follows, indented.
4.2.1. TODO Get the car repaired
Try: on "Get the car repaired", press <C-c><C-t> then w. In the
*Org Note* window type Garage opens on Monday and press <C-c><C-c>.
Expect:
*** WAITING Get the car repaired - State "WAITING" from "TODO" [2026-09-28 Mon 15:08] \\ Garage opens on Monday
Try: now press <C-c><C-t> then n.
Expect: a new line on top of the first one (newest first):
- State "NEXT" from "WAITING" [2026-09-28 Mon 15:08]. There was
no note: leaving WAITING only logs the time (/!).
4.2.2. TODO Old gym membership
Try: press <C-c><C-t> then c, and in the note window press
<C-c><C-k> (cancel).
Expect: CANCELLED Old gym membership with a CLOSED: line, but no
- State line: a cancelled note logs nothing, the state change stays.
4.2.3. WAITING Reply from the landlord
- State "WAITING" from "TODO"
Emailed the landlord about the heating.
4.3. Forcing or skipping the note
4<C-c><C-t>(EmacsC-u C-c C-t) asks for a note for this change even if the keyword has no@.:Org todo_without_note(EmacsC-0 C-c C-t) changes the state and records a timestamp where a note would be asked.<C-c><C-z>adds a free-form note to the entry at any time.
In the note window, lines starting with # and a space are dropped, so
you can keep reminders there.
4.3.1. TODO Plan the team dinner
Try: on "Plan the team dinner", press 4<C-c><C-t> then n, type
Waiting for the head count and press <C-c><C-c>.
Expect: NEXT Plan the team dinner and a log item
- State "NEXT" from "TODO" [...] \\ followed by the note.
Try: press <C-c><C-z>, type Booked Luigi's for Friday,
<C-c><C-c>.
Expect: a new item on top:
- Note taken on [2026-09-28 Mon 15:08] \\ and your text below it.
Try: type :Org todo_without_note and press <CR>, then w.
Expect: WAITING with a line
- State "WAITING" from "NEXT" [...] and no note window.
4.4. Logging into a drawer (LOG_INTO_DRAWER)
By default the log items go directly under the heading. They can go into a drawer instead, which folds away:
:LOG_INTO_DRAWER: ton an entry (inherited by its children) uses the:LOGBOOK:drawer;:LOG_INTO_DRAWER: NOTESuses a drawer called:NOTES:;nilturns it off again for a subtree;#+STARTUP: logdrawer/nologdrawerdoes it for the whole file;log_into_drawer = true(or a drawer name) in your config does it everywhere.
4.4.1. Tasks that log into LOGBOOK
- TODO Order new business cards
Try: on "Order new business cards", press
<C-c><C-t>thend. Expect: below the heading, theCLOSED:line, then a new drawer: a line:LOGBOOK:, the line- State "DONE" from "TODO" [...]and a line:END:.<Tab>on the:LOGBOOK:line folds the drawer. - TODO Update the website
Try: press
<C-c><C-t>thenw, type a note,<C-c><C-c>. Expect: the new item appears at the top of the existing:LOGBOOK:(newest first,log_states_order_reversed = true, like Emacs;#+STARTUP: nologstatesreversedappends at the end instead).
4.5. Logging per subtree (LOGGING property)
The LOGGING property overrides logging for a whole subtree (it is
inherited). Its value is a list of words:
nilturns logging off completely (noCLOSED:, no- Statelines);logdone,lognotedone,nologdone,logrepeat,lognoterepeat,nologrepeatset done/repeat logging;- keyword specs like
WAITING(@) DONE(!)replace the flags of the keyword definitions. Keywords not listed log nothing here.
4.5.1. Quiet area
4.5.2. Notes when done
5. Repeating tasks
5.1. Repeaters: , + and .+
A SCHEDULED: or DEADLINE: timestamp (or any active timestamp in the
entry) can carry a repeater. When the task is marked done, org.nvim moves
the date forward and puts the task back into the first state of its
sequence (TODO), instead of leaving it done.
| Repeater | Meaning | Typical use |
|---|---|---|
+1w |
shift by 1 week, once | pay the rent |
++1w |
shift by weeks until the date is in the future | weekly meeting |
| (the weekday stays the same) | ||
.+2d |
shift to 2 days after today | water plants |
Units: h hours, d days, w weeks, m months, y years. Months keep
the day of the month and roll over like Emacs: January 31 with +1m
becomes March 3.
The change is logged (log_repeat = "time", the default, or
#+STARTUP: logrepeat): a - State "DONE" from "TODO" line and a
LAST_REPEAT property with the time. nologrepeat / lognoterepeat
switch this off / ask for a note. No CLOSED: line is added.
The expected dates below assume you do the exercises on Mon 2026-09-28.
On another day, + gives the same result; for ++ and .+ the result is
computed from your today.
5.1.1. TODO Pay the rent
Try: on "Pay the rent", press <C-c><C-t> then d.
Expect: the heading is TODO again (not DONE), the deadline shows
2026-11-01 Sun +1m, and under it:
:PROPERTIES: :LAST_REPEAT: [2026-09-28 Mon 15:08] :END: - State "DONE" from "TODO" [2026-09-28 Mon 15:08]
5.1.2. TODO Weekly team meeting notes
Try: mark "Weekly team meeting notes" done.
Expect: SCHEDULED: shows 2026-10-05 Mon ++1w: three weeks were
missed, and ++ jumped over all of them to the first Monday after today.
A plain +1w would have given 2026-09-14, still in the past.
5.1.3. TODO Water the plants
Try: mark "Water the plants" done.
Expect: SCHEDULED: shows 2026-10-01 Thu .+3d: three days after
today, no matter when it was last scheduled.
5.1.4. TODO Submit the monthly report
Try: mark it done.
Expect: DEADLINE: shows 2026-10-30 Fri +1m -5d (the warning period
stays).
5.1.5. TODO Renew the passport
Try: mark it done.
Expect: both dates move one year: 2027-10-12 Tue +1y and
2027-11-15 Mon +1y (org.nvim writes DEADLINE: first on the line).
5.1.6. TODO Stretching break
Try: mark it done.
Expect: 2026-09-28 Mon 12:00 +2h, two hours later on the same day.
5.1.7. TODO Book club
Meets on .
Try: mark it done.
Expect: the timestamp in the body becomes 2026-10-13 Tue 19:00 +1w:
plain active timestamps with a repeater shift too.
5.2. Choosing the state after a repeat (REPEAT_TO_STATE)
The REPEAT_TO_STATE property (or todo_repeat_to_state in your config)
picks the state a repeating task returns to. todo_repeat_to_state = true
returns to the state it had before it was marked done.
5.2.1. NEXT Stand-up notes
Try: mark it done.
Expect: NEXT Stand-up notes (not TODO), scheduled
2026-09-29 Tue +1d, and a LAST_REPEAT line in the drawer.
5.3. Finishing a repeating task for good
Marking a repeating task done always repeats it. To stop the series,
remove the repeater, or use :Org todo_cancel_repeaters (Emacs
C-- 1 C-c C-t): it sets every repeater of the entry to 0 and then
changes the state, so the task stays done.
5.3.1. TODO Physiotherapy exercises
Try: type :Org todo_cancel_repeaters and press <CR>, then d.
Expect: DONE Physiotherapy exercises, and the planning line reads
CLOSED: [2026-09-28 Mon 15:08] SCHEDULED: followed by
2026-09-29 Tue .+0d in angle brackets: the task no longer repeats.
5.4. Habits
A habit is a repeating task with :STYLE: habit. It is scheduled with a
.+ repeater, optionally with a maximum interval (.+2d/4d: at least
every 2 days, at most every 4). The agenda draws a consistency graph from
the past done dates of the entry (the - State "DONE" lines):
| Color | Meaning |
|---|---|
| blue | before the scheduled date: not due yet |
| green | due, still within the interval |
| yellow | the last day of the interval |
| red | overdue |
* |
a day the habit was done (! marks today) |
Habits show only in today's agenda, and only in the agenda (not in this buffer). Habits log into a drawer so the history stays folded.
5.4.1. TODO Go for a run
Try: press <prefix>a then a (week agenda), go to today.
Expect: under today, a line todo: TODO Go for a run followed by
a graph starting at column 40 (agenda.habits.graph_column), 21 days back
and 7 ahead: * on the five days of the :LOGBOOK: and ! on today,
colored as in the table above. On a later day the last days turn red: the
habit is overdue.
Try: back here, mark the habit done, then refresh the agenda (r).
Expect: SCHEDULED: becomes two days from today, and a new
- State "DONE" line is at the top of the :LOGBOOK:. The habit is gone
from today's agenda: it is not due again before that date (habits are only
shown for today, agenda.habits.show_habits_only_for_today).
6. Dependencies
6.1. Children block their parent
With enforce_todo_dependencies = true (set in examples/minimal_init.lua)
a task can't be marked done while any of its child tasks is still open.
Children without a keyword don't count.
6.1.1. TODO Move to the new flat
Try: on "Move to the new flat", press <C-c><C-t> then d.
Expect: the message
TODO state change from TODO to DONE blocked (by has unfinished child
tasks) and the heading is unchanged.
Try: mark "Hire the movers" done, then "Move to the new flat". Expect: both are DONE now.
Try: on a blocked parent press 64<C-c><C-t> (Emacs C-u C-u C-u C-c
C-t) and pick d.
Expect: the change goes through even though children are open.
6.2. Ordered subtasks (ORDERED)
With :ORDERED: t on the parent, each child can only be marked done once
all the siblings before it are done. <C-c><C-x>o toggles the property
(message "Subtasks must be completed in sequence").
6.2.1. TODO Bake bread
Try: mark "Bake for 40 minutes" done.
Expect: the message
TODO state change from TODO to DONE blocked (by previous sibling
(ORDERED) is not done: Mix the dough): it names the first open sibling.
Try: mark "Mix the dough" done, then "Let it rise", then "Bake for 40 minutes", then "Bake bread". Expect: each one works in this order.
Try: on "Bake bread", press <C-c><C-x>o.
Expect: the :ORDERED: line disappears and the message
"Subtasks can be completed in arbitrary order".
6.3. The BLOCKED special property and NOBLOCKING
The special property BLOCKED is t for an open task that can't be
marked done right now, empty otherwise. Use it in searches, e.g. the
agenda match BLOCKED"t"= (<prefix>a then m). A :NOBLOCKING: t
property switches blocking off for one entry.
6.3.1. TODO Launch the website
Try: mark "Launch the website" done.
Expect: it works although its child is open, thanks to NOBLOCKING.
6.4. Checkboxes can block too
enforce_todo_checkbox_dependencies = true also blocks a task while its
body has unchecked ([ ]) or partial ([-]) checkboxes. It is off by
default; run this block to switch it on for this session:
require("org.config").opts.enforce_todo_checkbox_dependencies = true
6.4.1. TODO Pack for the trip [1/3]
[X]Passport[ ]Charger[ ]Toothbrush
Try: run the block, then mark "Pack for the trip" done.
Expect: ... blocked (by contained checkboxes).
Try: check the other two boxes with <C-Space> on each, then mark it
done.
Expect: the cookie shows [3/3] and the task becomes DONE.
7. Progress: statistics cookies
7.1. Counting child tasks: [/] and [%]
A [/] or [%] cookie anywhere in a heading shows how many of its direct
children with a TODO keyword are done. It is updated whenever a child
changes state; <prefix># (<C-c>#) or <C-c><C-c> on the cookie
updates it by hand, and 4<prefix># updates every cookie of the buffer.
7.1.1. TODO Organise the conference [1/4]
Done states all count as done, CANCELLED included.
Try: on the cookie [1/4] press <C-c><C-c>.
Expect: [2/4]: the cookie was out of date on purpose (CANCELLED is a
done state too).
Try: mark "Invite the speakers" done.
Expect: [3/4].
7.1.2. TODO Renovate the kitchen [0%]
Try: mark the children done one by one.
Expect: [33%], [66%], [100%] (percentages are rounded down).
7.1.3. Both cookies on one heading [/] [%]
Try: press <C-c><C-c> on either cookie.
Expect: [1/2] [50%].
7.1.4. A cookie on a leaf [/]
Try: with the cursor on this heading, press <prefix>#.
Expect: [0/0]: no children, nothing to count.
7.2. Counting the whole subtree (COOKIE_DATA recursive)
By default only direct children count. :COOKIE_DATA: recursive on the
heading counts every TODO of its subtree; the option
hierarchical_todo_statistics = false does it for all cookies.
7.2.1. TODO Release version 2.0 [0/5]
Try: press <C-c><C-c> on [0/5].
Expect: [1/5] (one of the five is done).
Try: mark "Linux" done.
Expect: [2/5]; "Test on all platforms" can now be marked done too.
7.3. Checkboxes vs TODO children (COOKIE_DATA todo / checkbox)
When the body of a heading has checkboxes, its cookie counts the
checkboxes instead (see 03-lists.org). :COOKIE_DATA: todo forces
counting child tasks, :COOKIE_DATA: checkbox forces checkboxes.
7.3.1. TODO Prepare the talk [0/2]
[X]Pick a title[X]Write the abstract[X]Book the room
Try: press <C-c><C-c> on the cookie.
Expect: still [0/2]: the two child tasks are counted, not the three
checked boxes. Delete the :COOKIE_DATA: line (and the now empty drawer),
press <C-c><C-c> on the cookie again: [3/3].
7.4. Automatic parent state (after_todo_statistics_hooks)
Emacs users often add org-summary-todo, which marks the parent DONE when
all its children are done. In org.nvim this is the Lua option
after_todo_statistics_hooks. Run the block to try it:
require("org.config").opts.after_todo_statistics_hooks = {
function(n_done, n_not_done, target)
require("org.todo").change_state(target,
n_not_done == 0 and "DONE" or "TODO", { no_log = true })
end,
}
7.4.1. TODO Weekend chores [0/2]
Try: run the block, then mark "Vacuum" and "Laundry" done.
Expect: after the second one, the parent turns into
DONE Weekend chores [2/2] by itself. Set a child back to TODO and
the parent goes back to TODO.
require("org.config").opts.after_todo_statistics_hooks = {}
8. Tags that follow the state (todo_state_tags_triggers)
todo_state_tags_triggers adds or removes tags when the state changes
(Emacs org-todo-state-tags-triggers). The keys are a keyword, "todo"
(any open state), "done" (any done state) or "" (no keyword); the
values map tags to true (add) or false (remove). The changes of the
keyword itself are applied first, then those of "todo" / "done", so a
"todo" entry that removes waiting would also undo WAITING's own
tag: that is why the block below names TODO and NEXT instead. It is a
Lua option; run the block to set it for this session:
require("org.config").opts.todo_state_tags_triggers = {
WAITING = { waiting = true },
CANCELLED = { cancelled = true },
TODO = { waiting = false, cancelled = false },
NEXT = { waiting = false, cancelled = false },
done = { waiting = false },
}
8.1. TODO Ask for the reimbursement
Try: run the block, then on "Ask for the reimbursement" press
<C-c><C-t> w (type any note, <C-c><C-c>).
Expect: the heading gets the tag :waiting: at the right margin.
Try: press <C-c><C-t> t.
Expect: the :waiting: tag is removed again.
Try: press <C-c><C-t> c (any note).
Expect: the tag :cancelled: is added.
9. Reacting to state changes (autocmds)
Every state change fires the User autocmd OrgTodoStateChange (Emacs
org-after-todo-state-change-hook); a repeating task marked done also
fires OrgTodoRepeat. ev.data has from, to, done, repeated,
bufnr and lnum.
vim.api.nvim_create_autocmd("User", {
pattern = "OrgTodoStateChange",
callback = function(ev)
local d = ev.data
vim.notify(("%s -> %s"):format(d.from or "none", d.to or "none"))
end,
})
9.1. TODO Watch the message line
Try: run the block, then press cit on "Watch the message line".
Expect: the message TODO -> NEXT.
10. Priorities
10.1. Priority cookies and the range
A priority is a cookie like [#A] right after the keyword (or right after
the stars when there is no keyword). By default the range is A (highest)
to C (lowest) and a heading without a cookie counts as B. This file
widens it with:
#+PRIORITIES: A E C
i.e. highest A, lowest E, default C. In your config:
priority_highest = "A", priority_lowest = "E",
priority_default = "C".
Priorities sort the agenda: in the global TODO list (<prefix>a t) the
tasks below come in the order A, B, C (the one without cookie), D. The
[#E] heading has no keyword, so it is not a TODO item and isn't listed.
10.1.1. TODO Fix the production outage
10.1.2. TODO Review the pull request
10.1.3. TODO Clean up the downloads folder
10.1.4. A heading without keyword can have a priority too
10.1.5. TODO No priority: treated as the default C
10.2. Changing it: S-Up / S-Down, C-a / C-x, <prefix>,
<S-Up>/<S-Down>on a headline raise / lower the priority. From no cookie, the first press sets the default (Chere). PastA(or pastE) the cookie is removed, and one more press in the same direction wraps around to the other end.<C-a>/<C-x>with the cursor on the[#B]cookie do the same.<prefix>,(<C-c>,) asks for a letter:atoeset it (upper or lower case),<Space>removes it.4<prefix>,(C-u C-c ,) and:Org priority_showshow the priority value Emacs sorts by: 1000 × (lowest − priority). HereEis the lowest, so[#A]is4000,[#C](and no cookie)2000.
10.2.1. TODO Call the insurance
Try: on "Call the insurance", press <S-Up>.
Expect: TODO [#C] Call the insurance (the default).
Try: press <S-Up> twice more, then once more.
Expect: [#B], [#A], then the cookie is removed (message "Priority
removed").
Try: press <S-Up> again.
Expect: [#E]: it wrapped around to the lowest priority.
10.2.2. TODO Order a new keyboard
Try: put the cursor on the B of [#B] and press <C-x>, then <C-a>
twice.
Expect: [#C], then [#B], then [#A].
Try: press <prefix>, then d.
Expect: [#D]. With <prefix>, then <Space> the cookie disappears.
<prefix>, then z says "Priority must be between A and E".
Try: press 4<prefix>,.
Expect: the message "Priority is 1000" for [#D] (1000 × (E − D)).
10.3. Numeric priorities
Priorities can also be numbers from 0 to 64, like Emacs:
#+PRIORITIES: 1 10 5 uses [#1] (highest) .. [#10] (lowest), default
[#5]. With a two-digit range, <prefix>, asks for the number in a
prompt.
10.3.1. TODO A task for numeric priorities
Try: change the header line of this file to #+PRIORITIES: 1 10 5,
press <C-c><C-c> on it, then on this heading press <prefix>,, type 3
and press <CR>.
Expect: TODO [#3] A task for numeric priorities.
Try: press <S-Down>, then <S-Up> twice.
Expect: [#4], then [#3], then [#2].
Put the header back to #+PRIORITIES: A E C (and <C-c><C-c> on it)
afterwards; with the numeric range, the letter cookies of this file are
out of range, and :Org lint reports them.
11. Finding TODO items
<prefix>/thent(Emacs<C-c>/ t): sparse tree of every open TODO in this buffer;Tasks for keywords, e.g.WAITING|NEXT.<prefix>athent: the global TODO list of all agenda files;Tasks for keywords. In the list,tchanges the state of the entry at point,,its priority.<prefix>athenm: a tags/property match, e.g.TODO"WAITING"= orPRIORITY"A", or =+work/NEXT(tag work, keyword NEXT).
See 10-sparse-trees.org and 09-agenda.org.
Try: press <prefix>/ then t.
Expect: the buffer folds so that only open TODO entries (and their
parents) are visible, highlighted. <C-c><C-c> removes the highlights.
Try: press <prefix>/ then T, type WAITING and <CR>.
Expect: only the WAITING entries of this file are shown.
12. Further reading
:h org-todo– keywords, logging,C-c C-tcounts:h org-logging-property– the LOGGING property:h org-todo-tags-triggersand:h org-todo-events– triggers, autocmds:h org-repeat– repeaters:h org-todo-dependenciesand:h org-todo-statistics:h org-priority(in the same section asorg-todo):h org-agenda-contents– habits in the agenda:h org-differences– what differs from Emacs Org- Related example files: 03-lists (checkboxes), 05-tags, 07-dates (scheduling), 09-agenda, 10-sparse-trees.