Hi all,

finally here is my patch to suggest to run makeindex when needed.  In
a complex document with index and bibliography AUCTeX now suggests to
run

    LaTeX
    BibTeX
    LaTeX
    LaTeX
    Index
    LaTeX
    LaTeX

which is the same list suggested by Enrico Gregorio here:
http://tex.blogoverflow.com/2012/09/dont-forget-to-run-makeindex/
Well, there is and extra LaTeX run at the end, but there is a warning
suggesting to run LaTeX once more.  For the record, latexmk for the
same document runs

    pdflatex
    makeindex
    bibtex
    pdflatex
    makeindex
    bibtex
    pdflatex
    pdflatex

Now, implementation of my patch:  there are two variables,
`TeX-idx-md5-alist' and `TeX-idx-changed-alist' (probably `LaTeX-*'
would be better names), which record the md5 hashes of idx files and
whether they changed after a LaTeX run.  md5 hash is calculated in
`TeX-run-TeX', and then checked again in `TeX-LaTeX-sentinel': if md5
hash changed, `TeX-idx-changed-alist' for current idx file is set to
t.  At this point, if `TeX-command-next' is one between "Dvips" and
`TeX-command-Show', then `TeX-command-default' suggest to run "Index",
because makeindex should be run when the document is almost complete,
not after the fist latex run as latexmk does.

A note about the fact I used alists instead of local variables for
`TeX-idx-md5-alist' and `TeX-idx-changed-alist'.  I first thought to
set local variables in idx files, but we need to open those files and
hope the user won't kill them.  Another possibility would be to set
those variables locally in output buffer since `TeX-command-default'
already requires that buffer to be still alive, but it seems local
variables are killed there before running a command.  My last choice
has been to use a global alist.  Does someone have better idea about
how to store md5 hash and the information about status of idx file?

Any other comment welcome.

Bye,
Mosè

2015-09-01 7:50 GMT+02:00 Tassilo Horn <[email protected]>:
> Mosè Giordano <[email protected]> writes:
>
> Hi Mosè,
>
>> differently from what it's said in section 1.3.2.1 of the manual,
>> AUCTeX never suggests to run makeindex when needed.  Does someone know
>> how can we check whether we need to run makeindex?  The .idx file is
>> rewritten after every latex run, so it's useless to look to its
>> modification time, and no warning is emitted by the compiler.
>>
>> A possibility is to store the md5 hash of the .idx file and check
>> whehter it's changed after running latex.  md5 is pretty fast compared
>> to other algorithms and I don't think this feature is security-wise.
>> If I recall correctly, latexmk does the same check.
>
> `md5' sounds reasonable for this purpose, and it's available in all
> emacsen we support.
>
> Bye,
> Tassilo
>
>
> _______________________________________________
> auctex-devel mailing list
> [email protected]
> https://lists.gnu.org/mailman/listinfo/auctex-devel
diff --git a/tex-buf.el b/tex-buf.el
index c13a87e..d98f067 100644
--- a/tex-buf.el
+++ b/tex-buf.el
@@ -336,6 +336,17 @@ This works only with TeX commands and if the
 (defconst TeX-error-overview-buffer-name "*TeX errors*"
   "Name of the buffer in which to show error list.")
 
+(defvar TeX-idx-md5-alist nil
+  "Alist of MD5 hashes of idx file.
+
+Car is the idx file, cdr is its md5 hash.")
+
+(defvar TeX-idx-changed-alist nil
+  "Whether the idx files changed.
+
+Car is the idx file, cdr is whether idx changed after LaTeX
+run.")
+
 (defcustom TeX-check-engine t
   "Whether AUCTeX should check the correct engine has been set before running LaTeX commands."
   :group 'TeX-command
@@ -642,7 +653,7 @@ omitted) and `TeX-region-file'."
 	      TeX-command-sequence-command command))
        (t
 	(setq cmd (TeX-command-default
-		   (funcall TeX-command-sequence-file-function nil t))
+		   (funcall TeX-command-sequence-file-function))
 	      TeX-command-sequence-command t)))
       (TeX-command cmd TeX-command-sequence-file-function 0)
       (when reset
@@ -685,28 +696,44 @@ omitted) and `TeX-region-file'."
 
 (defun TeX-command-default (name)
   "Guess the next command to be run on NAME."
-  (cond ((if (string-equal name TeX-region)
-	     (TeX-check-files (concat name "." (TeX-output-extension))
-			      (list name)
-			      TeX-file-extensions)
-	   (TeX-save-document (TeX-master-file)))
-	 TeX-command-default)
-	((and (memq major-mode '(doctex-mode latex-mode))
-	      ;; Want to know if bib file is newer than .bbl
-	      ;; We don't care whether the bib files are open in emacs
-	      (TeX-check-files (concat name ".bbl")
-			       (mapcar 'car
-				       (LaTeX-bibliography-list))
-			       (append BibTeX-file-extensions
-				       TeX-Biber-file-extensions)))
-	 ;; We should check for bst files here as well.
-	 (if LaTeX-using-Biber TeX-command-Biber TeX-command-BibTeX))
-	((TeX-process-get-variable name
-				   'TeX-command-next
-				   (if (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)
-				       "Dvips"
-				     TeX-command-Show)))
-	(TeX-command-Show)))
+  (let ((command-next nil))
+    (cond ((if (string-equal name TeX-region)
+	       (TeX-check-files (concat name "." (TeX-output-extension))
+				(list name)
+				TeX-file-extensions)
+	     (TeX-save-document (TeX-master-file)))
+	   TeX-command-default)
+	  ((and (memq major-mode '(doctex-mode latex-mode))
+		;; Want to know if bib file is newer than .bbl
+		;; We don't care whether the bib files are open in emacs
+		(TeX-check-files (concat name ".bbl")
+				 (mapcar 'car
+					 (LaTeX-bibliography-list))
+				 (append BibTeX-file-extensions
+					 TeX-Biber-file-extensions)))
+	   ;; We should check for bst files here as well.
+	   (if LaTeX-using-Biber TeX-command-Biber TeX-command-BibTeX))
+	  ((and
+	    ;; Rational: makeindex should be run when final document is
+	    ;; almost complete (see
+	    ;; http://tex.blogoverflow.com/2012/09/dont-forget-to-run-makeindex/),
+	    ;; otherwise after following latex runs index pages may change
+	    ;; due to changes in final document, resulting in extra
+	    ;; makeindex and latex runs.
+	    (member
+	     (setq command-next
+		   (TeX-process-get-variable
+		    name
+		    'TeX-command-next
+		    (if (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)
+			"Dvips"
+		      TeX-command-Show)))
+	     (list "Dvips" TeX-command-Show))
+	    (cdr (assoc (expand-file-name (concat name ".idx"))
+			TeX-idx-changed-alist)))
+	   "Index")
+	  (command-next)
+	  (TeX-command-Show))))
 
 (defun TeX-command-query (name)
   "Query the user for what TeX command to use."
@@ -928,7 +955,8 @@ run of `TeX-run-TeX', use
   ;; Save information in TeX-error-report-switches
   ;; Initialize error to nil (no error) for current master.
   ;; Presence of error is reported inside `TeX-TeX-sentinel-check'
-  (let ((current-master (TeX-master-file)))
+  (let ((current-master (TeX-master-file))
+	(idx-file nil) (element nil))
     ;; the current master file is saved because error routines are
     ;; parsed in other buffers;
     (setq TeX-error-report-switches
@@ -937,7 +965,22 @@ run of `TeX-run-TeX', use
     ;; reset error to nil (no error)
     (setq TeX-error-report-switches
 	  (plist-put TeX-error-report-switches
-		     (intern current-master) nil)))
+		     (intern current-master) nil))
+
+    ;; Store md5 hash of the index file before running LaTeX.
+    (and (memq major-mode '(doctex-mode latex-mode))
+	 (prog1 (file-exists-p
+		 (setq idx-file (expand-file-name (concat file ".idx"))))
+	   ;; In order to avoid confusion and pollution of `TeX-idx-md5-alist',
+	   ;; remove from this alist all md5 hashes of the current index file.
+	   ;; Note `assq-delete-all' doesn't work with string keys and has
+	   ;; problems with non-list elements in Emacs 21 (see file
+	   ;; tex-site.el).
+	   (while (setq element (assoc idx-file TeX-idx-md5-alist))
+	     (setq TeX-idx-md5-alist (delq element TeX-idx-md5-alist))))
+	 (with-temp-buffer
+	   (insert-file-contents idx-file)
+	   (push (cons idx-file (md5 (current-buffer))) TeX-idx-md5-alist))))
 
   ;; can we assume that TeX-sentinel-function will not be changed
   ;; during (TeX-run-format ..)? --pg
@@ -989,6 +1032,25 @@ run of `TeX-run-TeX', use
         process
       (TeX-synchronous-sentinel name file process))))
 
+(defun TeX-run-index (name command file)
+  "Create a process for NAME using COMMAND to compile the index file."
+  (let ((process (TeX-run-command name command file))
+	(element nil))
+    (setq TeX-sentinel-function 'TeX-index-sentinel)
+    ;; Same cleaning as that for `TeX-idx-md5-alist' in `TeX-run-TeX'.
+    (while (setq element
+		 ;; `file' has been determined in `TeX-command-buffer', while
+		 ;; this function has `TeX-master-directory' as
+		 ;; `default-directory', then we have to expand `file' file-name
+		 ;; in the same directory of `TeX-command-buffer'.
+		 (assoc (with-current-buffer TeX-command-buffer
+			    (expand-file-name (concat file ".idx")))
+			TeX-idx-changed-alist))
+      (setq TeX-idx-changed-alist (delq element TeX-idx-changed-alist)))
+    (if TeX-process-asynchronous
+        process
+      (TeX-synchronous-sentinel name file process))))
+
 (defun TeX-run-compile (name command file)
   "Ignore first and third argument, start compile with second argument."
   (let ((default-directory (TeX-master-directory)))
@@ -1375,6 +1437,27 @@ Rerun to get mark in right position\\." nil t)
 	(t
 	 (message "%s%s%s" name ": problems after " (TeX-current-pages))
 	 (setq TeX-command-next TeX-command-default)))
+
+  ;; Check whether the idx file changed.
+  (let ((idx-file nil) (master nil))
+    (and (file-exists-p
+	  (setq idx-file
+		(concat
+		 (setq master
+		       (with-current-buffer TeX-command-buffer
+			 (expand-file-name (TeX-active-master)))) ".idx")))
+	 ;; imakeidx package automatically runs makeindex, thus, we need to be
+	 ;; sure .ind file isn't newer than .idx.
+	 (TeX-check-files (concat master ".ind")
+			  (list (file-name-nondirectory master)) '("idx"))
+	 (with-temp-buffer
+	   (insert-file-contents idx-file)
+	   (not (equal
+		 ;; Compare old md5 hash of the idx file with the new one.
+		 (cdr (assoc idx-file TeX-idx-md5-alist))
+		 (md5 (current-buffer)))))
+	 (push (cons idx-file t) TeX-idx-changed-alist)))
+
   (unless TeX-error-list
     (run-hook-with-args 'TeX-after-TeX-LaTeX-command-finished-hook
 			(with-current-buffer TeX-command-buffer
@@ -1456,6 +1539,19 @@ Rerun to get mark in right position\\." nil t)
 	      TeX-output-extension "pdf"))
     (message "ps2pdf finished successfully. "))))
 
+(defun TeX-index-sentinel (_process _name)
+  "Cleanup TeX output buffer after compiling index."
+  (goto-char (point-max))
+  (cond
+   ((search-backward "TeX Output exited abnormally" nil t)
+    (message "Index failed.  Type `%s' to display output."
+	     (substitute-command-keys
+              "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]")))
+   (t
+    (setq TeX-command-next TeX-command-default)
+    (message (concat "Index finished successfully. "
+		     "Run LaTeX again to get index right.")))))
+
 (defun TeX-command-sequence-sentinel (process string)
   "Call the appropriate sentinel for the current process.
 
diff --git a/tex.el b/tex.el
index fa2c475..1c9b95b 100644
--- a/tex.el
+++ b/tex.el
@@ -156,7 +156,8 @@ If nil, none is specified."
      :help "Convert DVI file to PostScript")
     ("Ps2pdf" "ps2pdf %f" TeX-run-ps2pdf nil t
      :help "Convert PostScript file to PDF")
-    ("Index" "makeindex %s" TeX-run-command nil t :help "Create index file")
+    ("Index" "makeindex %s" TeX-run-index nil t
+     :help "Run makeindex to create index file")
     ("Xindy" "texindy %s" TeX-run-command nil t
      :help "Run xindy to create index file")
     ("Check" "lacheck %s" TeX-run-compile nil (latex-mode)
_______________________________________________
auctex-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/auctex-devel

Reply via email to