aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst1
-rw-r--r--nov.el50
2 files changed, 48 insertions, 3 deletions
diff --git a/README.rst b/README.rst
index 0a38d7f..8e55494 100644
--- a/README.rst
+++ b/README.rst
@@ -11,6 +11,7 @@ About
Features:
- Basic navigation (jump to TOC, previous/next chapter)
+- Remembering and restoring the last read position
- Jump to next chapter when scrolling beyond end
- Renders EPUB2 (.ncx) and EPUB3 (<nav>) TOCs
- Hyperlinks to internal and external targets
diff --git a/nov.el b/nov.el
index 61967f4..f8e47c1 100644
--- a/nov.el
+++ b/nov.el
@@ -30,6 +30,7 @@
;; Features:
;;
;; - Basic navigation (jump to TOC, previous/next chapter)
+;; - Remembering and restoring the last read position
;; - Jump to next chapter when scrolling beyond end
;; - Renders EPUB2 (.ncx) and EPUB3 (<nav>) TOCs
;; - Hyperlinks to internal and external targets
@@ -91,6 +92,13 @@ should change it to contain the rendered version of it.")
:type 'hook
:group 'nov)
+(defcustom nov-save-place-file (locate-user-emacs-file "nov-places")
+ "File name where last reading places are saved to and restored from.
+If set to `nil', no saving and restoring is performed."
+ :type '(choice (file :tag "File name")
+ (const :tag "Don't save last reading places" nil))
+ :group 'nov)
+
(defvar-local nov-temp-dir nil
"Temporary directory containing the buffer's EPUB files.")
@@ -233,7 +241,7 @@ UUID."
(id (car (esxml-node-children (esxml-query selector content)))))
(when (not id)
(error "Unique identifier not found by its name: %s" name))
- (replace-regexp-in-string "^urn:uuid:" "" id)))
+ (intern (replace-regexp-in-string "^urn:uuid:" "" id))))
;; NOTE: unique identifier is queried separately as identifiers can
;; appear more than once and only one of them can be the unique one
@@ -374,8 +382,13 @@ Each alist item consists of the identifier and full path."
map))
(defun nov-clean-up ()
- "Delete temporary files of all current EPUB buffer."
+ "Delete temporary files of the current EPUB buffer."
(when nov-temp-dir
+ (let ((identifier (cdr (assq 'identifier nov-metadata)))
+ (index (if (integerp nov-documents-index)
+ nov-documents-index
+ 0)))
+ (nov-save-place identifier index (point)))
(nov-ignore-file-errors
(delete-directory nov-temp-dir t))))
@@ -612,6 +625,30 @@ Internal URLs are visited with `nov-visit-relative-file'."
(browse-url url)
(apply 'nov-visit-relative-file (nov-url-filename-and-target url)))))
+(defun nov-saved-places ()
+ "Retrieve saved places in `nov-save-place-file'."
+ (when (and nov-save-place-file (file-exists-p nov-save-place-file))
+ (with-temp-buffer
+ (insert-file-contents-literally nov-save-place-file)
+ (goto-char (point-min))
+ (read (current-buffer)))))
+
+(defun nov-saved-place (identifier)
+ "Retrieve saved place for IDENTIFIER in `nov-saved-place-file'."
+ (cdr (assq identifier (nov-saved-places))))
+
+(defun nov-save-place (identifier index point)
+ "Save place as identified by IDENTIFIER, INDEX and POINT.
+Saving is only done if `nov-save-place-file' is set."
+ (when nov-save-place-file
+ (let* ((place `(,identifier (index . ,index)
+ (point . ,point)))
+ (places (cons place (assq-delete-all identifier (nov-saved-places))))
+ print-level
+ print-length)
+ (with-temp-file nov-save-place-file
+ (insert (prin1-to-string places))))))
+
;;;###autoload
(define-derived-mode nov-mode special-mode "EPUB"
"Major mode for reading EPUB documents"
@@ -644,7 +681,14 @@ Internal URLs are visited with `nov-visit-relative-file'."
(setq nov-documents-index 0))
(setq buffer-undo-list t)
(set-visited-file-name nil t) ; disable autosaves and save questions
- (nov-render-document))
+ (let ((place (nov-saved-place (cdr (assq 'identifier nov-metadata)))))
+ (if place
+ (let ((index (cdr (assq 'index place)))
+ (point (cdr (assq 'point place))))
+ (setq nov-documents-index index)
+ (nov-render-document)
+ (goto-char point))
+ (nov-render-document))))
(provide 'nov)
;;; nov.el ends here