Skip to content

Documents with no level-1 heading subsume all level-2 headings under the first level-2 heading #571

@DivineDominion

Description

@DivineDominion

Sample document

---
title: Wat
---
## Section a

### Sub 1

### Sub 11

## Section b

### Sub 2

The imenu output of counsel-imenu and also the outline in treemacs shows this hierarchy:

image

I expected Section b and Section a to be siblings, but Section b is demoted to a child of Section a.

The code that is responsible for this is likely this parser:

markdown-mode/markdown-mode.el

Lines 5532 to 5587 in 4d7f525

(defun markdown-imenu-create-nested-index ()
"Create and return a nested imenu index alist for the current buffer.
See `imenu-create-index-function' and `imenu--index-alist' for details."
(let* ((root '(nil . nil))
cur-alist
(cur-level 0)
(empty-heading "-")
(self-heading ".")
hashes pos level heading)
(save-excursion
;; Headings
(goto-char (point-min))
(while (re-search-forward markdown-regex-header (point-max) t)
(unless (markdown-code-block-at-point-p)
(cond
((match-string-no-properties 2) ;; level 1 setext
(setq heading (match-string-no-properties 1))
(setq pos (match-beginning 1)
level 1))
((match-string-no-properties 3) ;; level 2 setext
(setq heading (match-string-no-properties 1))
(setq pos (match-beginning 1)
level 2))
((setq hashes (markdown-trim-whitespace
(match-string-no-properties 4)))
(setq heading (match-string-no-properties 5)
pos (match-beginning 4)
level (length hashes))))
(let ((alist (list (cons heading pos))))
(cond
((= cur-level level) ; new sibling
(setcdr cur-alist alist)
(setq cur-alist alist))
((< cur-level level) ; first child
(dotimes (_ (- level cur-level 1))
(setq alist (list (cons empty-heading alist))))
(if cur-alist
(let* ((parent (car cur-alist))
(self-pos (cdr parent)))
(setcdr parent (cons (cons self-heading self-pos) alist)))
(setcdr root alist)) ; primogenitor
(setq cur-alist alist)
(setq cur-level level))
(t ; new sibling of an ancestor
(let ((sibling-alist (last (cdr root))))
(dotimes (_ (1- level))
(setq sibling-alist (last (cdar sibling-alist))))
(setcdr sibling-alist alist)
(setq cur-alist alist))
(setq cur-level level))))))
;; Footnotes
(let ((fn (markdown-get-defined-footnotes)))
(if (or (zerop (length fn))
(null markdown-add-footnotes-to-imenu))
(cdr root)
(nconc (cdr root) (list (cons "Footnotes" fn))))))))

I may or may not be able to adjust this myself, we'll see, as my elisp isn't that good :) So I'm posting this issue to track the behavior. If someone else chimes in, great!.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions