GNU Emacs带有一个简单实用的书签管理工具——bookmark。
简单地说,它有四个主要的元素:
- filename: 书签所对应的文件名
- position: 书签在对应文件里的位置
- bookmark-set: 在当前buffer的当前光标位置设置书签
- bookmark-jump: 跳到相应的书签位置
bookmark还提供了一定的扩展功能,如果上述四个概念不足以实现某种特定的书签,可以在其基础上扩展。
doc-view是GNU Emacs用来查看PDF文件的工具,它首先把PDF转换成图片,每页一张图,然后把图片显示出来。对于doc-view来说,书签定义的位置是页,而不是某个字符的位置,所以doc-view必须通过扩展才能使用bookmark。
扩展方式很简单,首先为doc-view-mode定义一个单独的书签创建函数,在书签创建时两条额外的信息
- 页数
- 以及一个处理该书签的函数,以跳到相应的页数
(defun doc-view-bookmark-make-record ()
(nconc (bookmark-make-record-default)
`((page . ,(doc-view-current-page))
(handler . doc-view-bookmark-jump))))
;;;###autoload
(defun doc-view-bookmark-jump (bmk)
;; This implements the `handler' function interface for record type
;; returned by `doc-view-bookmark-make-record', which see.
(prog1 (bookmark-default-handler bmk)
(let ((page (bookmark-prop-get bmk 'page)))
(when (not (eq major-mode 'doc-view-mode))
(doc-view-toggle-display))
(with-selected-window
(or (get-buffer-window (current-buffer) 0)
(selected-window))
(doc-view-goto-page page)))))
然后用该函数替换掉默认的书签创建函数。具体实现参见doc-view.el文件。
(set (make-local-variable 'bookmark-make-record-function)
'doc-view-bookmark-make-record)
然而,doc-view提供的书签有一点小小的缺陷,就是没有保存解析度(doc-view-resolution)。doc-view本身提高缩放功能,但是如果缩放比例没有保存的话,使用书签后PDF将以默认比例打开,阅读体验不太友好。
修改的方式和前面几乎一样,唯一的区别是在doc-view-mode-hook里面替换掉doc-view-mode原来的书签创建函数,改用自己写的那个。代码部分摘录如下,具体参见我的wl-ebook-viewer.el中关于doc-view的部分(其中还包括了自动设置书签和打开PDF时自动跳到书签位置的代码,用于模拟定位上次阅读位置功能)。
(defun wl-doc-view-bookmark-make-record ()
(nconc (bookmark-make-record-default)
`((page . ,(doc-view-current-page))
(resolution . ,doc-view-resolution)
(handler . wl-doc-view-bookmark-jump))))
(defun wl-bookmark-get-resolution (bookmark)
"Get doc view resolution."
(or (bookmark-prop-get bookmark 'resolution)
(default-value 'doc-view-resolution)))
(defun wl-doc-view-bookmark-jump (bookmark)
(prog1 (doc-view-bookmark-jump bookmark)
(let ((resolution (wl-bookmark-get-resolution bookmark)))
(assert (> resolution 0))
(when (/= doc-view-resolution resolution)
(set (make-local-variable 'doc-view-resolution) resolution)
(doc-view-reconvert-doc)))))





