dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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