From 4b6c1f39af545327d63f0e280b3a8d451070c9e3 Mon Sep 17 00:00:00 2001
From: "Leo C. Stein" <leo.stein@gmail.com>
Date: Mon, 16 Sep 2024 19:50:51 -0500
Subject: [PATCH] Make style/graphicx.el parse \graphicspath for searching

---
 style/graphicx.el | 24 ++++++++++++++++++++++--
 tex.el            | 17 +++++++++++------
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/style/graphicx.el b/style/graphicx.el
index 2151ed67..31f9eb2d 100644
--- a/style/graphicx.el
+++ b/style/graphicx.el
@@ -172,12 +172,31 @@ May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.")
 ;; Add the variable to `TeX-normal-mode-reset-list':
 (add-to-list 'TeX-normal-mode-reset-list 'LaTeX-includegraphics-global-files)
 
+(defun LaTeX-parse-graphicspath ()
+  "Parse the current document for \\graphicspath commands.
+Return value is a list of paths."
+  (let ((results '())
+        (graphicspath-regex "\\\\graphicspath{\\({\\([^}]*\\)}\\)*}")
+        (single-path-regex "{\\([^{}]*\\)}"))
+    (save-excursion
+      (goto-char 0)
+      (while (re-search-forward graphicspath-regex nil t)
+        (let ((full-match (match-string 0))
+              (start-pos (match-beginning 0))
+              (end-pos (match-end 0)))
+          (save-excursion
+            (goto-char start-pos)
+            (while (re-search-forward single-path-regex end-pos t)
+              (push (match-string 1) results)))))
+      (nreverse results))))
+
 (defun LaTeX-includegraphics-read-file-TeX ()
   "Read image file for \\includegraphics.
 Offers all graphic files found in the TeX search path.  See
 `LaTeX-includegraphics-read-file' for more."
   (let ((LaTeX-includegraphics-extensions
-         (LaTeX-includegraphics-extensions-list)))
+         (LaTeX-includegraphics-extensions-list))
+        (extra-dirs (LaTeX-parse-graphicspath)))
     (unless LaTeX-includegraphics-global-files
       (message "Searching for graphic files...")
       (setq LaTeX-includegraphics-global-files
@@ -189,7 +208,8 @@ Offers all graphic files found in the TeX search path.  See
      "Image file: "
      (append
       (TeX-search-files-by-type 'graphics 'local t
-                                LaTeX-includegraphics-strip-extension-flag)
+                                LaTeX-includegraphics-strip-extension-flag
+                                extra-dirs)
       LaTeX-includegraphics-global-files)
      nil nil nil)))
 
diff --git a/tex.el b/tex.el
index b4643ee0..730ef8fc 100644
--- a/tex.el
+++ b/tex.el
@@ -4678,15 +4678,18 @@ EXTENSIONS defaults to `TeX-file-extensions'."
 ;; 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.
-(defun TeX-search-files-kpathsea (var extensions scope nodir strip)
+(defun TeX-search-files-kpathsea (var extensions scope nodir strip &optional extra-dirs)
   "Return a list of files in directories determined by expanding VAR.
 Only files which match EXTENSIONS are returned.  SCOPE defines
 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."
+non-nil, remove file extension.
+If SCOPE is `local' and the optional argument EXTRA-DIRS is passed, it
+is appended to the list of local directories to search.  In `global'
+scope, EXTRA-DIRS does nothing."
   (when TeX-kpathsea-path-delimiter
     (let ((dirs (if (eq scope 'local)
-                    '("./")
+                    (append '("./") extra-dirs)
                   (TeX-tree-expand (list var) nil)))
           result)
       (if (eq scope 'global)
@@ -4773,7 +4776,7 @@ Each AUCTeX mode should set the variable buffer-locally with a
 more specific value.  See `LaTeX-search-files-type-alist' for an
 example.")
 
-(defun TeX-search-files-by-type (filetype &optional scope nodir strip)
+(defun TeX-search-files-by-type (filetype &optional scope nodir strip extra-dirs)
   "Return a list of files in TeX's search path with type FILETYPE.
 FILETYPE is a symbol used to choose the search paths and
 extensions.  See `TeX-search-files-type-alist' for supported
@@ -4786,7 +4789,9 @@ in the global directories only and nil in both.
 
 If optional argument NODIR is non-nil, remove directory part.
 
-If optional argument STRIP is non-nil, remove file extension."
+If optional argument STRIP is non-nil, remove file extension.
+
+The optional argument EXTRA-DIRS is passed to `TeX-search-files-kpathsea'."
   (let* ((gc-cons-threshold 10000000)
          (spec (assq filetype TeX-search-files-type-alist))
          (kpse-var (nth 1 spec))
@@ -4794,7 +4799,7 @@ If optional argument STRIP is non-nil, remove file extension."
          (exts (nth 3 spec))
          expdirs dirs local-files)
     (setq exts (if (symbolp exts) (eval exts t) exts))
-    (or (TeX-search-files-kpathsea kpse-var exts scope nodir strip)
+    (or (TeX-search-files-kpathsea kpse-var exts scope nodir strip extra-dirs)
         (progn
           (unless (eq scope 'global)
             (setq local-files
-- 
2.45.0

