From 374ae3de24187512adddf01a56e5eb52c79db65f Mon Sep 17 00:00:00 2001 From: Blendoit Date: Sat, 1 Aug 2020 15:18:40 -0700 Subject: Include contents of elpa/ sources + theme update. --- elpa/pdf-tools-20200512.1524/pdf-outline.el | 598 ++++++++++++++++++++++++++++ 1 file changed, 598 insertions(+) create mode 100644 elpa/pdf-tools-20200512.1524/pdf-outline.el (limited to 'elpa/pdf-tools-20200512.1524/pdf-outline.el') diff --git a/elpa/pdf-tools-20200512.1524/pdf-outline.el b/elpa/pdf-tools-20200512.1524/pdf-outline.el new file mode 100644 index 0000000..e141ca8 --- /dev/null +++ b/elpa/pdf-tools-20200512.1524/pdf-outline.el @@ -0,0 +1,598 @@ +;;; pdf-outline.el --- Outline for PDF buffer -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; 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 . + +;;; Commentary: +;; + +(require 'outline) +(require 'pdf-links) +(require 'pdf-view) +(require 'pdf-util) +(require 'cl-lib) +(require 'imenu) +(require 'let-alist) + +;;; Code: + +;; +;; User options +;; + +(defgroup pdf-outline nil + "Display a navigatable outline of a PDF document." + :group 'pdf-tools) + +(defcustom pdf-outline-buffer-indent 2 + "The level of indent in the Outline buffer." + :type 'integer + :group 'pdf-outline) + +(defcustom pdf-outline-enable-imenu t + "Whether `imenu' should be enabled in PDF documents." + :group 'pdf-outline + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-imenu-keep-order t + "Whether `imenu' should be advised not to reorder the outline." + :group 'pdf-outline + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-imenu-use-flat-menus nil + "Whether the constructed Imenu should be a list, rather than a tree." + :group 'pdf-outline + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-display-buffer-action '(nil . nil) + "The display action used, when displaying the outline buffer." + :group 'pdf-outline + :type display-buffer--action-custom-type) + +(defcustom pdf-outline-display-labels nil + "Whether the outline should display labels instead of page numbers. + +Usually a page's label is it's displayed page number." + :group 'pdf-outline + :type 'boolean) + +(defvar pdf-outline-minor-mode-map + (let ((km (make-sparse-keymap))) + (define-key km (kbd "o") 'pdf-outline) + km) + "Keymap used for `pdf-outline-minor-mode'.") + +(defvar pdf-outline-buffer-mode-map + (let ((kmap (make-sparse-keymap))) + (dotimes (i 10) + (define-key kmap (vector (+ i ?0)) 'digit-argument)) + (define-key kmap "-" 'negative-argument) + (define-key kmap (kbd "p") 'previous-line) + (define-key kmap (kbd "n") 'next-line) + (define-key kmap (kbd "b") 'outline-backward-same-level) + (define-key kmap (kbd "d") 'hide-subtree) + (define-key kmap (kbd "a") 'show-all) + (define-key kmap (kbd "s") 'show-subtree) + (define-key kmap (kbd "f") 'outline-forward-same-level) + (define-key kmap (kbd "u") 'pdf-outline-up-heading) + (define-key kmap (kbd "Q") 'hide-sublevels) + (define-key kmap (kbd "<") 'beginning-of-buffer) + (define-key kmap (kbd ">") 'pdf-outline-end-of-buffer) + (define-key kmap (kbd "TAB") 'outline-toggle-children) + (define-key kmap (kbd "RET") 'pdf-outline-follow-link) + (define-key kmap (kbd "C-o") 'pdf-outline-display-link) + (define-key kmap (kbd "SPC") 'pdf-outline-display-link) + (define-key kmap [mouse-1] 'pdf-outline-mouse-display-link) + (define-key kmap (kbd "o") 'pdf-outline-select-pdf-window) + (define-key kmap (kbd ".") 'pdf-outline-move-to-current-page) + ;; (define-key kmap (kbd "Q") 'pdf-outline-quit) + (define-key kmap (kbd "C-c C-q") 'pdf-outline-quit-and-kill) + (define-key kmap (kbd "q") 'quit-window) + (define-key kmap (kbd "M-RET") 'pdf-outline-follow-link-and-quit) + (define-key kmap (kbd "C-c C-f") 'pdf-outline-follow-mode) + kmap) + "Keymap used in `pdf-outline-buffer-mode'.") + +;; +;; Internal Variables +;; + +(define-button-type 'pdf-outline + 'face nil + 'keymap nil) + +(defvar-local pdf-outline-pdf-window nil + "The PDF window corresponding to this outline buffer.") + +(defvar-local pdf-outline-pdf-document nil + "The PDF filename or buffer corresponding to this outline + buffer.") + +(defvar-local pdf-outline-follow-mode-last-link nil) + +;; +;; Functions +;; + +;;;###autoload +(define-minor-mode pdf-outline-minor-mode + "Display an outline of a PDF document. + +This provides a PDF's outline on the menu bar via imenu. +Additionally the same outline may be viewed in a designated +buffer. + +\\{pdf-outline-minor-mode-map}" + nil nil nil + (pdf-util-assert-pdf-buffer) + (cond + (pdf-outline-minor-mode + (when pdf-outline-enable-imenu + (pdf-outline-imenu-enable))) + (t + (when pdf-outline-enable-imenu + (pdf-outline-imenu-disable))))) + +(define-derived-mode pdf-outline-buffer-mode outline-mode "PDF Outline" + "View and traverse the outline of a PDF file. + +Press \\[pdf-outline-display-link] to display the PDF document, +\\[pdf-outline-select-pdf-window] to select it's window, +\\[pdf-outline-move-to-current-page] to move to the outline item +of the current page, \\[pdf-outline-follow-link] to goto the +corresponding page or \\[pdf-outline-follow-link-and-quit] to +additionally quit the Outline. + +\\[pdf-outline-follow-mode] enters a variant of +`next-error-follow-mode'. Most `outline-mode' commands are +rebound to their respective last character. + +\\{pdf-outline-buffer-mode-map}" + (setq-local outline-regexp "\\( *\\).") + (setq-local outline-level + (lambda nil (1+ (/ (length (match-string 1)) + pdf-outline-buffer-indent)))) + + (toggle-truncate-lines 1) + (setq buffer-read-only t) + (when (> (count-lines 1 (point-max)) + (* 1.5 (frame-height))) + (hide-sublevels 1)) + (message "%s" + (substitute-command-keys + (concat + "Try \\[pdf-outline-display-link], " + "\\[pdf-outline-select-pdf-window], " + "\\[pdf-outline-move-to-current-page] or " + "\\[pdf-outline-follow-link-and-quit]")))) + +(define-minor-mode pdf-outline-follow-mode + "Display links as point moves." + nil nil nil + (setq pdf-outline-follow-mode-last-link nil) + (cond + (pdf-outline-follow-mode + (add-hook 'post-command-hook 'pdf-outline-follow-mode-pch nil t)) + (t + (remove-hook 'post-command-hook 'pdf-outline-follow-mode-pch t)))) + +(defun pdf-outline-follow-mode-pch () + (let ((link (pdf-outline-link-at-pos (point)))) + (when (and link + (not (eq link pdf-outline-follow-mode-last-link))) + (setq pdf-outline-follow-mode-last-link link) + (pdf-outline-display-link (point))))) + +;;;###autoload +(defun pdf-outline (&optional buffer no-select-window-p) + "Display an PDF outline of BUFFER. + +BUFFER defaults to the current buffer. Select the outline +buffer, unless NO-SELECT-WINDOW-P is non-nil." + (interactive (list nil (or current-prefix-arg + (consp last-nonmenu-event)))) + (let ((win + (display-buffer + (pdf-outline-noselect buffer) + pdf-outline-display-buffer-action))) + (unless no-select-window-p + (select-window win)))) + +(defun pdf-outline-noselect (&optional buffer) + "Create an PDF outline of BUFFER, but don't display it." + (save-current-buffer + (and buffer (set-buffer buffer)) + (pdf-util-assert-pdf-buffer) + (let* ((pdf-buffer (current-buffer)) + (pdf-file (pdf-view-buffer-file-name)) + (pdf-window (and (eq pdf-buffer (window-buffer)) + (selected-window))) + (bname (pdf-outline-buffer-name)) + (buffer-exists-p (get-buffer bname)) + (buffer (get-buffer-create bname))) + (with-current-buffer buffer + (unless buffer-exists-p + (when (= 0 (save-excursion + (pdf-outline-insert-outline pdf-buffer))) + (kill-buffer buffer) + (error "PDF has no outline")) + (pdf-outline-buffer-mode)) + (set (make-local-variable 'other-window-scroll-buffer) + pdf-buffer) + (setq pdf-outline-pdf-window pdf-window + pdf-outline-pdf-document (or pdf-file pdf-buffer)) + (current-buffer))))) + +(defun pdf-outline-buffer-name (&optional pdf-buffer) + (unless pdf-buffer (setq pdf-buffer (current-buffer))) + (let ((buf (format "*Outline %s*" (buffer-name pdf-buffer)))) + ;; (when (buffer-live-p (get-buffer buf)) + ;; (kill-buffer buf)) + buf)) + +(defun pdf-outline-insert-outline (pdf-buffer) + (let ((labels (and pdf-outline-display-labels + (pdf-info-pagelabels pdf-buffer))) + (nitems 0)) + (dolist (item (pdf-info-outline pdf-buffer)) + (let-alist item + (when (eq .type 'goto-dest) + (insert-text-button + (concat + (make-string (* (1- .depth) pdf-outline-buffer-indent) ?\s) + .title + (if (> .page 0) + (format " (%s)" + (if labels + (nth (1- .page) labels) + .page)) + "(invalid)")) + 'type 'pdf-outline + 'help-echo (pdf-links-action-to-string item) + 'pdf-outline-link item) + (newline) + (cl-incf nitems)))) + nitems)) + +(defun pdf-outline-get-pdf-window (&optional if-visible-p) + (save-selected-window + (let* ((buffer (cond + ((buffer-live-p pdf-outline-pdf-document) + pdf-outline-pdf-document) + ((bufferp pdf-outline-pdf-document) + (error "PDF buffer was killed")) + (t + (or + (find-buffer-visiting + pdf-outline-pdf-document) + (find-file-noselect + pdf-outline-pdf-document))))) + (pdf-window + (if (and (window-live-p pdf-outline-pdf-window) + (eq buffer + (window-buffer pdf-outline-pdf-window))) + pdf-outline-pdf-window + (or (get-buffer-window buffer) + (and (null if-visible-p) + (display-buffer + buffer + '(nil (inhibit-same-window . t)))))))) + (setq pdf-outline-pdf-window pdf-window)))) + + +;; +;; Commands +;; + +(defun pdf-outline-move-to-current-page () + "Move to the item corresponding to the current page. + +Open nodes as necessary." + (interactive) + (let (page) + (with-selected-window (pdf-outline-get-pdf-window) + (setq page (pdf-view-current-page))) + (pdf-outline-move-to-page page))) + +(defun pdf-outline-quit-and-kill () + "Quit browsing the outline and kill it's buffer." + (interactive) + (pdf-outline-quit t)) + +(defun pdf-outline-quit (&optional kill) + "Quit browsing the outline buffer." + (interactive "P") + (let ((win (selected-window))) + (pdf-outline-select-pdf-window t) + (quit-window kill win))) + +(defun pdf-outline-up-heading (arg &optional invisible-ok) + "Like `outline-up-heading', but `push-mark' first." + (interactive "p") + (let ((pos (point))) + (outline-up-heading arg invisible-ok) + (unless (= pos (point)) + (push-mark pos)))) + +(defun pdf-outline-end-of-buffer () + "Move to the end of the outline buffer." + (interactive) + (let ((pos (point))) + (goto-char (point-max)) + (when (and (eobp) + (not (bobp)) + (null (button-at (point)))) + (forward-line -1)) + (unless (= pos (point)) + (push-mark pos)))) + +(defun pdf-outline-link-at-pos (&optional pos) + (unless pos (setq pos (point))) + (let ((button (or (button-at pos) + (button-at (1- pos))))) + (and button + (button-get button + 'pdf-outline-link)))) + +(defun pdf-outline-follow-link (&optional pos) + "Select PDF window and move to the page corresponding to POS." + (interactive) + (unless pos (setq pos (point))) + (let ((link (pdf-outline-link-at-pos pos))) + (unless link + (error "Nothing to follow here")) + (select-window (pdf-outline-get-pdf-window)) + (pdf-links-action-perform link))) + +(defun pdf-outline-follow-link-and-quit (&optional pos) + "Select PDF window and move to the page corresponding to POS. + +Then quit the outline window." + (interactive) + (let ((link (pdf-outline-link-at-pos (or pos (point))))) + (pdf-outline-quit) + (unless link + (error "Nothing to follow here")) + (pdf-links-action-perform link))) + +(defun pdf-outline-display-link (&optional pos) + "Display the page corresponding to the link at POS." + (interactive) + (unless pos (setq pos (point))) + (let ((inhibit-redisplay t) + (link (pdf-outline-link-at-pos pos))) + (unless link + (error "Nothing to follow here")) + (with-selected-window (pdf-outline-get-pdf-window) + (pdf-links-action-perform link)) + (force-mode-line-update t))) + +(defun pdf-outline-mouse-display-link (event) + "Display the page corresponding to the position of EVENT." + (interactive "@e") + (pdf-outline-display-link + (posn-point (event-start event)))) + +(defun pdf-outline-select-pdf-window (&optional no-create-p) + "Display and select the PDF document window." + (interactive) + (let ((win (pdf-outline-get-pdf-window no-create-p))) + (and (window-live-p win) + (select-window win)))) + +(defun pdf-outline-toggle-subtree () + "Toggle hidden state of the current complete subtree." + (interactive) + (save-excursion + (outline-back-to-heading) + (if (not (outline-invisible-p (line-end-position))) + (hide-subtree) + (show-subtree)))) + +(defun pdf-outline-move-to-page (page) + "Move to an outline item corresponding to PAGE." + (interactive + (list (or (and current-prefix-arg + (prefix-numeric-value current-prefix-arg)) + (read-number "Page: ")))) + (goto-char (pdf-outline-position-of-page page)) + (save-excursion + (while (outline-invisible-p) + (outline-up-heading 1 t) + (show-children))) + (save-excursion + (when (outline-invisible-p) + (outline-up-heading 1 t) + (show-children))) + (back-to-indentation)) + +(defun pdf-outline-position-of-page (page) + (let (curpage) + (save-excursion + (goto-char (point-min)) + (while (and (setq curpage (alist-get 'page (pdf-outline-link-at-pos))) + (< curpage page)) + (forward-line)) + (point)))) + + + +;; +;; Imenu Support +;; + + +;;;###autoload +(defun pdf-outline-imenu-enable () + "Enable imenu in the current PDF buffer." + (interactive) + (pdf-util-assert-pdf-buffer) + (setq-local imenu-create-index-function + (if pdf-outline-imenu-use-flat-menus + 'pdf-outline-imenu-create-index-flat + 'pdf-outline-imenu-create-index-tree)) + (imenu-add-to-menubar "PDF Outline")) + +(defun pdf-outline-imenu-disable () + "Disable imenu in the current PDF buffer." + (interactive) + (pdf-util-assert-pdf-buffer) + (setq-local imenu-create-index-function nil) + (local-set-key [menu-bar index] nil) + (when (eq pdf-view-mode-map + (keymap-parent (current-local-map))) + (use-local-map (keymap-parent (current-local-map))))) + + +(defun pdf-outline-imenu-create-item (link &optional labels) + (let-alist link + (list (format "%s (%s)" .title (if labels + (nth (1- .page) labels) + .page)) + 0 + 'pdf-outline-imenu-activate-link + link))) + +(defun pdf-outline-imenu-create-index-flat () + (let ((labels (and pdf-outline-display-labels + (pdf-info-pagelabels))) + index) + (dolist (item (pdf-info-outline)) + (let-alist item + (when (eq .type 'goto-dest) + (push (pdf-outline-imenu-create-item item labels) + index)))) + (nreverse index))) + + +(defun pdf-outline-imenu-create-index-tree () + (pdf-outline-imenu-create-index-tree-1 + (pdf-outline-treeify-outline-list + (cl-remove-if-not + (lambda (type) + (eq type 'goto-dest)) + (pdf-info-outline) + :key (apply-partially 'alist-get 'type))) + (and pdf-outline-display-labels + (pdf-info-pagelabels)))) + +(defun pdf-outline-imenu-create-index-tree-1 (nodes &optional labels) + (mapcar (lambda (node) + (let (children) + (when (consp (caar node)) + (setq children (cdr node) + node (car node))) + (let ((item + (pdf-outline-imenu-create-item node labels))) + (if children + (cons (alist-get 'title node) + (cons item (pdf-outline-imenu-create-index-tree-1 + children labels))) + item)))) + nodes)) + +(defun pdf-outline-treeify-outline-list (list) + (when list + (let ((depth (alist-get 'depth (car list))) + result) + (while (and list + (>= (alist-get 'depth (car list)) + depth)) + (when (= (alist-get 'depth (car list)) depth) + (let ((item (car list))) + (when (and (cdr list) + (> (alist-get 'depth (cadr list)) + depth)) + (setq item + (cons + item + (pdf-outline-treeify-outline-list (cdr list))))) + (push item result))) + (setq list (cdr list))) + (reverse result)))) + +(defun pdf-outline-imenu-activate-link (&rest args) + ;; bug #14029 + (when (eq (nth 2 args) 'pdf-outline-imenu-activate-link) + (setq args (cdr args))) + (pdf-links-action-perform (nth 2 args))) + +(defadvice imenu--split-menu (around pdf-outline activate) + "Advice to keep the original outline order. + + Calls `pdf-outline-imenu--split-menu' instead, if in a PDF + buffer and `pdf-outline-imenu-keep-order' is non-nil." + (if (not (and (pdf-util-pdf-buffer-p) + pdf-outline-imenu-keep-order)) + ad-do-it + (setq ad-return-value + (pdf-outline-imenu--split-menu menulist title)))) + +(defvar imenu--rescan-item) +(defvar imenu-sort-function) +(defvar imenu-create-index-function) +(defvar imenu-max-items) + +(defun pdf-outline-imenu--split-menu (menulist title) + "Replacement function for `imenu--split-menu'. + +This function does not move sub-menus to the top, therefore +keeping the original outline order of the document. Also it does +not call `imenu-sort-function'." + (let ((menulist (copy-sequence menulist)) + keep-at-top) + (if (memq imenu--rescan-item menulist) + (setq keep-at-top (list imenu--rescan-item) + menulist (delq imenu--rescan-item menulist))) + (if (> (length menulist) imenu-max-items) + (setq menulist + (mapcar + (lambda (menu) + (cons (format "From: %s" (caar menu)) menu)) + (imenu--split menulist imenu-max-items)))) + (cons title + (nconc (nreverse keep-at-top) menulist)))) + +;; bugfix for imenu in Emacs 24.3 and below. +(when (condition-case nil + (progn (imenu--truncate-items '(("" 0))) nil) + (error t)) + (eval-after-load "imenu" + '(defun imenu--truncate-items (menulist) + "Truncate all strings in MENULIST to `imenu-max-item-length'." + (mapc (lambda (item) + ;; Truncate if necessary. + (when (and (numberp imenu-max-item-length) + (> (length (car item)) imenu-max-item-length)) + (setcar item (substring (car item) 0 imenu-max-item-length))) + (when (imenu--subalist-p item) + (imenu--truncate-items (cdr item)))) + menulist)))) + + + +(provide 'pdf-outline) + +;;; pdf-outline.el ends here + +;; Local Variables: +;; byte-compile-warnings: (not obsolete) +;; End: -- cgit v1.2.3