From 1832ca950d97093436088bba97f6256d414c344a Mon Sep 17 00:00:00 2001 From: jao Date: Mon, 5 Apr 2021 03:14:50 +0100 Subject: add to doc-view the bits we need: outline and imenu --- lib/doc/jao-doc-view.el | 157 +++++++++++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 67 deletions(-) (limited to 'lib/doc/jao-doc-view.el') diff --git a/lib/doc/jao-doc-view.el b/lib/doc/jao-doc-view.el index 5060452..af87c9e 100644 --- a/lib/doc/jao-doc-view.el +++ b/lib/doc/jao-doc-view.el @@ -1,6 +1,6 @@ -;; jao-doc-view.el -- Remembering visited documents +;; jao-doc-view.el -- Remembering visited documents -*- lexical-binding: t; -*- -;; Copyright (c) 2013, 2015, 2017, 2018, 2019 Jose Antonio Ortega Ruiz +;; Copyright (c) 2013, 2015, 2017, 2018, 2019, 2021 Jose Antonio Ortega Ruiz ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -20,14 +20,16 @@ ;;; Comentary: -;; Some utilities to keep track of visited documents and the last -;; visited page. +;; Some utilities to keep track of visited documents and their structure. ;;; Code: -(defvar jao-doc-view-bmk-file "~/.emacs.d/doc-view-bmk") + +;;; Session + +(require 'doc-view) + (defvar jao-doc-view-session-file "~/.emacs.d/doc-view-session") -(defvar jao-doc-view--current-bmks nil) (defun jao-doc-view--read-file (file) (let ((buff (find-file-noselect file))) @@ -42,65 +44,10 @@ (insert (format "%S" value)) (save-buffer))) -(defun jao-doc-view--read-bmks () - (let ((bmks (jao-doc-view--read-file jao-doc-view-bmk-file))) - (if (hash-table-p bmks) bmks (make-hash-table :test 'equal)))) - -(defun jao-doc-view--current-bmks () - (or jao-doc-view--current-bmks - (setq jao-doc-view--current-bmks (jao-doc-view--read-bmks)))) - -(defun jao-doc-view-purge-bmks () - (interactive) - (when jao-doc-view--current-bmks - (maphash (lambda (k v) - (when (or (not k) (= 1 v) (not (file-exists-p k))) - (remhash k jao-doc-view--current-bmks))) - jao-doc-view--current-bmks))) - -(defun jao-doc-view-goto-bmk () - (interactive) - (when (eq major-mode 'pdf-view-mode) - (let* ((bmks (jao-doc-view--current-bmks)) - (fname (buffer-file-name)) - (p (when fname (gethash (expand-file-name fname) bmks 1)))) - (when (and (numberp p) (> p 1)) - (message "Found bookmark at page %d" p) - (ignore-errors (pdf-view-goto-page p)))))) - -(defun jao-doc-view-open (file) - (let* ((buffs (buffer-list)) - (b (catch 'done - (while buffs - (when (string-equal (buffer-file-name (car buffs)) file) - (throw 'done (car buffs))) - (setq buffs (cdr buffs)))))) - (if b - (pop-to-buffer b) - (when (file-exists-p file) (find-file file))))) - (defun jao-doc-view-session (&optional file) (let ((file (or file jao-doc-view-session-file))) (jao-doc-view--read-file file))) -(defun jao-doc-view-load-session (&optional file) - (interactive) - (let ((docs (jao-doc-view-session file))) - (when (not (listp docs)) (error "Empty session")) - (dolist (d docs) (other-window 1) (jao-doc-view-open d)))) - -(defun jao-doc-view--save-bmks () - (jao-doc-view-purge-bmks) - (jao-doc-view--save-to-file jao-doc-view-bmk-file - (jao-doc-view--current-bmks))) - -(defun jao-doc-view--save-bmk (&rest ignored) - (when (eq major-mode 'pdf-view-mode) - (ignore-errors - (puthash (buffer-file-name) - (max (pdf-view-current-page) 1) - (jao-doc-view--current-bmks))))) - (defun jao-doc-view-save-session (&optional skip-current) (interactive) (let ((docs '()) @@ -109,15 +56,12 @@ (with-current-buffer b (when (and (equalp major-mode 'pdf-view-mode) (not (equalp cb b))) - (jao-doc-view--save-bmk) (add-to-list 'docs (buffer-file-name))))) - (jao-doc-view--save-bmks) (when (> (length docs) 0) (jao-doc-view--save-to-file jao-doc-view-session-file docs)))) (defun jao-doc-view--save-session-1 () - (when (equalp major-mode 'pdf-view-mode) - (jao-doc-view-purge-bmks) + (when (derived-mode-p 'pdf-view-mode 'doc-view-mode) (jao-doc-view-save-session t))) (defvar jao-doc-session-timer nil) @@ -141,9 +85,88 @@ t 'jao-doc-view--save-session))) + +;;; PDF info + +(defvar-local jao--pdf-outline nil) + +(defmacro jao-doc-view--pdf-call (a b &rest args) + `(cond ((derived-mode-p 'pdf-view-mode) (,a ,@args)) + ((derived-mode-p 'doc-view-mode) (,b ,@args)))) + +(defun jao-doc-view-is-pdf (file) (string-match-p ".*\\.pdf$" file)) + +(defun jao-doc-view-title (&optional fname) + (let ((base (file-name-base (or fname (buffer-file-name))))) + (capitalize (replace-regexp-in-string "-" " " base)))) + +(defun jao-doc-view-title->file (title) + (concat (mapconcat 'downcase (split-string title nil t) "-") ".pdf")) + +(defun jao-doc-view-current-page () + (jao-doc-view--pdf-call pdf-view-current-page doc-view-current-page)) + +(defun jao-doc-view-goto-page (page &optional height) + (when page + (jao-doc-view--pdf-call pdf-view-goto-page doc-view-goto-page page)) + (when (and height (derived-mode-p 'pdf-view-mode)) + (image-set-window-vscroll + (round (/ (* height (cdr (pdf-view-image-size))) (frame-char-height)))))) + +(defun jao-doc-view-pdf-outline () + (if (derived-mode-p 'pdf-view-mode) + (pdf-info-outline) + (let ((outline nil) + (fn (shell-quote-argument (buffer-file-name)))) + (with-temp-buffer + (insert (shell-command-to-string (format "mutool show %s outline" fn))) + (goto-char (point-min)) + (while (re-search-forward ".+\\(\t+\\)\"\\(.+\\)\"\t#\\([0-9]+\\)," nil t) + (push `((level . ,(length (match-string 1))) + (title . ,(match-string 2)) + (page . ,(string-to-number (match-string 3)))) + outline))) + (nreverse outline)))) + +(defun jao-doc-view-section-title (&optional page) + (when (not jao--pdf-outline) + (setq-local jao--pdf-outline (jao-doc-view-pdf-outline))) + (let ((page (or page (jao-doc-view-current-page))) + (outline jao--pdf-outline) + (cur-page 0) + (cur-title (jao-doc-view-title))) + (while (and (car outline) (< cur-page page)) + (setq cur-page (cdr (assoc 'page (car outline)))) + (when (<= cur-page page) + (setq cur-title (cdr (assoc 'title (car outline))))) + (setq outline (cdr outline))) + (replace-regexp-in-string "[[:blank:]]+" " " cur-title))) + + +;;; imenu +(defun jao-doc-view--enable-imenu () + (setq-local imenu-create-index-function #'jao-doc-view--imenu-create-index) + (imenu-add-to-menubar "PDF outline")) + +(defun jao-doc-view--imenu-create-index () + (let (index) + (dolist (item (or jao--pdf-outline + (setq jao--pdf-outline (jao-doc-view-pdf-outline)))) + (let-alist item + (let* ((lvl (make-string (max 0 (1- .level)) ?.)) + (title (format "%s%s (%s)" lvl .title .page))) + (push `(,title 0 jao-doc-view--go ,item) index)))) + (nreverse index))) + +(defun jao-doc-view--go (&rest args) + (when-let (item (car (last args))) + (let-alist item (jao-doc-view-goto-page .page)))) + + +;; install +;;;###autoload (defun jao-doc-view-install () - (jao-doc-view--current-bmks) - (add-hook 'kill-buffer-hook 'jao-doc-view--save-bmk) + (add-hook 'doc-view-mode-hook #'jao-doc-view--enable-imenu) (add-hook 'kill-buffer-hook 'jao-doc-view--save-session-1 t) (add-hook 'kill-emacs-hook 'jao-doc-view-save-session) (jao-doc-view-start-session-timer)) -- cgit v1.2.3