5

I use org-capture a lot, it's a terrific feature.

However, sometimes i'd like to choose the target of the note during or at the end of the process, not at the beginning from the template.

The process I imagine (below I use the exact terms of the variable org-capture-template, in italic:

  1. C-c c
  2. choosing the entry for it's template, not caring for it's target
  3. typing my note
  4. C-c C-c refiles my note at the place I want

So far, my org-capture-template is : (("t" "Test" entry (file+headline "my/path/to/notes.org" "Entries to be refiled") (file "my/path/to/my-org-capture-template.org")))

with org-capture-template.org :

* %?
:PROPERTIES:
:TARGET-FILE:
:TARGET-HEADLINE:
:END:

What I want is C-c C-c running a function inferring the target, file and headline, from the value of TARGET-FILE and TARGET-HEADLINE, and refiling my note accordingly.

5
  • 2
    You can do this interactively by ending with C-c C-w instead of C-c C-c. Dec 31, 2014 at 12:08
  • ok, sorry if that was not clear, but I do not want to do that interactively. I want to do that automatically from the content of the not, eg :TARGET-FILE: and :TARGET-HEADLINE: values
    – JeanMichel
    Dec 31, 2014 at 16:45
  • What happens when two or more org files have the same headline -- how do you determine programmatically which file to insert the newly created capture entry -- and what happens if the user has duplicate headlines in the same file -- and what happens if none of the files have a matching headline -- it gets a little complicated to start searching and then adding prompts for the user to choose, bit is nevertheless doable.
    – lawlist
    Dec 31, 2014 at 17:37
  • I do not want to do that with prompts, but automatically from the contents of the note.
    – JeanMichel
    Dec 31, 2014 at 18:01
  • There are some situations where the computer will choose incorrectly if it is done entirely automatically without any prompts, and I have named just a few of those computer-confusing situations in the previous comment.
    – lawlist
    Dec 31, 2014 at 18:27

2 Answers 2

6

There are several ways to choose where a captured entry will go.

You can always use org-refile (C-c C-w) in the capture buffer to move the capture. This will also finalize the capture.

If you want to encode the target headline in the capture template, use file+headline as the target, thusly:

("t" "Todo" entry
  (file+headline "/path/to/file.org" "Target Headline")
  "* TODO %?"
)

Another solution is to use file+function as the target for your capture template. First define a function that prompts for a headline and jumps to it.

(defun org-get-target-headline (&optional prompt)
  "Prompt for a location in an org file and jump to it.

This is for promping for refile targets when doing captures."
    (let* ((target (save-excursion
                     (org-refile-get-location prompt nil nil t)))
           (file (nth 1 target))
           (pos (nth 3 target))
           )
    (with-current-buffer (find-file-noselect file)
        (goto-char pos)
        (org-end-of-subtree)
        (org-return)
    )))

Then add a capture template using this function to get the target:

            '("t" "Todo" entry
              (file+function "/path/to/file.org" org-get-target-headline)
             "* TODO %?")

You will be prompted for the target before being dropped into the capture buffer. This is most useful when the template has :immediate-finish t and you never get a capture buffer to refile from.

And that's not all! There are a number of other ways for a template to select it's target, see the manual for org-capture-templates for a list of them. The most general version is to use function as the target, which lets you give an arbitrary function for both the target file and headline.

EDIT:

As of org-mode 9 the above function no longer works. Instead use

(defun org-get-target-headline (&optional targets prompt)
  "Prompt for a location in an org file and jump to it.

This is for promping for refile targets when doing captures.
Targets are selected from `org-refile-targets'. If TARGETS is
given it temporarily overrides `org-refile-targets'. PROMPT will
replace the default prompt message.

If CAPTURE-LOC is is given, capture to that location instead of
prompting."
  (let ((org-refile-targets (or targets org-refile-targets))
        (prompt (or prompt "Capture Location")))
      (org-refile t nil nil prompt)))

which does the same thing, but also allows you to restrict the set of possible targets.

3
  • As answered above, I should have made it clear : for what I want to do, C-c C-w is not an option. The other solutions doesn't either fulfill the requirement : I want to automatically (not interactively) refile, at the end of the process, from the contents of the note, eg from :TARGET-FILE: and :TARGET-HEADLINE: values that I would have defined in the note.
    – JeanMichel
    Dec 31, 2014 at 16:50
  • thx. the function gives me an error: save-excursion: Wrong number of arguments: (0 . 3), 4Invalid face reference: quote. any clue?
    – zeltak
    Apr 22, 2017 at 13:06
  • I haven't seen the Invalid face error, but I do get the a Wrong number of arguments error. This must have stopped working with some org-mode upgrade. I have a version that works in Org 9 that I'll edit in.
    – erikstokes
    Apr 22, 2017 at 14:47
1

I'm not aware of any simple way to do what want here.

To run something after your note has been captured, you could try using the org-capture-after-finalize-hook. At that point you may be able to do something like this:

  • jump to the last captured note (org-capture-goto-last-stored)
  • parse the org element for your custom target information
  • call org-refile and pass a custom refile location (RFLOC) based on what you've read from the note
2
  • Instead of using org-capture-after-finalize-hook and jumping to the last capture, maybe use org-capture-before-finalize-hook instead? The capture buffer is still around and widened when before-finalize runs.
    – erikstokes
    Jan 1, 2015 at 0:10
  • That makes sense - save a step.
    – glucas
    Jan 1, 2015 at 0:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.