1

Within the same org buffer, how to jump to heading with a specific Custom_ID property value?
Edit:
I need an Elisp function that takes a string argument and jumps to the heading with a Custom_Id property's value equal to that string.
Sorry for not being clear from the start. I didn't anticipate that my project would require me to work specifically with Elisp programming.
Note about the accepted answer:

  • The first answer , shows how to accomplish my request interactively.

  • The second answer, shows how to accomplish my request by using Elisp

    Both answers should have been accepted, and the separation is due to my lack of consistency and clarity from the start.

2

2 Answers 2

1

The modified question asks for a Lisp function to jump to the headline whose CUSTOM_ID property has the given value. The question is underspecified because there may be multiple headlines with a CUSTOM_ID property having that value.

The following solution assumes that you want to go to the first match, but can be modified fairly easily to do something else (which is left for you to figure out and implement).

The first function finds all the matches as a list and returns a list of positions, the positions of the headlines that match. That is completely general and can be used even if my assumption about the first match is inadequate.

The second function then checks that the list is non-empty and jumps to the position that is first on that list.


(defun my/find-custom-id (value)
  (org-map-entries #'point (format "CUSTOM_ID=\"%s\"" value) 'file))

(defun my/goto-first-match (value)
  (interactive "sCUSTOM_ID value: ")
  (let ((poslist (my/find-custom-id value)))
    (if (> (length poslist) 0)
        (goto-char (nth 0 (my/find-custom-id value)))
      (message "No CUSTOM_ID with value %s" value))))

You could simplify the test of non-emptiness for poslist but I left it like this to make it more easily generalizable.

You can call it from Lisp like this: (my/goto-first-match "foo") or you can call it interactively like this: M-x my/goto-first-match and enter foo at the prompt.

2

You can use a sparse tree search C-c / p custom_id RET <value>. See Sparse Trees in the manual. The sparse tree is (mostly) folded, but top-level headlines that match are highlighted and lower-level headlines that match unfolded up to the headline (you can change the behavior, but I think I am describing the default behavior). So it is easy to find all the matching headlines. You can exit the sparse tree view with C-c C-c.

For example, if I have an Org mode file like this:

* something
wild
* one
:PROPERTIES:
:CUSTOM_ID: foo
:END:

* something
wicked this way comes
* two
** two.one
:PROPERTIES:
:CUSTOM_ID: barfoo
:END:

* something
completely different
* three
** three.one
*** three.one.one
:PROPERTIES:
:CUSTOM_ID: foo
:END:

** three.two

*** three.two.one

and I do C-c / p CUSTOM_ID RET foo, I get this view:

property search results

The highlights (on the one headline and the three.one.one headline - note that the red rectangle is my cursor, it is not a highlight) indicate a match, so you can TAB on each one to open it and on the PROPERTIES drawer underneath to verify. Note that all other headlines (in particular the three something headlines) don't match and remain folded and un-highlighted. When you are done, exit the sparse tree view with C-c C-c.

C-c / can yield sparse trees based on different matching criteria: p for properties, r for regexps, m for matching tags and properties (see Matching tags and properties in the manual), and others.

For example, doing C-c / r CUSTOM_ID RET will find all CUSTOM_ID properties (as well as other places mentioning CUSTOM_ID: it just uses it the string CUSTOM_ID as a regexp). This is what that looks like on the example above:

regexp search results

C-c / m can do all sorts of searches but you need to practice: the matching language is somewhat peculiar. You'll probably have to reread the section I linked to above a few times.

1
  • As a new Emacs user , thank you for introducing me to Org-sparse-tree. However, I am looking to satisfy my same request using Elisp programming. I need an Elisp function that takes a string argument and jumps to the heading with a Custom_Id property's value equal to that string. Sorry for not being clear from the start. I didn't anticipate that my project would require me to work with Elisp programming.
    – cuore RT
    Jun 17, 2023 at 13:55

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.