diff --git a/org/config-org-tags.el b/org/config-org-tags.el index 2782765..a04b174 100644 --- a/org/config-org-tags.el +++ b/org/config-org-tags.el @@ -1,7 +1,3 @@ -; log to drawer of entry -(setq org-log-into-drawer t) -(setq org-treat-insert-todo-heading-as-state-change t) - ; the ! tells org to log state changes for todo entries (setq org-todo-keywords '((sequence "TODO(t!)" "READY(r!)" "WIP(w!)" "|" "SKIPPED(k!)" "COMPLETE(c!)" "CANCELED(x!)")) @@ -27,3 +23,67 @@ "@kemonine" "@waltdk" ))) +; log to drawer of entry +(setq org-log-into-drawer t) +(setq org-treat-insert-todo-heading-as-state-change t) + +; set completion stats to auto-calc for checkboxes and nested todo's +(setq org-provide-todo-statistics t) +(setq org-checkbox-hierarchical-statistics nil) +(setq org-hierarchical-todo-statistics nil) + +; From https://christiantietze.de/posts/2021/02/emacs-org-todo-doing-done-checkbox-cycling/ +; Ensure the uppermost todo, in a nested tree, has an appropriate status based on all sub-items in the tree +; Basically: - can only be marked 'complete' if all sub-items are in a completed state +; - auto-marked as 'todo' if no sub-items are complete +; - auto-marked as 'wip' if some sub-items are complete +; - auto-marked as 'complete' if all sub-items are complete +(defun org-todo-if-needed (state) + "Change header state to STATE unless the current item is in STATE already." + (unless (string-equal (org-get-todo-state) state) + (org-todo state))) + +(defun ct/org-summary-todo-cookie (n-done n-not-done) + "Switch header state to DONE when all subentries are DONE, to TODO when none are DONE, and to DOING otherwise" + (let (org-log-done org-log-states) ; turn off logging + (org-todo-if-needed (cond ((= n-done 0) + "TODO") + ((= n-not-done 0) + "COMPLETE") + (t + "WIP"))))) +(add-hook 'org-after-todo-statistics-hook #'ct/org-summary-todo-cookie) + +(defun ct/org-summary-checkbox-cookie () + "Switch header state to DONE when all checkboxes are ticked, to TODO when none are ticked, and to DOING otherwise" + (let (beg end) + (unless (not (org-get-todo-state)) + (save-excursion + (org-back-to-heading t) + (setq beg (point)) + (end-of-line) + (setq end (point)) + (goto-char beg) + ;; Regex group 1: %-based cookie + ;; Regex group 2 and 3: x/y cookie + (if (re-search-forward "\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]" + end t) + (if (match-end 1) + ;; [xx%] cookie support + (cond ((equal (match-string 1) "100%") + (org-todo-if-needed "COMPLETE")) + ((equal (match-string 1) "0%") + (org-todo-if-needed "TODO")) + (t + (org-todo-if-needed "WIP"))) + ;; [x/y] cookie support + (if (> (match-end 2) (match-beginning 2)) ; = if not empty + (cond ((equal (match-string 2) (match-string 3)) + (org-todo-if-needed "COMPLETE")) + ((or (equal (string-trim (match-string 2)) "") + (equal (match-string 2) "0")) + (org-todo-if-needed "TODO")) + (t + (org-todo-if-needed "WIP"))) + (org-todo-if-needed "WIP")))))))) +(add-hook 'org-checkbox-statistics-hook #'ct/org-summary-checkbox-cookie)