diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 5b462b24f5..6ac1fb4945 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2007-2022 Free Software Foundation, Inc. ;; ;; Author: Tassilo Horn -;; Keywords: files, pdf, ps, dvi +;; Keywords: files, pdf, ps, dvi, epub, djvu ;; This file is part of GNU Emacs. @@ -25,15 +25,16 @@ ;; Viewing PS/PDF/DVI files requires Ghostscript, `dvipdf' (comes with ;; Ghostscript) or `dvipdfm' (comes with teTeX or TeXLive) and ;; `pdftotext', which comes with xpdf (https://www.foolabs.com/xpdf/) -;; or poppler (https://poppler.freedesktop.org/). -;; Djvu documents require `ddjvu' (from DjVuLibre). -;; ODF files require `soffice' (from LibreOffice). +;; or poppler (https://poppler.freedesktop.org/). EPUB documents +;; require `mutool' which comes with mupdf +;; (https://mupdf.com/index.html). Djvu documents require `ddjvu' +;; (from DjVuLibre). ODF files require `soffice' (from LibreOffice). ;;; Commentary: ;; DocView is a document viewer for Emacs. It converts a number of -;; document formats (including PDF, PS, DVI, Djvu and ODF files) to a -;; set of PNG files, one PNG for each page, and displays the PNG +;; document formats (including PDF, EPUB, PS, DVI, Djvu and ODF files) +;; to a set of PNG files, one PNG for each page, and displays the PNG ;; images inside an Emacs buffer. This buffer uses `doc-view-mode' ;; which provides convenient key bindings for browsing the document. ;; @@ -147,7 +148,7 @@ ;;;; Customization Options (defgroup doc-view nil - "In-buffer viewer for PDF, PostScript, DVI, and DJVU files." + "In-buffer viewer for PDF, EPUB, PostScript, DVI, and DJVU files." :link '(function-link doc-view) :version "22.2" :group 'applications @@ -257,8 +258,8 @@ doc-view-dvipdf-program :type 'file) (define-obsolete-variable-alias 'doc-view-unoconv-program - 'doc-view-odf->pdf-converter-program - "24.4") + 'doc-view-odf->pdf-converter-program + "24.4") (defcustom doc-view-odf->pdf-converter-program (cond @@ -329,6 +330,7 @@ doc-view--current-converter-processes "Only used internally.") (defun doc-view-new-window-function (winprops) + ;; TODO: write documentation! ;; (message "New window %s for buf %s" (car winprops) (current-buffer)) (cl-assert (or (eq t (car winprops)) (eq (window-buffer (car winprops)) (current-buffer)))) @@ -382,7 +384,7 @@ doc-view--buffer-file-name (defvar doc-view-doc-type nil "The type of document in the current buffer. -Can be `dvi', `pdf', `ps', `djvu' or `odf'.") +Can be `dvi', `pdf', 'epub', `ps', `djvu' or `odf'.") (defvar doc-view-single-page-converter-function nil "Function to call to convert a single page of the document to a bitmap file. @@ -738,7 +740,7 @@ doc-view-kill-proc (interactive) (while (consp doc-view--current-converter-processes) (ignore-errors ;; Some entries might not be processes, and maybe - ;; some are dead already? + ;; some are dead already? (kill-process (pop doc-view--current-converter-processes)))) (when doc-view--current-timer (cancel-timer doc-view--current-timer) @@ -810,11 +812,12 @@ doc-view-mode-p (executable-find doc-view-dvipdf-program)) (and doc-view-dvipdfm-program (executable-find doc-view-dvipdfm-program))))) - ((memq type '(postscript ps eps pdf)) - (or (and doc-view-ghostscript-program - (executable-find doc-view-ghostscript-program)) - (and doc-view-pdfdraw-program - (executable-find doc-view-pdfdraw-program)))) + ((memq type '(postscript ps eps pdf epub)) + (if-let (command (and (memq type '(pdf epub)) (executable-find "mutool"))) + command + (unless (eq type 'epub) + (and doc-view-ghostscript-program + (executable-find doc-view-ghostscript-program))))) ((eq type 'odf) (and doc-view-odf->pdf-converter-program (executable-find doc-view-odf->pdf-converter-program) @@ -1053,7 +1056,7 @@ doc-view-start-process ;; some file-name-handler-managed dir, for example). (let* ((default-directory (or (unhandled-file-name-directory default-directory) - (expand-file-name "~/"))) + (expand-file-name "~/"))) (proc (apply #'start-process name doc-view-conversion-buffer program args))) (push proc doc-view--current-converter-processes) @@ -1189,7 +1192,7 @@ doc-view-pdf/ps->png "Convert PDF-PS to PNG asynchronously." (funcall (pcase doc-view-doc-type - ('pdf doc-view-pdf->png-converter-function) + ((or 'pdf 'epub) doc-view-pdf->png-converter-function) ('djvu #'doc-view-djvu->tiff-converter-ddjvu) (_ #'doc-view-ps->png-converter-ghostscript)) pdf-ps png nil @@ -1227,20 +1230,20 @@ doc-view-document->bitmap (let ((rest (cdr pages))) (funcall doc-view-single-page-converter-function pdf (format png (car pages)) (car pages) - (lambda () - (if rest - (doc-view-document->bitmap pdf png rest) - ;; Yippie, the important pages are done, update the display. - (clear-image-cache) - ;; For the windows that have a message (like "Welcome to - ;; DocView") display property, clearing the image cache is - ;; not sufficient. - (dolist (win (get-buffer-window-list (current-buffer) nil 'visible)) - (with-selected-window win - (when (stringp (overlay-get (doc-view-current-overlay) 'display)) - (doc-view-goto-page (doc-view-current-page))))) - ;; Convert the rest of the pages. - (doc-view-pdf/ps->png pdf png))))))) + (lambda () + (if rest + (doc-view-document->bitmap pdf png rest) + ;; Yippie, the important pages are done, update the display. + (clear-image-cache) + ;; For the windows that have a message (like "Welcome to + ;; DocView") display property, clearing the image cache is + ;; not sufficient. + (dolist (win (get-buffer-window-list (current-buffer) nil 'visible)) + (with-selected-window win + (when (stringp (overlay-get (doc-view-current-overlay) 'display)) + (doc-view-goto-page (doc-view-current-page))))) + ;; Convert the rest of the pages. + (doc-view-pdf/ps->png pdf png))))))) (defun doc-view-pdf->txt (pdf txt callback) "Convert PDF to TXT asynchronously and call CALLBACK when finished." @@ -1337,7 +1340,12 @@ doc-view-convert-current-doc ;; Rename to doc.pdf (rename-file opdf pdf) (doc-view-pdf/ps->png pdf png-file))))) - ((or 'pdf 'djvu) + ((or 'pdf 'epub 'djvu) + (when (eq doc-view-doc-type 'epub) + (unless (eq doc-view-pdf->png-converter-function 'doc-view-pdf->png-converter-mupdf) + (user-error "Viewing epub documents requires the`mutool' command to be available, +and `doc-view-pdf->png-converter-function' variable set to +`doc-view-pdf->png-converter-mupdf'"))) (let ((pages (doc-view-active-pages))) ;; Convert doc to bitmap images starting with the active pages. (doc-view-document->bitmap doc-view--buffer-file-name png-file pages))) @@ -1869,6 +1877,8 @@ doc-view-set-doc-type ("dvi" dvi) ;; PDF ("pdf" pdf) ("epdf" pdf) + ;; EPUB + ("epub" epub) ;; PostScript ("ps" ps) ("eps" ps) ;; DjVu @@ -1889,7 +1899,8 @@ doc-view-set-doc-type ((looking-at "%!") '(ps)) ((looking-at "%PDF") '(pdf)) ((looking-at "\367\002") '(dvi)) - ((looking-at "AT&TFORM") '(djvu)))))) + ((looking-at "AT&TFORM") '(djvu)) + ((looking-at "PK") '(epub)))))) (setq-local doc-view-doc-type (car (or (nreverse (seq-intersection name-types content-types #'eq)) diff --git a/lisp/files.el b/lisp/files.el index a11786fca2..74f9d83d4e 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2925,7 +2925,7 @@ auto-mode-alist ("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode) ("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MS-DOS ("\\.[eE]?[pP][sS]\\'" . ps-mode) - ("\\.\\(?:PDF\\|DVI\\|OD[FGPST]\\|DOCX\\|XLSX?\\|PPTX?\\|pdf\\|djvu\\|dvi\\|od[fgpst]\\|docx\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe) + ("\\.\\(?:PDF\\|EPUB\\|DVI\\|OD[FGPST]\\|DOCX\\|XLSX?\\|PPTX?\\|pdf\\|epub\\|djvu\\|dvi\\|od[fgpst]\\|docx\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe) ("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode) ("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode) ("BROWSE\\'" . ebrowse-tree-mode)