Emacs 有没有可以看epub格式的插件呢?

想用Emacs看一本epub格式的书.

虽然Win下面有许多程序可以看, 但是考虑到可能要翻译字词或者做做笔记什么的, 于是就想和 Emacs 结合一下, 但是直接打开似乎是无法做到, 默认的功能也没有 epub 相关的mode 所以请教一下论坛, 有没有类似的解决方案呢? 谢谢~

1 个赞

https://www.emacswiki.org/emacs/epubmode.el

不好意思,不支持 Windows。需要 Cygwin 之类的。

找了一圈,这个看起来还靠谱。

nov.el ,由 Evil maintainer 开发的,似乎只是需要PATH 路径安装了 unzip。

1 个赞

嗯嗯, 在 package list 里面找到了, 不过打开文件的时候error了:joy:

path 设置了 unzip.

不过打开报了一个错

nov-mode: EPUB extraction failed with exit code 9 Mark set

内容也是一些乱码, 看起来好像是编码的问题.

还是谢谢回答

1 个赞

真是非常抱歉,一年多了还来挖坟 :rofl:

今天正好试用了这个包,也遇到了和楼主一样的问题。我发现这是 unzip 解压失败导致的,只发生在 「Windows + 中文文件名」这种情况下。以下设置可以解决这个问题:

(with-eval-after-load "nov"
  (when (string-equal system-type "windows-nt")
    (setq process-coding-system-alist
          (cons `(,nov-unzip-program . (gbk . gbk))
                process-coding-system-alist))))

具体的原理我还没弄得很清楚,但基本可以确定是「coding system for subprocess I/O」的问题。

5 个赞

因为windows的中文是用gbk编码的。emacs里默认utf8

1 个赞

呃,用第二个在Windows10上打开好几本书都只有一片空白,不知道原因…

在win10下用这个能看一些书,但Springer出的一些材料类的epub用它打开都只能看目录,在章节上一回车,Emacs就死在那儿了…

成功解决问题…感谢感谢…

有时候打开 epub 无法处理 unicode 字符,可以用下面这个 workaround

;; FIXME: errors while opening `nov' files with Unicode characters
(with-no-warnings
    (defun my-nov-content-unique-identifier (content)
      "Return the the unique identifier for CONTENT."
      (when-let* ((name (nov-content-unique-identifier-name content))
                  (selector (format "package>metadata>identifier[id='%s']"
                                    (regexp-quote name)))
                  (id (car (esxml-node-children (esxml-query selector content)))))
        (intern id)))
    (advice-add #'nov-content-unique-identifier :override #'my-nov-content-unique-identifier))
5 个赞

这段代码加上后,各种问题都解决了… 包括之前从目录进章节导致Emacs停止响应的那本书, 也能打开了… 感觉很神奇的样子… 谢谢。

可惜作者不愿意改,说书的格式不正确就应该报错。幸亏 Emacs,我可以自己改了。

2 个赞

有些中文书打开是乱码,有些则正常。

你需要检查下电子书的格式和编码是否正确了。

谢谢,最近正好遇到了这两个问题。不过问题好像还没有完全解决,又遇到了一个 “EPUB 3 ID not found"的问题,查了一下nov.el源码,好像是在nov–content-epub3-files这个函数里,esxml-query找不到 id,不知可有办法?

我没有遇到这个问题,你可以按照相同思路修改一下,分享到这里

找到问题的原因了,部分版本号显示为EPUB3格式的电子书实际上格式是EPUB2,这样就导致按照EPUB3方式解析出错。实现思路是在按照EPUB3解析失败后再退回到EPUB2解析。不过我对elisp是个新手,对于nov–content-epub3-files中的error不知道怎么处理,也没有找到相关资料,麻烦帮忙看看。

(defun nov--content-epub2-files (content manifest files)
  (let* ((node (esxml-query "package>spine[toc]" content))
         (id (esxml-node-attribute 'toc node)))
    (when (not id)
      (error "EPUB 2 NCX ID not found"))
    (setq nov-toc-id (intern id))
    (let ((toc-file (assq nov-toc-id manifest)))
      (when (not toc-file)
        (error "EPUB 2 NCX file not found"))
      (cons toc-file files))))

(defun nov--content-epub3-files (content manifest files)
  (let* ((node (esxml-query "package>manifest>item[properties~=nav]" content))
         (id (esxml-node-attribute 'id node)))
    (when (not id)
      (error "EPUB 3 <nav> ID not found"))
    (setq nov-toc-id (intern id))
    (let ((toc-file (assq nov-toc-id manifest)))
      (when (not toc-file)
        (error "EPUB 3 <nav> file not found"))
      (setq files (--remove (eq (car it) nov-toc-id) files))
      (cons toc-file files))))
2 个赞

整体思路没错,不过跟nov.el本身的设计思路相悖。nov作者的本意是如果格式错误就直接报错退出。如果要修改就不能用error,因为error会直接退出处理。nov--content-epub2-files, nov--content-epub3-files, nov-centent-files等多个函数都需要修改,改动会比较大。

发现错误后,用EpubCheck 检查修复下文件可能才是解决之道。

如果非要改,可以试试下面这个workaround(刚随手写的,没有测试过):

(defun nov--content-epub2-files (content manifest files)
    (let* ((node (esxml-query "package>spine[toc]" content))
           (id (esxml-node-attribute 'toc node)))
      (when (not id)
        (throw 'error "EPUB 2 NCX ID not found"))
      (setq nov-toc-id (intern id))
      (let ((toc-file (assq nov-toc-id manifest)))
        (when (not toc-file)
          (throw 'error "EPUB 2 NCX file not found"))
        (cons toc-file files))))

  (defun nov--content-epub3-files (content manifest files)
    (let* ((node (esxml-query "package>manifest>item[properties~=nav]" content))
           (id (esxml-node-attribute 'id node)))
      (when (not id)
        (throw 'error "EPUB 3 <nav> ID not found"))
      (setq nov-toc-id (intern id))
      (let ((toc-file (assq nov-toc-id manifest)))
        (when (not toc-file)
          (throw 'error "EPUB 3 <nav> file not found"))
        (setq files (--remove (eq (car it) nov-toc-id) files))
        (cons toc-file files))))

  (defun nov-content-files (directory content)
    "Create correctly ordered file alist for CONTENT in DIRECTORY.
Each alist item consists of the identifier and full path."
    (let* ((manifest (nov-content-manifest directory content))
           (spine (nov-content-spine content))
           (files (mapcar (lambda (item) (assq item manifest)) spine)))
      (catch 'error (nov--content-epub3-files content manifest files))
      (catch 'error (nov--content-epub2-files content manifest files))))

代码试过了,完全正常了,终于可以开开心心看书了,谢谢。 虽然我也知道是书的问题,只是在别的软件中好像都能正常显示,是不是说明其他软件都做了容错。 你说的EpubCheck我还是第一次听说,谢谢安利,我回头试试。