nov.el
does not provide an easy function to search the whole of the ebook content. Every search performed on buffer only applies to the "document" or chapter of the book on display at that time.
I wrote my own search function with reference to this answer below:
(defun nov-search (pattern)
"Search whole ebook in nov."
(interactive "sEnter search pattern: ")
(let ((doc-size (length nov-documents))
(version nov-epub-version)
(doc-index 1)
result)
(while (< doc-index (1- doc-size))
(seq-let (id &rest path) (aref nov-documents doc-index)
;; prepare temp buffer for search
(with-temp-buffer
(cond
((and (version< version "3.0")
(eq id nov-toc-id))
(insert (nov-ncx-to-html path)))
(t
(insert (nov-slurp path))))
(nov-render-html)
(goto-char (point-min))
;; search function
(while (search-forward pattern nil t)
(push (list (concat (file-name-base path) ": " (replace-regexp-in-string "\n" " " (thing-at-point 'sentence)))
doc-index
(point))
result))
;; iterate to next document
(setq doc-index (1+ doc-index)))))
(seq-let (doc pos) (alist-get (completing-read "Jump to: " (reverse result)) result nil nil #'string=)
(nov-goto-document doc)
(goto-char pos)
)))
The function generally does what is expected, but response is relatively slow - for a 10MB ebook, a simple search term takes more than 10 seconds to generate results.
I would like to seek help in this review to improve the efficiency of the search, possibly (1) by the implementation of some form of indexing beforehand, or (2) through a refactoring of the above search function to make use of existing libraries more suited for the task and (3) point out algorithmic design issues that affect response speed in the code above, if there is any.