Emacs Markdown heading refiling (and "Paste as Markdown")
Tools
Yesterday evening was "what even is going on in custom.el?", which a Doom user is not supposed to worry about because the 🚨 ⚠️ DO NOT TOUCH THIS ⚠️ 🚨 messages you get when you try to use Customize are adequate for most people. Not me, apparently.
Upon decrufting it stuff that was not working suddenly started working again. A scroll through the kill ring afterward was a little dizzying and disorienting. I have no idea what problems I thought I was solving, but have become acutely aware of all the problems I caused.
Anyhow, it was all in service of trying to dial in my particular plaintext writing workflow:
I like org's refile and archive functions a lot — you pick a heading and move it to another file, either appending it or situating it under an existing heading — and I've seen them replicated elsewhere in the Markdown ecosystem (e.g. as Obsidian plugins). It's great for moving atomic notes into a working doc or—in Doom's literate config—moving configuration ideas into the historical record where you can revisit them later, or learn from them, without relying on git for that kind of historic excavation.
We just enabled Gemini at work and I've been trying to help some folks get up and running with custom Gems, so I used that as an excuse to futz during work hours. Is this good elisp? I dunno. And given we're working with lightly formatted text files, something is going to throw it off. But it solves a small problem and, unlike org's refile options, it doesn't touch the current file (which is versioned anyhow, in case something subtle starts going wrong). I guess it's not really "refiling" at this point, but let's see how it works just copying for a while.
(defun markdown-refile-heading-section-direct ()
"Append Markdown heading section at point to a chosen file."
(interactive)
(save-excursion
(unless (looking-at "^\\(\#+\\) ")
(error "Point must be on a Markdown heading line"))
(let* ((current-level (length (match-string 1)))
(start (point))
end
(target-file (read-file-name "Refile section to file: ")))
;; Move past the current heading line
(forward-line 1)
;; Find the next heading of the same or shallower level
(setq end
(catch 'found
(while (re-search-forward "^\\(\#+\\) " nil t)
(when (<= (length (match-string 1)) current-level)
(throw 'found (match-beginning 0))))
(point-max))) ; If not found, go to end of buffer
;; Append to target file
(when (and target-file (not (string-empty-p target-file)))
(append-to-file start end target-file)))))