Skip to content

Commit

Permalink
Follow link in toc: M-x markdown-toc-follow-toc-link-at-point
Browse files Browse the repository at this point in the history
Related #42
  • Loading branch information
ardumont committed May 17, 2020
1 parent 189d5f1 commit 9ef2b32
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 2 deletions.
43 changes: 41 additions & 2 deletions markdown-toc.el
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Return the end position if it exists, nil otherwise."
markdown-toc-header-toc-end))

(defcustom markdown-toc-indentation-space 4
"Let the user decide the indentation level")
"Let the user decide the indentation level.")

(defcustom markdown-toc-user-toc-structure-manipulation-fn
(lambda (toc-structure) toc-structure)
Expand Down Expand Up @@ -264,6 +264,8 @@ If called interactively with prefix arg REPLACE-TOC-P, replaces previous TOC."
markdown-toc--generate-toc
insert)))

(defalias 'markdown-toc/generate-toc 'markdown-toc-generate-toc)

;;;###autoload
(defun markdown-toc-generate-or-refresh-toc ()
"Generate a TOC for markdown file at current point or refreshes an already generated TOC."
Expand All @@ -284,7 +286,44 @@ If called interactively with prefix arg REPLACE-TOC-P, replaces previous TOC."
(save-excursion
(markdown-toc--delete-toc t)))

(defalias 'markdown-toc/generate-toc 'markdown-toc-generate-toc)
(defun markdown-toc--read-title-out-of-link (link)
"Extract the link title out of a markdown LINK title.
This assumes no funky stuff in the markdown link format ` - [<title>](...) ` "
(->> link
s-trim
(s-chop-prefix "- [")
(s-split "]")
car))

(defun markdown-toc--title-level (link)
"Determine the markdown title LINK out of its indentation.
If misindented or not prefixed by `-`, it's considered not a link
and returns nil. Otherwise, returns the level number."
(when (s-prefix? "-" (-> link s-trim)) ;; if not, it's not a link title
(let ((indent (->> link
(s-split "-")
car ;; first string contains a string with empty spaces
;; which should be a multiple of
;; `markdown-toc-indentation-space`
length)))
(when (zerop (% indent markdown-toc-indentation-space))
(+ 1 (/ indent markdown-toc-indentation-space))))))

;;;###autoload
(defun markdown-toc-follow-toc-link-at-point ()
"On a given toc link, navigate to the current markdown header.
If the toc is misindented (according to
markdown-toc-indentation-space`) or if not on a toc link, this
does nothing.
"
(interactive)
(let* ((full-title (buffer-substring-no-properties (point-at-bol) (point-at-eol))))
(let ((level (markdown-toc--title-level full-title)))
(when level ;; nil if misindented or not on a title
(let ((title (markdown-toc--read-title-out-of-link full-title)))
(goto-char (point-min))
(search-forward-regexp (format "%s %s" (s-repeat level "#") title))))
(message "markdown-toc: Not on a link (or misindented), nothing to do"))))

(defun markdown-toc--bug-report ()
"Compute the bug report for the user to include."
Expand Down
85 changes: 85 additions & 0 deletions test/markdown-toc-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -716,5 +716,90 @@ System information:
((:input '((:message2)) :output :res2))))
(markdown-toc-bug-report)))))

(ert-deftest markdown-toc--read-title-out-of-link ()
(should (string= "this is the title"
(markdown-toc--read-title-out-of-link " - [this is the title](#this-is-the-link) ")))
(should (string= "another title"
(markdown-toc--read-title-out-of-link " - [another title](#this-is-the-link)
with multiple line
should not matter "))))

(ert-deftest markdown-toc--title-level ()
(should (eq 1
(markdown-toc--title-level "- [this is the title](#this-is-the-link)")))
(should (eq 4
(let ((markdown-toc-indentation-space 4))
(markdown-toc--title-level " - [this is the title](#this-is-the-link)"))))
(should (eq 2
(let ((markdown-toc-indentation-space 2))
(markdown-toc--title-level " - [another title](#this-is-the-link)
with multiple line
should not matter "))))
(should (eq 2
(let ((markdown-toc-indentation-space 3))
(markdown-toc--title-level " - [another title](#this-is-the-link)
with multiple line
should not matter "))))
;; no - as prefix so considered not a title
(should-not (markdown-toc--title-level "[this is the title](#this-is-the-link)"))
;; prefixed with a dash but misaligned, title should be indented with a
;; multiple of `markdown-toc-indentation-space` blank spaces
(should-not (markdown-toc--title-level " - [title](#this-is-the-link)")))

(ert-deftest markdown-toc-follow-toc-link-at-point()
"Follow a correct toc link should follow to the title"
(should (string= "## Sources"
(with-temp-buffer
(insert "- [some markdown page title](#some-markdown-page-title)
- [main title](#main-title)
- [Sources](#sources)
- [Marmalade (recommended)](#marmalade-recommended)
# main title
## Sources
### marmalade
...
")
(search-backward "- [Sources]")
(call-interactively 'markdown-toc-follow-toc-link-at-point)
(buffer-substring-no-properties (point-at-bol) (point-at-eol))))))

(ert-deftest markdown-toc-follow-toc-link-at-point-failures()
"Follow a misindented toc link should do nothing"
(should
;; not move
(string= " - [Sources](#sources) <- misindented 3 instead of 4 here"
(with-temp-buffer
(insert "- [some markdown page title](#some-markdown-page-title)
- [main title](#main-title)
- [Sources](#sources) <- misindented 3 instead of 4 here
# main title
## Sources
...
")
(search-backward "- [Sources]")
(call-interactively 'markdown-toc-follow-toc-link-at-point)
(buffer-substring-no-properties (point-at-bol) (point-at-eol)))))

(should
;; not move as well because
(string= "not a title"
(with-temp-buffer
(insert "- [some markdown page title](#some-markdown-page-title)
- [main title](#main-title)
- [Sources](#sources)
- [Marmalade (recommended)](#marmalade-recommended)
# main title
## Sources
### marmalade
not a title
...
")
(search-backward "not a title")
(call-interactively 'markdown-toc-follow-toc-link-at-point)
(buffer-substring-no-properties (point-at-bol) (point-at-eol))))))

(provide 'markdown-toc-tests)
;;; markdown-toc-tests.el ends here

0 comments on commit 9ef2b32

Please sign in to comment.