org-alert icon indicating copy to clipboard operation
org-alert copied to clipboard

Use org-ql to match org headings to be alerted.

Open rickyson96 opened this issue 1 year ago • 17 comments

Hi! I've implemented a way to fetch only the related headings for alerting.

I kind of cheat a little using org-ql, but I think it worked out pretty well.

It should fix #27, though I'm not sure if I have handled all use cases.

I try to implement it in a way that's backward compatible, so some customization might not be in place right now.

We could also potentially make the org-alert-check customizable too, but I've put this off for now since I think the current implementation is good enough.

To use this new feature, we need to add:

;; or setopt for fancier option :)
(setq org-alert-match-string 'org-ql
      ;; use non-greedy regex to match the `from' time.
      org-alert-time-match-string "\\(?:SCHEDULED\\|DEADLINE\\):.*?<.*?\\([0-9]\\{2\\}:[0-9]\\{2\\}\\).*>")

rickyson96 avatar Aug 29 '24 14:08 rickyson96

Wow thanks for this! I didn't know about org-ql. I need to take a slightly closer look at how it works, but it seems really promising. Is there any reason not to use org-ql exclusively? (ah besides backwards compatibility) If we're already adding the dependency, I wouldn't mind making this the default/only behavior. org-alert-match-string has always felt very brittle to me anyway.

ntBre avatar Aug 29 '24 17:08 ntBre

If you're okay with the breaking changes, I think we can remove much of the old logic and depend solely on org-ql (note the changes on run-at-time too because it enables the cronjob behaviour).

rickyson96 avatar Aug 30 '24 03:08 rickyson96

I've updated the implementation to only use org-ql.

The problem is that I've borked the REMINDERN property. I've done a little bit of testing to see if we could do it with org-ql, but haven't get to implement it on the PR yet. :D

rickyson96 avatar Aug 30 '24 09:08 rickyson96

Thanks again for doing this! I've added a few superficial comments, mostly trying to avoid changes unrelated to adding org-ql. I probably won't get to a fuller review until this weekend, but besides these minor issues it looks very promising.

I'm not necessarily against these other changes (except changing the default after-event behavior), but I would rather separate them from the main task at hand to make this easier to review.

ntBre avatar Aug 30 '24 15:08 ntBre

Just was running into this very problem -- largely I do not use Scheduled or Deadline except for a few significant things, but meeting notices are something I very much would like to get a warning for. I tried to follow the discussion but in the end I'm not entirely sure I know how to set this up, aside from looking and installing the org-ql package.

Are there some examples of putting this into practice? It might also be an interesting exercise to mark an agenda item with a property that makes it remindable (to distinguish from birthdays and other sundry times that don't need a 10 minute reminder).

Remillard avatar Oct 03 '24 18:10 Remillard

This is still an open pull request that has not been merged into the version of org-alert available on Melpa. You could give it a try by installing the version from this PR branch (https://github.com/rickyson96/org-alert/tree/master), but I'm not quite sure how to take advantage of the new org-ql changes either. I've been dragging my heels on merging this because I'm not super enthusiastic about taking on more dependencies, and I need to familiarize myself with org-ql myself to review this fully.

mark an agenda item with a property that makes it remindable

This is also an interesting suggestion, but from the previous discussion, I think this PR also makes it harder to access properties in general. Again, I think it'll take some work for me to feel comfortable with org-ql and resolve these points.

I'm still somewhat optimistic that org-ql will both simplify the code and add some of these handy features, but I haven't had a chance to look closely enough yet.

ntBre avatar Oct 03 '24 18:10 ntBre

@rickyson96 Sorry for the delay on this. I've come back around on switching to org-ql, and I've just merged a PR adding more tests and some CI. Could you rebase or merge master here and clean up the git conflicts? Based on the previous discussion, I expect at least the REMINDERN tests to fail, but hopefully the others will still pass.

No rush on this, obviously, and happy holidays! And if I left you hanging too long, I'm also happy to take it from here. Thanks again for bringing org-ql to my attention either way!

ntBre avatar Dec 26 '24 00:12 ntBre

Ah tests are failing because org-ql isn't installed. Can you extend ci.sh with the new packages that need to be added:

https://github.com/spegoraro/org-alert/blob/0bc04cea718387134c37c9fc4c22215adc3f79db/ci.sh#L5-L7

I'm picturing something like this:

 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 org-ql :ensure t)'

I guess a line for ts also? I'd make the change myself, but I don't think I can push to your branch.

ntBre avatar Dec 26 '24 03:12 ntBre

Hey @ntBre, I've also not been able to take on this until recently. Last time I left this, I've made sure to let the REMINDERN works, so hopefully I can catch everything here.

currently I'm still figuring out running ERT on my machine though, and seems like it fails even with the dependencies. I'll add those to ci files too, but it'll probably take a while to resolve this.

rickyson96 avatar Dec 26 '24 03:12 rickyson96

Sounds good, no rush at all. On my machine, I just run make test in the test subdirectory, but I'm not sure how fragile this test setup is. I have a feeling there must be a better approach, but I was just happy to get something running today.

I'm curious to play with org-ql too, so I'll help to resolve the test failures once we get CI running!

ntBre avatar Dec 26 '24 03:12 ntBre

updated the ci dependencies.

I see, I don't notice the Makefile there 😂

One thing that I realized is if I load the test directly to my emacs session, I can run M-x ert, but it breaks my emacs perceived time. It has something to do with the TZ env that's being set in the test. Not sure if there's a better way out, though.

rickyson96 avatar Dec 26 '24 03:12 rickyson96

Oh weird, I was wary of messing with TZ, but I thought wrapping it in with-environment-variables instead of setting it directly would help.

I'm debugging the test failures now, starting with the remindern test. It looks like if I remove the (let ((org-alert-notify-after-event-cutoff 60)) line, the test passes, so it looks like an issue with the after-event-cutoff part of the query.

Something weird is going on with the check-alert-some test because it passes when I run it alone (with -eval '(ert-run-tests-batch-and-exit "check-alert-some")' as the last line in the Makefile) but fails when run with the other tests.

The caching section of the org-ql readme makes me wonder if we're running into an issue with the cache for check-alert-some. I think the query would be identical between check-alert-none and check-alert-some, with the only change being us overriding current-time, so that hitting the cache would make sense to me. I was able to get around this by making a separate org file (plain2.org) for that test but not by using set-file-times.

However, this makes me a little worried about using org-ql in general. It will usually be the case that the agenda file has not changed, so I think this will mean the queries always return the same values. The cache section in the README makes it sound like it's not yet possible to invalidate the cache easily too.

Just for a concrete example, even after the plain2.org "fix", I added two more calls to org-alert-check to the check-alert-some test:

(ert-deftest check-alert-some ()
  (with-test-org "plain2.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)))))

But this fails with 1 notification received instead of 3, again presumably because of this caching. This works as expected on the current master branch.

ntBre avatar Dec 26 '24 18:12 ntBre

I guess we can just use something like this to empty the cache:

(let ((org-ql-cache (make-hash-table)))
  (org-ql-select ...))

As suggested here, so we don't have to give up on org-ql entirely.

ntBre avatar Dec 26 '24 18:12 ntBre

huh thats weird, I've never noticed it during my daily use.

I used this snippet to interactively test using org-ql, changing the scheduled time in test.org file to few minutes ahead of now.

(let ((org-directory ".")
      (org-agenda-files '("test.org")))
  (org-alert-check))

If I eval it multiple times, I'm able to get the alert multiple times. I've also changed it to setq-ing the variables and run org-alert-check interactively, it still produces the same result.

Does the cache only happens because we're running it as a test (thus having the buffer to point the cache to)?

rickyson96 avatar Dec 27 '24 06:12 rickyson96

Hmm, you're right, I get multiple notifications with your snippet too. Maybe I was too quick to blame the cache.

However, changing check-alert-some to disable the cache does make it pass:

(ert-deftest check-alert-some ()
  (let ((org-ql-cache (make-hash-table)))
    (with-test-org "plain.org"
      (with-current-time (25704 52957 0 0) ; 9:45:01
        (org-alert-check)
        (should (= (length test-alert-notifications) 1))))))

I'd probably lean toward doing this in org-alert-check both to pass the test and just in case the cache can act up in real scenarios too.

ntBre avatar Dec 28 '24 02:12 ntBre

I've added the cache invalidation and other stuff, but the default test is still failing. One hypothesis that I have is that we only check the time for the alert, thus if the time is after the scheduled time, but it's actually past event, we wouldn't get the alert.

I'm not sure whether this is from master branch too, but one way out of this is to also check the day on org-alert--check-time.

rickyson96 avatar Dec 28 '24 12:12 rickyson96

Well it looks like all the tests are passing here. I just want to resolve the org-alert-notify-after-event-cutoff rather than comment out that part of the tests and then this is good to go.

I still need to read more about the available org-ql query types to suggest anything here, but my guess is that we're missing some kind of conditional on whether org-alert-notify-after-event-cutoff is defined in org-alert-check. If it's undefined, we don't want an upper bound on when to notify (ie always send late notifications, even hours or days later). I'm not honestly sure how useful/preferable this behavior is, but it is the current behavior.

Btw, it appears to be safe to comment the cutoff back in for check-alert-none-remindern. Only check-alert-some-remindern is failing for me locally with the comments removed.

This is fine to leave out of the scope of this PR, but I also feel like (hope?) we could use org-ql more heavily. Does it provide any of the parsing functionality that we're currently doing manually? I'm dreaming of something SQL-like such as

SELECT headline, time, properties 
FROM org-agenda
WHERE time > org-alert-notify-cutoff AND time < org-alert-notify-after-event-cutoff

Basically if org-ql could handle all of the selecting behavior, we would just map over the results to send notifications for each headline: time pair, and we could delete everything like org-alert--parse-entry, org-alert--check-time, etc.

ntBre avatar Dec 28 '24 17:12 ntBre