1

Is there in Emacs such a function to search within all headings of all Org mode files within a folder or group of folders?

2
  • See the following similar question: emacs.stackexchange.com/questions/74802/… - as I said there, I don't know of a way to do a search across a set of Org mode files (unless they are part of your agenda files, or you create a temporary org-agenda-files list with just those files). I describe a method to search for headlines in a single file in there. If you combine those two ideas, you might be able to do what you want.
    – NickD
    Commented Dec 6, 2022 at 13:25
  • Thanks, indeed it searches and lists all headings. I want to be able to search for a specific heading, not list them.
    – Adelita
    Commented Dec 8, 2022 at 9:38

2 Answers 2

3

Adapted from the answer given here. The following function will list all org mode headings in the directories passed to the function (more info in the docstring):

(require 'xref)

(setq my-search-dirs '("~/.emacs.d" "dir-2"))

(defun my-search-heading-across-directories ()
  "Lists all org-mode headings in DIRECTORIES.
Takes any number of directories (separate by `SPC').

When called interactively then prompts for a directory after
which it lists all org mode headings in files of that directory."
  (interactive)
  (let ((files (seq-filter (lambda (b) (string-match "org$" b))
                           (mapcan (lambda (d)
                                     (mapcar (lambda (f)
                                               (concat (file-name-as-directory d) f))
                                             (directory-files d)))
                                   my-search-dirs))))
    (xref--show-xrefs
     (apply-partially #'xref-matches-in-files "^*\+"
                      (mapcar #'expand-file-name files))
     nil)))

Functionality to subsequently easily search/narrow down over the headings is provided by packages like helm-xref and ivy-xref.

To search in multiple directories do

M-: (my-search-heading-across-projects "~/dir-1" "dir-2")

To call it with a list of folders, call it using apply.

There exists xref-matches-in-directory also, but it requires some 'trickery' to make it work with xref--show-xrefs while searching in multiple directories.

27
  • 1
    Apparently, the function xref-show-xrefs, which calls xref--show-xrefs was only added in Emacs 29. In Emacs < 29 one should call xref--show-xrefs directly. I have updated the answer, where I have also fixed some other details. Please search the web for the meaning/usage of apply (and its difference from funcall) in elisp/Emacs. Commented Dec 7, 2022 at 13:57
  • 1
    If you use some completion framework like vertico/ivy/helm, then you can further narrow down to some specific heading (as mentioned in the linked answer). If you are not using any of these, then you can use 'isearch' (C-s) to further search for some specific heading. Alternatively, you could modify the function and filter the results returned by xref-matches-in-files directly, but I would recommend you install one of the aforementioned completion frameworks (for simplicity I would recommend Ivy, which is what I use, but all of them are good). Commented Dec 8, 2022 at 10:19
  • 1
    I've updated the answer, please try again to see what I mean, there is no extra typing compared to the other answer (when called via M-x, i.e. it prompts directly to find the heading). Before the update, there was the extra step of selecting directories, but I mentioned the option of using apply to pass the directories as a list. Anyway, now you can just configure the list like in the other answer. Commented Dec 9, 2022 at 9:59
  • 1
    Okay, I have found that it requires the package helm-xref. I assumed this was simply configured by helm. I will again update the answer. Sorry, for the misunderstanding, and thanks for keep trying/and the feedback. B.t.w. I do think that this answer, i.c.w. helm-xref, does provide the nicer solution. Commented Dec 9, 2022 at 10:34
  • 1
    Did you see my latest comment (and the updated answer)? Because it mentions, that this functionality requires the package helm-xref to be installed. Then, you can narrow down, with helm (as usual in helm). Commented Dec 9, 2022 at 11:56
2

There is. You can search with grep. For example, M-x rgrep * todo should list your TODOs. There's also a grep-find command you try.

Personally, I like a combination of helm and ripgrep, so to search all headings in the current directory I use M-x helm-do-grep-ag ^\*+ foobar.

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.