From f5046e1f1ec45cf974cf4e6cc0740cbebdf0ec4b Mon Sep 17 00:00:00 2001 From: ndwarshuis Date: Sat, 25 Dec 2021 16:42:33 -0500 Subject: [PATCH] ENH show only leaf goals in the goals agenda view --- etc/conf.org | 10 ++++++++ local/lib/org-x/org-x.el | 51 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/etc/conf.org b/etc/conf.org index a279343..7f3c45f 100644 --- a/etc/conf.org +++ b/etc/conf.org @@ -181,6 +181,15 @@ Some useful external libraries that I use all over the place (use-package f :straight t) #+END_SRC +*** hash tables +:PROPERTIES: +:CREATED: [2021-12-24 Fri 16:05] +:ID: 2e1f9b7b-c565-464d-8abb-6e8608910ba3 +:END: +#+begin_src emacs-lisp +(use-package ht + :straight t) +#+end_src ** internal :PROPERTIES: :ID: d0696764-48ab-4ec6-ab42-42775dc8f793 @@ -3245,6 +3254,7 @@ In the order of display `((org-agenda-overriding-header "Goals") (org-agenda-files '("~/Org/reference/goals")) + (org-agenda-skip-function #'org-x-goal-skip-function) (org-agenda-sorting-strategy '(time-up scheduled-down)) (org-super-agenda-groups diff --git a/local/lib/org-x/org-x.el b/local/lib/org-x/org-x.el index bc1cff6..0582b68 100644 --- a/local/lib/org-x/org-x.el +++ b/local/lib/org-x/org-x.el @@ -33,6 +33,7 @@ (require 'org-ml) (require 'dash) (require 's) +(require 'ht) (require 'org) (require 'org-x-agg) @@ -319,7 +320,8 @@ the current time." "Open PATH and execute BODY." (declare (indent 1)) `(with-current-buffer (find-file-noselect ,path) - ,@body)) + (save-excursion + ,@body))) (defun org-x-parse-file-subtrees (path which) "Return a list of headlines from file at PATH. @@ -948,6 +950,44 @@ should be this function again)." (t (error (concat "invalid keyword detected: " keyword))))))) +;; goals + +(defun org-x-buffer-get-goal-links (file) + (org-x-with-file file + (let ((acc)) + (cl-flet + ((get-goal + () + (-when-let (g (org-entry-get nil org-x-prop-goal)) + (setq acc (cons g acc))))) + ;; TODO need to return nothing if a file has a toplevel prop drawer with + ;; a goal in it but no TODO headlines + (goto-char (point-min)) + (get-goal) + (while (outline-next-heading) + (get-goal)) + acc)))) + +(defun org-x-get-goal-links () + (-mapcat #'org-x-buffer-get-goal-links (org-files-list))) + +(defun org-x-get-goal-ids () + (--map (cadr (s-match "^\\[\\[id:\\(.*\\)\\]\\[.*\\]\\]$" it)) + (org-x-get-goal-links))) + +(defmacro org-x-id-get-ids-with (form) + "" + `(--filter (let ((it (cdr it))) ,form) (ht->alist org-id-locations))) + +(defun org-x-id-get-goal-ids () + (let ((goals-file (f-canonical (f-expand "~/Org/reference/goals.org")))) + (->> (org-x-id-get-ids-with (equal (f-canonical (f-expand it)) goals-file)) + (-map #'car)))) + +(defun org-x-get-leaf-goals () + "" + ()) + ;; iterators (defun org-x--clone-get-iterator-project-status (kw) @@ -1089,6 +1129,15 @@ function will simply return the point of the next headline." (org-x-skip-headings-with-tags (list org-x-tag-no-agenda org-x-tag-maybe org-x-tag-refile))) +(defun org-x-goal-skip-function () + "Skip function for goals view. +This is similar to the task skip function (only show TODO leaf +nodes of the outline)." + (org-with-wide-buffer + (let ((keyword (org-get-todo-state))) + (when (org-x-headline-is-project-p keyword) + (org-x-skip-heading))))) + (defun org-x-task-skip-function () "Skip function for task view." (org-with-wide-buffer