;; jao-doc-view-imenu.el --- old docview/imenu  -*- lexical-binding: t; -*-

;; Copyright (C) 2022  jao

;; Author: jao <mail@jao.io>
;; Keywords:

;; 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 <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Old code that made its way into emacs 29.  It defines imenu entries for
;; docview.

;;; Code:

(defvar jao-pdf--outline-rx
  "[^\t]+\\(\t+\\)\"\\(.+\\)\"\t#\\(?:page=\\)?\\([0-9]+\\)")

(defun jao-pdf-outline (&optional file-name)
  "Return an alist describing the given FILE-NAME (or current if nil).
The result is cached as a local buffer variable."
  (let* ((outline nil)
         (fn (or file-name (buffer-file-name)))
         (fn (shell-quote-argument (expand-file-name fn))))
    (with-temp-buffer
      (insert (shell-command-to-string (format "mutool show %s outline" fn)))
      (goto-char (point-min))
      (while (re-search-forward jao-pdf--outline-rx nil t)
        (push `((level . ,(length (match-string 1)))
                (title . ,(match-string 2))
                (page . ,(string-to-number (match-string 3))))
              outline)))
    (setq jao-pdf--outline (nreverse outline))))

(defun jao-pdf-imenu--index (items act)
  (let ((level (alist-get 'level (car items)))
        (index nil))
    (while (and (car items) (<= level (alist-get 'level (car items))))
      (let-alist (car items)
        (let ((title (format "%s%s (%s)" "" .title .page)))
          (if (> .level level)
              (let ((sub (jao-pdf-imenu--index items act))
                    (fst (car index)))
                (setq index (cdr index))
                (push (cons (car fst) (cons fst (car sub))) index)
                (setq items (cdr sub)))
            (push `(,title 0 ,act ,.page) index)
            (setq items (cdr items))))))
    (cons (nreverse index) items)))

(defun jao-pdf-imenu-index (&optional goto-page-fn file-name)
  "Create an imenu index using `jao-pdf-outline'."
  (let* ((goto (or goto-page-fn 'doc-view-goto-page))
         (act (lambda (_name _pos page) (funcall goto page)))
         (items (jao-pdf-outline file-name)))
    (car (jao-pdf-imenu--index items act))))

(defun jao-pdf-set-up-imenu ()
  (setq-local imenu-create-index-function #'jao-pdf-imenu-index
              imenu-submenus-on-top nil
              imenu-sort-function nil)
  (imenu-add-to-menubar "Outline"))
