0

I'm a beginner at elisp and I'd like your input on my strategy for writing some code for my org/org-roam setup.

I have a file called inbox.org, that I capture stuff into when I'm on the go (via Plain Org). It's structured like this:

#+title: Capture inbox
* First thing I captured
  Some text
* Second thing I captured
  etc

I also use the org-roam dailies feature, where I create a new daily note every day. My template for dailies looks like this:

#+title: %<%Y-%m-%d (%a)>
#+location: %(gt/daily-location)
#+weather: %(gt/daily-weather)

* Diary

(gt/daily-* are helper functions that I wrote, these basically run shell scripts and insert the output)

Here's what I would like to do: I want to add a new tree to my daily file called Inbox and move all the trees out of inbox.org into that tree in my daily file. Once that's done, I want my inbox.org to contain only its title (#+title: Capture inbox) and nothing else.

I have two ideas on how to do this:

  1. Add another helper function call to my daily template, that will open inbox.org, and return the raw contents. That's easy enough to do, but the formatting is messy: top level headers from my inbox file will be at the top level of my daily note as well, and not under the Inbox tree as I would like.

  2. Hook into the org-roam-dailies-find-file-hook, which is triggered whenever you open a daily file. In that case, I would have to somehow check if the daily file opened is for today, if it's just being created (rather than me coming back to it later, when I would not want to insert the contents of inbox.org), etc.

The second option feels like the start of a cleaner solution, but I'm not sure how to proceed. Would anyone have any advice on how this could be accomplished?

gosha
  • 113
  • 5
  • Have you looked at `org-refile`? See [Refiling and Archiving](https://orgmode.org/manual/Refiling-and-Archiving.html) in the Org mode manual. – NickD Nov 16 '22 at 01:28
  • Thanks @NickD, `org-refile` is what I needed, but it was more the logic around it that I found difficult to figure out. – gosha Nov 17 '22 at 09:47

1 Answers1

1

After a lot of trial and error, I came up with a solution that works for me (with inspiration from this answer). Here it is:

(setq gt/org-inbox-file (file-name-concat org-directory "inbox.org"))

(defun gt/refile-to-file-headline (file headline)
  "Refile tree to a specific file and a specific headline"
  (let ((pos (save-excursion
               (find-file file)
               (org-find-exact-headline-in-buffer headline))))
    (org-refile nil nil (list headline file nil pos))))

(defun gt/org-roam-today-daily-path ()
  "Return the path for today's org-roam daily note"
  (file-name-concat
   org-roam-directory
   org-roam-dailies-directory
   (format-time-string "%F.org")))

(defun gt/refile-inbox-to-org-roam-today-daily ()
  "Refile all org trees from inbox file to today's org-roam daily note"
  (let ((inbox-buffer (find-file-noselect gt/org-inbox-file)))
    (set-buffer inbox-buffer)
    (org-map-entries
     (lambda ()
       (setq org-map-continue-from 0)
       (gt/refile-to-file-headline
        (gt/org-roam-today-daily-path)
        "Inbox")))
    (save-buffer)))

(defun gt/org-roam-daily-hook ()
  "Hook called upon visiting an org-roam daily note"
  (let ((daily-buffer (current-buffer)))
    ;; Only perform this if we're visiting the buffer for today's daily
    (when (string= (buffer-file-name daily-buffer) (gt/org-roam-today-daily-path))
      (gt/refile-inbox-to-org-roam-today-daily)
      (set-buffer daily-buffer))))

(add-hook 'org-roam-dailies-find-file-hook 'gt/org-roam-daily-hook)

gosha
  • 113
  • 5