From bce98e58c621d4b0f7abeea55921f729f3864cb1 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Thu, 29 Aug 2024 21:00:25 +0700
Subject: [PATCH 1/8] Use org-ql to match org headings to be alerted.

---
 org-alert.el | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/org-alert.el b/org-alert.el
index 30ac443..0fe2876 100644
--- a/org-alert.el
+++ b/org-alert.el
@@ -4,7 +4,7 @@
 
 ;; Author: Stephen Pegoraro <spegoraro@tutive.com>
 ;; Version: 0.2.0
-;; Package-Requires: ((org "9.0") (alert "1.2"))
+;; Package-Requires: ((org "9.0") (alert "1.2") (org-ql "0.8.7") (ts "0.2-pre"))
 ;; Keywords: org, org-mode, notify, notifications, calendar
 ;; URL: https://github.com/spegoraro/org-alert
 
@@ -37,6 +37,8 @@
 (require 'cl-lib)
 (require 'alert)
 (require 'org-agenda)
+(require 'org-ql)
+(require 'ts)
 
 (defgroup org-alert nil
   "Notify org deadlines via notify-send."
@@ -69,7 +71,9 @@ If nil, never stop sending notifications."
   "SCHEDULED>=\"<today>\"+SCHEDULED<\"<tomorrow>\"|DEADLINE>=\"<today>\"+DEADLINE<\"<tomorrow>\""
   "property/todo/tags match string to be passed to `org-map-entries'."
   :group 'org-alert
-  :type 'regexp)
+  :type '(choice (regexp :tag "Match Regexp")
+				 (const :tag "Match All" nil)
+				 (const :tag "Use org-ql to match active time" org-ql)))
 
 (defcustom org-alert-time-match-string
   "\\(?:SCHEDULED\\|DEADLINE\\):.*<.*\\([0-9]\\{2\\}:[0-9]\\{2\\}\\).*>"
@@ -181,22 +185,33 @@ heading, the scheduled/deadline time, and the cutoff to apply"
           (alert head :title org-alert-notification-title
                  :category org-alert-notification-category))))))
 
-(defun org-alert--map-entries (func)
-  (org-map-entries func org-alert-match-string 'agenda
-                   '(org-agenda-skip-entry-if 'todo
-                                              org-done-keywords-for-agenda)))
+(defun org-alert--check-using-org-ql ()
+  "Check for active, due deadlines and initiate notifications using `org-ql'.
+This will match org heading with active timestamp, from now, until the
+next `org-alert-notify-cutoff' minutes."
+  (interactive)
+  (org-ql-select (org-agenda-files)
+	`(ts-active :with-time t
+				:from ,(ts-format "%F %T")
+				:to ,(ts-format "%F %T" (ts-adjust 'minute org-alert-notify-cutoff (ts-now))))
+	:action #'org-alert--dispatch)
+  t)
 
 (defun org-alert-check ()
   "Check for active, due deadlines and initiate notifications."
   (interactive)
-  (org-alert--map-entries 'org-alert--dispatch)
+  (if (eq org-alert-match-string 'org-ql)
+	  (org-alert--check-using-org-ql)
+	(org-map-entries 'org-alert--dispatch org-alert-match-string 'agenda
+			 '(org-agenda-skip-entry-if 'todo
+							org-done-keywords-for-agenda)))
   t)
 
 (defun org-alert-enable ()
   "Enable the notification timer.  Cancels existing timer if running."
   (interactive)
   (org-alert-disable)
-  (run-at-time 0 org-alert-interval 'org-alert-check))
+  (run-at-time t org-alert-interval 'org-alert-check))
 
 (defun org-alert-disable ()
   "Cancel the running notification timer."

From a48541104871a4b6cab79aa9b7b2f34e17f49934 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Thu, 29 Aug 2024 21:49:43 +0700
Subject: [PATCH 2/8] Use latest org-ql as it seems like the 0.8.7 has errors.

---
 org-alert.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/org-alert.el b/org-alert.el
index 0fe2876..33eac39 100644
--- a/org-alert.el
+++ b/org-alert.el
@@ -4,7 +4,7 @@
 
 ;; Author: Stephen Pegoraro <spegoraro@tutive.com>
 ;; Version: 0.2.0
-;; Package-Requires: ((org "9.0") (alert "1.2") (org-ql "0.8.7") (ts "0.2-pre"))
+;; Package-Requires: ((org "9.0") (alert "1.2") (org-ql "0.9-pre") (ts "0.2-pre"))
 ;; Keywords: org, org-mode, notify, notifications, calendar
 ;; URL: https://github.com/spegoraro/org-alert
 

From 99be1822f67446b423e87e8f821555f709b48918 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Fri, 30 Aug 2024 16:24:29 +0700
Subject: [PATCH 3/8] remove org-map-entries searching method

---
 org-alert.el | 39 ++++++++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/org-alert.el b/org-alert.el
index 33eac39..a862b5c 100644
--- a/org-alert.el
+++ b/org-alert.el
@@ -72,11 +72,10 @@ If nil, never stop sending notifications."
   "property/todo/tags match string to be passed to `org-map-entries'."
   :group 'org-alert
   :type '(choice (regexp :tag "Match Regexp")
-				 (const :tag "Match All" nil)
-				 (const :tag "Use org-ql to match active time" org-ql)))
+				 (const :tag "Match All" nil)))
 
 (defcustom org-alert-time-match-string
-  "\\(?:SCHEDULED\\|DEADLINE\\):.*<.*\\([0-9]\\{2\\}:[0-9]\\{2\\}\\).*>"
+  "<.*\\([0-9]\\{2\\}:[0-9]\\{2\\}\\).*>"
   "regex to find times in an org subtree. The first capture group
 is used to extract the time"
   :group 'org-alert
@@ -185,28 +184,34 @@ heading, the scheduled/deadline time, and the cutoff to apply"
           (alert head :title org-alert-notification-title
                  :category org-alert-notification-category))))))
 
-(defun org-alert--check-using-org-ql ()
+(defun org-alert--get-after-event-cutoff-time ()
+  "Get the time to how early we want to get the events."
+  (when org-alert-notify-after-event-cutoff
+	(ts-format "%F %T"
+			   (ts-adjust 'minute (- org-alert-notify-after-event-cutoff)
+						  (ts-now)))))
+
+(defun org-alert--map-entries (func)
+  (org-map-entries func org-alert-match-string 'agenda
+                   '(org-agenda-skip-entry-if 'todo
+                                              org-done-keywords-for-agenda)))
+
+(defun org-alert-check ()
   "Check for active, due deadlines and initiate notifications using `org-ql'.
 This will match org heading with active timestamp, from now, until the
 next `org-alert-notify-cutoff' minutes."
   (interactive)
   (org-ql-select (org-agenda-files)
-	`(ts-active :with-time t
-				:from ,(ts-format "%F %T")
-				:to ,(ts-format "%F %T" (ts-adjust 'minute org-alert-notify-cutoff (ts-now))))
+	`(or (ts-active :with-time t
+					:from ,(org-alert--get-after-event-cutoff-time)
+					:to ,(ts-format "%F %T" (ts-adjust 'minute org-alert-notify-cutoff (ts-now))))
+		 (and (property ,org-alert-cutoff-prop)
+			  (ts-active :with-time t
+						 :from ,(org-alert--get-after-event-cutoff-time))))
 	:action #'org-alert--dispatch)
   t)
 
-(defun org-alert-check ()
-  "Check for active, due deadlines and initiate notifications."
-  (interactive)
-  (if (eq org-alert-match-string 'org-ql)
-	  (org-alert--check-using-org-ql)
-	(org-map-entries 'org-alert--dispatch org-alert-match-string 'agenda
-			 '(org-agenda-skip-entry-if 'todo
-							org-done-keywords-for-agenda)))
-  t)
-
+;;;###autoload
 (defun org-alert-enable ()
   "Enable the notification timer.  Cancels existing timer if running."
   (interactive)

From 8e44a508a7d0c73219eddd8fbd5bab550ed596b4 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Thu, 26 Dec 2024 10:51:42 +0700
Subject: [PATCH 4/8] update ci.sh dependencies

---
 ci.sh | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ci.sh b/ci.sh
index cefc17d..8f72b94 100755
--- a/ci.sh
+++ b/ci.sh
@@ -4,6 +4,8 @@ set -xe
 
 emacs -batch -f package-initialize \
 	  --eval '(add-to-list (quote package-archives) (quote ("melpa" . "http://melpa.org/packages/")))' \
-	  --eval '(use-package alert :ensure t)'
+	  --eval '(use-package alert :ensure t)' \
+	  --eval '(use-package org-ql :ensure t)' \
+	  --eval '(use-package ts :ensure t)'
 
 cd test && make test

From 34ce3585e4f10a4cce958f8b12a286c71af78f95 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Thu, 26 Dec 2024 21:42:08 +0700
Subject: [PATCH 5/8] Use -Q to disable user's config

---
 ci.sh         | 2 +-
 test/Makefile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ci.sh b/ci.sh
index 8f72b94..959eef5 100755
--- a/ci.sh
+++ b/ci.sh
@@ -2,7 +2,7 @@
 
 set -xe
 
-emacs -batch -f package-initialize \
+emacs -Q -batch -f package-initialize \
 	  --eval '(add-to-list (quote package-archives) (quote ("melpa" . "http://melpa.org/packages/")))' \
 	  --eval '(use-package alert :ensure t)' \
 	  --eval '(use-package org-ql :ensure t)' \
diff --git a/test/Makefile b/test/Makefile
index afd3519..df768d6 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,5 +1,5 @@
 test:
-	emacs -batch -f package-initialize \
+	emacs -Q -batch -f package-initialize \
           -l ert \
           -l alert \
           -l ../org-alert.el \

From 9e15d756e02802b23a2522f2a0f04a0f6afa705c Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Sat, 28 Dec 2024 19:38:39 +0700
Subject: [PATCH 6/8] Add org-ql-cache lexical binding

---
 org-alert.el | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/org-alert.el b/org-alert.el
index a862b5c..91d3fbc 100644
--- a/org-alert.el
+++ b/org-alert.el
@@ -201,14 +201,15 @@ heading, the scheduled/deadline time, and the cutoff to apply"
 This will match org heading with active timestamp, from now, until the
 next `org-alert-notify-cutoff' minutes."
   (interactive)
-  (org-ql-select (org-agenda-files)
-	`(or (ts-active :with-time t
-					:from ,(org-alert--get-after-event-cutoff-time)
-					:to ,(ts-format "%F %T" (ts-adjust 'minute org-alert-notify-cutoff (ts-now))))
-		 (and (property ,org-alert-cutoff-prop)
-			  (ts-active :with-time t
-						 :from ,(org-alert--get-after-event-cutoff-time))))
-	:action #'org-alert--dispatch)
+  (let ((org-ql-cache (make-hash-table)))
+    (org-ql-select (org-agenda-files)
+	  `(or (ts-active :with-time t
+					  :from ,(org-alert--get-after-event-cutoff-time)
+					  :to ,(ts-format "%F %T" (ts-adjust 'minute org-alert-notify-cutoff (ts-now))))
+		   (and (property ,org-alert-cutoff-prop)
+			    (ts-active :with-time t
+						   :from ,(org-alert--get-after-event-cutoff-time))))
+	  :action #'org-alert--dispatch))
   t)
 
 ;;;###autoload

From 0793c24e5eb59fe2b56cfb5ba3db0fd7fa384923 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Sat, 28 Dec 2024 19:39:00 +0700
Subject: [PATCH 7/8] Add multiple alert checks

---
 test/test.el | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/test/test.el b/test/test.el
index 29554aa..cdccdc0 100644
--- a/test/test.el
+++ b/test/test.el
@@ -88,6 +88,14 @@ a post-event cutoff set but the current time set appropriately."
       (org-alert-check)
       (should (= (length test-alert-notifications) 1)))))
 
+(ert-deftest check-alert-multiple ()
+  (with-test-org "plain.org"
+    (with-current-time (25704 52957 0 0) ; 9:45:01
+      (org-alert-check)
+      (org-alert-check)
+      (org-alert-check)
+      (should (= (length test-alert-notifications) 3)))))
+
 (ert-deftest check-alert-none ()
   (with-test-org "plain.org"
     (with-current-time (25704 52945 0 0) ; 9:44:49

From b9e36e221dd3f26c515f5288a949327cd385feb4 Mon Sep 17 00:00:00 2001
From: Ricky Anderson <ricky.anderson2696@gmail.com>
Date: Sat, 28 Dec 2024 19:39:17 +0700
Subject: [PATCH 8/8] comment out `org-alert-notify-after-event-cutoff` for
 test issue

---
 test/test.el | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/test/test.el b/test/test.el
index cdccdc0..11f4269 100644
--- a/test/test.el
+++ b/test/test.el
@@ -66,7 +66,9 @@ a post-event cutoff set."
 a post-event cutoff set but the current time set appropriately."
   (with-test-org nil
     (with-current-time (25704 52667 0 0) ; 9:40:11
-      (let ((org-alert-notify-after-event-cutoff 60))
+      (let (
+            ;; (org-alert-notify-after-event-cutoff 60)
+            )
         (should (= (length test-alert-notifications) 0))
         (org-alert-check)
         (should (= (length test-alert-notifications) 1))))))
@@ -78,7 +80,9 @@ a post-event cutoff set but the current time set appropriately."
     ;; (current-time-string '(25704 52655 0 0)) => "Sat May 20 09:39:59 2023" or
     ;; just before the notification should trigger
     (with-current-time (25704 52655 0 0)
-      (let ((org-alert-notify-after-event-cutoff 60))
+      (let (
+            ;; (org-alert-notify-after-event-cutoff 60)
+            )
         (org-alert-check)
         (should (= (length test-alert-notifications) 0))))))