diff options
Diffstat (limited to 'filtering-org-tasks.post')
-rw-r--r-- | filtering-org-tasks.post | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/filtering-org-tasks.post b/filtering-org-tasks.post new file mode 100644 index 0000000..1678cca --- /dev/null +++ b/filtering-org-tasks.post @@ -0,0 +1,85 @@ +;;;;; +title: Filtering org tasks +tags: tips, emacs, org-mode +date: 2013-08-25 00:38 +format: md +;;;;; + +I want to be able to easily see a list of tasks that are relevant to +the currently loaded desktop file. As I use `desktop.el` as a kind of +project system, this means I only want the tasks for the project I'm +currently working on. + +First I wrote the `tagify` function, because `org-mode` tags can't +contain `.` or `-` characters (among others I'm sure, but these are +the only ones that have caused me any trouble so far). It's a simple +string replacement: + +``` emacs-lisp +(defun tagify (str) + "Remove dots, replace - with _ in STR." + (replace-regexp-in-string + "-" "_" (replace-regexp-in-string "\\." "" (downcase str)))) +``` + +Then I wrote a function to filter the task list by not showing +anything that wasn't tagged with the name of the currently loaded +desktop, unless it isn't tagged at all or no desktop has been loaded. +And set this function to be the value of +`org-agenda-before-sorting-filter-function`. + +``` emacs-lisp +(defun filter-by-desktop (entry) + "Return ENTRY if it has no tags or a tag corresponding to the desktop." + (require 'desktop) + (let ((label (when desktop-dirname + (tagify (file-name-base + (directory-file-name + (expand-file-name desktop-dirname)))))) + (tags (get-text-property 0 'tags entry))) + (when (or (null desktop-dirname) (null tags) (member label tags)) + entry))) + +(setq org-agenda-before-sorting-filter-function #'filter-by-desktop) +``` + +This works fine. I keep untagged tasks in the list as well because +they might be important at all times and I don't want them falling +through the cracks. I also want a complete list if no desktop has been +loaded so I can browse through my tasks and decide what I'm going to +do next. + +The downside of this solution is that I have to close my current +project in order to see the whole list. + +Then I discovered the `/` key in the agenda buffer. I can't believe I +didn't notice this key before. Anyway, that changed my solution. + +Instead of setting `org-agenda-before-sorting-filter-function` I add a +hook to the `org-agenda-finalize-hook`. The `filter-by-desktop` +function looks a little different now: + +``` emacs-lisp +(defun org-init-filter-by-desktop () + "Filter agenda by current label." + (when desktop-dirname + (let ((label (tagify (file-name-base + (directory-file-name + (expand-file-name desktop-dirname)))))) + (org-agenda-filter-apply (cons label nil) 'tag)))) + +(add-hook 'org-agenda-finalize-hook 'org-init-filter-by-desktop) +``` + +I don't need to compare any tags now, and if I want to see my entire +list of tasks I can easily just press `/ /`. Since it is easier to get +back to the overview of my tasks it also doesn't bother me so much +that this way any untagged tasks don't show up in the filtered buffer. + +I haven't stopped using `/` since I discovered it. Filtering in this +way is one of the things I like about `ibuffer` as well, now for +`org-mode` it works excellently as well. + +<!-- Local Variables: --> +<!-- mode: markdown --> +<!-- End: --> |