Hello,

Attached is a patch to AUCTeX that implements the output-directory option 
`TeX-output-dir` (defaults to nil) based on the discussion in this thread.

Setting it using something like `(setq TeX-output-dir "auto/build")` should 
output all temporary and output files to a sub-directory `auto/build` next to 
the master file.

I implemented this using a new expansion string `%(output-dir)`, which means 
that any user-defined
commands must explicitly pass this option in the compilation command for this 
functionality to work.

Any comments or feedback is most welcome.

Best regards,
-- Al
diff --git a/tex-buf.el b/tex-buf.el
index ff6be7e6..0ae553cf 100644
--- a/tex-buf.el
+++ b/tex-buf.el
@@ -82,7 +82,7 @@ Return non-nil if document needs to be re-TeX'ed."
   (if (string-equal name "")
       (setq name (TeX-master-file)))
 
-  (TeX-check-files (concat name "." (TeX-output-extension))
+  (TeX-check-files (concat name "." (TeX-output-extension))   ;; TODO: This might need changing when TeX-output-dir is set
 		   (cons name (TeX-style-list))
 		   TeX-file-extensions))
 
@@ -826,7 +826,7 @@ omitted) and `TeX-region-file'."
 	   ;; comparison.
 	   (if (string-equal (expand-file-name name)
 			     (expand-file-name (TeX-region-file)))
-	       (TeX-check-files (concat name "." (TeX-output-extension))
+	       (TeX-check-files (concat name "." (TeX-output-extension))   ;; TODO: This might need changing when TeX-output-dir is set
 				;; Each original will be checked for all dirs
 				;; in `TeX-check-path' so this needs to be just
 				;; a filename without directory.
diff --git a/tex.el b/tex.el
index 9a1d1b6d..2ff7b20b 100644
--- a/tex.el
+++ b/tex.el
@@ -116,7 +116,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"
@@ -327,7 +327,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
@@ -494,6 +494,8 @@ string."
     ("%(cntxcom)" ConTeXt-expand-command)
     ("%(execopts)" ConTeXt-expand-options)
     ("%(extraopts)" (lambda () TeX-command-extra-options))
+    ("%(output-dir)" (lambda () (when TeX-output-dir
+                                  (concat "--output-directory=\"" TeX-output-dir "\""))))
     ("%S" TeX-source-correlate-expand-options)
     ("%dS" TeX-source-specials-view-expand-options)
     ("%cS" TeX-source-specials-view-expand-client)
@@ -1165,7 +1167,7 @@ entry in `TeX-view-program-list-builtin'."
 			    	 (get-file-buffer (TeX-region-file t)))
 			       (current-buffer))
 	(pdf-sync-forward-search))
-    (let ((pdf (concat file "." (TeX-output-extension))))
+    (let ((pdf (TeX-active-master (TeX-output-extension))))
       (pop-to-buffer (or (find-buffer-visiting pdf)
 			 (find-file-noselect pdf))))))
 
@@ -1189,7 +1191,7 @@ viewer."
   (require 'url-util)
   (let* ((uri (concat "file://" (url-encode-url
 				 (expand-file-name
-				  (concat file "." (TeX-output-extension))))))
+				  (TeX-active-master (TeX-output-extension))))))
 	 (owner (dbus-call-method
 		 :session (format "org.%s.%s.Daemon" de app)
 		 (format "/org/%s/%s/Daemon" de app)
@@ -2202,40 +2204,45 @@ Used as a default in TeX, LaTeX and docTeX mode.")
 
 (autoload 'dired-mark-pop-up "dired")
 
+(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 "\\|")))
+
 (defun TeX-clean (&optional arg)
   "Delete generated files associated with current master and region files.
 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* ((master (TeX-master-output-file))
+         (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 regexp
+                  (directory-files (or master-dir ".") nil regexp))))
     (if files
-	(when (or (not TeX-clean-confirm)
-		  (dired-mark-pop-up " *Deletions*" 'delete
-				     (if (> (length files) 1)
-					 files
-				       (cons t files))
-				     'y-or-n-p "Delete files? "))
-	  (dolist (file files)
-	    (delete-file (concat master-dir file))))
+        (when (or (not TeX-clean-confirm)
+                  (dired-mark-pop-up " *Deletions*" 'delete
+                                     (if (> (length files) 1)
+                                         files
+                                       (cons t files))
+                                     'y-or-n-p "Delete files? "))
+          (dolist (file files)
+            (delete-file (concat master-dir file))))
       (message "No files to be deleted"))))
 
 ;;; Master File
@@ -2331,6 +2338,30 @@ this variable to \"<none>\"."
 						   'path))
 	     (TeX-add-local-master))))))
 
+
+;;;###autoload
+(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
+        ;; Expand file name in case the master directory is different from the
+        ;; current directory
+        (setq name (concat (expand-file-name 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.
 
@@ -2391,7 +2422,11 @@ 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)
+    (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)))
 
@@ -2409,7 +2444,7 @@ name of master file if it cannot be determined otherwise."
 
       (if extension
 	  (concat name "." extension)
-	name))))
+	name)))))
 
 (defun TeX-master-directory ()
   "Directory of master file."
@@ -2491,6 +2526,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.
 

Reply via email to