Hello all,

The treatment of path separator of output of kpsewhich differs between
`TeX-tree-expand' and `TeX-search-files-kpathsea' and both of them have
trouble on w32 platform, which can mess up things.

A. `TeX-tree-expand' assumes that the separator is ";" if the output
begins with dos drive letter[1], but this is not the case if the first
component of the output is a relative directory name.

B. When `TeX-kpathsea-path-delimiter' is t, `TeX-search-files-kpathsea'
assumes that the separator is ";" if the output contains ";"[2], but
this is not the case if the output consists of only one componet,
especially when the function is called with `local' SCOPE argument.
Once this wrong assumption was made on w32 platform,
`TeX-kpathsea-path-delimiter' is set to the wrong value ":" and
subsequently this function always use ":" as path separator as long as
that emacs session runs.

I don't think that it is reliable to determine the path separator from
the output of kpsewhich command.  In fact, `TeX-tree-expand' even
presumes the separator when it supplies the argument to kpsewhich[3],
before the output is obtained.  Three different logics [1][2][3] is not
a good way to take.

So I propose the attached change which includes code refactoring of the
part related to kpathsea.  The changes are summarized below:
(1) Do not try to find the right separator from the output.  Instead,
just use `path-separator' as the default value for
`TeX-kpathsea-path-delimiter' and use it in the relavant two functions.
(2) Use `TeX-tree-expand' as a helper function in
`TeX-search-files-kpathsea'.  The former half of the current code of
`TeX-search-files-kpathsea' is quite similar to `TeX-tree-expand', so
they can and should be unified.

What do you think about this?  I would appreciate your thoughts and
comments.

Best regards,
Ikumi Keita

[1] Quote from `TeX-tree-expand':
      (let ((separators (if (string-match "^[A-Za-z]:" path-list)
                            "[\n\r;]"
                          "[\n\r:]"))

[2] Quote from `TeX-search-files-kpathsea':
           (when (eq TeX-kpathsea-path-delimiter t)
             (setq TeX-kpathsea-path-delimiter
                   (if (string-match ";" dirs) ";" ":")))

[3] Quote from `TeX-tree-expand':
                               (mapconcat #'identity vars
                                          (if (eq system-type 'windows-nt)
                                              ";" ":"))))))))

>From [email protected] Wed Sep 06 00:19:08 2017
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH] Bug fix and code refactoring related to kpathsea
X-Mercurial-Node: d6fb1315a1178691fe5c87e95a88d8da62a60384
X-Mercurial-Series-Index: 1
X-Mercurial-Series-Total: 1
Message-Id: <[email protected]>
X-Mercurial-Series-Id: <[email protected]>
User-Agent: Mercurial-patchbomb/4.3.1
Date: Wed, 06 Sep 2017 00:19:08 +0900
From: Ikumi Keita <[email protected]>
To: dummy

* tex.el (TeX-kpathsea-path-delimiter): Use `path-separator' for
default value.  Drop t from the candidates because auto detection
sometimes fails for w32 platform.
(TeX-tree-expand): Always use `TeX-kpathsea-path-delimiter' if
non-nil.
Disable subsequent use of kpathsea if kpsewhich causes error or
returns non-zero exit value.
Accept nil for PROGRAM argument.
(TeX-search-files-kpathsea): Always use `TeX-kpathsea-path-delimiter' if
non-nil.
Use `TeX-tree-expand'.
Don't signal error even if kpsewhich causes error or returns non-zero
exit value.

diff --git a/tex.el b/tex.el
--- a/tex.el
+++ b/tex.el
@@ -2680,45 +2680,63 @@
 	  (setq answers (cons entry answers))))
     answers))
 
+(defcustom TeX-kpathsea-path-delimiter path-separator
+  "Path delimiter for kpathsea output.
+nil means kpathsea is disabled."
+  :group 'TeX-file
+  :type '(choice (const ":")
+		 (const ";")
+		 (const :tag "Off" nil)))
+;; backward compatibility
+(when (eq TeX-kpathsea-path-delimiter t)
+  (setq TeX-kpathsea-path-delimiter path-separator))
+
 (defun TeX-tree-expand (vars program &optional subdirs)
   "Return directories corresponding to the kpathsea variables VARS.
 This is done calling `kpsewhich --expand-path' for the variables.
-PROGRAM is passed as the parameter for --progname.  SUBDIRS are
-subdirectories which are appended to the directories of the TeX
-trees.  Only existing directories are returned."
+PROGRAM if non-nil is passed as the parameter for --progname.
+Optional argument SUBDIRS are subdirectories which are appended
+to the directories of the TeX trees.  Only existing directories
+are returned."
   ;; FIXME: The GNU convention only uses "path" to mean "list of directories"
   ;; and uses "filename" for the name of a file even if it contains possibly
   ;; several elements separated by "/".
-  (let* ((exit-status 1)
-	 (path-list (ignore-errors
-		      (with-output-to-string
-			(setq exit-status
-			      (call-process
-			       "kpsewhich"  nil
-			       (list standard-output nil) nil
-			       "--progname" program
-			       "--expand-path"
-			       (mapconcat #'identity vars
-					  (if (eq system-type 'windows-nt)
-					      ";" ":"))))))))
-    (when (zerop exit-status)
-      (let ((separators (if (string-match "^[A-Za-z]:" path-list)
-			    "[\n\r;]"
-			  "[\n\r:]"))
-	    path input-dir-list)
-	(dolist (item (condition-case nil
-			  (split-string path-list separators t)
-			;; COMPATIBILITY for XEmacs <= 21.4.15
-			(error (delete "" (split-string path-list separators)))))
-	  (if subdirs
-	      (dolist (subdir subdirs)
-		(setq path (file-name-as-directory (concat item subdir)))
-		(when (file-exists-p path)
-		  (pushnew path input-dir-list :test #'equal)))
-	    (setq path (file-name-as-directory item))
-	    (when (file-exists-p path)
-	      (pushnew path input-dir-list :test #'equal))))
-	(nreverse input-dir-list)))))
+  (when TeX-kpathsea-path-delimiter
+    (let* ((exit-status 1)
+	   (args (append (if program
+			     `("--progname" ,program))
+			 `("--expand-path"
+			   ,(mapconcat #'identity vars
+				       TeX-kpathsea-path-delimiter))))
+	   (path-list (ignore-errors
+			(with-output-to-string
+			  (setq exit-status
+				(apply #'call-process
+				       "kpsewhich" nil
+				       (list standard-output nil) nil
+				       args))))))
+      (if (not (zerop exit-status))
+	  ;; kpsewhich is not available.  Disable subsequent usage.
+	  (setq TeX-kpathsea-path-delimiter nil)
+	(let ((separators (format "[\n\r%s]" TeX-kpathsea-path-delimiter))
+	      path input-dir-list)
+	  (dolist (item (condition-case nil
+			    (split-string path-list separators t)
+			  ;; COMPATIBILITY for XEmacs <= 21.4.15
+			  (error (delete "" (split-string path-list separators)))))
+	    (if subdirs
+		(dolist (subdir subdirs)
+		  (setq path (file-name-as-directory (concat item subdir)))
+		  (when (file-exists-p path)
+		    (pushnew path input-dir-list :test #'equal)))
+	      (setq path (file-name-as-directory item))
+	      (when (file-exists-p path)
+		(pushnew path input-dir-list :test #'equal))))
+	  ;; No duplication in result is assured since `pushnew' is
+	  ;; used above.  Should we introduce an option for speed just
+	  ;; to accumulate all the results without care for
+	  ;; duplicates?
+	  (nreverse input-dir-list))))))
 
 (defun TeX-macro-global ()
   "Return directories containing the site's TeX macro and style files."
@@ -4541,15 +4559,6 @@
   :group 'TeX-file
   :type '(repeat directory))
 
-(defcustom TeX-kpathsea-path-delimiter t
-  "Path delimiter for kpathsea output.
-t means autodetect, nil means kpathsea is disabled."
-  :group 'TeX-file
-  :type '(choice (const ":")
-		 (const ";")
-		 (const :tag "Autodetect" t)
-		 (const :tag "Off" nil)))
-
 ;; We keep this function in addition to `TeX-search-files' because it
 ;; is faster.  Since it does not look further into subdirectories,
 ;; this comes at the price of finding a smaller number of files.
@@ -4559,45 +4568,26 @@
 the scope for the search and can be `local' or `global' besides
 nil.  If NODIR is non-nil, remove directory part.  If STRIP is
 non-nil, remove file extension."
-  (and TeX-kpathsea-path-delimiter
-       (catch 'no-kpathsea
-	 (let* ((dirs (if (eq scope 'local)
-			  "."
-			(with-output-to-string
-			  (unless (zerop (call-process
-					  "kpsewhich" nil
-					  (list standard-output nil) nil
-					  (concat "-expand-path=" var)))
-			    (if (eq TeX-kpathsea-path-delimiter t)
-				(throw 'no-kpathsea
-				       (setq TeX-kpathsea-path-delimiter nil))
-			      (error "kpsewhich error"))))))
-		result)
-	   (when (eq TeX-kpathsea-path-delimiter t)
-	     (setq TeX-kpathsea-path-delimiter
-		   (if (string-match ";" dirs) ";" ":")))
-	   (unless TeX-kpathsea-path-delimiter
-	     (throw 'no-kpathsea nil))
-	   (setq dirs (TeX-delete-duplicate-strings
-		       (delete "" (split-string
-				   dirs (concat "[\n\r"
-						TeX-kpathsea-path-delimiter
-						"]+")))))
-	   (if (eq scope 'global)
-	       (setq dirs (delete "." dirs)))
-	   (setq extensions (concat "\\." (regexp-opt extensions t) "\\'")
-		 result (apply #'append (mapcar (lambda (x)
-						  (when (file-readable-p x)
-						    (directory-files
-						     x (not nodir) extensions)))
-						dirs)))
-	   (if strip
-	       (mapcar (lambda(x)
-			 (if (string-match extensions x)
-			     (substring x 0 (match-beginning 0))
-			   x))
-		       result)
-	     result)))))
+  (when TeX-kpathsea-path-delimiter
+    (let ((dirs (if (eq scope 'local)
+		    '("./")
+		  (TeX-tree-expand (list var) nil)))
+	  result)
+      (if (eq scope 'global)
+	  (setq dirs (delete "./" dirs)))
+      (setq extensions (concat "\\." (regexp-opt extensions t) "\\'")
+	    result (apply #'append (mapcar (lambda (x)
+					     (when (file-readable-p x)
+					       (directory-files
+						x (not nodir) extensions t)))
+					   dirs)))
+      (if strip
+	  (mapcar (lambda (x)
+		    (if (string-match extensions x)
+			(substring x 0 (match-beginning 0))
+		      x))
+		  result)
+	result))))
 
 (defun TeX-search-files (&optional directories extensions nodir strip)
   "Return a list of all reachable files in DIRECTORIES ending with EXTENSIONS.


_______________________________________________
auctex-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/auctex-devel

Reply via email to