4
votes

I'd like to have a shortcut to change the state of a TODO straight to DONE (and back) with the CLOSED time tag folded when I'm at any position on the line (not like speed-keys requiring to be before the first asterisk).

Currently I have 2 options:

  1. C-c C-t d TAB (with org-use-fast-todo-selection set to t, d is my DONE state shortcut and TAB hides the subtree), or

  2. S-right TAB (using org-shiftright, DONE is the first state after TODO).

Can you please help me bind this to a single shortcut like C-c C-d. Please note I have more states than TODO and DONE but this shortcut should just toggle between those too.

Bonus points: Additional command that also starts a new TODO item on the next line at the same level as the previous task.

Thank you very much!

2
Have a look at worf. cwd will change state to DONE, and wta will add a new TODO.abo-abo
If you enable the "speed keys", then you'll have as well "t d" when in first column of a task.fniessen
You'd be better to use a C-c <letter> binding like C-c d, as all such bindings are reserved for end-users, whereas C-c C-d could end up clashing with something else.phils

2 Answers

7
votes

Not sure what you mean by "time tag", but based on the workflows you listed, the following command should do what you want:

(defun org-toggle-todo-and-fold ()
  (interactive)
  (save-excursion
    (org-back-to-heading t) ;; Make sure command works even if point is
                            ;; below target heading
    (cond ((looking-at "\*+ TODO")
           (org-todo "DONE")
           (hide-subtree))
          ((looking-at "\*+ DONE")
           (org-todo "TODO")
           (hide-subtree))
          (t (message "Can only toggle between TODO and DONE.")))))

(define-key org-mode-map (kbd "C-c C-d") 'org-toggle-todo-and-fold)

As for inserting new TODO items on the same level as the current task, org-mode has built-in commands for this. You can read up on them by doing

  • C-h f org-insert-todo-heading RET
  • C-h f org-insert-todo-heading-respect-content RET
4
votes

A simple toggle command could look like the following

(defun my-org-todo-toggle ()
  (interactive)
  (let ((state (org-get-todo-state))
        post-command-hook)
    (if (string= state "TODO")
        (org-todo "DONE")
      (org-todo "TODO"))
    (run-hooks 'post-command-hook)
    (org-flag-subtree t)))

(define-key org-mode-map (kbd "C-c C-d") 'my-org-todo-toggle)

The post-command-hook is a bit tricky, but is required since otherwise notes are added (and revealed) after the command, which makes the time log partially unfolded.

In order to start a new TODO item, you might have a look at the existing org-insert-todo-heading (bound to <M-S-return>)