For example, a simple org-mode file like this:

* Header one
** Sub-header one
** Sub-header two
* Header two
** Sub-header one

After exporting this org-mode file into html file, the html in browser will be like:

1. Header one
1.1 Sub-header one
1.2 Sub-header two
2. Header two
2.1 Sub-header one

But I do rarely convert org files into html files, I do a lot of note-takings from a webpage or book, so it is very friendly if the org-mode buffer can show the numbers like the html file in browser directly instead of just asterisks. Of course, when inserting header/subheader or deleting header/subheader, org-mode should change the numbers according the context just like the list in org-mode.

Is it possible to do that?

  • See related question.
    – Basil
    May 22 '17 at 11:52
  • @Basil No, it's not related.
    – CodyChan
    May 23 '17 at 1:58
  • Sorry, what I meant to say was, "you may be interested in..."
    – Basil
    May 23 '17 at 13:46

There is a package called org section numbers that does exactly this.

  • It is fine, but not good, it is not dynamic, if you insert header, the new header will still start with asterisk instead of numbers , if you delete header, the numbers of context will not change dynamically. You have to execute org-section-numbers-toggle repeatedly to make the numbers change.
    – CodyChan
    May 23 '17 at 1:57

According to lrkry's answer at reddit.com/r/emacs, I'll post his/her answer here if anyone sees this.

(define-minor-mode org-numbers-overlay-mode
  "Add overlays to org headings which number them"
  nil " *1." nil
  (let ((hooks '(after-save-hook
        (funcs '(org-promote
                 ;; org-cycle-level
    (if org-numbers-overlay-mode
          (dolist (fn funcs)
            (advice-add fn :after #'org-numbers-overlay-update))
          (dolist (hook hooks)
            (add-hook hook #'org-numbers-overlay-update)))
        (dolist (fn funcs)
          (advice-add fn :after #'org-numbers-overlay-update))
        (dolist (hook hooks)
          (remove-hook hook #'org-numbers-overlay-update))
        (remove-overlays (point-min) (point-max) 'type 'org-number)))))
(defun org-numbers-overlay-update (&rest args)
  (when org-numbers-overlay-mode
    (let ((continue t)
          (levels (make-vector 10 0))
          (any-unnumbered (member "UNNUMBERED" (org-buffer-property-keys))))
        (goto-char (point-min))
        (or (outline-on-heading-p)
        (overlay-recenter (point-max))
        (remove-overlays (point-min) (point-max) 'type 'org-number)
        (while continue
          (let* ((detail (org-heading-components))
                 (level (- (car detail) 1)))
            (when (or (not any-unnumbered)
                      (org-entry-get (point) "UNNUMBERED" 'selective))
              (let* ((lcounter (1+ (aref levels level)))
                (aset levels level lcounter)
                (loop for i from (1+ level) to 9
                      do (aset levels i 0))
                (loop for i across levels
                      until (zerop i)
                      do (setf text (if text
                                        (format "%s.%d" text i)
                                      (format " %d" i))))
                (let  ((o (make-overlay (point) (+ (point) (car detail)) nil t t)))
                  (overlay-put o 'type 'org-number)
                  (overlay-put o 'evaporate t)
                  (overlay-put o 'after-string text)))))
          (setq continue (outline-next-heading))

You can either add (provide 'org-numbers-overlay) line at the end of the code and save all of them to a file, then use it as a package, or you can just add this after that code snippet in your init.el/.emacs

(add-hook 'org-mode-hook
          (lambda ()

In case the author updates the source code, this is the original source code link.

  • This version of solution will make `emacsclient -a "" -n -c -e "(org-capture)" fail to lanuch emacs (at least for terminal emacs). org-num.el file from orgmode v9.3 supports this feature.
    – CodyChan
    Apr 18 '19 at 8:40

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.