As NickD points out, there is a hook that allows this. It falls under Advanced Configuration in the Org manual.
Specifically,
The export process executes two hooks before the actual exporting begins. The first hook, org-export-before-processing-hook
, runs before any expansions of macros, Babel code, and include keywords in the buffer. The second hook, org-export-before-parsing-hook
, runs before the buffer is parsed.
I think the before-parsing
hook is the better fit for this problem, but I’m not sure.
The manual doesn’t mention this, but the hook is actually an abnormal hook, so its functions must take an argument (the exporting backend).
It's also worth mentioning that these functions don't execute in the context of the org buffer you're exporting from. Like all export transformations, they run in a temporary buffer that starts with a copy of the org buffer's text.
To do the prefix insertion, use org-babel-map-src-blocks
and take advantage of how it dynamically binds useful context variables like the source block language and the beginning / end of the code body.
(defun my-insert-shell-prompt (_backend)
(org-babel-map-src-blocks nil ; nil implies current buffer
(let (;; capture macro-defined variables
(lang lang)
(beg-body beg-body)
(end-body end-body)
;; other variables
(shell-langs '("sh" "shell"))
(prefix "$ "))
(when (member lang shell-langs)
(goto-char beg-body)
(skip-chars-forward "\n\s-" end-body)
(while (< (point) end-body)
(insert prefix)
(end-of-line)
(skip-chars-forward "\n\s-" end-body)))))))
(add-hook 'org-export-before-parsing-hook #'my-insert-shell-prompt)
org-export-filter-src-block-functions
), although I don't know how to select justshell
src-blocks. See Advanced configuration in the org manual and the (admittedly opaque-unless-you-know-the-code) reference docs on Worg.filter-src-block
functions act too late to recognize the source block language (they only receive the post-processed string value of the source block). But I'm pretty sure I can work something into thefilter-parse-tree
functions that walks the tree and modifies shell source blocks specifically.org-babel-map-src-blocks
and the two hooksorg-export-before-{processing,parsing}-hook
. That's probably what I'm going to do.