I've implemented the following functions to implement this feature:
my-org-capture-under-headline: the main command.
- Some advice around
org-capture to provide a new
C-u 2 prefix argument
;; Create ‘C-u 2 M-x org-capture’ command to refile org-capture template under
;; headline at point.
(defun my-org-capture-under-headline (&optional _goto keys)
"Capture under the headline at current point.
This finds an appropriate point at the end of the subtree to capture the new
entry to, then call ‘org-capture’ with \"C-u 0\" to capture at this new point,
and finally fixes the level of the newly-captured entry to be a child of the
headline at which this function was called.
KEYS are passed to ‘org-capture’ in its KEYS argument. _GOTO corresponds to the
GOTO argument of ‘org-capture’, but is is ignored because we intentionally place
the point where we want it."
(unless (eq major-mode 'org-mode)
(user-error "Must be called from an Org-mode buffer"))
(let* ((headline-marker (point-marker))
(unless (org--line-empty-p 1)
;; If :begin-marker doesn’t point to a buffer, the capture
;; has already been finalized, so don’t try to do any work
;; in that case.
(when-let* ((begin-marker (org-capture-get :begin-marker))
;; Go to the capture buffer.
;; Make the captured headline one level below the original headline.
(while (< (org-current-level) (+ 1 headline-level))
(while (> (org-current-level) (+ 1 headline-level))
;; Store the original ‘org-capture-finalize’ for the override before.
((symbol-function 'org-capture-finalize-orig) (symbol-function 'org-capture-finalize))
;; Need to fixup level in case ‘:immediate-finish’ set in ‘org-capture-templates’
(lambda (&optional stay-with-capture)
(apply #'org-capture 0 keys)
;; If the template didn’t contain ‘:immediate-finish’, we fix up
;; levels now.
(defun my-org-capture-under-headline-prefix (_orig-fn &rest _args)
"Provide an additional “C-u 2” prefix arg to `org-capture'.
When ‘org-capture’ is called with this prefix argument, it will capture a
headline according to the template you select, and then immediately refile that
headline under the headline at the current point."
(let ((goto (nth 0 _args)))
(if (equal goto 2)
(apply #'my-org-capture-under-headline _args)
(apply _orig-fn _args))))
(advice-add 'org-capture :around #'my-org-capture-under-headline-prefix)
Update 2022-02-22: make the function more robust.