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