Hi list, I've implemented TeX-update, as suggested in the wishlist. My work follows the same logic of http://www.emacswiki.org/emacs/TN#toc8 and is in part based on it: a function runs the compilation command and calls a sentinel which, when the command finishes, calls back the function and so on until a stopping condition is reached.
Some comments about possible copyrights concerns: - `TeX-command-default' is extracted from `TeX-command-query', there is nothing new in it; - the sentinel function `TeX-command-sequence-sentinel' is similar to `TeX-texify-sentinel' of EmacsWiki, but I don't know how a basic sentinel could be written otherwise. Moreover, how to test whether there have been errors in the last compilation is reported literally in the docstring of `TeX-error-report-switches'; - `TeX-command-sequence' has only the last three lines in common with `TeX-texify' of EmacsWiki, which are the setting of a sentinel, how could it be done otherwise? For the rest these functions are different: `TeX-command-sequence' is much more flexible (see the docstring and the possible values of the first argument) and stopping after a command has been run N times in a row does work, in `TeX-texify' it doesn't. In addition, in the second patch I've added "dvips" and "ps2pdf" rules to `TeX-command-list', and there is a new option `TeX-PDF-via-dvips-ps2pdf' so that one can produce a PDF using latex + dvips + ps2pdf. Using `TeX-update' all this boils down to a single C-c C-u :-) I've been using `TeX-update' and dvips + ps2pdf for a week, without problems. Comments and suggestions welcome. Bye, Mosè
From 4ea34d2d4510c84d722ed8c0c4b82345e1cb88f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= <m...@gnu.org> Date: Mon, 17 Aug 2015 00:28:03 +0200 Subject: [PATCH 1/2] Implement TeX-update. --- tex-buf.el | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- tex.el | 12 ++--- 2 files changed, 154 insertions(+), 29 deletions(-) diff --git a/tex-buf.el b/tex-buf.el index b5ed365..668a5b5 100644 --- a/tex-buf.el +++ b/tex-buf.el @@ -1,6 +1,6 @@ ;;; tex-buf.el --- External commands for AUCTeX. -;; Copyright (C) 1991-1999, 2001-2014 Free Software Foundation, Inc. +;; Copyright (C) 1991-1999, 2001-2015 Free Software Foundation, Inc. ;; Maintainer: auctex-devel@gnu.org ;; Keywords: tex, wp @@ -460,6 +460,114 @@ ORIGINALS which are modified but not saved yet." (setq found t))) found)) +(defcustom TeX-command-sequence-max-runs-same-command 4 + "Maximum number of runs of the same command." + :type 'integer + :group 'TeX-command) + +(defcustom TeX-command-sequence-max-runs 12 + "Maximum number of total runs." + :type 'integer + :group 'TeX-command) + +(defvar TeX-command-sequence-count-same-command 1 + "Counter for the runs of the same command in `TeX-command-sequence'.") + +(defvar TeX-command-sequence-count 1 + "Counter for the total runs of `TeX-command-sequence'.") + +(defvar TeX-command-sequence-last-command nil + "Last command run in `TeX-command-sequence'.") + +(defvar TeX-command-sequence-sentinel nil + "Sentinel for `TeX-command-sequence'.") + +(defvar TeX-command-sequence-command nil + "Command argument for `TeX-command-sequence'. + +It is set in `TeX-command-sequence' and used in +`TeX-command-sequence-sentinel' to call again +`TeX-command-sequence' with the appropriate command argument.") + +(defun TeX-command-sequence (command &optional reset) + "Run a sequence of TeX commands defined by COMMAND. + +The COMMAND argument may be + + * nil: no command will be run in this case + + * a string with a command from `TeX-command-list' + + * a non-nil list of strings, which are commands from + `TeX-command-list'; the car of the list is used as command to + be executed in the first run of `TeX-command-sequence', the + cdr of the list will be passed to the function in the next + run, etc. + + * a function name, returning a string which is command from + `TeX-command-list'; it will be funcall'd (without arguments!) + and used again in the next run of `TeX-command-sequence'. + + * with any other value the function `TeX-command-default' is + used to determine the command to run, until a stopping + condition is met. + +This function runs at most +`TeX-command-sequence-max-runs-same-command' times the same +command in a row, and `TeX-command-sequence-max-runs' times in +total in any case. It ends when `TeX-command-Show' is the +command to be run. + +A non-nil value for the optional argument RESET means this is the +first run of the function and some variables need to be reset." + (if (null command) + (message "No command to run.") + (let (cmd process) + (cond + ((stringp command) + (setq cmd command + TeX-command-sequence-command nil)) + ((listp command) + (setq cmd (pop command) + TeX-command-sequence-command command)) + ((functionp command) + (setq cmd (funcall command) + TeX-command-sequence-command command)) + (t + (setq cmd (TeX-command-default (TeX-master-file)) + TeX-command-sequence-command t))) + (TeX-command cmd 'TeX-master-file 0) + (when reset + (setq TeX-command-sequence-count-same-command 1 + TeX-command-sequence-count 1 + TeX-command-sequence-last-command nil)) + (cond + ;; Stop when the same command has been run + ;; `TeX-command-sequence-max-runs-same-command' times in a row. + ((>= TeX-command-sequence-count-same-command + TeX-command-sequence-max-runs-same-command) + (message "Stopping after running %S %d times in a row." + TeX-command-sequence-last-command + TeX-command-sequence-count-same-command)) + ;; Stop when there have been `TeX-command-sequence-max-runs' total + ;; compilations. + ((>= TeX-command-sequence-count TeX-command-sequence-max-runs) + (message "Stopping after %d compilations." TeX-command-sequence-count)) + ;; The command just run is `TeX-command-Show'. + ((equal command TeX-command-Show)) + ;; In any other case continue: increase counters (when needed), update + ;; `TeX-command-sequence-last-command' and run the sentinel. + (t + (if (equal cmd TeX-command-sequence-last-command) + (setq TeX-command-sequence-count-same-command + (1+ TeX-command-sequence-count-same-command)) + (setq TeX-command-sequence-count-same-command 1)) + (setq TeX-command-sequence-count (1+ TeX-command-sequence-count) + TeX-command-sequence-last-command cmd) + (and (setq process (get-buffer-process (current-buffer))) + (setq TeX-command-sequence-sentinel (process-sentinel process)) + (set-process-sentinel process 'TeX-command-sequence-sentinel))))))) + (defcustom TeX-save-query t "*If non-nil, ask user for permission to save files before starting TeX." :group 'TeX-command @@ -467,29 +575,32 @@ ORIGINALS which are modified but not saved yet." (defvar TeX-command-history nil) +(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 + TeX-command-Show)) + (TeX-command-Show))) + (defun TeX-command-query (name) "Query the user for what TeX command to use." - (let* ((default - (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 - TeX-command-Show)) - (TeX-command-Show))) + (let* ((default (TeX-command-default name)) (completion-ignore-case t) (answer (or TeX-command-force (completing-read @@ -1173,6 +1284,22 @@ Rerun to get mark in right position\\." nil t) "Run LaTeX again to get citations right.")) (setq TeX-command-next TeX-command-default)))) +(defun TeX-command-sequence-sentinel (process string) + "Call the appropriate sentinel for the current process. + +If there are no errors, call back `TeX-command-sequence' using +`TeX-command-sequence-command' as command argument, unless this +variable is nil." + (with-current-buffer (process-buffer process) + (funcall TeX-command-sequence-sentinel process string) + (if (string-match "\\(finished\\|exited\\)" string) + (with-current-buffer TeX-command-buffer + (unless + (or + (plist-get TeX-error-report-switches (intern (TeX-master-file))) + (null TeX-command-sequence-command)) + (TeX-command-sequence TeX-command-sequence-command)))))) + ;;; Process Control diff --git a/tex.el b/tex.el index 07fa371..ee2dccf 100644 --- a/tex.el +++ b/tex.el @@ -1276,13 +1276,6 @@ restarting Emacs." (repeat :tag "List of executables" (string :tag "Name")) (const :tag "No executable" nil))))) -;; XXX: Regarding a possibility to (manually) run an update command, -;; one could support this through `TeX-view' by letting it temporarily -;; set a variable which is checked with a predicate in the viewer -;; selection. If the check is positive, the update command is run -;; instead of the normal viewer command. Direct support through the -;; View command would require a predicate which knows when an update -;; has to be done. (defcustom TeX-view-program-selection (cond ((eq system-type 'windows-nt) @@ -2050,6 +2043,10 @@ output files." (delete-file (concat master-dir file)))) (message "No files to be deleted")))) +(defun TeX-update () + "Compile the current document until an error occurs or it is finished." + (interactive) + (TeX-command-sequence t t)) ;;; Master File @@ -4657,6 +4654,7 @@ Brace insertion is only done if point is in a math construct and (define-key map "\C-c\C-r" 'TeX-command-region) (define-key map "\C-c\C-b" 'TeX-command-buffer) (define-key map "\C-c\C-c" 'TeX-command-master) + (define-key map "\C-c\C-u" 'TeX-update) (define-key map "\C-c\C-k" 'TeX-kill-job) (define-key map "\C-c\C-l" 'TeX-recenter-output-buffer) (define-key map "\C-c^" 'TeX-home-buffer) -- 2.5.0
From 927de03cd3ccba6cefd19f89e233666a8e98b3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= <m...@gnu.org> Date: Mon, 17 Aug 2015 00:33:01 +0200 Subject: [PATCH 2/2] Generate PDF via dvips + ps2pdf. --- tex-buf.el | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- tex.el | 27 +++++++++++++++++-- 2 files changed, 101 insertions(+), 14 deletions(-) diff --git a/tex-buf.el b/tex-buf.el index 668a5b5..8164831 100644 --- a/tex-buf.el +++ b/tex-buf.el @@ -322,7 +322,7 @@ This works only with TeX commands and if the (TeX-parse-TeX (- arg) nil) ;; XXX: moving backward in the errors hasn't yet been implemented for ;; other parsing functions. - (error "Jumping to previous error not supported."))))) + (error "Jumping to previous error not supported"))))) ;;; Command Query @@ -427,8 +427,8 @@ without further expansion." (defun TeX-check-files (derived originals extensions) "Check if DERIVED is newer than any of the ORIGINALS. Try each original with each member of EXTENSIONS, in all directories -in `TeX-check-path'. Returns true if any of the ORIGINALS with any of the -EXTENSIONS are newer than DERIVED. Will prompt to save the buffer of any +in `TeX-check-path'. Returns true if any of the ORIGINALS with any of the +EXTENSIONS are newer than DERIVED. Will prompt to save the buffer of any ORIGINALS which are modified but not saved yet." (let (existingoriginals found @@ -595,7 +595,9 @@ first run of the function and some variables need to be reset." (if LaTeX-using-Biber TeX-command-Biber TeX-command-BibTeX)) ((TeX-process-get-variable name 'TeX-command-next - TeX-command-Show)) + (if (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode) + "Dvips" + TeX-command-Show))) (TeX-command-Show))) (defun TeX-command-query (name) @@ -778,7 +780,8 @@ Return the new process." (defun TeX-run-set-command (name command) "Remember TeX command to use to NAME and set corresponding output extension." (setq TeX-command-default name - TeX-output-extension (if TeX-PDF-mode "pdf" "dvi")) + TeX-output-extension + (if (and (null TeX-PDF-via-dvips-ps2pdf) TeX-PDF-mode) "pdf" "dvi")) (let ((case-fold-search t) (lst TeX-command-output-list)) (while lst @@ -862,6 +865,22 @@ run of `TeX-run-TeX', use process (TeX-synchronous-sentinel name file process)))) +(defun TeX-run-Dvips (name command file) + "Create a process for NAME using COMMAND to convert FILE with Dvips." + (let ((process (TeX-run-command name command file))) + (setq TeX-sentinel-function 'TeX-Dvips-sentinel) + (if TeX-process-asynchronous + process + (TeX-synchronous-sentinel name file process)))) + +(defun TeX-run-ps2pdf (name command file) + "Create a process for NAME using COMMAND to convert FILE with ps2pdf." + (let ((process (TeX-run-command name command file))) + (setq TeX-sentinel-function 'TeX-ps2pdf-sentinel) + (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))) @@ -1075,7 +1094,10 @@ errors or warnings to show." (TeX-parse-all-errors)) (if (and TeX-error-overview-open-after-TeX-run TeX-error-list) (TeX-error-overview)) - (setq TeX-command-next TeX-command-Show))) + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next "Dvips") + (setq TeX-command-next TeX-command-Show)))) (defun TeX-current-pages () "Return string indicating the number of pages formatted." @@ -1116,7 +1138,10 @@ Return nil ifs no errors were found." 'TeX-current-master)) t)) t) - (setq TeX-command-next TeX-command-Show) + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next "Dvips") + (setq TeX-command-next TeX-command-Show)) nil)) (defun TeX-LaTeX-sentinel-has-warnings () @@ -1198,12 +1223,18 @@ Rerun to get outlines right" nil t) ((re-search-forward "^LaTeX Warning: Reference" nil t) (message "%s%s%s" name ": there were unresolved references, " (TeX-current-pages)) - (setq TeX-command-next TeX-command-Show)) + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next "Dvips") + (setq TeX-command-next TeX-command-Show))) ((re-search-forward "^\\(?:LaTeX Warning: Citation\\|\ Package natbib Warning:.*undefined citations\\)" nil t) (message "%s%s%s" name ": there were unresolved citations, " (TeX-current-pages)) - (setq TeX-command-next TeX-command-Show)) + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next "Dvips") + (setq TeX-command-next TeX-command-Show))) ((re-search-forward "Package longtable Warning: Table widths have \ changed\\. Rerun LaTeX\\." nil t) (message @@ -1229,7 +1260,10 @@ Rerun to get mark in right position\\." nil t) ")")))) (message "%s" (concat name ": successfully formatted " (TeX-current-pages) add-info))) - (setq TeX-command-next TeX-command-Show)) + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next "Dvips") + (setq TeX-command-next TeX-command-Show))) (t (message "%s%s%s" name ": problems after " (TeX-current-pages)) (setq TeX-command-next TeX-command-default))) @@ -1284,6 +1318,36 @@ Rerun to get mark in right position\\." nil t) "Run LaTeX again to get citations right.")) (setq TeX-command-next TeX-command-default)))) +(defun TeX-Dvips-sentinel (_process _name) + "Cleanup TeX output buffer after running Dvips." + (goto-char (point-max)) + (cond + ((search-backward "TeX Output exited abnormally" nil t) + (message "Dvips failed. Type `%s' to display output." + (substitute-command-keys + "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) + (t + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-output-extension "ps" + TeX-command-next "Ps2pdf")) + (message "Dvips finished successfully. ")))) + +(defun TeX-ps2pdf-sentinel (_process _name) + "Cleanup TeX output buffer after running ps2pdf." + (goto-char (point-max)) + (cond + ((search-backward "TeX Output exited abnormally" nil t) + (message "ps2pdf failed. Type `%s' to display output." + (substitute-command-keys + "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) + (t + (if (with-current-buffer TeX-command-buffer + (and TeX-PDF-via-dvips-ps2pdf TeX-PDF-mode)) + (setq TeX-command-next TeX-command-Show + TeX-output-extension "pdf")) + (message "ps2pdf finished successfully. ")))) + (defun TeX-command-sequence-sentinel (process string) "Call the appropriate sentinel for the current process. @@ -1770,7 +1834,7 @@ If optional argument REPARSE is non-nil, reparse the output log." ;; be ignored, because `TeX-next-error' can call any of these functions. (defun TeX-parse-command (arg reparse) "We can't parse anything but TeX." - (error "I cannot parse %s output, sorry." + (error "I cannot parse %s output, sorry" (if (TeX-active-process) (process-name (TeX-active-process)) "this"))) @@ -3004,7 +3068,7 @@ forward, if negative)." (TeX-command name (if (string-match "_region_" file) 'TeX-region-file 'TeX-master-file)))) - (error "Unable to find what command to run."))) + (error "Unable to find what command to run"))) (provide 'tex-buf) diff --git a/tex.el b/tex.el index ee2dccf..b4a1812 100644 --- a/tex.el +++ b/tex.el @@ -152,6 +152,10 @@ If nil, none is specified." :visible TeX-queue-command) ("File" "%(o?)dvips %d -o %f " TeX-run-command t t :help "Generate PostScript file") + ("Dvips" "%(o?)dvips %d -o %f " TeX-run-Dvips nil t + :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") ("Xindy" "texindy %s" TeX-run-command nil t :help "Run xindy to create index file") @@ -445,8 +449,9 @@ string." (TeX-style-check LaTeX-command-style))) ("%(PDF)" (lambda () (if (and (eq TeX-engine 'default) - (or TeX-PDF-mode - TeX-DVI-via-PDFTeX)) + (if TeX-PDF-mode + (not TeX-PDF-via-dvips-ps2pdf) + TeX-DVI-via-PDFTeX)) "pdf" ""))) ("%(PDFout)" (lambda () @@ -1923,6 +1928,20 @@ already established, don't do anything." :group 'TeX-command :type 'boolean) +(defcustom TeX-PDF-via-dvips-ps2pdf nil + "Whether to produce PDF output through the (La)TeX - dvips - ps2pdf sequence." + :group 'TeX-command + :type 'boolean) +(make-variable-buffer-local 'TeX-PDF-via-dvips-ps2pdf) +(put 'TeX-PDF-via-dvips-ps2pdf 'safe-local-variable 'booleanp) + +(defun TeX-toggle-PDF-via-dvips-ps2pdf () + "Toggle `TeX-PDF-via-dvips-ps2pdf'." + (interactive) + (setq TeX-PDF-via-dvips-ps2pdf (not TeX-PDF-via-dvips-ps2pdf)) + (message (concat "TeX-PDF-via-dvips-ps2pdf: " + (if TeX-PDF-via-dvips-ps2pdf "on" "off")))) + (define-minor-mode TeX-interactive-mode "Minor mode for interactive runs of TeX." nil nil nil @@ -4740,6 +4759,10 @@ Brace insertion is only done if point is in a math construct and :style toggle :selected TeX-PDF-mode :active (not (eq TeX-engine 'omega)) :help "Use PDFTeX to generate PDF instead of DVI"] + [ "PDF via dvips + ps2pdf" TeX-toggle-PDF-via-dvips-ps2pdf + :style toggle :selected TeX-PDF-via-dvips-ps2pdf + :visible TeX-PDF-mode + :help "Compile with (La)TeX and convert to PDF with dvips + ps2pdf"] [ "Run Interactively" TeX-interactive-mode :style toggle :selected TeX-interactive-mode :keys "C-c C-t C-i" :help "Stop on errors in a TeX run"] -- 2.5.0
_______________________________________________ auctex-devel mailing list auctex-devel@gnu.org https://lists.gnu.org/mailman/listinfo/auctex-devel