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 +++++++++++++++++++++++++++-------------------- lib/doc/jao-org-links.el | 86 ++++++++++---------------- 2 files changed, 121 insertions(+), 122 deletions(-) (limited to 'lib/doc') 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)) diff --git a/lib/doc/jao-org-links.el b/lib/doc/jao-org-links.el index 2defa7c..5848698 100644 --- a/lib/doc/jao-org-links.el +++ b/lib/doc/jao-org-links.el @@ -1,30 +1,25 @@ ;; -*- lexical-binding: t; -*- +(require 'pdf-tools nil t) + (require 'jao-org-notes) +(require 'jao-doc-view) (require 'jao-maildir) -(require 'pdf-info) -(defvar jao-org--sink-dir "./") -(defvar jao-org-open-pdf-fun 'jao-org--pdf-tools-open) +(declare pdf-info-outline "pdf-info") -(defun jao-org--pdf-go (page height) - (when page (pdf-view-goto-page page)) - (when height - (image-set-window-vscroll - (round (/ (* height (cdr (pdf-view-image-size))) (frame-char-height)))))) +(defvar jao-org--sink-dir "./") +(defvar jao-org-open-pdf-fun #'jao-org--pdf-tools-open) (defun jao-org--pdf-tools-open (path page &optional height) (org-open-file path 1) - (jao-org--pdf-go path page)) + (jao-doc-view-goto-page page height)) (defun jao-org--pdf-open (path page &optional height) - (funcall (or jao-org-open-pdf-fun 'jao-org--pdf-tools-open) path page height)) - -(defun jao-org--pdf-p (file) (string-match-p ".*\\.pdf$" file)) + (funcall (or jao-org-open-pdf-fun #'jao-org--pdf-tools-open) path page height)) (defun jao-org-links--open-pdf (link) "Open LINK in pdf-view-mode." - (require 'pdf-tools) (cond ((string-match "\\(.*\\)::\\([0-9]*\\)\\+\\+\\([[0-9]\\.*[0-9]*\\)" link) (let* ((path (match-string 1 link)) (page (string-to-number (match-string 2 link))) @@ -45,7 +40,7 @@ (read-file-name "Import file: " jao-org--sink-dir link link)))) (shell-command (format "mv %s %s" real-file dest-path)))) - (if (jao-org--pdf-p dest-path) + (if (jao-doc-view-is-pdf dest-path) (jao-org-links--open-pdf full-link) (browse-url (format "file://%s" (expand-file-name dest-path)))))) @@ -53,33 +48,10 @@ (let ((default-directory jao-org--sink-dir)) (let ((f (replace-regexp-in-string "^file:" "doc:" (org-file-complete-link arg)))) - (if (jao-org--pdf-p f) + (if (jao-doc-view-is-pdf f) (concat f "::" (read-from-minibuffer "Page: " "1")) f)))) -(defsubst jao-org--title->file (title) - (concat (mapconcat 'downcase (split-string title nil t) "-") ".pdf")) - -(defun jao-org--pdf-title (&optional fname) - (let ((base (file-name-base (or fname (pdf-view-buffer-file-name))))) - (capitalize (replace-regexp-in-string "-" " " base)))) - -(defvar-local jao--pdf-outline nil) - -(defun jao-org--pdf-section-title (&optional page) - (when (not jao--pdf-outline) - (setq-local jao--pdf-outline (pdf-info-outline))) - (let ((page (or page (pdf-view-current-page))) - (outline jao--pdf-outline) - (cur-page 0) - (cur-title (jao-org--pdf-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))) - (defun jao-org-links-open-mail (fname) (let ((group (jao-maildir-file-to-group fname)) (id (with-temp-buffer @@ -96,10 +68,10 @@ (defun jao-org-links--store-pdf-link () (or (when (fboundp jao-org-links-pdf-store-fun) (funcall jao-org-links-pdf-store-fun)) - (when (derived-mode-p 'pdf-view-mode) + (when (derived-mode-p 'pdf-view-mode 'doc-view-mode) (jao-org-links-store-pdf-link buffer-file-name - (pdf-view-current-page) - (jao-org--pdf-section-title))))) + (jao-doc-view-current-page) + (jao-doc-view-section-title))))) ;;;###autoload (defun jao-org-links-store-pdf-link (path page title) @@ -111,17 +83,7 @@ ;;;###autoload (defun jao-org-insert-doc (title) (interactive "sDocument title: ") - (insert (format "[[doc:%s][%s]]" (jao-org--title->file title) title))) - -;;;###autoload -(defun jao-org-links-setup (sink-dir) - (interactive) - (org-link-set-parameters "doc" - :follow #'jao-org-links--follow-doc - :complete #'jao-org-links--complete-doc - :store #'jao-org-links--store-pdf-link) - (org-link-set-parameters "message" :follow #'jao-org-links-open-mail) - (setq jao-org--sink-dir (file-name-as-directory sink-dir))) + (insert (format "[[doc:%s][%s]]" (jao-doc-view-title->file title) title))) ;;;###autoload (defun jao-org-org-to-pdf-file () @@ -143,7 +105,7 @@ ;;;###autoload (defun jao-org-insert-doc-skeleton (&optional title) - (insert "#+title: " (or title (jao-org--pdf-title (buffer-file-name))) + (insert "#+title: " (or title (jao-doc-view-title (buffer-file-name))) "\n#+author:\n#+filetags: ") (jao-org-notes-insert-tags) (insert "\n#+startup: latexpreview\n\n")) @@ -151,16 +113,19 @@ ;;;###autoload (defun jao-org-pdf-goto-org (arg) (interactive "P") - (when (jao-org--pdf-p buffer-file-name) + (when (jao-doc-view-is-pdf buffer-file-name) (let* ((file (jao-org-pdf-to-org-file)) (new (not (file-exists-p file))) - (title (jao-org--pdf-title))) + (title (jao-doc-view-title))) (when (or arg new) (org-store-link nil t)) (find-file-other-window file) (when new (jao-org-insert-doc-skeleton title) (org-insert-link))))) +;;;###autoload +(defun jao-org-pdf-goto-org* () (interactive) (jao-org-pdf-goto-org t)) + ;;;###autoload (defun jao-org-org-goto-pdf () (interactive) @@ -168,4 +133,15 @@ (find-file-other-window f) (user-error "No PDF file associated with this buffer"))) +;;;###autoload +(defun jao-org-links-setup (sink-dir) + (interactive) + (org-link-set-parameters "doc" + :follow #'jao-org-links--follow-doc + :complete #'jao-org-links--complete-doc + :store #'jao-org-links--store-pdf-link) + (org-link-set-parameters "docview" :store #'ignore) + (org-link-set-parameters "message" :follow #'jao-org-links-open-mail) + (setq jao-org--sink-dir (file-name-as-directory sink-dir))) + (provide 'jao-org-links) -- cgit v1.2.3