emacs: Fine tune org-agenda timers

This commit is contained in:
Nathan McCarty 2022-05-26 16:46:14 -04:00
parent 6bf99aefee
commit 27530c6f0f
Signed by: thatonelutenist
GPG Key ID: D70DA3DD4D1E9F96
1 changed files with 59 additions and 31 deletions

View File

@ -206,9 +206,27 @@ Setup some basic cosmetic improvements
Automatically add all files in the org dir to the agenda. This performs some filtering of the files returned from ~directory-files~ to exclude some things that would confuse org-agenda. Automatically add all files in the org dir to the agenda. This performs some filtering of the files returned from ~directory-files~ to exclude some things that would confuse org-agenda.
We also setup an idle timer, with a short duration, only 30 seconds, to update the ~org-agenda-files~ list, as well as a longer regular timer with a duration of 300 seconds (5 minutes) to keep the agenda up to date even when we are actively using emacs. We also setup an idle timer, with a short duration, only 30 seconds, to update the ~org-agenda-files~ list, as well as a longer regular timer with a duration of 300 seconds (5 minutes) to keep the agenda up to date even when we are actively using emacs.
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; A function to update the org-agenda files (defvar nm/org-agenda-files-timer nil
"Timer for automatically updating the org-agenda files")
(defvar nm/time-at-agenda-update 0
"Time at last agenda update")
(defun nm/update-org-agenda-files () (defun nm/update-org-agenda-files ()
(setq org-agenda-files "Helper function for updating the org-agenda files."
;; Calcuate time since last update
(let* ((time-seconds (float-time (current-time)))
(seconds-since (- time-seconds nm/time-at-agenda-update))
(idle-time (current-idle-time))
(idle-seconds (if idle-time (float-time idle-time) 0)))
;; If it has been more than 10 minutes since our last agenda file update, then go ahead and update
;; Additionally update if the idle timer is greater than 30 seconds
(when (or
(> seconds-since 600)
(> idle-seconds 30))
;; Update our time variable
(setq nm/time-at-agenda-update seconds-since)
;; Update our agenda files
(setq org-agenda-files
(seq-filter (lambda (item) (seq-filter (lambda (item)
(and (and
;; Only accept things that are a directory, or an org file ;; Only accept things that are a directory, or an org file
@ -218,49 +236,59 @@ Setup some basic cosmetic improvements
(not (string-match-p ".*stfolder$" item)) (not (string-match-p ".*stfolder$" item))
;; Exclude the elfeed data folder ;; Exclude the elfeed data folder
(not (string-match-p (concat "^" (regexp-quote org-directory) "elfeed/.*") item)))) (not (string-match-p (concat "^" (regexp-quote org-directory) "elfeed/.*") item))))
(directory-files-recursively org-directory directory-files-no-dot-files-regexp)))) (directory-files-recursively org-directory directory-files-no-dot-files-regexp)))))
;; Update the timer, first canceling the old one
(when nm/org-agenda-update-timer
(cancel-timer nm/org-agenda-update-timer))
(setq nm/org-agenda-update-timer (run-with-timer 60 nil 'nm/org-agenda-update-timer)))
(after! org (after! org
;; Set the agenda files on first start ;; Set the agenda files on first start
(nm/update-org-agenda-files) ;; This also configures the timer for us
;; Set up a timer to automatically update them in the background (nm/update-org-agenda-files))
;; This first one is an idle timer that runs when emacs has been idle for 30 seconds
(run-with-idle-timer 25 t 'nm/update-org-agenda-files)
;; Then setup the non-idle timer for 5 minutes
(run-with-timer "5 min" t 'nm/update-org-agenda-files))
#+end_src #+end_src
Set up two different timers for updating the org-agenda buffer. Set up two different timers for updating the org-agenda buffer.
+ Idle timer + Idle timer
The idle timer simply updates the views unconditionally, and is set with a slightly higher timeout than our idle time that updates the org agenda files. This idle time can safely modify the state of the buffer without any other checks, as if the user is idle, they aren't doing anything in the buffer The idle timer simply updates the views unconditionally, and is set with a slightly higher timeout than our idle time that updates the org agenda files. This idle time can safely modify the state of the buffer without any other checks, as if the user is idle, they aren't doing anything in the buffer
+ Timer timer + Timer timer
Setup a timer that attempts to update the org-agenda buffer every 5 minutes. This timer is a little bit unsafe, so it _could_ end up annyoing the user by updating the state while they are in the middle of doing something, so it cancels out and does nothing if the user is currently focused on the agenda buffer. Setup a timer that attempts to update the org-agenda buffer every 5 minutes. This timer is a little bit unsafe, so it _could_ end up annoying the user by updating the state while they are in the middle of doing something, so it cancels out and does nothing if the user is currently focused on the agenda buffer.
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; Helper function to refresh the buffer (defvar nm/org-agenda-update-timer nil
(defun nm/org-agenda-refresh () "Timer for automatically updating the org-agenda views")
;; Attempt to get the org agenda buffer
(when-let ((buffer (get-buffer org-agenda-buffer-name)))
;; Update the views
(with-current-buffer buffer
(org-agenda-redo-all))))
;; Helper function to only refresh the buffer if it isn't focused, we don't want to annoy ourselves
;; by refreshing in the middle of faffing around, the idle timer will clean us up when we are done
;; anyway
(defun nm/org-agenda-refresh-conditional () (defun nm/org-agenda-refresh-conditional ()
;; Attempt to get the org agenda buffer "Helper function to only refresh the org-agenda views if it
(when-let ((buffer (get-buffer org-agenda-buffer-name))) either isn't focused or we have been idle long enough. This
;; Get the currently selected window and see if it contains the org-agenda buffer, we don't want avoids updating the buffer, and thus annoying the user, while
;; to trample the current state if the user (me) is currently active in the buffer they are in the middle of doing something.
(when (not (eq (window-buffer (selected-window)) buffer))
;; Since we are not in the org-agenda-buffer it is safe to rebuild the views This function will run on a 60 second loop, only actually doing
(with-current-buffer buffer work if it thinks it needs to."
(org-agenda-redo-all))))) ;; Make sure the org-agenda-buffer exists, bail out if it doesnt
(when (boundp 'org-agenda-buffer-name)
;; Attempt to get the org agenda buffer
(when-let ((buffer (get-buffer org-agenda-buffer-name)))
;; Calcuate idle time
(let* ((idle-time (current-idle-time))
(idle-seconds (if idle-time (float-time idle-time) 0)))
;; Update the org-agenda views if any of the following apply:
;; - The agenda buffer is not in focus
;; - The idle time is greater than one minute
(when (or
(not (eq (window-buffer (selected-window)) buffer))
(> idle-seconds 60))
;; Since we are not in the org-agenda-buffer it is safe to rebuild the views
(with-current-buffer buffer
(org-agenda-redo-all))))))
;; Update the timer, first canceling the old one
(when nm/org-agenda-update-timer
(cancel-timer nm/org-agenda-update-timer))
(setq nm/org-agenda-update-timer (run-with-timer 60 nil 'nm/org-agenda-refresh-conditional)))
(after! org (after! org
;; Set up an idle time that's slighty longer than our update-org-agenda-files idle timer ;; This method sets up the timer on its own
(run-with-idle-timer 30 t 'nm/org-agenda-refresh) (nm/org-agenda-refresh-conditional))
(run-with-timer "5 min" t 'nm/org-agenda-refresh-conditional))
#+end_src #+end_src
Log state changes into a drawer Log state changes into a drawer