finito.el
allows for the management of books and reading lists from within Emacs. Books are presented in modified org mode buffers, and books along with user collections can be viewed/queried using transient.
This package is a thin client for https://github.com/laurencewarne/libro-finito, more information on collection management and cutomization can be found there. Here's a demo of some of its features:
finito-demo-copy2.mp4
finito-same-series-demo-cut.mp4
You can install it from melpa:
(use-package finito
:demand t
;; The main entry point for finito commands
:bind ("C-c b" . finito)
;; Optional, but can improve the aesthetics of book descriptions
:hook (finito-view-mode . visual-line-mode)
:config
;; Downloads the server asynchronously, you can also download the server
;; jar manually from the releases page:
;; https://github.com/LaurenceWarne/libro-finito/releases and place it in
;; `finito-server-directory'
(finito-download-server-if-not-exists
;; Optional, but we can specify a callback to run when the server has
;; finished downloading, we choose here to start the server to override
;; the default lazy behaviour which starts the server whenever a finito
;; command is invoked.
;; Note this callback is still called in the event a server has already
;; been downloaded
(lambda () (finito-start-server-if-not-already))))
Most of the features can be navigated through via the transient prefix command finito
, available via C-c b
with the recommended installation. Some highlights are:
- Create a new collection:
C-c b
c
n
- Search for books:
C-c b
s
- Generate a yearly summary:
M-x finito-summary
Key | Action |
---|---|
a |
Add the book at point to some prompted collection |
m |
Add the book at point to the "My Books" collection |
A |
Search for books by the same author as the book at point |
n |
Goto the next book |
p |
Goto the previous book |
o |
Dump this buffer's contents in a normal org mode buffer |
d |
Toggle |
q |
Kill the current buffer |
k |
Kill the current buffer |
b |
Open an Open Library page for the book at point |
r |
Rate the book at point |
s |
Start the book at point |
S |
Start the book at point at a prompted date |
f |
Finish the book at point |
F |
Finish the book at point at a prompted date |
e |
Search for books in the same series* |
w |
Copy the title of the book at point to the kill ring |
g |
Refresh the buffer |
M |
Toggle display of minimal mode |
l |
Edit the last search |
C-m |
Open the "My Books" collection |
C-r |
Open the "Currently Reading" collection |
*Results may vary, thoughts on the Wikidata implementation are very welcome. If you see 'Could not find a series for xyz', you may find that it's just the case that the relevant Wikidata information is incomplete, in which case Wikidata welcomes contributions!
Key | Action |
---|---|
d |
Toggle display of descriptions for the current collection |
D |
Delete the book at point from the current collection |
N |
Open the next page (if applicable) of books for this collection |
P |
Open the previous page (if applicable) of books for this collection |
R |
Review the book at point from the current collection |
W |
Toggle display of reviews for the current collection |
(in addition to all the base bindings)
Key | Action |
---|---|
d |
Toggle display of descriptions for the current buffer |
(in addition to all the base bindings)
finito-create-book
- will prompt you to create a book with custom attributes, useful if you cannot find the book you want through searchingfinito-delete-data-for-book-at-point
- deletes all held data about the book at point (except for its collection membership), use this for example if you set the incorrect date started/endedfinito-open-playground
- opens the finito server's graphql playground
This object can be used to customize how books are written into finito buffers. The finito-book-writer
class can be extended to provide ad-hoc cutomization. Example:
(defclass my-book-writer (finito-book-writer)
nil
"My class for writing book information to a buffer.")
(cl-defmethod finito-insert-title ((_writer my-book-writer) title)
(insert (concat "* " title "\n\n")))
(setq finito-writer-instance (my-book-writer))
This writer class will insert titles as level one headings, and otherwise behave exactly the same way as the default writer.
finito
also defines the custom finito-book-writer
implementation finito-minimal-book-writer
, which displays each book on a single line. By default M
can be used to toggle this view, or you can alternatively set it as the default using (setq finito-writer-instance finito-minimal-writer-instance)
.
The two instances used for for toggling minimal and detailed mode, finito-minimal-writer-instance
and finito-detailed-writer-instance
, can be customised similarly.
This variable holds the name of the collection to open when the "My Books" suffix is invoked from the finito
prefix command.
It can be changed to some other user created collection, though note its default value ("My Books") is marked as a special collection (by default) by the server - more specifically the default collection which automatically adds all books added to any other collection or started/completed/rated to itself.
Therefore, once you have:
(setq finito-my-books-collection "good books, some say the greatest")
In order to accumulate all added books you will have to mark it as a special collection and add hooks (or not if you prefer books not be added automagically everywhere).
This variable holds the name of the collection to open when the "Currently Reading" suffix is invoked from the finito
prefix command.
The situation is similar to that of finito-my-books-collection
above in that the default value "Currently Reading" is regarded as a special collection, though only books marked as "started" will be added to this collection.
Variable | Description | Default |
---|---|---|
finito-language |
The language search queries should request responses in | "en" |
finito-server-directory |
The directory the finito server should be downloaded to | (concat user-emacs-directory "/finito") |
finito-img-cache-directory |
The directory of the finito image cache | (concat finito-server-directory "/images") |
finito-browse-function |
The function to be invoked by finito-browse-book-at-point |
finito--browse-function |
finito-add-book-collection-blacklist |
Collections to ignore for finito-add-book-at-point |
("Currently Reading") |
finito-save-last-search |
A flag to indicate whether the arguments to the last search query should be saved | t |
finito-use-image-uris |
A flag to indicate whether to insert image uris or image file names into finito buffers | nil |
finito-montage-image-columns |
How many columns per row in a book montage (generated by summaries) | 6 |
finito-montage-large-image-rating-threshold |
If the rating for a given book is >= this value, then render the book as large on a book montage |
5 |
finito-summary-include-added |
Include added books in addition to read books in montage images | t |
finito-show-descriptions-default |
A flag which controls whether descriptions are shown by default | t |
finito-show-reviews-default |
A flag which controls whether reviews are shown by default | nil |
More information is available via C-h v
. A non-nil value for finito-use-image-uris
can be useful if for example you are using org-display-remote-inline-images
.
To transport your data, you can copy ~/.local/share/libro-finito/db.sqlite
across to a different machine.
The changelog can be viewed here.