1

Often I have a problem that I browse through the content of the heading but I forget what is a heading I'm currently at. So I leave the mark, go back to the heading, read it, and jump back to the mark. It disrupts the workflow and wastes time.

I think the solution to this problem would be displaying the current heading (or entire heading path separated by "/" or similar) in the echo area while I browse/edit heading content or make it stick to the top in a similar way position: sticky in CSS3 works.

Are there any plugins or configuration options that address this issue?

3

You can add something to either the mode line or the header line to keep track of such things. Here I use the header line because the mode line is usually rather crowded, whereas the header line is not used as frequently.

You can add a header line to any buffer by

(setq header-line-format "foo")

That makes header-line-format a buffer-local variable with the value foo which is displayed at the top of the buffer window. Whenever the value of header-line-format changes, the buffer is marked for redisplay, so you always see the currently set value.

You can have the header line dynamically change by doing this:

(setq header-line-format '(:eval FORM))

The form is evaluated whenever emacs thinks that it should be - but you can force the re-evaluation if needed - my experiments show that it is not needed: emacs does the right thing on its own.

So all we have to do for this particular case is write a function ndk/org-breadcrumbs that calculates what you want to show and do

(setq header-line-format '(:eval (ndk/org-breadcrumbs)))

The function is modeled after a similar calculation that is done in the agenda for the %b specification in org-agenda-prefix where the name breadcrumbs is used to indicate the chain of headings that get you to the current heading.

(defun ndk/heading-title ()
   "Get the heading title."
   (save-excursion
     (if (not (org-at-heading-p))
       (org-previous-visible-heading 1))
     (org-element-property :title (org-element-at-point))))

(defun ndk/org-breadcrumbs ()
   "Get the chain of headings from the top level down
    to the current heading."
   (let ((breadcrumbs (org-format-outline-path
                         (org-get-outline-path)
                         (1- (frame-width))
                         nil "->"))
         (title (ndk/heading-title)))
     (if (string-empty-p breadcrumbs)
         title
       (format "%s->%s" breadcrumbs title))))

(setq header-line-format '(:eval (ndk/org-breadcrumbs)))

If you just want the title of the containing section, you can just use ndk/heading-title:

(setq header-line-format '(:eval (ndk/heading-title)))

but the extended breadcrumbs version seems attractive to me.

Setting the header-line-format variable can be done for a single buffer as above, or if you want this for every Org mode buffer it can be done in the mode hook:

(defun ndk/set-header-line-format()
  (setq header-line-format '(:eval (ndk/org-breadcrumbs))))

(add-hook 'org-mode-hook #'ndk/set-header-line-format)
| improve this answer | |
  • Thanks! This is perfect. – Adam Faryna Oct 11 at 20:43
  • Great! Glad you liked it :-) – NickD Oct 12 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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