branch: externals/calibre
commit 4b6af65d08e4130c2fbd829a7bd037ab11e6df73
Author: Kjartan Óli Ágústsson <[email protected]>
Commit: Kjartan Óli Ágústsson <[email protected]>
Support editing book metadata
* calibre-edit.el (eieio-custom):
(calibre-db):
(calibre-util):
(calibre-exec):
(calibre-edit--edited-books):
(calibre-edit-book):
(eieio-done-customizing):
(calibre-edit-revert):
(calibre-edit--find-original):
(calibre-edit--different-fields):
(calibre-util-uglify-field-name):
(calibre-edit--command):
(calibre-edit-commit-edits):
(calibre-edit):
Add
* calibre-library.el:
(calibre-library-mark-unmark): Undo edits if mark is M.
(calibre-library-mode-map): Bind e to calibre-edit-book.
(calibre-library-execute): Commit edits when executing.
---
calibre-edit.el | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
calibre-library.el | 36 +++++++++++----------
2 files changed, 112 insertions(+), 16 deletions(-)
diff --git a/calibre-edit.el b/calibre-edit.el
new file mode 100644
index 0000000000..8145726344
--- /dev/null
+++ b/calibre-edit.el
@@ -0,0 +1,92 @@
+;;; calibre-edit.el --- Edit Book metadata -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Kjartan Oli Agustsson
+
+;; This file is part of calibre.el.
+
+;; calibre.el is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; calibre.el is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with calibre.el. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'eieio-custom)
+(require 'calibre-db)
+(require 'calibre-util)
+(require 'calibre-exec)
+
+(defvar calibre-edit--edited-books nil
+ "A list containing the original copies of edited books.")
+
+(defun calibre-edit-book (book)
+ "Edit the metadata of BOOK."
+ (interactive (list (tabulated-list-get-id)) calibre-library-mode)
+ (unless (calibre-util-find-book book calibre-edit--edited-books)
+ (push (clone book) calibre-edit--edited-books))
+ (eieio-customize-object book))
+
+(cl-defmethod eieio-done-customizing ((book calibre-book))
+ (calibre-library--refresh)
+ (with-current-buffer (get-buffer calibre-library-buffer)
+ (calibre-library--find-book book)
+ (tabulated-list-put-tag "M")))
+
+(defun calibre-edit-revert (book)
+ "Undo any edits performed to BOOK in this session."
+ (let ((compare-ids (lambda (b)
+ (= (calibre-book-id book)
+ (calibre-book-id b)))))
+ (setf calibre--books
+ (cl-substitute-if (calibre-util-find-book book
calibre-edit--edited-books)
+ compare-ids
+ calibre--books))
+ (calibre-library--refresh)))
+
+(defun calibre-edit--find-original (book)
+ "Return BOOK absent any modifications performed in this session."
+ (calibre-util-find-book book calibre-edit--edited-books))
+
+(defun calibre-edit--different-fields (a b)
+ "Return a list of slot names whose values differ in A and B."
+ (let (diff)
+ (dolist (descriptor (eieio-class-slots 'calibre-book))
+ (let* ((slot-name (eieio-slot-descriptor-name descriptor))
+ (a (slot-value a slot-name))
+ (b (slot-value b slot-name)))
+ (unless (equal a b)
+ (push slot-name diff))))
+ diff))
+
+(defun calibre-util-uglify-field-name (field)
+ "Return FIELD replacing - with -."
+ (string-join (split-string (symbol-name field) "-") "_"))
+
+(defun calibre-edit--command (book)
+ "Return the command to commit edits to BOOK to disk."
+ `("set_metadata"
+ ,@(flatten-list (mapcar (lambda (field)
+ `("-f" ,(format "%s:%s"
(calibre-util-uglify-field-name field)
+ (cl-case field
+ (authors (string-join
(calibre-book-authors book) ","))
+ (title (calibre-book-title
book))
+ (publisher
(calibre-book-publisher book))
+ (series (calibre-book-series
book))
+ (series-index
(calibre-book-series-index book))
+ (tags (string-join
(calibre-book-tags book) ","))))))
+ (calibre-edit--different-fields book
(calibre-edit--find-original book))))
+ ,(format "%d" (calibre-book-id book))))
+
+(defun calibre-edit-commit-edits (books)
+ "Commit edits to BOOKS to disk."
+ (calibre-exec--queue-commands (mapcar #'calibre-edit--command books)))
+
+(provide 'calibre-edit)
+;;; calibre-edit.el ends here
diff --git a/calibre-library.el b/calibre-library.el
index a9f5765b91..546cf92d34 100644
--- a/calibre-library.el
+++ b/calibre-library.el
@@ -28,6 +28,7 @@
(require 'calibre-book)
(require 'calibre-search)
(require 'calibre-virtual-library)
+(require 'calibre-edit)
;;;###autoload
(defun calibre-library-add-book (file)
@@ -59,32 +60,34 @@
(tabulated-list-put-tag "D" t))
(defun calibre-library-mark-unmark (&optional _num)
- "Clear any mark on a book and move to the next line."
+ "Clear any marks on a book and move to the next line."
(interactive "p" calibre-library-mode)
- (tabulated-list-put-tag " " t))
+ (let ((book (tabulated-list-get-id)))
+ (beginning-of-line)
+ (when (char-equal (char-after) ?M)
+ (calibre-edit-revert book))
+ (calibre-library--find-book book)
+ (tabulated-list-put-tag " " t)))
(defun calibre-library-execute ()
"Performed marked Library actions."
(interactive nil calibre-library-mode)
- (let (remove-list mark)
+ (let (remove-list modified-list mark)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(setf mark (char-after))
- (cl-case mark
- (?\D (push (tabulated-list-get-id) remove-list)))
+ (let ((book (tabulated-list-get-id)))
+ (cl-case mark
+ (?D (push book remove-list))
+ (?M (push book modified-list))))
(forward-line)))
- (when remove-list (calibre-library-remove-books remove-list)))
- (calibre--books t)
- (calibre-library--refresh))
-
-(defun calibre-library--find-book (book)
- "Move point to the line representing BOOK."
- (goto-char (point-min))
- (while (not (or (eobp)
- (= (calibre-book-id (tabulated-list-get-id))
- (calibre-book-id book))))
- (forward-line)))
+ (when remove-list (calibre-library-remove-books remove-list))
+ (when modified-list (calibre-edit-commit-edits modified-list)))
+ (calibre-library-revert)
+ (setf calibre-edit--edited-books nil)
+ (calibre-exec--start-execution)
+ (tabulated-list-clear-all-tags))
(defun calibre-library-revert (&rest _IGNORED)
(let ((pos (tabulated-list-get-id)))
@@ -108,6 +111,7 @@
:parent tabulated-list-mode-map
"d" #'calibre-library-mark-remove
"u" #'calibre-library-mark-unmark
+ "e" #'calibre-edit-book
"x" #'calibre-library-execute
"a" #'calibre-library-add-book
"v" #'calibre-select-virtual-library