diff --git a/tex-buf.el b/tex-buf.el index 40a2acca..9a8769a5 100644 --- a/tex-buf.el +++ b/tex-buf.el @@ -1138,6 +1138,10 @@ run of `TeX-run-TeX', use ;; Presence of error is reported inside `TeX-TeX-sentinel-check' (let ((current-master (TeX-master-file)) (idx-file nil) (element nil)) + + ;; Ensure that the output directory exists + (TeX--ensure-output-dir) + ;; the current master file is saved because error routines are ;; parsed in other buffers; (setq TeX-error-report-switches diff --git a/tex.el b/tex.el index b59aee05..1fdde1a9 100644 --- a/tex.el +++ b/tex.el @@ -182,7 +182,7 @@ If nil, none is specified." ;; `TeX-expand-list-builtin' for a description of the % escapes (defcustom TeX-command-list - '(("TeX" "%(PDF)%(tex) %(file-line-error) %`%(extraopts) %S%(PDFout)%(mode)%' %t" + '(("TeX" "%(PDF)%(tex) %(file-line-error) %`%(extraopts) %(output-dir) %S%(PDFout)%(mode)%' %t" TeX-run-TeX nil (plain-tex-mode ams-tex-mode texinfo-mode) :help "Run plain TeX") ("LaTeX" "%`%l%(mode)%' %T" @@ -202,11 +202,11 @@ If nil, none is specified." ("ConTeXt Full" "%(cntxcom) %(extraopts) %(execopts)%t" TeX-run-TeX nil (context-mode) :help "Run ConTeXt until completion") - ("BibTeX" "bibtex %s" TeX-run-BibTeX nil + ("BibTeX" "bibtex %(O?aux)" TeX-run-BibTeX nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode context-mode) :help "Run BibTeX") - ("Biber" "biber %s" TeX-run-Biber nil + ("Biber" "biber %s %(output-dir)" TeX-run-Biber nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Run Biber") ("View" "%V" TeX-run-discard-or-function t t :help "Run Viewer") @@ -219,17 +219,17 @@ If nil, none is specified." ("Dvips" "%(o?)dvips %d -o %f " TeX-run-dvips nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Convert DVI file to PostScript") - ("Dvipdfmx" "dvipdfmx %d" TeX-run-dvipdfmx nil + ("Dvipdfmx" "dvipdfmx %d -o %(O?pdf)" TeX-run-dvipdfmx nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Convert DVI file to PDF with dvipdfmx") - ("Ps2pdf" "ps2pdf %f" TeX-run-ps2pdf nil + ("Ps2pdf" "ps2pdf %f %(O?pdf)" TeX-run-ps2pdf nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Convert PostScript file to PDF") - ("Glossaries" "makeglossaries %s" TeX-run-command nil + ("Glossaries" "makeglossaries %(O?aux)" TeX-run-command nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Run makeglossaries to create glossary file") - ("Index" "makeindex %s" TeX-run-index nil + ("Index" "makeindex %(O?idx)" TeX-run-index nil (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) :help "Run makeindex to create index file") ("upMendex" "upmendex %s" TeX-run-index t @@ -393,7 +393,7 @@ The executable `latex' is LaTeX version 2e." (defcustom LaTeX-command-style ;; They have all been combined in LaTeX 2e. - '(("" "%(PDF)%(latex) %(file-line-error) %(extraopts) %S%(PDFout)")) + '(("" "%(PDF)%(latex) %(file-line-error) %(extraopts) %(output-dir) %S%(PDFout)")) "List of style options and LaTeX commands. If the first element (a regular expression) matches the name of one of @@ -563,6 +563,11 @@ string." ("%(cntxcom)" ConTeXt-expand-command) ("%(execopts)" ConTeXt-expand-options) ("%(extraopts)" (lambda () TeX-command-extra-options)) + ("%(output-dir)" (lambda () (if-let ((out-dir (if TeX-current-process-region-p + (file-name-directory TeX-region) + TeX-output-dir))) + (concat "--output-directory=\"" out-dir "\"") + ""))) ("%S" TeX-source-correlate-expand-options) ("%dS" TeX-source-specials-view-expand-options) ("%cS" TeX-source-specials-view-expand-client) @@ -632,6 +637,9 @@ string." ("%n" TeX-current-line) ("%d" TeX-active-master-with-quotes "dvi" t) ("%f" TeX-active-master-with-quotes "ps" t) + ("%(O?aux)" TeX-active-master-with-quotes "aux" t) + ("%(O?idx)" TeX-active-master-with-quotes "idx" t) + ("%(O?pdf)" TeX-active-master-with-quotes "pdf" t) ("%o" (lambda nil (TeX-active-master-with-quotes (TeX-output-extension) t))) ;; for source specials the file name generated for the xdvi ;; command needs to be relative to the master file, just in @@ -2210,26 +2218,20 @@ Used as a default in TeX, LaTeX and docTeX mode.") If prefix ARG is non-nil, not only remove intermediate but also output files." (interactive "P") - (let* ((mode-prefix (TeX-mode-prefix)) - (suffixes (append (symbol-value - (intern (concat mode-prefix - "-clean-intermediate-suffixes"))) - (when arg - (symbol-value - (intern (concat mode-prefix - "-clean-output-suffixes")))))) - (master (TeX-active-master)) - (master-dir (file-name-directory master)) - (regexp (concat "\\(" - (regexp-quote (file-name-nondirectory master)) "\\|" - (regexp-quote (TeX-region-file nil t)) - "\\)" - "\\(" - (mapconcat 'identity suffixes "\\|") - "\\)\\'" - "\\|" (regexp-quote (TeX-region-file t t)))) - (files (when regexp - (directory-files (or master-dir ".") nil regexp)))) + (let* (;; Add output extension then remove it, to make sure we get the correct + ;; directory in cases TeX-output-dir is non-nil + (master (file-name-sans-extension (TeX-active-master (TeX-output-extension)))) + (master-dir (file-name-directory master)) + (regexp (concat "\\(" + (regexp-quote (file-name-nondirectory master)) "\\|" + (regexp-quote (TeX-region-file nil t)) + "\\)" + "\\(" + (TeX--clean-extensions-regexp arg) + "\\)\\'" + "\\|" (regexp-quote (TeX-region-file t t)))) + (files (when (and regexp (or (not master-dir) (file-exists-p master-dir))) + (directory-files (or master-dir ".") nil regexp)))) (if files (when (or (not TeX-clean-confirm) (dired-mark-pop-up " *Deletions*" 'delete @@ -2241,6 +2243,19 @@ output files." (delete-file (concat master-dir file)))) (message "No files to be deleted")))) +(defun TeX--clean-extensions-regexp (&optional arg) + "Returns a regexp to match extensions that should be cleaned by TeX-clean. +If the optional argument ARG is non-nil then output files are included" + (when-let ((mode-prefix (TeX-mode-prefix)) + (suffixes (append (symbol-value + (intern (concat mode-prefix + "-clean-intermediate-suffixes"))) + (when arg + (symbol-value + (intern (concat mode-prefix + "-clean-output-suffixes"))))))) + (mapconcat 'identity suffixes "\\|"))) + ;;; Master File (defcustom TeX-master t @@ -2334,6 +2349,25 @@ this variable to \"\"." 'path)) (TeX-add-local-master)))))) +(defun TeX-master-output-file (&optional extension) + "Returns an output file based on `TeX-output-dir' in the +master-file, opening it if necessary. if the optional argument +EXTENSION is non-nil it is appended as an extension to the output +file. If EXTENSION is t then (TeX-output-extension) is used." + (interactive) + (if (eq extension t) + (setq extension (TeX-output-extension))) + (let ((file (TeX-master-file t)) name) + (with-current-buffer + (or (find-buffer-visiting file) + (find-file-noselect file)) + (when TeX-output-dir + (setq name (concat TeX-output-dir "/" (TeX-master-file))))) + (if name + (if extension (concat name "." extension) + name) + (TeX-master-file extension)))) + (defun TeX-master-file (&optional extension nondirectory ask) "Set and return the name of the master file for the current document. @@ -2394,9 +2428,13 @@ name of master file if it cannot be determined otherwise." ;; Ask the user (but add it as a local variable). (ask (TeX-master-file-ask))))) - (let ((name (if (stringp TeX-master) - TeX-master - my-name))) + (if (and TeX-output-dir + (when-let (reg (TeX--clean-extensions-regexp t)) + (string-match-p reg (concat "." extension)))) + (TeX-master-output-file extension) + (let ((name (if (stringp TeX-master) + TeX-master + my-name))) (if (TeX-match-extension name) ;; If it already has an extension... @@ -2411,8 +2449,8 @@ name of master file if it cannot be determined otherwise." (setq name (file-name-nondirectory name))) (if extension - (concat name "." extension) - name)))) + (concat name "." extension) + name))))) (defun TeX-master-directory () "Directory of master file." @@ -2494,6 +2532,16 @@ be relative to that." :group 'TeX-file :type 'string) +(defcustom TeX-output-dir nil + "The directory where the output files will be generated. The + directory cannot start with a `.'. + +If this variable is nil, AUCTeX will assume that the output +directory is the same as the directory of TeX-master." + :group 'TeX-file + :type '(string :format "%v")) +(put 'TeX-output-dir 'safe-local-variable 'stringp-or-null-p) + (defcustom TeX-style-local "style" "Directory containing hand generated TeX information. @@ -2502,6 +2550,12 @@ be relative to that." :group 'TeX-file :type 'string) +(defun TeX--ensure-output-dir nil + "Checks if the output directory exists, creating it if it does not." + (when TeX-output-dir + (unless (file-exists-p TeX-output-dir) + (make-directory TeX-output-dir)))) + (defun TeX-split-string (regexp string) "Return a list of strings. Given REGEXP the STRING is split into sections which in string was