summaryrefslogtreecommitdiffstats
path: root/filtering-org-tasks.post
diff options
context:
space:
mode:
Diffstat (limited to 'filtering-org-tasks.post')
-rw-r--r--filtering-org-tasks.post85
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: -->