1

What's the easiest way to jump to a heading in a datetree programmatically?

I basically want: whenever I open my org file with file+olp+datetree structure to jump to a current day, if there's no heading for the current day, then the latest available one.

2 Answers 2

1

What this function does is it checks for a headline that matches the current date and jumps to it when it finds. I'm assuming recent entries are placed at the beginning of the file. If that's not the case you may want to start parsing from the end of the file.

(defun datetree-jump ()
  (let ((point (point)))
    (catch 'found
      (goto-char (point-min))
      (while (outline-next-heading)
        (let* ((hl (org-element-at-point))
               (title (org-element-property :raw-value hl)))
          (when (string= title (format-time-string "%F %A"))
            (org-show-context)
            (setq point (point))
            (throw 'found t)))))
    (goto-char point)))

Here's a more thorough attempt at solving both parts of your problem. The first function returns a list of fallback dates starting from today (defaults to one year). The second function jumps to the first headline in the buffer matching any of the fallback dates.

(defun datetree-dates ()
  (let (dates
        (day (string-to-number (format-time-string "%d")))
        (month (string-to-number (format-time-string "%m")))
        (year (string-to-number (format-time-string "%Y"))))
    (dotimes (i 365)
      (push (format-time-string "%F %A" (encode-time 1 1 0 (- day i) month year))
            dates))
    (nreverse dates)))

(defun datetree-jump ()
  (let ((point (point)))
    (catch 'found
      (goto-char (point-min))
      (while (outline-next-heading)
        (let* ((hl (org-element-at-point))
               (title (org-element-property :raw-value hl)))
          (when (member title (datetree-dates))
            (org-show-context)
            (setq point (point))
            (throw 'found t)))))
    (goto-char point)))
2
  • Thank you very much. Your posted code snippet was incredibly useful. I learned a few things from it.
    – iLemming
    Commented May 19, 2019 at 8:01
  • To bind this function to some keys (e.g. C-c e) I had to add (interactive) as the first line of the datetree-jump function (that is between (defun datetree-jump () and (let ((point (point)))). I bind it with (bind-keys :map org-mode-map ("C-c e" . datetree-jump)).
    – Giuseppe
    Commented Sep 28, 2021 at 8:27
1

As suggested in the accepted answer, it can be useful to parse the buffer from the bottom up in case the headlines with later dates are further in the buffer.

Here is the version of the datetree-jump function that does this. I also added (interactive) to be able to bind it to a key combination.

(defun datetree-jump ()
  (interactive)
  (let ((point (point)))
    (catch 'found
      (goto-char (point-max))
      (while (outline-previous-heading)
        (let* ((hl (org-element-at-point))
               (title (org-element-property :raw-value hl)))
          (when (member title (datetree-dates))
            (org-show-context)
            (setq point (point))
            (throw 'found t)))))
    (goto-char point)))

NB: Only these two lines had to be changed:

      (goto-char (point-min))
      (while (outline-next-heading)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.