From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Visuwesh Newsgroups: gmane.emacs.bugs Subject: bug#73530: [PATCH] Add imenu index function for Djvu files in doc-view Date: Wed, 02 Oct 2024 13:49:55 +0530 Message-ID: <87y136dihg.fsf@gmail.com> References: <8734ljg6f5.fsf@gmail.com> <86msjr6ayu.fsf@gnu.org> <874j5ziudn.fsf@gnu.org> <87y13bel5m.fsf@gmail.com> <-wirQcNBR0cpaXo0jL0sp8CxUkFsFX_iWUm_BoGq4ChYLccOyN7QJN53eHf0Q-AncT65owrhqfPWYnnQO3gRHw==@protonmail.internalid> <87setjhcm6.fsf@gnu.org> <87zfnrzjl7.fsf@mail.jao.io> <87h69zh9nw.fsf@gnu.org> <87v7yfzhfz.fsf@mail.jao.io> <87h69yh7zp.fsf@gnu.org> <87ttdyedga.fsf@gmail.com> <87y13ae8it.fsf@gnu.org> <87plome7oc.fsf@gmail.com> <87ikuddp8q.fsf@gmail.com> <875xqb2efq.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="12948"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Eli Zaretskii , "Jose A. Ortega Ruiz" , 73530@debbugs.gnu.org To: Tassilo Horn Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Oct 02 10:22:26 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1svucq-0003BP-S0 for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 02 Oct 2024 10:22:25 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1svucZ-0007LN-Qw; Wed, 02 Oct 2024 04:22:07 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1svucU-0007Kv-MM for bug-gnu-emacs@gnu.org; Wed, 02 Oct 2024 04:22:03 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1svucT-0003x4-Ok for bug-gnu-emacs@gnu.org; Wed, 02 Oct 2024 04:22:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:References:In-Reply-To:From:To:Subject; bh=eDCL1ou1JTN9zVEWiK+8N7GmA+VUVi+2pFQV/sL/S1Y=; b=cvATo3Ptul2mJwEHQNyE0puNklAxLbNjNhi30KFsIcicfTDhue5TGKiGJRXaZwQG3KMxzc8Gb8zHIfjTypjJACt4Wgrf48Ye25pZgL4t8sCGtlDltflmGpJ1RYLQvryR0wWmQuxCRzKwr6/REz0b0+IgUvI6SOSKFCAvyBYghbMAkU4lHIDBoQrZX7ckf4nexWoCrO0HreOCUC/4hXIZmuqK5BFH+vTMiDxeXmYSaWrNvTyyHnoup5e8kUcziZDeqJPulhyGCUcZ58wx+fQA+nwqmwcdETyI9RfHtYsUb1oA7V+bTNRl54We58tnBkFKQcfdqqii0dFFk2KobQEKYQ==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1svucT-0000Iu-NH for bug-gnu-emacs@gnu.org; Wed, 02 Oct 2024 04:22:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Visuwesh Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 02 Oct 2024 08:22:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 73530 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 73530-submit@debbugs.gnu.org id=B73530.17278572701052 (code B ref 73530); Wed, 02 Oct 2024 08:22:01 +0000 Original-Received: (at 73530) by debbugs.gnu.org; 2 Oct 2024 08:21:10 +0000 Original-Received: from localhost ([127.0.0.1]:56525 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1svubd-0000Gt-LC for submit@debbugs.gnu.org; Wed, 02 Oct 2024 04:21:10 -0400 Original-Received: from mail-pl1-f195.google.com ([209.85.214.195]:42305) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1svubb-0000GD-AU for 73530@debbugs.gnu.org; Wed, 02 Oct 2024 04:21:08 -0400 Original-Received: by mail-pl1-f195.google.com with SMTP id d9443c01a7336-20b01da232aso4498945ad.1 for <73530@debbugs.gnu.org>; Wed, 02 Oct 2024 01:21:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727857201; x=1728462001; darn=debbugs.gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=eDCL1ou1JTN9zVEWiK+8N7GmA+VUVi+2pFQV/sL/S1Y=; b=cUhkj+G6fwjXMk7qJk8dVb6paRkCRQ0OxonV/2GyqVEodc9yJhxBnpaAn9GKN/QF94 uerYeYqlbC0mRp9LJJAjRUKaMsbUZ+wz+HrUR+2XjGBOTVWX2ZG3BgcQSPWvUAcWA3YA yYZDnioCjKLz7/U69UVLtnUeno2OHqv1odOn6eTxcYML8HXcGHyzGBPzv/DpcKwSNWQb O0Vm122AMhFLd7tarMWbiB1ywSYHEmgVoofG+lxJots/9s+goKeHTXZEF8LG4pr8Gh7a Y8J94k7Ui48Fh8wrknhWoWt/vFivyeWtB+8uOKipWv1gZDLUpi+bDMADPaxmQAAcFz5/ FjcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727857201; x=1728462001; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=eDCL1ou1JTN9zVEWiK+8N7GmA+VUVi+2pFQV/sL/S1Y=; b=Z0MnsLwKgc1JF00CPRkHFnwUcL7AJ4Cr6veajmvyfnwX1Tcp7ONgj6LWUkIZsY8E7Q 8sE0DndVq+18tLMjEQ8TOrKTNMqKT/Q799+gVYaQUe7PsCxGyF6LKapHhOZWZy2uJ3qW Uq9KVG2QShpaDyBUUhNDZAjlpVRZ+lpdW1NTM7aE4y+BS4aYkW+tEw6pFRuJRB934t/+ wgkqmcZDC4/TD1ct8L/pcGY7KdgrRxVXWQ4vjy3TPUTktBaFTWMh2yF4jd8y65lsI7h6 15cLnarAUz8c61NDAatO11r7HUvG6oRl/QSe9fM9rWMPTT+9bVTA4VUqB+wKN4a6MXB7 C0qA== X-Forwarded-Encrypted: i=1; AJvYcCVje2gvSNzxyhkJy4jGMpspyT9Em5peWZBCV9rvGW7gJzF4a89AOnSqDnUfTLU1UCY9q6SLBg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YzTQp/tNxy9VwXIl6rGlW+KEV+7zOOIefswE4ElgZ/MLi6m2mK0 q7En94joLabn08GLvvZKgb1OAKQPllve3itGUh0ZU8rhc8n1VoaG X-Google-Smtp-Source: AGHT+IF0NP4fA0SitpMDYDqxdHYzrZpkyHKakZeKnsgC7dr84ROtbQrrzQb7dOJe8IJQfNIjEhHPVQ== X-Received: by 2002:a17:903:2409:b0:1fd:9648:2d66 with SMTP id d9443c01a7336-20bc5b97ba9mr36976155ad.17.1727857201097; Wed, 02 Oct 2024 01:20:01 -0700 (PDT) Original-Received: from localhost ([1.7.159.70]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-20b37e4dbc0sm80424305ad.243.2024.10.02.01.19.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2024 01:20:00 -0700 (PDT) In-Reply-To: <875xqb2efq.fsf@gnu.org> (Tassilo Horn's message of "Wed, 02 Oct 2024 08:42:49 +0200") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:292828 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable [=E0=AE=AA=E0=AF=81=E0=AE=A4=E0=AE=A9=E0=AF=8D =E0=AE=85=E0=AE=95=E0=AF=8D= =E0=AE=9F=E0=AF=8B=E0=AE=AA=E0=AE=B0=E0=AF=8D 02, 2024] Tassilo Horn wrote: > Visuwesh writes: > > Hi Visuwesh, > > [Sorry if this message appears twice but it seems to have bounced > yesterday.] [ I did not get the previous mail FYI. ] >> Please review the attached. > > First of all, the patch doesn't apply on master's NEWS and misc.texi > here. If I exclude those, the changes to doc-view.el can be applied. Oops, I suppose I can no longer be lazy about pulling from remote anymore. > Unfortunately, I didn't find a PDF nor DjVu document on my computer > where an index can be built. I have the relevant tools installed but > get the message that no index can be built for that document and > doc-view--outline becomes 'unavailable. > > I've tried various PDFs generated by LaTeX with many section, > subsections, etc. The PDF generated by LaTeX can have a wildly different outline than matched by doc-view's regexp: % mutool show test.pdf outline | "Text" #nameddest=3Dsection.1 | "Annotations" #nameddest=3Dsection.2 | "Links" #nameddest=3Dsection.3 | "Attachments" #nameddest=3Dsection.4 + "Outline" #nameddest=3Dsection.5 + "subsection" #nameddest=3Dsubsection.5.1 | "subsubsection" #nameddest=3Dsubsubsection.5.1.1 Compare it with: % mutool show atkins_physical_chemistry.pdf outline | "Cover" #page=3D1&view=3DFit | "PREFACE" #page=3D7&view=3DFit | "USING THE BOOK" #page=3D8&view=3DFit | "ABOUT THE AUTHORS" #page=3D12&view=3DFit | "ACKNOWLEDGEMENTS" #page=3D13&view=3DFit | "BRIEF CONTENTS" #page=3D15&view=3DFit | "FULL CONTENTS" #page=3D17&view=3DFit | "CONVENTIONS" #page=3D27&view=3DFit | "LIST OF TABLES" #page=3D28&view=3DFit ... > For DjVu, my sample size is 1, and that's a presentation, so at least > here I'm not sure if there should be an index available... I will send the link to the DjVu file that I wrote the feature for off-list. I will send a link to a PDF file too. > That said, I haven't used the imenu feature before so I can't say if it > ever worked for me... > >> diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi >> index e19e554fb26..332d5b1468f 100644 >> --- a/doc/emacs/misc.texi >> +++ b/doc/emacs/misc.texi >> @@ -581,17 +581,14 @@ DocView Navigation >> default size for DocView, customize the variable >> @code{doc-view-resolution}. >>=20=20 >> -@vindex doc-view-imenu-enabled >> @vindex doc-view-imenu-flatten >> @vindex doc-view-imenu-format >> - When the @command{mutool} program is available, DocView will use it >> -to generate entries for an outline menu, making it accessible via the >> -@code{imenu} facility (@pxref{Imenu}). To disable this functionality >> -even when @command{mutool} can be found on your system, customize the >> -variable @code{doc-view-imenu-enabled} to the @code{nil} value. You >> -can further customize how @code{imenu} items are formatted and >> -displayed using the variables @code{doc-view-imenu-format} and >> -@code{doc-view-imenu-flatten}. >> + DocView can generate an outline menu for PDF and Djvu documents using > > Didn't Eli say the official spelling was DjVu? That's at least the > spelling that the djvused man pages also uses and they should know. Fixed. >> +the @command{mutool} and the @command{djvused} programs respectively >> +when they are available. This is made accessible via the >> @code{imenu} +facility (@pxref{Imenu}). You can customize how >> @code{imenu} items are +formatted and displayed using the variables >> @code{doc-view-imenu-format} +and @code{doc-view-imenu-flatten}. > > I guess you should mention the new defcustom doc-view-djvused-program > here, too. Done. On this note, should we use doc-view-pdfdraw-program in place of mutool in doc-view--pdf-outline? >> +(defcustom doc-view-imenu-enabled (and (or (executable-find "mutool") >> + (executable-find "djvused")) >> + t) >> + "Whether to generate imenu outline for PDF and Djvu files. >> +This uses \"mutool\" for PDF files and \"djvused\" for Djvu files." >> :type 'boolean >> - :version "29.1") >> + :version "31.1") >> +(make-obsolete-variable 'doc-view-imenu-enabled >> + "Imenu index is generated unconditionally, when available" >> + "31.1") > > Ah, I thought our last agreement was that we keep that variable (as > suggested by Jose) as it is used right now but make it possible to have > a value that tells to index only PDF or DjVu documents. Ahh, I misunderstood the suggestion. > Well, I actually have no strong opinion here. Technically, I like your > approach better because of its simplicity. I would like to test with > some larger documents to see how long index building takes, though. I tried the function with a large PDF file: % time mutool show atkins_physical_chemistry.pdf outline >/dev/null 0m00.32s real 0m00.30s user 0m00.02s system % time mutool show atkins_physical_chemistry.pdf outline >/dev/null 0m00.30s real 0m00.26s user 0m00.03s system % mutool show atkins_physical_chemistry.pdf outline |wc -l 925 % du -h atkins_physical_chemistry.pdf=20 97M atkins_physical_chemistry.pdf (benchmark-run 10 (doc-view--pdf-outline "~/doc/uni/refb/atkins_physical_chemistry.pdf"= )) ;; =3D> (3.0118861719999996 0 0.0) (benchmark-run 1 (doc-view--pdf-outline "~/doc/uni/refb/atkins_physical_chemistry.pdf"= )) ;; =3D> (0.306343039 0 0.0) which honestly isn't that long a time to wait for the first time you say M-g i. Now for the DjVu file that I was testing on: % time djvused -e print-outline Solid_State_Physics_Ashcroft.djvu >/dev= /null 0m00.24s real 0m00.23s user 0m00.01s system % djvused -e print-outline Solid_State_Physics_Ashcroft.djvu |wc -l 115 % du -sh Solid_State_Physics_Ashcroft.djvu=20 83M Solid_State_Physics_Ashcroft.djvu (benchmark-run 10 (doc-view--djvu-outline "~/tmp/Solid_State_Physics_Ashcroft.djvu")) ;; =3D> (2.2234427809999997 0 0.0) (benchmark-run 1 (doc-view--djvu-outline "~/tmp/Solid_State_Physics_Ashcroft.djvu")) ;; =3D> (0.239040117 0 0.0) IIRC, there's a djvu file somewhere stashed in my home directory that had an index. I can benchmark making the index for that file too if you want. For my init.el which has a (length imenu--index-alist) =3D 852, (benchmark-run 10 (setq imenu--index-alist nil) (imenu--make-index-alist)) ;; =3D> (7.113529254 0 0.0) with REPETITIONS=3D1, I get (0.854962398 0 0.0). In conclusion, the waiting time is barely an inconvenience. > Anyhow, please write a complete sentence in the deprecation, so a dot at > the end. And remove the comma. Done. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Add-imenu-index-function-for-DjVu-files-in-doc-view.patch >From 54c6050fa054dfb23b9f73c46661bfb8c69cc931 Mon Sep 17 00:00:00 2001 From: Visuwesh Date: Wed, 2 Oct 2024 13:48:25 +0530 Subject: [PATCH] Add imenu index function for DjVu files in doc-view * lisp/doc-view.el (doc-view-imenu-enabled): Tweak the default value to check for 'djvused', and make it obsolete. (doc-view--djvu-outline, doc-view--parse-djvu-outline): Add new functions to return imenu index for a Djvu file. (doc-view--outline): Add new function to create the imenu index depending on the file type. (doc-view--outline): Document new possible variable value. (doc-view-imenu-index): Use the above function instead. (doc-view-imenu-setup): Try to create the imenu index unconditionally. * doc/emacs/misc.texi (DocView Navigation): Mention index creation using 'djvused' too. * etc/NEWS: Announce the change. (Bug#73530) --- doc/emacs/misc.texi | 18 ++++---- etc/NEWS | 7 +++ lisp/doc-view.el | 101 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index b074eb034b2..7b11a829b0b 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -581,17 +581,17 @@ DocView Navigation default size for DocView, customize the variable @code{doc-view-resolution}. -@vindex doc-view-imenu-enabled @vindex doc-view-imenu-flatten @vindex doc-view-imenu-format - When the @command{mutool} program is available, DocView will use it -to generate entries for an outline menu, making it accessible via the -@code{imenu} facility (@pxref{Imenu}). To disable this functionality -even when @command{mutool} can be found on your system, customize the -variable @code{doc-view-imenu-enabled} to the @code{nil} value. You -can further customize how @code{imenu} items are formatted and -displayed using the variables @code{doc-view-imenu-format} and -@code{doc-view-imenu-flatten}. +@vindex doc-view-djvused-program + DocView can generate an outline menu for PDF and DjVu documents using +the @command{mutool} and the @command{djvused} programs respectively +when they are available. This is made accessible via the @code{imenu} +facility (@pxref{Imenu}). You can customize how @code{imenu} items are +formatted and displayed using the variables @code{doc-view-imenu-format} +and @code{doc-view-imenu-flatten}. The filename of the +@command{djvused} program can be customized by changing the +@code{doc-view-djvused-program} user option. @cindex registers, in DocView mode @findex doc-view-page-to-register diff --git a/etc/NEWS b/etc/NEWS index abe316547aa..bbcef80b762 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -351,6 +351,13 @@ Docview can store current page to buffer-local registers with the new command 'doc-view-page-to-register' (bound to 'm'), and later the stored page can be restored with 'doc-view-jump-to-register' (bound to '''). ++++ +*** Docview can generate imenu index for DjVu files. +When the 'djvused' program is available, Docview can now generate imenu +index for DjVu files from its outline. +The name of the 'djvused' program can be customized by changing the user +option 'doc-view-djvused-program'. + ** Tramp +++ diff --git a/lisp/doc-view.el b/lisp/doc-view.el index e79295a8b01..6aa90926465 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -27,8 +27,10 @@ ;; `pdftotext', which comes with xpdf (https://www.foolabs.com/xpdf/) ;; or poppler (https://poppler.freedesktop.org/). EPUB, CBZ, FB2, XPS ;; and OXPS documents require `mutool' which comes with mupdf -;; (https://mupdf.com/index.html). Djvu documents require `ddjvu' +;; (https://mupdf.com/index.html). DjVu documents require `ddjvu' ;; (from DjVuLibre). ODF files require `soffice' (from LibreOffice). +;; `djvused' (from DjVuLibre) can be optionally used to generate imenu +;; outline for DjVu documents when available. ;;; Commentary: @@ -216,10 +218,23 @@ doc-view-mupdf-use-svg :type 'boolean :version "30.1") -(defcustom doc-view-imenu-enabled (and (executable-find "mutool") t) - "Whether to generate an imenu outline when \"mutool\" is available." +(defcustom doc-view-djvused-program (and (executable-find "djvused") + "djvused") + "Name of \"djvused\" program to generate imenu outline for DjVu files. +This is part of DjVuLibre." + :type 'file + :version "31.1") + +(defcustom doc-view-imenu-enabled (and (or (executable-find "mutool") + (executable-find "djvused")) + t) + "Whether to generate imenu outline for PDF and DjVu files. +This uses \"mutool\" for PDF files and \"djvused\" for DjVu files." :type 'boolean - :version "29.1") + :version "31.1") +(make-obsolete-variable 'doc-view-imenu-enabled + "Imenu index is generated unconditionally when available." + "31.1") (defcustom doc-view-imenu-title-format "%t (%p)" "Format spec for imenu's display of section titles from docview documents. @@ -1958,7 +1973,9 @@ doc-view--outline-rx "[^\t]+\\(\t+\\)\"\\(.+\\)\"\t#\\(?:page=\\)?\\([0-9]+\\)") (defvar-local doc-view--outline nil - "Cached PDF outline, so that it is only computed once per document.") + "Cached PDF outline, so that it is only computed once per document. +It can be the symbol `unavailable' to indicate that outline is +unavailable for the document.") (defun doc-view--pdf-outline (&optional file-name) "Return a list describing the outline of FILE-NAME. @@ -1973,6 +1990,7 @@ doc-view--pdf-outline (fn (expand-file-name fn))) (with-temp-buffer (unless (eql 0 (call-process "mutool" nil (current-buffer) nil "show" fn "outline")) + (setq doc-view--outline 'unavailable) (imenu-unavailable-error "Unable to create imenu index using `mutool'")) (goto-char (point-min)) (while (re-search-forward doc-view--outline-rx nil t) @@ -1983,6 +2001,42 @@ doc-view--pdf-outline outline))) (nreverse outline))))) +(defun doc-view--djvu-outline (&optional file-name) + "Return a list describing the outline of FILE-NAME. +If FILE-NAME is nil or omitted, it defaults to the current buffer's file +name. + +For the format, see `doc-view--pdf-outline'." + (unless file-name (setq file-name (buffer-file-name))) + (with-temp-buffer + (call-process doc-view-djvused-program nil (current-buffer) nil + "-e" "print-outline" file-name) + (goto-char (point-min)) + (when (eobp) + (setq doc-view--outline 'unavailable) + (imenu-unavailable-error "Unable to create imenu index using `djvused'")) + (nreverse (doc-view--parse-djvu-outline (read (current-buffer)))))) + +(defun doc-view--parse-djvu-outline (bookmark &optional level) + "Return a list describing the djvu outline from BOOKMARK. +Optional argument LEVEL is the current heading level, which defaults to 1." + (unless level (setq level 1)) + (let ((res)) + (unless (eq (car bookmark) 'bookmarks) + (user-error "Unknown outline type: %S" (car bookmark))) + (pcase-dolist (`(,title ,page . ,rest) (cdr bookmark)) + (push `((level . ,level) + (title . ,title) + (page . ,(string-to-number (string-remove-prefix "#" page)))) + res) + (when (and rest (listp (car rest))) + (setq res (append + (doc-view--parse-djvu-outline + (cons 'bookmarks rest) + (+ level 1)) + res)))) + res)) + (defun doc-view--imenu-subtree (outline act) "Construct a tree of imenu items for the given outline list and action. @@ -2015,19 +2069,36 @@ doc-view-imenu-index For extensibility, callers can specify a FILE-NAME to indicate the buffer other than the current buffer, and a jumping function GOTO-PAGE-FN other than `doc-view-goto-page'." - (let* ((goto (or goto-page-fn 'doc-view-goto-page)) - (act (lambda (_name _pos page) (funcall goto page))) - (outline (or doc-view--outline (doc-view--pdf-outline file-name)))) - (car (doc-view--imenu-subtree outline act)))) + (unless doc-view--outline + (setq doc-view--outline (doc-view--outline file-name))) + (unless (eq doc-view--outline 'unavailable) + (let* ((goto (or goto-page-fn #'doc-view-goto-page)) + (act (lambda (_name _pos page) (funcall goto page))) + (outline doc-view--outline)) + (car (doc-view--imenu-subtree outline act))))) + +(defun doc-view--outline (&optional file-name) + "Return the outline for the file FILE-NAME. +If FILE-NAME is nil, use the current file instead." + (unless file-name (setq file-name (buffer-file-name))) + (let ((outline + (pcase doc-view-doc-type + ('djvu + (when doc-view-djvused-program + (doc-view--djvu-outline file-name))) + (_ + (doc-view--pdf-outline file-name))))) + (when outline (imenu-add-to-menubar "Outline")) + ;; When the outline could not be made due to unavailability of the + ;; required program, or its absency from the document, return + ;; 'unavailable'. + (or outline 'unavailable))) (defun doc-view-imenu-setup () "Set up local state in the current buffer for imenu, if needed." - (when doc-view-imenu-enabled - (setq-local imenu-create-index-function #'doc-view-imenu-index - imenu-submenus-on-top nil - imenu-sort-function nil - doc-view--outline (doc-view--pdf-outline)) - (when doc-view--outline (imenu-add-to-menubar "Outline")))) + (setq-local imenu-create-index-function #'doc-view-imenu-index + imenu-submenus-on-top nil + imenu-sort-function nil)) ;;;; User interface commands and the mode -- 2.45.2 --=-=-=--