pdf-history.el (5239B)
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 (define-key kmap (kbd "l") #'pdf-history-backward) 44 (define-key kmap (kbd "r") #'pdf-history-forward) 45 kmap) 46 "Keymap used in `pdf-history-minor-mode'.") 47 48 ;;;###autoload 49 (define-minor-mode pdf-history-minor-mode 50 "Keep a history of previously visited pages. 51 52 This is a simple stack-based history. Turning the page or 53 following a link pushes the left-behind page on the stack, which 54 may be navigated with the following keys. 55 56 \\{pdf-history-minor-mode-map}" 57 :group 'pdf-history 58 (pdf-util-assert-pdf-buffer) 59 (pdf-history-clear) 60 (cond 61 (pdf-history-minor-mode 62 (pdf-history-push) 63 (add-hook 'pdf-view-after-change-page-hook 64 #'pdf-history-before-change-page-hook nil t)) 65 (t 66 (remove-hook 'pdf-view-after-change-page-hook 67 #'pdf-history-before-change-page-hook t)))) 68 69 (defun pdf-history-before-change-page-hook () 70 "Push a history item, before leaving this page." 71 (when (and pdf-history-minor-mode 72 (not (bound-and-true-p pdf-isearch-active-mode)) 73 (pdf-view-current-page)) 74 (pdf-history-push))) 75 76 (defun pdf-history-push () 77 "Push the current page on the stack. 78 79 This function does nothing, if current stack item already 80 represents the current page." 81 (interactive) 82 (let ((item (pdf-history-create-item))) 83 (unless (and pdf-history-stack 84 (equal (nth pdf-history-index 85 pdf-history-stack) item)) 86 (setq pdf-history-stack 87 (last pdf-history-stack 88 (- (length pdf-history-stack) 89 pdf-history-index)) 90 pdf-history-index 0) 91 (push item pdf-history-stack)))) 92 93 (defun pdf-history-clear () 94 "Remove all history items." 95 (interactive) 96 (setq pdf-history-stack nil 97 pdf-history-index 0) 98 (pdf-history-push)) 99 100 (defun pdf-history-create-item () 101 "Create a history item representing the current page." 102 (list 103 (pdf-view-current-page))) 104 105 (defun pdf-history-beginning-of-history-p () 106 "Return t, if at the beginning of the history." 107 (= pdf-history-index 0)) 108 109 (defun pdf-history-end-of-history-p () 110 "Return t, if at the end of the history." 111 (= pdf-history-index 112 (1- (length pdf-history-stack)))) 113 114 (defun pdf-history-backward (n) 115 "Go N times backward in the history." 116 (interactive "p") 117 (cond 118 ((and (> n 0) 119 (pdf-history-end-of-history-p)) 120 (error "End of history")) 121 ((and (< n 0) 122 (pdf-history-beginning-of-history-p)) 123 (error "Beginning of history")) 124 ((/= n 0) 125 (let ((i (min (max 0 (+ pdf-history-index n)) 126 (1- (length pdf-history-stack))))) 127 (prog1 128 (- (+ pdf-history-index n) i) 129 (pdf-history-goto i)))) 130 (t 0))) 131 132 (defun pdf-history-forward (n) 133 "Go N times forward in the history." 134 (interactive "p") 135 (pdf-history-backward (- n))) 136 137 (defun pdf-history-goto (n) 138 "Go to item N in the history." 139 (interactive "p") 140 (when (null pdf-history-stack) 141 (error "The history is empty")) 142 (cond 143 ((>= n (length pdf-history-stack)) 144 (error "End of history")) 145 ((< n 0) 146 (error "Beginning of history")) 147 (t 148 (setq pdf-history-index n) 149 (pdf-view-goto-page 150 (car (nth n pdf-history-stack)))))) 151 152 (defun pdf-history-debug () 153 "Visualize the history in the header-line." 154 (interactive) 155 (setq header-line-format 156 '(:eval 157 (let ((pages (mapcar 'car pdf-history-stack)) 158 (index pdf-history-index) 159 header) 160 (dotimes (i (length pages)) 161 (push (propertize 162 (format "%s" (nth i pages)) 163 'face 164 (and (= i index) 'match)) 165 header)) 166 (concat 167 "(" (format "%d" index) ") " 168 (mapconcat 'identity (nreverse header) " | ")))))) 169 170 (provide 'pdf-history) 171 172 ;;; pdf-history.el ends here