1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
;;; pdf-history.el --- A simple stack-based history in PDF buffers. -*- lexical-binding: t -*-
;; Copyright (C) 2013, 2014 Andreas Politz
;; Author: Andreas Politz <politza@fh-trier.de>
;; Keywords: files, multimedia
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
(require 'pdf-view)
(require 'pdf-util)
;;; Code:
(defgroup pdf-history nil
"A simple stack-based history."
:group 'pdf-tools)
(defvar-local pdf-history-stack nil
"The stack of history items.")
(defvar-local pdf-history-index nil
"The current index into the `pdf-history-stack'.")
(defvar pdf-history-minor-mode-map
(let ((kmap (make-sparse-keymap)))
(define-key kmap (kbd "B") 'pdf-history-backward)
(define-key kmap (kbd "N") 'pdf-history-forward)
kmap)
"Keymap used in `pdf-history-minor-mode'.")
;;;###autoload
(define-minor-mode pdf-history-minor-mode
"Keep a history of previously visited pages.
This is a simple stack-based history. Turning the page or
following a link pushes the left-behind page on the stack, which
may be naviagted with the following keys.
\\{pdf-history-minor-mode-map}"
nil nil nil
(pdf-util-assert-pdf-buffer)
(pdf-history-clear)
(cond
(pdf-history-minor-mode
(pdf-history-push)
(add-hook 'pdf-view-after-change-page-hook
'pdf-history-before-change-page-hook nil t))
(t
(remove-hook 'pdf-view-after-change-page-hook
'pdf-history-before-change-page-hook t))))
(defun pdf-history-before-change-page-hook ()
"Push a history item, before leaving this page."
(when (and pdf-history-minor-mode
(not (bound-and-true-p pdf-isearch-active-mode))
(pdf-view-current-page))
(pdf-history-push)))
(defun pdf-history-push ()
"Push the current page on the stack.
This function does nothing, if current stack item already
represents the current page."
(interactive)
(let ((item (pdf-history-create-item)))
(unless (and pdf-history-stack
(equal (nth pdf-history-index
pdf-history-stack) item))
(setq pdf-history-stack
(last pdf-history-stack
(- (length pdf-history-stack)
pdf-history-index))
pdf-history-index 0)
(push item pdf-history-stack))))
(defun pdf-history-clear ()
"Remove all history items."
(interactive)
(setq pdf-history-stack nil
pdf-history-index 0)
(pdf-history-push))
(defun pdf-history-create-item ()
"Create a history item representing the current page."
(list
(pdf-view-current-page)))
(defun pdf-history-beginning-of-history-p ()
"Return t, if at the beginning of the history."
(= pdf-history-index 0))
(defun pdf-history-end-of-history-p ()
"Return t, if at the end of the history."
(= pdf-history-index
(1- (length pdf-history-stack))))
(defun pdf-history-backward (n)
"Go N-times backward in the history."
(interactive "p")
(cond
((and (> n 0)
(pdf-history-end-of-history-p))
(error "End of history"))
((and (< n 0)
(pdf-history-beginning-of-history-p))
(error "Beginning of history"))
((/= n 0)
(let ((i (min (max 0 (+ pdf-history-index n))
(1- (length pdf-history-stack)))))
(prog1
(- (+ pdf-history-index n) i)
(pdf-history-goto i))))
(t 0)))
(defun pdf-history-forward (n)
"Go N-times forward in the history."
(interactive "p")
(pdf-history-backward (- n)))
(defun pdf-history-goto (n)
"Go to item N in the history."
(interactive "p")
(when (null pdf-history-stack)
(error "The history is empty"))
(cond
((>= n (length pdf-history-stack))
(error "End of history"))
((< n 0)
(error "Beginning of history"))
(t
(setq pdf-history-index n)
(pdf-view-goto-page
(car (nth n pdf-history-stack))))))
(defun pdf-history-debug ()
"Visualize the history in the header-line."
(interactive)
(setq header-line-format
'(:eval
(let ((pages (mapcar 'car pdf-history-stack))
(index pdf-history-index)
header)
(dotimes (i (length pages))
(push (propertize
(format "%s" (nth i pages))
'face
(and (= i index) 'match))
header))
(concat
"(" (format "%d" index) ") "
(mapconcat 'identity (nreverse header) " | "))))))
(provide 'pdf-history)
;;; pdf-history.el ends here
|