5

Let's say that I have a tree of tasks like so:

* TODO Launch website
** TODO Get database running
*** TODO Select MySQL vs. PostgreSQL

Let's say I'm looking at the "Select MySQL vs. PostgreSQL" and I decide I want to file a task under that headline using my Org Capture template. Is there a way to directly tell org-capture to file the new headline under the current headline (i.e., the headline at (point))? I'm aware of the (clock) capture target, but I don't necessarily want to have to clock in at the current point.

2 Answers 2

3

Go to a new line below the headline *** TODO Select MySQL vs. PostgreSQL Then press C-u 0 before your capture key, i.e.

C-u 0 <your_capture_key>

and you're good to go. The indentation level will be three stars, so you have to indent it manually by M- rightarrow

You can also press C-0 <your_capture_key> and Emacs will interpret it as C-u 0

3
  • Yes, this works pretty well actually! I might change my answer to be based on this one, since I still do want to automatically adjust the indentation level. Aug 9, 2020 at 20:57
  • Let me know when you figure out the automatic indentation. I'd be interested, too
    – GNUmon
    Aug 10, 2020 at 16:49
  • Hi, I've updated my function at emacs.stackexchange.com/a/58009/17182 to be more robust Feb 2, 2022 at 20:54
1

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."
  (interactive "P")
  (unwind-protect
      (progn
        (unless (eq major-mode 'org-mode)
          (user-error "Must be called from an Org-mode buffer"))
        (org-with-point-at (point)
          (org-back-to-heading t)
          (let* ((headline-marker (point-marker))
                 (headline-level (org-current-level)))
            (org-end-of-subtree t)
            (unless (org--line-empty-p 1)
              (end-of-line)
              (open-line 1)
              (forward-line 1))
            (cl-letf*
                (((symbol-function 'my-org-capture-under-headline--fixup-level)
                  (lambda ()
                    ;; 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))
                                ((marker-buffer begin-marker)))
                      ;; Go to the capture buffer.
                      (org-goto-marker-or-bmk begin-marker)
                      ;; Make the captured headline one level below the original headline.
                      (while (< (org-current-level) (+ 1 headline-level))
                        (save-excursion (org-demote-subtree)))
                      (while (> (org-current-level) (+ 1 headline-level))
                        (save-excursion (org-promote-subtree))))))
                 ;; 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’
                 ((symbol-function 'org-capture-finalize)
                  (lambda (&optional stay-with-capture)
                    (my-org-capture-under-headline--fixup-level)
                    (org-capture-finalize-orig stay-with-capture))))
              (apply #'org-capture 0 keys)
              ;; If the template didn’t contain ‘:immediate-finish’, we fix up
              ;; levels now.
              (my-org-capture-under-headline--fixup-level)))))))
(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.

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.