branch: externals/org-gnosis
commit 1d082d0b41f50ac214e4035128ea60f59c397bdb
Author: Thanos Apollo <pub...@thanosapollo.org>
Commit: Thanos Apollo <pub...@thanosapollo.org>

    [fix] mark-todo-as-done: Add last-done-date property
---
 org-gnosis.el | 211 +++++++++++++++++++++++++++-------------------------------
 1 file changed, 99 insertions(+), 112 deletions(-)

diff --git a/org-gnosis.el b/org-gnosis.el
index dd6fb8302f..ee52bd0c75 100644
--- a/org-gnosis.el
+++ b/org-gnosis.el
@@ -308,7 +308,7 @@ Removes all contents of FILE in database, adding them anew."
     (when (and journal-p file)
       (let ((done-todos (org-gnosis-get-checked-items 
(org-element-parse-buffer))))
         (cl-loop for done-todo in done-todos
-                do (org-gnosis-mark-todo-as-done done-todo file))))))
+                do (org-gnosis-mark-todo-as-done done-todo))))))
 
 (defun org-gnosis-delete-file (&optional file)
   "Delete FILE.
@@ -535,6 +535,104 @@ If file or id are not found, use `org-open-at-point'."
          (t (org-open-at-point)))
     (org-gnosis-mode 1)))
 
+;; Should we use `org-get'?
+(defun org-gnosis-get--todos (file)
+  "Get TODO items for FILE."
+  (let ((todos))
+    (with-temp-buffer
+      (insert-file-contents file)
+      (org-mode)
+      (org-element-map (org-element-parse-buffer) 'headline
+        (lambda (headline)
+          (when (string= (org-element-property :todo-keyword headline) "TODO")
+            (let* ((title (org-element-property :raw-value headline))
+                   (timestamp (org-element-property :raw-value
+                           (org-element-property :scheduled headline))))
+              (push `(,title ,timestamp ,file) todos))))))
+    (nreverse todos)))
+
+(defun org-gnosis-find-file-with-heading (title files)
+  "Find first org file in FILES containing heading TITLE."
+  (catch 'found
+    (dolist (file files)
+      (with-temp-buffer
+        (insert-file-contents file)
+        (org-mode)
+        (goto-char (point-min))
+        (when (org-find-exact-headline-in-buffer title)
+          (throw 'found file))))))
+
+(defun org-gnosis-get-todos (&optional files)
+  "Get TODO items for FILES.
+
+If TITLE is non-nil, return the file that has a TODO TITLE."
+  (let ((files (or files org-gnosis-todo-files))
+       todos)
+    (cl-loop for file in files
+            do (push (org-gnosis-get--todos file) todos))
+    (nreverse (apply #'append todos))))
+
+(defun org-gnosis-todos ()
+  "Output todos as checkboxes in a string for current date."
+  (let ((todos (org-gnosis-get-todos))
+       (current-date (format-time-string "%Y-%m-%d"))
+       todos-string)
+    (cl-loop for todo in todos
+            do
+            (let ((todo-title (car todo))
+                  (todo-timestamp (cadr todo)))
+              (when (or
+                     (null todo-timestamp)
+                     (string-match-p (regexp-quote current-date) 
todo-timestamp))
+                (setq todos-string
+                      (concat todos-string
+                              (format "%s [ ] %s\n" 
org-gnosis-bullet-point-char
+                                      todo-title))))))
+    (or todos-string "")))
+
+(defun org-gnosis-get-checked-items (element)
+  "Get checked items for org ELEMENT.
+
+ELEMENT should be the output of `org-element-parse-buffer'."
+  (let ((checked-items))
+    (org-element-map element 'item
+      (lambda (item)
+        (when (eq (org-element-property :checkbox item) 'on)
+          (push (car (split-string
+                     (substring-no-properties
+                      (string-trim
+                       (org-element-interpret-data
+                        (org-element-contents item))))
+                     "\n"))
+                checked-items))))
+    (nreverse checked-items)))
+
+(defun org-gnosis-mark-todo-as-done (todo-title)
+  "Mark scheduled TODO with TODO-TITLE as DONE if not already done today.
+ENTRY: Journal entry linked under the heading."
+  (let* ((file (org-gnosis-find-file-with-heading todo-title 
org-gnosis-todo-files))
+         (today (format-time-string "%Y-%m-%d")))
+    (when file
+      (save-current-buffer
+        (with-current-buffer (find-file-noselect file)
+          (let ((found nil))
+            (save-excursion
+              (org-element-map (org-element-parse-buffer) 'headline
+                (lambda (headline)
+                  (when (and (not found)
+                             (string= (org-element-property :raw-value 
headline)
+                                      todo-title)
+                             (string= (org-element-property :todo-keyword 
headline)
+                                      "TODO")
+                            ;; Check if not done today
+                             (not (org-entry-get (org-element-property :begin 
headline)
+                                                "LAST_DONE_DATE")))
+                    (org-with-point-at (org-element-property :begin headline)
+                      (org-todo 'done)
+                      (org-entry-put nil "LAST_DONE_DATE" today))
+                    (setq found t))))))
+          (save-buffer))))))
+
 (defvar-keymap org-gnosis-mode-map
   :doc "org-gnosis keymap"
   "C-c C-o" #'org-gnosis-goto-id)
@@ -627,117 +725,6 @@ If called with ARG do not initialize the database."
       (pcase-dolist (`(,table ,schema) org-gnosis-db--table-schemata)
        (emacsql org-gnosis-db [:create-table $i1 $S2] table schema))
       (emacsql org-gnosis-db [:pragma (= user-version 
org-gnosis-db-version)]))))
-;; should we use `org-get'
-(defun org-gnosis-get--todos (file)
-  "Get TODO items for FILE."
-  (let ((todos))
-    (with-temp-buffer
-      (insert-file-contents file)
-      (org-mode)
-      (org-element-map (org-element-parse-buffer) 'headline
-        (lambda (headline)
-          (when (string= (org-element-property :todo-keyword headline) "TODO")
-            (let* ((title (org-element-property :raw-value headline))
-                   (timestamp (org-element-property :raw-value
-                           (org-element-property :scheduled headline))))
-              (push `(,title ,timestamp ,file) todos))))))
-    (nreverse todos)))
-
-(defun org-gnosis-find-file-with-heading (title files)
-  "Find first org file in FILES containing heading TITLE."
-  (catch 'found
-    (dolist (file files)
-      (with-temp-buffer
-        (insert-file-contents file)
-        (org-mode)
-        (goto-char (point-min))
-        (when (org-find-exact-headline-in-buffer title)
-          (throw 'found file))))))
-
-(defun org-gnosis-get-todos (&optional files)
-  "Get TODO items for FILES.
-
-If TITLE is non-nil, return the file that has a TODO TITLE."
-  (let ((files (or files org-gnosis-todo-files))
-       todos)
-    (cl-loop for file in files
-            do (push (org-gnosis-get--todos file) todos))
-    (nreverse (apply #'append todos))))
-
-(defun org-gnosis-todos ()
-  "Output todos as checkboxes in a string for current date."
-  (let ((todos (org-gnosis-get-todos))
-       (current-date (format-time-string "%Y-%m-%d"))
-       todos-string)
-    (cl-loop for todo in todos
-            do
-            (let ((todo-title (car todo))
-                  (todo-timestamp (cadr todo)))
-              (when (or
-                     (null todo-timestamp)
-                     (string-match-p (regexp-quote current-date) 
todo-timestamp))
-                (setq todos-string
-                      (concat todos-string
-                              (format "%s [ ] %s\n" 
org-gnosis-bullet-point-char
-                                      todo-title))))))
-    (or todos-string "")))
-
-(defun org-gnosis-get-checked-items (element)
-  "Get checked items for org ELEMENT.
-
-ELEMENT should be the output of `org-element-parse-buffer'."
-  (let ((checked-items))
-    (org-element-map element 'item
-      (lambda (item)
-        (when (eq (org-element-property :checkbox item) 'on)
-          (push (car (split-string
-                     (substring-no-properties
-                      (string-trim
-                       (org-element-interpret-data
-                        (org-element-contents item))))
-                     "\n"))
-                checked-items))))
-    (nreverse checked-items)))
-
-;; TODO: Break this into smaller functions
-(defun org-gnosis-mark-todo-as-done (todo-title entry)
-  "Mark the TODO Heading with TODO-TITLE as DONE.
-ENTRY: Journal entry linked under the heading."
-  (let* ((file (org-gnosis-find-file-with-heading todo-title 
org-gnosis-todo-files))
-         (today (org-time-string-to-absolute (format-time-string "%Y-%m-%d"))))
-    (when file
-      (save-current-buffer
-        (with-current-buffer (find-file-noselect file)
-          (let ((found nil))
-            (save-excursion
-              (org-element-map (org-element-parse-buffer) 'headline
-                (lambda (headline)
-                  (let ((scheduled (org-element-property :scheduled headline)))
-                    (when (and (not found)
-                             (string= (org-element-property :raw-value 
headline)
-                                    todo-title)
-                             (string= (org-element-property :todo-keyword 
headline)
-                                    "TODO")
-                             (or (null scheduled)
-                                 (= (org-time-string-to-absolute
-                                     (org-element-property :raw-value 
scheduled))
-                                    today)))
-                      (org-with-point-at
-                          (save-excursion
-                            (goto-char (point-min))
-                            (let ((case-fold-search t))
-                              (re-search-forward (concat "^\\*+ .*"
-                                                       (regexp-quote 
todo-title)))))
-                        (org-todo 'done)
-                        (org-end-of-subtree)
-                        (insert "\n " org-gnosis-bullet-point-char " ")
-                        (org-insert-link
-                         nil
-                         (format "file:%s"
-                                (expand-file-name entry 
org-gnosis-journal-dir))
-                         "Journal File"))
-                      (setq found t)))))))
-          (save-buffer))))))
 
 (provide 'org-gnosis)
 ;;; org-gnosis.el ends here

Reply via email to