If I'm in an org file, I want a command that narrows a candidate list, in ivy/helm style, comprised of all org headlines in the file and lets me choose the headline, through fuzzy searching, to which I want to jump to. Is there a way to do that?
8 Answers
The Org Manual node on Motion gives a somewhat laconic description of the built-in command org-goto
(default binding: C-c C-j
), whose behaviour can easily be customised to achieve the desired effect:
- Inspect the documentation of the customisable variable listed at the end of this manual node:
C-h v org-goto-interface RET
If you are happy to forgo the default
org-goto
behaviour of incrementally searching through the buffer's outline, you can switch to picking a headline via completion:(setq org-goto-interface 'outline-path-completion)
Users of completion packages like
ido
/ivy
/helm
will probably want to change the following setting in order to see the whole target path at once:(setq org-outline-path-complete-in-steps nil)
See here for more discussion.
This approach has the added benefit (over using, say, helm
-specific functionality) of working with all completion frameworks that plug into the default completing-read
, including, as I can personally confirm, ivy
.
ADDENDUM:
When using the outline-path-completion
interface to the org-goto
command as described in this answer, the customisable variable org-goto-max-level
determines the maximum depth of headlines to offer.
EDIT:
I found an older, relevant question with useful answers: https://stackoverflow.com/q/15011703/3084001
CLARIFICATION (as prompted by Att Righ's comment):
Setting org-goto-interface
to one of the two recognised values does not mean sacrificing the alternative interface. Calling org-goto
with a prefix argument (i.e. C-u C-c C-j
or C-u M-x org-goto RET
) automatically selects the alternative interface for the current completion. This way, you can set org-goto-interface
to the interface you are likely to use most often and use the prefix argument when you wish to temporarily switch behaviour. If even this does not suit your needs, you can always write your own wrapper around org-goto
, as per Att Righ's example.
-
> forgo the default org-goto behaviour, you can work around this by using a let binding around the functional call
(defun my-org-goto () (let ((org-goto-interface 'outline-path-completion)) (org-goto)))
– Att RighCommented May 7, 2017 at 1:07 -
outline-path-completion
does not play nicely withhelm
on my box (it can't complete past one level - achieved by pressing<TAB>
ifhelm
is disabled: seehelm-completing-read-handlers-alist
)– Att RighCommented May 7, 2017 at 1:28 -
@AttRigh Sure,
let
-expressions can be used for any sort of temporary binding; this question is more about relevant settings/functionality/packages. A more general way to achieve a temporary switch of interface is to callorg-goto
with a prefix argument. I'll add a note to this answer.– BasilCommented May 7, 2017 at 2:19 -
1thanks @Basil for the detaild answer. Unfortunately, the completion in this approach does not work as well as
worf
orcounsel-imenu
.– ninrodCommented May 8, 2017 at 1:48 -
1@Basil, actually, org-goto is my preferred method now because it maintains the tree context while worf does not.– ninrodCommented Oct 24, 2017 at 20:37
I use the package worf, but I bind only one of its functions:
(use-package worf
:diminish worf-mode
:bind (:map org-mode-map ("C-c h" . worf-goto)))
worf-goto
gives you a list of the headings in the buffer in the mini buffer, which you can then filter.
The package is made by the author of ivy, so if you like ivy, you might like worf.
Some relevant snippets from worf.el:
;; - "g" (`worf-goto'): select an outline in the current buffer, with
;; completion. It's very good when you want to search/navigate to
;; a heading by word or level. See https://github.com/abo-abo/lispy
;; for a package that uses this method to navigate Lisp code.
(defun worf-goto-action (x)
(with-ivy-window
(goto-char (cdr x))
(outline-show-children 1000)
(worf-more)))
(defun worf-goto ()
"Jump to a heading with completion."
(interactive)
(let ((cands (worf--goto-candidates)))
(cond ((eq worf-completion-method 'helm)
(require 'helm-multi-match)
(let (helm-update-blacklist-regexps
helm-candidate-number-limit)
(helm :sources
`((name . "Headings")
(candidates . ,cands)
(action . worf-goto-action)
(pattern-transformer . worf--pattern-transformer)))))
((eq worf-completion-method 'ivy)
(ivy-read "Heading: " cands
:action 'worf-goto-action)))))
-
1thanks @tirocinium.
counsel-imenu
completion works better than worf but can't search through level1 org headlines. worfs searches all levels, so I think this what I'm looking for.– ninrodCommented May 8, 2017 at 1:50 -
@ninrod Have you tried setting
org-imenu-depth
to something greater than the default of 2?– eeowaaCommented Jun 11, 2019 at 22:04
I find helm-org-rifle particularly nice. Also anything that takes imenu source will be able to display headers (e. g. Helm with imenu).
-
It should be noted that
helm-org-rifle
searches the content of org entries in addition to their titles. I found no way to alter this behaviour.helm-org-rifle
referencesorg-search-goto
which does search all headlines but doesn't really support fuzzy searching.– Att RighCommented May 7, 2017 at 1:02 -
Att Righ is right,
helm-org-rifle
does not search only headings. It could be expanded to do this, but there's little reason to do so, sincehelm-org-in-buffer-headings
, etc. exist in Helm itself.– user3871Commented May 8, 2017 at 23:09
imenu
is built into Emacs and can be paired with helm/ivy to provide the fuzzy search required. I'd recommend helm-org-rifle
if you use helm, however.
I use counsel-imenu
; it will list the different heads, you can type some letters to narrow your selection and then just press <return>
.
-
hi @gnuvince. this does not allow me to jump to level 1 org files right?– ninrodCommented May 6, 2017 at 20:02
Flagrant self-promotion, but you might like to try out orgnav. Which is my kind of alpha (but actively used by me) project for this purpose.
orgnav searches headlines rather than content, can vary the depth of search, search subtrees rather than the entire file (though this can also be achieved with narrowing).
Here's a video of some features: https://asciinema.org/a/1r0fp33xgwh48lfgsh7mllw4u
You should probably also be aware of helm-org
package which is part of helm
which was the inspiration for this package (or rather whose limitations were the inspiration for this package), as well as helm-org-rifle
discussed in other posts.
(Courtesy of answers here: https://www.reddit.com/r/emacs/comments/69mc6l/how_to_jump_directly_to_an_orgheadline/
)
Also potentially of interest is the worf-goto
function as part of worf
(an org navigation mode that applies a different set of keybindings over "*" before headlines). This seems very much analogous to helm-org
.
The swiper library has a new feature in 0.9.0, which is completion for headlines of files in your org-agenda-files.
counsel-org-agenda-headlines
Just need to setup your agenda files list in org init.
(setq org-agenda-files (list "~/org/work.org"
"~/org/school.org"
"~/org/home.org"))
In relation to @tirocinium's answer, this provides the same but for many agenda files.
I recommend helm-org-in-buffer-headings
. It's built-in to Helm, and it respects narrowed buffers, which is important if you use indirect buffers to edit subtrees independently. There's also helm-org-parent-headings
for navigating up a tree, and helm-org-agenda-files-headings
for navigating across all agenda files.