This repository has been archived by the owner on Aug 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 160
/
Copy pathpdf-history.el
170 lines (142 loc) · 5 KB
/
pdf-history.el
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 <[email protected]>
;; 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 navigated 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