aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/calibredb-epub-config.el48
1 files changed, 48 insertions, 0 deletions
diff --git a/modules/calibredb-epub-config.el b/modules/calibredb-epub-config.el
index 4243e509..9f09e392 100644
--- a/modules/calibredb-epub-config.el
+++ b/modules/calibredb-epub-config.el
@@ -327,6 +327,54 @@ Try to use the Calibre book id from the parent folder name (for example,
("t" . nov-goto-toc)
("C-c C-b" . cj/nov-jump-to-calibredb)))
+;; ------------------------- Nov bookmark naming -------------------------------
+;; In a nov buffer "m" is bound to `bookmark-set' (above). nov's
+;; `nov-bookmark-make-record' names the record after `(buffer-name)' -- the EPUB
+;; filename, extension and all. Rebuild it as "Author, Title" parsed from the
+;; filename: under Calibre's "<Title> - <Author>.epub" naming the filename is
+;; more complete than the EPUB's embedded metadata (which carries truncated
+;; titles and author-sort "Last, First" forms).
+
+(defun cj/--nov-clean-title (s)
+ "Clean a title or author S parsed from an EPUB filename, or nil when blank.
+Restores a colon where Calibre sanitized \":\" to \"_\" (\"Frege_ A Guide\"
+-> \"Frege: A Guide\"), turns any leftover underscore into a space, and
+collapses runs of whitespace."
+ (when (stringp s)
+ (let* ((colon (replace-regexp-in-string "_ " ": " s))
+ (spaced (replace-regexp-in-string "_" " " colon))
+ (out (string-trim (replace-regexp-in-string "[ \t]+" " " spaced))))
+ (and (not (string-empty-p out)) out))))
+
+(defun cj/--nov-bookmark-name-from-file (path)
+ "Return \"Author, Title\" derived from an EPUB PATH's filename, or nil.
+Splits the filename (sans extension) on its last \" - \" into title and
+author per Calibre's \"<Title> - <Author>\" convention, restoring colons and
+reordering to \"Author, Title\". Falls back to the cleaned whole name when
+there is no \" - \" separator."
+ (when (and (stringp path) (not (string-empty-p path)))
+ (let ((base (file-name-sans-extension (file-name-nondirectory path))))
+ (if (string-match "\\`\\(.+\\) - \\(.+\\)\\'" base)
+ (let ((title (cj/--nov-clean-title (match-string 1 base)))
+ (author (cj/--nov-clean-title (match-string 2 base))))
+ (cond ((and author title) (format "%s, %s" author title))
+ (title title)
+ (author author)
+ (t nil)))
+ (cj/--nov-clean-title base)))))
+
+(defun cj/--nov-bookmark-rename-record (record)
+ "Replace RECORD's bookmark name with \"Author, Title\" from its EPUB filename.
+Advice (:filter-return) on `nov-bookmark-make-record'. RECORD is
+\(NAME . ALIST) carrying a `filename'; left unchanged when no name derives."
+ (let ((name (cj/--nov-bookmark-name-from-file
+ (alist-get 'filename (cdr record)))))
+ (if name (cons name (cdr record)) record)))
+
+(with-eval-after-load 'nov
+ (advice-add 'nov-bookmark-make-record :filter-return
+ #'cj/--nov-bookmark-rename-record))
+
(defun cj/--nov-image-padding-cols (col-width img-px font-width-px)
"Return left-padding columns to center an IMG-PX-wide image in COL-WIDTH cols.
FONT-WIDTH-PX is the column width in pixels; clamped up to 1 so a zero or