1

I have two files in my agenda: current.org and later.org. My setup has it so that current.org has all active tasks (state TODO) and later.org has all inactive ones (state LATER). Right now, in my agenda I have to change the state of a task using C-c C-t and then refile it to one file or the other using C-c C-w depending on the new state.

Is there a way to write a command so that in org-agenda I can change the state of a task and refile it to a different file in one go?

3
  • I'm not sure I understand. Your agenda has TODO and LATER tasks and you want a command that changes the state and refiles the entry conditionally. For example, if the entry is set to LATER you want the command to change it to TODO and refile it to current.org. If the entry is set to TODO you want the command to change it to LATER and refile it to later.org. Correct?
    – jagrg
    Commented Mar 11, 2019 at 22:25
  • @jagrg, yes exactly.
    – Tohiko
    Commented Mar 12, 2019 at 8:21
  • 1
    Do you need the LATER state, or is it enough to know which items are in the current.org file and which are in the later.org file? You can configure your agenda to show two lists of todos, one for each file. That way refiling an item from current.org to later.org would cause the item to switch to the later list, and you wouldn't need to worry about changing the state at all.
    – Tyler
    Commented Mar 12, 2019 at 21:00

1 Answer 1

1

Let me preface this with letting you know that I don't use org-mode for an agenda, so I have no experience with it; this is just an idea.

If you use C-c C-t to cycle states from TODO to LATER and have it automatically refile the entry into your later.org file, I could foresee this being an issue if you are trying to cycle past LATER, to DONE (or another state) because, as soon as it hits LATER, the entry would move to your other file and you would then have to swap to that other file to continue cycling.

To circumvent that issue, I would create a dedicated keybinding to call a custom function that would do the following:

  1. Toggle the state of the entry directly to LATER (regardless of what other states you have defined) by calling the pre-defined function org-todo with the ARG, later, then
  2. Call the function org-refile

Note: org-todo without any arguments simply cycles through states (which is what C-c C-t does by default), while including an ARG of a specific state sets the entry to the specified state.

Note2: org-refile is what C-c C-w does by default


AHA! I think I've managed to write some code to do exactly what you're looking to do!

Here is an example of what this might look like in elisp for your configuration file (note: I'm brand new to lisp, so if someone knows a better way to write/format this, please chime in):

Change the keybinding to anything you like (where I wrote "C-c c")

Also change the values in org-agenda-files and org-todo-keywords to point to your files and match your keywords

* Test =org-agenda= TODO/LATER toggle & refile for Tohiko
  #+BEGIN_SRC emacs-lisp
    (defun tohiko/org-toggle-later-todo-and-refile ()
      (interactive)
      (cond
       ;; if currently set to TODO, swap it to LATER and refile
       ((string= (org-get-todo-state) "TODO")
        (org-todo "LATER")
        (org-refile nil nil (list "NewHeadline" "~/gtd/later.org")))
       ;; if currently set to LATER, swap it to TODO and refile
       ((string= (org-get-todo-state) "LATER")
        (org-todo "TODO")
        (org-refile nil nil (list "NewHeadline" "~/gtd/current.org")))
       ;; if neither TODO nor LATER, do nothing but print a message
       (t (message "Oops! This item is neither TODO nor LATER"))))

    ;; define a keybinding that will call the above function when pressed
    (define-key org-mode-map (kbd "C-c c") 'tohiko/org-toggle-later-todo-and-refile)
  #+END_SRC


** Set refile targets
   #+BEGIN_SRC emacs-lisp
     (setq org-refile-targets '((nil :maxlevel . 9)
                                (org-agenda-files :maxlevel . 9)))
   #+END_SRC

** Set agenda files
   #+BEGIN_SRC emacs-lisp
     (setq org-agenda-files '("~/gtd/current.org"
                              "~/gtd/later.org"))
   #+END_SRC

** Set todo keywords
   #+BEGIN_SRC emacs-lisp
     (setq org-todo-keywords '((sequence "TODO" "LATER" "DONE")))
   #+END_SRC

Don't forget to also change the path to the files in each of the two calls to org-refile in the custom function to match the paths to your files

Hope that helps!

2
  • That is what I am planning to do. But I don't know how to setup this keyboard mapping on org-agenda or how to do the filing conditionally on the item-state.
    – Tohiko
    Commented Mar 12, 2019 at 8:22
  • I've edited my answer to include example code. I'm adding a comment here because I'm new to StackExchange and I'm not sure if the Asker will be notified when I edit my answer. If this is improper protocol, please let me know.
    – DerpKat
    Commented Mar 12, 2019 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.