[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/calibre 47ae488aed 07/10: Drop EIEIO in favor of custom
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/calibre 47ae488aed 07/10: Drop EIEIO in favor of custom editing solution |
|
Date: |
Thu, 18 May 2023 12:57:32 -0400 (EDT) |
branch: externals/calibre
commit 47ae488aed0ae84ecd0b20650e115abe262b9dae
Author: Kjartan Óli Ágústsson <kjartanoli@disroot.org>
Commit: Kjartan Óli Ágústsson <kjartanoli@disroot.org>
Drop EIEIO in favor of custom editing solution
* calibre-book.el: Don't require eieio.
(calibre-book): Define using cl-defstruct.
(calibre-book--slot): Delete since cl-defstruct provides this
automatically.
* calibre-cli.el (calibre-cli--make-book): Use the cl-defstruct
provided make-calibre-book.
* calibre-core.el (calibre-book--print-info, calibre-book--file): Drop
the use of EIEIO macro with-slots.
(calibre-core--get-titles, calibre-core--get-authors,
calibre-core--get-tags, calibre-core--get-formats,
calibre-core--get-series, calibre-core--get-publishers): Add an
ignored optional argument to be valid FUN arguments to
completion-table-dynamic.
(calibre-authors-completion-table,
calibre-publishers-completion-table, calibre-series-completion-table,
calibre-tags-completion-table): Create completion tables.
* calibre-db.el (calibre-db--make-book): Use the cl-defstruct provided
make-calibre-book.
* calibre-edit.el: Don't require eieio-custom.
Require wid-edit and calibre-widgets.
(calibre-edit--book, calibre-edit--title, calibre-edit--authors,
calibre-edit--publisher, calibre-edit--series, calibre-edit--tags):
Declare variables.
(calibre-edit-apply):
(calibre-edit-abort):
(calibre-edit-reset):
(calibre-edit-confirm):
(calibre-edit-mode-map, calibre-edit-field-keymap): Define keymaps for
editing books.
(calibre-edit-mode): Define a mode for editing books.
(calibre-edit-book):
(eieio-done-customizing): Remove
(calibre-edit--create-buffer): Add function to set up editing buffer.
(calibre-edit--different-fields): Adjust to the cl-lib struct API.
* calibre-widgets.el (calibre-author, calibre-publisher,
calibre-series, calibre-tag, calibre-date): Add widgets.
---
calibre-book.el | 107 ++++++++++++------------------
calibre-cli.el | 26 ++++----
calibre-core.el | 55 ++++++++++------
calibre-db.el | 20 +++---
calibre-edit.el | 189 +++++++++++++++++++++++++++++++++++++++++++++++++----
calibre-widgets.el | 73 +++++++++++++++++++++
6 files changed, 346 insertions(+), 124 deletions(-)
diff --git a/calibre-book.el b/calibre-book.el
index c83885fbba..d72fa0a388 100644
--- a/calibre-book.el
+++ b/calibre-book.el
@@ -25,75 +25,50 @@
;; representations of books
;;; Code:
-(require 'eieio)
(require 'parse-time)
-
-(defclass calibre-book ()
- ((id :initarg :id
- :type number
- :documentation "The ID of the book in the Calibre database.")
- (title :initarg :title
- :type string
- :documentation "The title of the book."
- :custom string)
- (authors :initarg :authors
- :type list
- :documentation "The authors of the book."
- :custom (repeat (string :tag "Author")))
- (publisher :initarg :publisher
- :type (or string null)
- :documentation "The publisher of the book."
- :custom (choice (const nil) string))
- (series :initarg :series
- :initform nil
- :type (or string null)
- :documentation "The series the book is a part of."
- :custom (choice (const nil) string))
- (series-index :initarg :series-index
- :initform 1
- :type real
- :documentation "The book's position within its series."
- :custom number)
- (formats :initarg :formats
- :type list)
- (timestamp :initarg :timestamp
- :type list)
- (pubdate :initarg :pubdate
- :type list)
- (last-modified :initarg :last-modified
- :type list)
- (tags :initarg :tags
- :initform '()
- :type list
- :documentation "Tags associated with the book."
- :custom (repeat (string :tag "Tag")))
- (path :initarg :path
+(cl-defstruct calibre-book
+ (id nil
+ :read-only t
+ :type integer
+ :documentation "The ID of the book in the Calibre database.")
+ (title nil
:type string
- :documentation "The book's position within the library")
- (file-name :initarg :file-name
- :type string
- :documentation "The book's filename, sans extension.")))
-
-(defmacro calibre-book--slot (slot &optional internal)
- "Create a function to access SLOT of a `calibre-book'.
-If INTERNAL is non nil the function name will follow the convention
-for private functions."
- `(defun ,(intern (format "calibre-book-%s%s" (if internal "-" "") slot))
(book)
- ,(format "Access the %s slot of a `calibre-book'." slot)
- (slot-value book ',slot)))
-
-(calibre-book--slot id)
-(calibre-book--slot title)
-(calibre-book--slot authors)
-(calibre-book--slot publisher)
-(calibre-book--slot series)
-(calibre-book--slot series-index)
-(calibre-book--slot tags)
-(calibre-book--slot formats)
-(calibre-book--slot path t)
-(calibre-book--slot file-name)
-(calibre-book--slot pubdate)
+ :documentation "The title of the book.")
+ (authors nil
+ :type list
+ :documentation "The authors of the book.")
+ (publisher nil
+ :type (or string null)
+ :documentation "The publisher of the book.")
+ (series nil
+ :type (or string null)
+ :documentation "The series the book is a part of.")
+ (series-index 1
+ :type number
+ :documentation "The book's position within its series.")
+ (formats nil
+ :read-only t
+ :type list
+ :documentation "The formats the book is available in.")
+ (timestamp nil
+ :read-only t
+ :type list)
+ (pubdate nil
+ :type list
+ :documentation "The book's publication date.")
+ (last-modified nil
+ :type list
+ :documentation "The last time the book was modified.")
+ (tags nil
+ :type list
+ :documentation "Tags associated with the book.")
+ (path nil
+ :type string
+ :documentation "The book's position within the library")
+ (file-name nil
+ :type string
+ :documentation "The book's filename, sans extension."))
(defcustom calibre-format-preferences '(pdf epub)
"The preference order of file formats."
diff --git a/calibre-cli.el b/calibre-cli.el
index 345407c648..554fd2756a 100644
--- a/calibre-cli.el
+++ b/calibre-cli.el
@@ -48,19 +48,19 @@
(defun calibre-cli--make-book (json)
"Make a `calibre-book' from JSON."
(let-alist json
- (calibre-book :id .id
- :title .title
- :authors (calibre-cli--parse-authors .authors)
- :publisher .publisher
- :series .series
- :series-index .series_index
- :timestamp (calibre-cli--parse-timestamp .timestamp)
- :pubdate (calibre-cli--parse-timestamp .pubdate)
- :last-modified (calibre-cli--parse-timestamp .last_modified)
- :tags .tags
- :formats (calibre-cli--parse-formats .formats)
- :path (calibre-cli--parse-path .formats)
- :file-name (calibre-cli--parse-file-name .formats))))
+ (make-calibre-book :id .id
+ :title .title
+ :authors (calibre-cli--parse-authors .authors)
+ :publisher .publisher
+ :series .series
+ :series-index .series_index
+ :timestamp (calibre-cli--parse-timestamp .timestamp)
+ :pubdate (calibre-cli--parse-timestamp .pubdate)
+ :last-modified (calibre-cli--parse-timestamp
.last_modified)
+ :tags .tags
+ :formats (calibre-cli--parse-formats .formats)
+ :path (calibre-cli--parse-path .formats)
+ :file-name (calibre-cli--parse-file-name .formats))))
(defun calibre-cli--parse-authors (authors)
"Parse AUTHORS a string, into a list of authors.
diff --git a/calibre-core.el b/calibre-core.el
index ff29f73641..52565ddd58 100644
--- a/calibre-core.el
+++ b/calibre-core.el
@@ -177,24 +177,25 @@ with values determined by `calibre-library-columns'."
"Return list suitable as a value of `tabulated-list-entries'.
BOOK is a `calibre-book'."
(list book
- (with-slots (id title authors publisher series series-index tags
formats pubdate) book
- (vconcat (mapcar (lambda (x)
- (let ((column (car x)))
- (cl-case column
- (id (int-to-string id))
- (title title)
- (authors (string-join authors ", "))
- (publisher (if (not publisher) "" publisher))
- (series (if (not series) "" series))
- (series-index (if series (format "%.1f"
series-index) ""))
- (tags (string-join tags ", "))
- (formats (string-join (mapcar (lambda (f)
(upcase (symbol-name f))) formats) ", "))
- (pubdate (format-time-string
calibre-library-time-format pubdate)))))
- calibre-library-columns)))))
+ (vconcat (mapcar (lambda (x)
+ (let ((column (car x)))
+ (cl-case column
+ (id (int-to-string (calibre-book-id book)))
+ (title (calibre-book-title book))
+ (authors (string-join (calibre-book-authors
book) ", "))
+ (publisher (let ((publisher
(calibre-book-publisher book)))
+ (if (not publisher) "" publisher)))
+ (series (let ((series (calibre-book-series
book))) (if (not series) "" series)))
+ (series-index (if (calibre-book-series book)
(format "%.1f" (calibre-book-series-index book)) ""))
+ (tags (string-join (calibre-book-tags book) ",
"))
+ (formats (string-join (mapcar (lambda (f)
(upcase (symbol-name f))) (calibre-book-formats book)) ", "))
+ (pubdate (format-time-string
calibre-library-time-format (calibre-book-pubdate book))))))
+ calibre-library-columns))))
(defun calibre-book--file (book format)
"Return the path to BOOK in FORMAT."
- (with-slots (path file-name) book
+ (let ((path (calibre-book-path book))
+ (file-name (calibre-book-file-name book)))
(file-name-concat (calibre--library)
path
(format "%s.%s" file-name format))))
@@ -246,30 +247,42 @@ FILTERS should be a list of vectors, for the exact
contents see
books)
books))))
-(defun calibre-core--get-titles ()
+;; The ignored optional argument makes these functions valid arguments
+;; to completion-table-dynamic.
+(defun calibre-core--get-titles (&optional _)
"Return a list of the titles in the active library."
(calibre-core--interface get-titles))
-(defun calibre-core--get-authors ()
+(defun calibre-core--get-authors (&optional _)
"Return a list of the authors in the active library."
(calibre-core--interface get-authors))
-(defun calibre-core--get-tags ()
+(defun calibre-core--get-tags (&optional _)
"Return a list of the tags in the active library."
(calibre-core--interface get-tags))
-(defun calibre-core--get-formats ()
+(defun calibre-core--get-formats (&optional _)
"Return a list of the file formats stored in the active library."
(calibre-core--interface get-formats))
-(defun calibre-core--get-series ()
+(defun calibre-core--get-series (&optional _)
"Return a list of the series in the active library."
(calibre-core--interface get-series))
-(defun calibre-core--get-publishers ()
+(defun calibre-core--get-publishers (&optional _)
"Return a list of the publishers in the active library."
(calibre-core--interface get-publishers))
+;; Completion tables
+(defvar calibre-authors-completion-table
+ (completion-table-dynamic #'calibre-core--get-authors))
+(defvar calibre-publishers-completion-table
+ (completion-table-dynamic #'calibre-core--get-publishers))
+(defvar calibre-series-completion-table
+ (completion-table-dynamic #'calibre-core--get-series))
+(defvar calibre-tags-completion-table
+ (completion-table-dynamic #'calibre-core--get-tags))
+
;; These functions should be in calibre-cli.el, but they require
;; calibre--books because the calibredb interface does not expose the
diff --git a/calibre-db.el b/calibre-db.el
index d5b76c720d..43d27be43a 100644
--- a/calibre-db.el
+++ b/calibre-db.el
@@ -38,19 +38,19 @@ TIMESTAMP is a string of the form YYYY-MM-DD
HH:MM:SS.xxxxxx+00:00."
ENTRY is a list of the form:
\(ID TITLE SERIES SERIES-INDEX TIMESTAMP PUBDATE LAST-MODIFIED)."
(seq-let [id title series series-index timestamp pubdate last-modified path]
entry
- (calibre-book :id id
- :title title
- :authors (calibre-db--get-book-authors id)
- :publisher (calibre-db--get-book-publisher id)
- :series series
- :series-index series-index
- :tags (calibre-db--get-book-tags id)
- :formats (calibre-db--get-book-formats id)
- :path path
- :file-name (calibre-db--get-book-file-name id))))
+ (make-calibre-book :id id
+ :title title
+ :authors (calibre-db--get-book-authors id)
+ :publisher (calibre-db--get-book-publisher id)
+ :series series
+ :series-index series-index
:timestamp (calibre-db--parse-timestamp timestamp)
:pubdate (calibre-db--parse-timestamp pubdate)
:last-modified (calibre-db--parse-timestamp
last-modified)
+ :tags (calibre-db--get-book-tags id)
+ :formats (calibre-db--get-book-formats id)
+ :path path
+ :file-name (calibre-db--get-book-file-name id))))
(defun calibre-db--get-book-authors (id)
"Return a list of authors for the book identified by ID."
diff --git a/calibre-edit.el b/calibre-edit.el
index 4c2664664d..b22e4b7623 100644
--- a/calibre-edit.el
+++ b/calibre-edit.el
@@ -18,7 +18,8 @@
;; along with calibre.el. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
-(require 'eieio-custom)
+(require 'wid-edit)
+(require 'calibre-widgets)
(require 'calibre-core)
(require 'calibre-util)
(require 'calibre-exec)
@@ -26,19 +27,179 @@
(defvar calibre-edit--edited-books nil
"A list containing the original copies of edited books.")
+;; Declare these variables to prevent free variable warnings
+(defvar-local calibre-edit--book nil
+ "The book being edited in the current buffer.")
+(defvar-local calibre-edit--title nil
+ "The title widget in the current buffer.")
+(defvar-local calibre-edit--authors nil
+ "The authors widget in the current buffer.")
+(defvar-local calibre-edit--publisher nil
+ "The publisher widget in the current buffer.")
+(defvar-local calibre-edit--series nil
+ "The series widget in the current buffer.")
+(defvar-local calibre-edit--tags nil
+ "The tags widget in the current buffer.")
+
+(defun calibre-edit-apply (&rest _)
+ "Apply any edits to the book in the current buffer."
+ (interactive)
+ (setf (calibre-book-title calibre-edit--book) (widget-value
calibre-edit--title)
+ (calibre-book-authors calibre-edit--book) (widget-value
calibre-edit--authors)
+ (calibre-book-publisher calibre-edit--book) (widget-value
calibre-edit--publisher)
+ (calibre-book-series calibre-edit--book) (if (consp (widget-value
calibre-edit--series))
+ (car (widget-value
calibre-edit--series))
+ nil)
+ (calibre-book-series-index calibre-edit--book) (if (consp
(widget-value calibre-edit--series))
+ (cdr (widget-value
calibre-edit--series))
+ 1)
+ (calibre-book-tags calibre-edit--book) (widget-value
calibre-edit--tags))
+ (calibre-library--refresh)
+ (let ((book calibre-edit--book))
+ (with-current-buffer (get-buffer calibre-library-buffer)
+ (calibre-library--find-book book)
+ (tabulated-list-put-tag (char-to-string calibre-mod-marker)))))
+
+(defun calibre-edit-abort (&rest _)
+ "Abort any changes made in the current buffer."
+ (interactive)
+ (let ((book calibre-edit--book))
+ (unless (calibre-edit--different-fields book (calibre-edit--find-original
book))
+ (setf calibre-edit--edited-books (seq-remove (lambda (b)
+ (= (calibre-book-id b)
+ (calibre-book-id
book)))
+
calibre-edit--edited-books))))
+ (quit-window t))
+
+(defun calibre-edit-reset (&rest _)
+ "Undo any changes made during this editing session."
+ (interactive)
+ (calibre-edit-book calibre-edit--book))
+
+(defun calibre-edit-confirm (&rest _)
+ "Apply any changes and exit."
+ (interactive)
+ (calibre-edit-apply)
+ (quit-window t))
+
+(defvar-keymap calibre-edit-mode-map
+ :doc "Keymap for `calibre-edit-mode'."
+ :parent widget-keymap
+ "C-c C-c" #'calibre-edit-confirm
+ "C-c C-a" #'calibre-edit-apply
+ "C-c C-r" #'calibre-edit-reset
+ "C-c C-k" #'calibre-edit-abort)
+
+(defvar-keymap calibre-edit-field-keymap
+ :doc "Keymap used inside editable fields in calibre edit buffers."
+ :parent widget-field-keymap
+ "C-c C-c" #'calibre-edit-confirm
+ "C-c C-a" #'calibre-edit-apply
+ "C-c C-r" #'calibre-edit-reset
+ "C-c C-k" #'calibre-edit-abort)
+
+(define-derived-mode calibre-edit-mode nil "Calibre Edit"
+ :group 'calibre
+ (widget-put (get 'editable-field 'widget-type) :keymap
calibre-edit-field-keymap))
+
(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))
- "Finalise the editing of BOOK."
- (calibre-library--refresh)
- (with-current-buffer (get-buffer calibre-library-buffer)
- (calibre-library--find-book book)
- (tabulated-list-put-tag (char-to-string calibre-mod-marker))))
+ (push (copy-calibre-book book) calibre-edit--edited-books))
+ (let ((buffer (calibre-edit--create-buffer book)))
+ (pop-to-buffer buffer)))
+
+(defun calibre-edit--create-buffer (book)
+ "Create a buffer for editing BOOK.
+Returns a buffer for editing BOOK, creating it if necessary."
+ (let ((buffer (get-buffer-create (format "*%s - Metadata*"
(calibre-book-title book)))))
+ (with-current-buffer buffer
+ (kill-all-local-variables)
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (remove-overlays)
+ (calibre-edit-mode)
+ (setf calibre-edit--book book)
+ (setq-local
+ header-line-format
+ (substitute-command-keys
+ "\\<calibre-edit-mode-map>Finish `\\[calibre-edit-confirm]', Apply
`\\[calibre-edit-apply]', Reset `\\[calibre-edit-reset]', Cancel
`\\[calibre-edit-abort]'"))
+ (setf calibre-edit--title
+ (widget-create 'string
+ :value (calibre-book-title book)
+ :tag "Title"
+ :doc "The title of the book."
+ :format "%t: %v%d"))
+ (widget-insert "\n")
+ (setf calibre-edit--authors
+ (widget-create 'repeat
+ :value (calibre-book-authors book)
+ :tag "Authors"
+ :doc "The authors of the book."
+ :format "%t:\n%v%i\n%d"
+ 'calibre-author))
+ (widget-insert "\n")
+ (setf calibre-edit--publisher
+ (widget-create 'choice
+ :value (calibre-book-publisher book)
+ :tag "Publisher"
+ :doc "The publisher of the book."
+ :format "%[%t%]%v%d"
+ '(const :tag ": None" :menu-tag "None" nil)
+ '(calibre-publisher :tag "" :menu-tag "Publisher")))
+ (widget-insert "\n")
+ (setf calibre-edit--series
+ (widget-create 'choice
+ :value (if (calibre-book-series book)
+ (cons (calibre-book-series book)
+ (calibre-book-series-index book))
+ nil)
+ :tag "Series"
+ :format "%[%t%]%v%d"
+ '(const :tag ": None" :menu-tag "None" nil)
+ `(cons :tag ""
+ :menu-tag "Series"
+ (calibre-series :tag "Name"
+ :doc "The series the book is
part of."
+ :format "%t: %v%d")
+ (number :tag "Index"
+ :doc "The book's position within its
series"
+ :format "%t: %v%d"
+ :value ,(calibre-book-series-index
book)))))
+ (widget-insert "\n")
+ (setf calibre-edit--tags
+ (widget-create 'repeat
+ :value (calibre-book-tags book)
+ :tag "Tags"
+ :doc "Tags associated with the book."
+ :format "%t:\n%v%i\n%d"
+ 'calibre-tag))
+ (widget-insert "\n")
+ (widget-create 'push-button
+ :tag "Confirm"
+ :help-echo "Apply any changes and exit."
+ :notify (lambda (&rest _)
+ (calibre-edit-confirm)
+ (kill-buffer)))
+ (widget-insert " ")
+ (widget-create 'push-button
+ :tag "Apply"
+ :help-echo "Apply any changes."
+ :notify #'calibre-edit-apply)
+ (widget-insert " ")
+ (widget-create 'push-button
+ :tag "Reset"
+ :help-echo "Undo any changes."
+ :notify #'calibre-edit-reset)
+ (widget-insert " ")
+ (widget-create 'push-button
+ :tag "Cancel"
+ :help-echo "Abort all changes."
+ :notify #'calibre-edit-abort)
+ (widget-setup)
+ (goto-char (point-min)))
+ buffer))
(defun calibre-edit-revert (book)
"Undo any edits performed to BOOK in this session."
@@ -58,10 +219,10 @@
(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)))
+ (dolist (descriptor (cdr (cl-struct-slot-info 'calibre-book)))
+ (let* ((slot-name (car descriptor))
+ (a (cl-struct-slot-value 'calibre-book slot-name a))
+ (b (cl-struct-slot-value 'calibre-book slot-name b)))
(unless (equal a b)
(push slot-name diff))))
diff))
diff --git a/calibre-widgets.el b/calibre-widgets.el
new file mode 100644
index 0000000000..641755b6dc
--- /dev/null
+++ b/calibre-widgets.el
@@ -0,0 +1,73 @@
+;;; calibre-widgets.el --- Widgets for editing book metadata. -*-
lexical-binding: t; -*-
+;; Copyright (C) 2023 Kjartan Óli Águstsson
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; This file contains widgets for use in editing book metadata.
+
+;;; Code:
+(require 'calibre-core)
+
+(define-widget 'calibre-author 'string
+ "A author widget.
+It reads an Author's name from an editable text field."
+ :completions calibre-authors-completion-table
+ :format "%{%t%}: %v"
+ :tag "Author")
+
+(define-widget 'calibre-publisher 'string
+ "A publisher widget.
+It reads a Publisher's name from an editable text field."
+ :completions calibre-publishers-completion-table
+ :tag ""
+ :format "%{%t%}: %v")
+
+(define-widget 'calibre-series 'string
+ "A series widget.
+It reads a series's name from an editable text field."
+ :completions calibre-series-completion-table
+ :tag "Series"
+ :format "%{%t%}: %v")
+
+(define-widget 'calibre-tag 'string
+ "A tag widget.
+It reads a tag from an editable text field."
+ :completions calibre-tags-completion-table
+ :tag "Tag"
+ :format "%t %v")
+
+(define-widget 'calibre-series 'cons
+ nil
+ 'calibre-series-name
+ '(number))
+
+(define-widget 'calibre-date 'vector
+ "A date widget.
+It reads a year, month, and day."
+ :value-to-internal (lambda (_widget value)
+ (message "%s" value)
+ (format-time-string "%F" value))
+ :value-to-external (lambda (_widget value)
+ (message "to-ext: %s" value)
+ (seq-let (year month day) value
+ (parse-iso8601-time-string (format
"%s-%s-%sT00:00:00" year month day))))
+ :convert-widget (lambda (widget)
+ (widget-put widget :args '(vector (integer :tag "Year"
:format "%t: %v")
+ (integer :tag "Month"
:format "%t: %v")
+ (integer :tag "Day"
:format "%t: %v")))
+ widget))
+
+(provide 'calibre-widgets)
+;;; calibre-widgets.el ends here
- [elpa] externals/calibre updated (e283a2c928 -> ba5fa17e31), ELPA Syncer, 2023/05/18
- [elpa] externals/calibre f0324a9d21 06/10: Move calibre-parse-timestamp to calibre-db, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre b237fd2e5e 05/10: Allow searching by title, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre 512b5a1197 02/10: Add mode line indicator when updating library, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre c07fa7d0f3 04/10: Require exact matching in calibre-cli search, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre cc66ec42bf 08/10: Remove seemingly unnecessary require, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre c6d0201342 09/10: Capture calibredb output, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre 47ae488aed 07/10: Drop EIEIO in favor of custom editing solution,
ELPA Syncer <=
- [elpa] externals/calibre ba5fa17e31 10/10: Update copyright headers, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre 524ce0353e 01/10: Fix docstring, ELPA Syncer, 2023/05/18
- [elpa] externals/calibre f096edd1d3 03/10: Return list instead of list of lists, ELPA Syncer, 2023/05/18