* Re: Elisp function to get the upcoming event with the closest scheduled date
2023-12-31 17:30 Elisp function to get the upcoming event with the closest scheduled date Rodrigo Morales
@ 2024-01-03 5:29 ` Rodrigo Morales
0 siblings, 0 replies; 2+ messages in thread
From: Rodrigo Morales @ 2024-01-03 5:29 UTC (permalink / raw)
To: emacs-orgmode
Rodrigo Morales <me@rodrigomorales.site> writes:
I managed to show the entry with the nearest upcoming scheduled date in
the tab bar with the following utilities (see code block below). Here's
an screenshot:
https://upload.wikimedia.org/wikipedia/commons/f/f3/Show_information_of_Org_Agenda_in_tab-bar.png
Here are some notes of the code:
+ The function my/org-agenda-nearest-upcoming-scheduled-search performs
linear search through all headings in all files listed in
org-agenda-files in order to search the entry with the nearest
upcoming scheduled date.
+ The variable my/org-agenda-nearest-upcoming-scheduled stores the
information of the event.
+ I added my/org-agenda-nearest-upcoming-scheduled-display to
tab-bar-format in order to display the information that I requested.
Because my/org-agenda-nearest-upcoming-scheduled-search uses linear
search it is a rather expensive operation if there are many entries to
look up. I haven't decided yet when this functino should be called so
that it is called the fewer amount of times and it actually shows th
entry with the nearest upcoming scheduled date. It is necessary that it
is called in the proper times so that the
my/org-agenda-nearest-upcoming-scheduled is updated accordingly when
setting the scheduled date for new entries.
#+BEGIN_SRC elisp
(defvar my/org-agenda-nearest-upcoming-scheduled nil
"Store entry with the nearest upcoming scheduled date.
The value should store a CONS CELL whose CAR is the title of the
entry and the CDR is the date of the entry.")
(defun my/org-agenda-nearest-upcoming-scheduled-search ()
"Set the value for variable that store the entry with the nearest upcoming scheduled date."
(let (nearest-entry
;; Store the scheduled date in seconds of the current entry.
entry-scheduled
(current-time (float-time)))
;; Iterate through all files in `org-agenda-files'
(dolist (file org-agenda-files)
(with-current-buffer (find-file-noselect file)
;; Iterate through all headings
(org-map-entries
(lambda ()
(when (and
;; Check the current entry has SCHEDULED
(setq entry-scheduled (org-entry-get nil "SCHEDULED"))
;; If the currenty entry has SCHEDULED, we proceed
;; to convert it to seconds using org-2ft. We cannot
;; write org-entry-get and org-2ft in the same
;; expression because it is possible that
;; org-entry-get returns nil and org-2ft returns 0
;; when nil is passed, so we won't be checking that
;; the entry has SCHEDULED.
(setq entry-scheduled (org-2ft entry-scheduled))
;; Check time of the entry is greater than the current time
(> entry-scheduled current-time))
;; If there's no nearest entry yet, then store the
;; current entry as the nearest entry.
;;
;; We use an if conditional because for plist-put to
;; work, it is needed that the property list is not nil.
(if (null nearest-entry)
(setq nearest-entry
`(:item ,(org-entry-get nil "ITEM")
:scheduled ,entry-scheduled
:scheduled-string ,(org-entry-get nil "SCHEDULED")
:marker ,(point-marker)))
;; If a nearest entry has been found previously,
;; compare their scheduled time.
(when (> (plist-get nearest-entry :scheduled) entry-scheduled)
(plist-put nearest-entry :item (org-entry-get nil "ITEM"))
(plist-put nearest-entry :scheduled entry-scheduled)
(plist-put nearest-entry :scheduled-string (org-entry-get nil "SCHEDULED"))
(plist-put nearest-entry :marker (point-marker)))))))))
(setq my/org-agenda-nearest-upcoming-scheduled nearest-entry)
(unless nearest-entry
(error "No event with scheduled date than the current date was found."))))
(defun my/org-agenda-nearest-upcoming-scheduled-display ()
(if my/org-agenda-nearest-upcoming-scheduled
(progn
;; If the previously found entry has an scheduled date that has
;; already passed, let's search for a new upcoming scheduled.
(when (<
(plist-get my/org-agenda-nearest-upcoming-scheduled :scheduled)
(float-time))
(my/org-agenda-nearest-upcoming-scheduled-search))
(let* ((time-difference
(truncate
(-
(plist-get my/org-agenda-nearest-upcoming-scheduled :scheduled)
(float-time))))
(days (/ time-difference 86400))
(hours (/ (% time-difference 86400) 3600))
(minutes (/ (% time-difference 3600) 60)))
;; TODO: The following is a list of menu items. I still
;; don't know the meaning of the first item in the menu item
;; definition, so I've written foo.
`((foo
menu-item
,(propertize
(concat
(plist-get my/org-agenda-nearest-upcoming-scheduled :item)
" | "
(string-join
(delq
nil
(funcall
'append
(unless (eq days 0) (list (number-to-string days) "days"))
(unless (eq hours 0) (list (number-to-string hours) "hours"))
(unless (eq minutes 0) (list (number-to-string minutes) "minutes"))))
" "))
'face
`(:background ,(face-attribute 'default :background)
:foreground ,(face-attribute 'default :foreground)
:box (:line-width (1 . 1)
:color ,(face-attribute 'default :foreground))))
my/org-agenda-nearest-upcoming-scheduled-jump
:help (plist-get my/org-agenda-nearest-upcoming-scheduled :scheduled-string)))))
`((foo
menu-item
,(propertize
"No entry found"
'face
`(:background ,(face-attribute 'default :background)
:foreground ,(face-attribute 'default :foreground)
:box (:line-width (1 . 1)
:color ,(face-attribute 'default :foreground))))
ignore
:help "No entry with the nearest upcoming scheduled date found."))))
(defun my/org-agenda-nearest-upcoming-scheduled-jump ()
(interactive)
(with-current-buffer (switch-to-buffer
(marker-buffer
(plist-get my/org-agenda-nearest-upcoming-scheduled :marker)))
(goto-char (plist-get my/org-agenda-nearest-upcoming-scheduled :marker))))
#+END_SRC
^ permalink raw reply [flat|nested] 2+ messages in thread