diff options
author | Yuchen Pei <id@ypei.org> | 2025-02-07 09:52:11 +1100 |
---|---|---|
committer | Yuchen Pei <id@ypei.org> | 2025-02-07 09:52:11 +1100 |
commit | 1302f96df75f4f93247beaafee0b0a780829be18 (patch) | |
tree | 7ae569f3ce8d16d386bd02882491b0e02ff8f2af /emacs/.emacs.d/lisp/my/belf.el | |
parent | 2f880075e7adc9c8070e5b0e606af7fbf78eaa0a (diff) |
Add follow mode. Display book cover in infobox. Render html
description in infobox.
Diffstat (limited to 'emacs/.emacs.d/lisp/my/belf.el')
-rw-r--r-- | emacs/.emacs.d/lisp/my/belf.el | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/emacs/.emacs.d/lisp/my/belf.el b/emacs/.emacs.d/lisp/my/belf.el index 035f44d..89f27c0 100644 --- a/emacs/.emacs.d/lisp/my/belf.el +++ b/emacs/.emacs.d/lisp/my/belf.el @@ -31,9 +31,14 @@ (defvar-keymap belf-mode-map :parent tabulated-list-mode-map - "i" #'belf-book-infobox + "F" #'belf-toggle-follow-mode + "d" #'belf-show-in-dired + "i" #'belf-book-infobox-at-point + "n" #'belf-next-line + "o" #'belf-open-book-other-window + "p" #'belf-previous-line "RET" #'belf-open-book - "o" #'belf-open-book-other-window) + ) (define-derived-mode belf-mode tabulated-list-mode "Bookshelf" "Major mode for browsing a list of books." @@ -77,9 +82,85 @@ (title . ,(match-string 2 base)) (year . ,(match-string 3 base)))))) -(defun belf-book-infobox () +(defun belf-book-infobox (file-name) (interactive) - (infobox-exiftool (tabulated-list-get-id))) + (belf-book-render-info (belf-exiftool-info file-name) file-name)) + +(defvar belf-exiftool-program "exiftool" "The exiftool program.") + +(defun belf-exiftool-info (file-name) + "Given a video URL, return an alist of its properties." + (with-temp-buffer + (call-process belf-exiftool-program nil t nil "-j" file-name) + (let ((start (point))) + (call-process-region + nil nil "jq" nil t nil + ".[0]|pick(.Title, .Author, .Creator, .Keywords, .Subject, .Publisher, .Identifier, .Series, .Title_sort, .Author_sort, .PageCount, .ISBN, .Language, .FileType, .Description)") + (goto-char start) + (json-read))) + ) + +(defun belf-book-cover (file-name) + "Get book cover. + +First look for an image file with the same file name. +Then for PDF, extract the first page. +For EPUB, looks for a cover image in the file. If not found, extract the first page." + (cond ((file-exists-p (file-name-with-extension file-name "jpg")) + (format "file://%s" (file-name-with-extension file-name "jpg"))) + (t nil))) + +(defun belf-book-infobox-at-point () + (interactive) + (let ((help-window-select (not belf-follow-mode))) + (belf-book-infobox (tabulated-list-get-id))) + ) + +(defun belf-book-render-info (info file-name) + (setf (alist-get 'Title info) + (concat (alist-get 'Title info) + " -- " + (buttonize + "xdg-open" + (lambda (_) (call-process "xdg-open" nil 0 nil file-name))) + " " (buttonize "find-file" (lambda (_) (find-file file-name)))) + (alist-get 'Thumbnail info) + (belf-book-cover file-name) + (alist-get 'Description info) + (when-let ((text (alist-get 'Description info))) + (with-temp-buffer + (insert text) + (shr-render-region (point-min) (point-max)) + (goto-char (point-min)) + (insert "\n") + (buffer-string)))) + (infobox-render + (infobox-translate info (infobox-default-specs info)) + `(belf-book-infobox ,file-name) + (called-interactively-p 'interactive))) + +(defvar belf-follow-mode nil "Whether follow mode is on.") + +(defun belf-toggle-follow-mode () + (interactive) + (setq belf-follow-mode (not belf-follow-mode))) + + +(defun belf-previous-line () + (interactive) + (previous-line) + (when belf-follow-mode + (belf-book-infobox-at-point))) + +(defun belf-next-line () + (interactive) + (next-line) + (when belf-follow-mode + (belf-book-infobox-at-point))) + +(defun belf-show-in-dired () + (interactive) + (dired-jump-other-window (tabulated-list-get-id))) (defun belf-open-book () (interactive) |