aboutsummaryrefslogtreecommitdiff
path: root/nov.el
diff options
context:
space:
mode:
authorVasilij Schneidermann <mail@vasilij.de>2020-05-03 22:18:19 +0200
committerVasilij Schneidermann <mail@vasilij.de>2020-05-03 22:18:19 +0200
commit2ff9bcfdd2d22781206d2f32f6ff650e4beeaaf3 (patch)
treea4051b50a6f0514aeaa45cc31cc8e3b285e3cf79 /nov.el
parent79eea769fb5a95c57df7510b9d19b3b42457b440 (diff)
Add Imenu interop
Closes #69
Diffstat (limited to 'nov.el')
-rw-r--r--nov.el44
1 files changed, 44 insertions, 0 deletions
diff --git a/nov.el b/nov.el
index 54c5828..9347897 100644
--- a/nov.el
+++ b/nov.el
@@ -858,5 +858,49 @@ See also `nov-bookmark-make-record'."
:follow 'nov-org-link-follow
:store 'nov-org-link-store)
+
+;;; Imenu interop
+
+(defun nov-imenu-goto-function (_name filename target)
+ "Visit imenu item using FILENAME and TARGET."
+ (nov-visit-relative-file filename target))
+
+(defun nov--imenu-create-epub2-index (toc-path)
+ (let ((toc (with-temp-buffer
+ (insert-file-contents toc-path)
+ (libxml-parse-xml-region (point-min) (point-max)))))
+ (mapcar
+ (lambda (node)
+ (-let* ((label-node (esxml-query "navLabel>text" node))
+ (content-node (esxml-query "content" node))
+ (href (nov-urldecode (esxml-node-attribute 'src content-node)))
+ (label (car (esxml-node-children label-node)))
+ ((filename target) (nov-url-filename-and-target href)))
+ (list label filename 'nov-imenu-goto-function target)))
+ (esxml-query-all "navPoint" toc))))
+
+(defun nov--imenu-create-epub3-index (toc-path)
+ (let ((toc (with-temp-buffer
+ (insert-file-contents toc-path)
+ (libxml-parse-html-region (point-min) (point-max)))))
+ (mapcar
+ (lambda (node)
+ (-let* ((href (esxml-node-attribute 'href node))
+ (label (car (esxml-node-children node)))
+ ((filename target) (nov-url-filename-and-target href)))
+ (list label filename 'nov-imenu-goto-function target)))
+ (esxml-query-all "a" toc))))
+
+(defun nov-imenu-create-index ()
+ "Generate Imenu index."
+ (let ((toc-path (cdr (aref nov-documents 0))))
+ (if (version< nov-epub-version "3.0")
+ (nov--imenu-create-epub2-index toc-path)
+ (nov--imenu-create-epub3-index toc-path))))
+
+(defun nov-imenu-setup ()
+ (setq imenu-create-index-function 'nov-imenu-create-index))
+(add-hook 'nov-mode-hook 'nov-imenu-setup)
+
(provide 'nov)
;;; nov.el ends here