Let's discuss low-level command that you need. org-todo
cycles the headline your cursor is on through TODO states. org-toggle-item
turns headlines into lists, org-toggle-heading
turns lists into headlines. In standard Emacs they are mapped to C-c C-t, C-c -, C-c * respectively.
org-todo
doesn't work on regions, but it would be cool if we could put a TODO state on every heading that doesn't have a TODO (and doesn't have other states, including DONE). This is how we would do that.
(defun outline-to-checkboxes (from to)
(interactive "r")
(save-excursion
(save-restriction
(with-undo-collapse
(narrow-to-region from to)
(end-of-buffer)
(while (outline-previous-heading)
(when (null (org-get-todo-state))
(org-todo "TODO")))))))
The reason I go to the end of buffer and apply outline-previous-heading
instead of going from top forward is described in a StackOverflow answer: while
always calls the first argument at least once, and if you started at the beginning of your buffer starts with an Org heading, you'll skip it.
with-undo-collapse
is a custom macro that allows you to undo the whole change in one action (follow the link to get the code).
Unfortunately, due to a bug in org-toggle-list
, changing headings to a list with checkboxes programmatically is difficult, so just go with the regex approach in Jesse's answer.