Refile targets with PROJECT state

February 20, 2024


I’m a long time user of org-mode inside Emacs. This is the most wonderful personal management tool, todo app, note taking app and planner, all in one. Quite recently I’ve started using a PROJECT state on TODO items in my TODO.org file, as a grouping mechanism. I also get less overwelmed of all the things that I apparently expect myself to do.

One problem though is that when tasks has been captured in my inbox and then are going to be refiled into it’s proper place I’ve only had my two files todo.org and someday.org as targets. The result’s been that I refile most things to todo.org and then manually move them around to the proper project. I would like to improve on that.

The sample structure in todo.org looks as following

#+TODO: PROJECT TODO NEXT(n!) IN-PROGRESS(p!) ON-HOLD(h@) | DONE(d!) REJECTED(r@)
#+TITLE: Todo

* NEXT Meeting: Foo Bar
* IN-PROGRESS Advent of Code
* DONE Add ticket for Boo Baz
* PROJECT Lorem
** NEXT Ipsum
** NEXT Dolor
** DONE Sit amet
* PROJECT Blog
** NEXT Write about emacs

What I want as my refile targets are:

- todo.org
- todo.org/Lorem
- todo.org/Blog
- someday.org

So, to emacs configuration. Here’ts the basic refile config. I have two variables here (er/org-todo & er/org-someday) that are just paths to my files. In order to include the headings in the files at all you have to give some level > 0. However, this includes all the headings.

(setq org-refile-targets '(
                           (er/org-todo :maxlevel . 1)
                           (er/org-someday :maxlevel . 1)))

Next is the filtering

(defun er/org-refile-filter-target ()
  (interactive)
  (member (nth 2 (org-heading-components)) '("PROJECT")))
(setq org-refile-target-verify-function 'er/org-refile-filter-target)

Line three makes sure that only headings with the status "PROJECT" are included in the list, and the last line just attatches the function to the hook. Technically, you can do arbitrary logic with crazy complex filtering here, so feel free to go nuts!

Last, in order to allow both headings and the top level file (I also want to refile to the ‘root’ node of todo.org) this option has to be set to 'file

(setq org-refile-use-outline-path 'file)

What happened though was that my Helm suggestion box only showed the file path:

- todo.org
- todo.org
- todo.org
- todo.org
- todo.org

That was solved by this setting

(setq org-outline-path-complete-in-steps nil)

So the result is a nice looking, short and contextual list

- todo.org
- todo.org/Lorem
- todo.org/Blog
- someday.org