branch: elpa/exec-path-from-shell
commit 3b280d30938d41fcc0d53b10a847332118b868ef
Author: Steve Purcell <[email protected]>
Commit: Steve Purcell <[email protected]>

    Set all variables using just one shell invocation
    
    This dramatically speeds things up, and requires only the assumption
    that none of the names or values of the environment variables contains
    a null character.
---
 exec-path-from-shell.el | 64 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/exec-path-from-shell.el b/exec-path-from-shell.el
index 124eb47efa..9dd66920cc 100644
--- a/exec-path-from-shell.el
+++ b/exec-path-from-shell.el
@@ -66,16 +66,62 @@
   "List of environment variables which are copied from the shell."
   :group 'exec-path-from-shell)
 
+(defun exec-path-from-shell-echo (str)
+  "Return the result of echoing STR in the user's shell.
+
+STR is inserted literally in a double-quoted argument to echo.
+Executes $SHELL as interactive login shell."
+  (with-temp-buffer
+    (call-process (getenv "SHELL") nil (current-buffer) nil
+                  "--login" "-i" "-c" (concat "echo \"__RESULT\\0" str "\""))
+    (goto-char (point-min))
+    (when (re-search-forward "__RESULT\0\\(.*\\)" nil t)
+      (match-string 1))))
+
+(defun exec-path-from-shell-getenvs (names)
+  "Get the environment variables with NAMES from the user's shell.
+
+Execute $SHELL as interactive login shell.  The result is a list
+of (NAME . VALUE) pairs."
+  (let ((values
+         (split-string
+          (exec-path-from-shell-echo
+           (mapconcat (lambda (n) (concat "$" n)) names "\\0"))
+          "\0"))
+        result)
+    (while names
+      (prog1
+          (push (cons (car names) (car values)) result)
+        (setq values (cdr values)
+              names (cdr names))))
+   result))
+
 (defun exec-path-from-shell-getenv (name)
   "Get the environment variable NAME from the user's shell.
 
 Execute $SHELL as interactive login shell, have it output the
 variable of NAME and return this output as string."
-  (with-temp-buffer
-    (call-process (getenv "SHELL") nil (current-buffer) nil
-                  "--login" "-i" "-c" (concat "echo __RESULT=$" name))
-    (when (re-search-backward "__RESULT=\\(.*\\)" nil t)
-      (match-string 1))))
+  (cdr (assoc name (exec-path-from-shell-getenvs (list name)))))
+
+(defun exec-path-from-shell-setenv (name value)
+  "Set the value of environment var NAME to VALUE.
+Additionally, if NAME is \"PATH\" then also set corresponding
+variables such as `exec-path'."
+  (setenv name value)
+  (when (string-equal "PATH" name)
+    (setq eshell-path-env value
+          exec-path (split-string value path-separator))))
+
+;;;###autoload
+(defun exec-path-from-shell-copy-envs (names)
+  "Set the environment variables with NAMES from the user's shell.
+
+As a special case, if the variable is $PATH, then `exec-path' and
+`eshell-path-env' are also set appropriately.  The result is an alist,
+as described by `exec-path-from-shell-getenvs'."
+  (mapc (lambda (pair)
+          (exec-path-from-shell-setenv (car pair) (cdr pair)))
+        (exec-path-from-shell-getenvs names)))
 
 ;;;###autoload
 (defun exec-path-from-shell-copy-env (name)
@@ -85,11 +131,7 @@ As a special case, if the variable is $PATH, then 
`exec-path' and
 `eshell-path-env' are also set appropriately.  Return the value
 of the environment variable."
   (interactive "sCopy value of which environment variable from shell? ")
-  (prog1
-      (setenv name (exec-path-from-shell-getenv name))
-    (when (string-equal "PATH" name)
-      (setq eshell-path-env (getenv "PATH")
-            exec-path (split-string (getenv "PATH") path-separator)))))
+  (cdar (exec-path-from-shell-copy-envs (list name))))
 
 ;;;###autoload
 (defun exec-path-from-shell-initialize ()
@@ -99,7 +141,7 @@ The values of all the environment variables named in
 `exec-path-from-shell-variables' are set from the corresponding
 values used in the user's shell."
   (interactive)
-  (mapc 'exec-path-from-shell-copy-env exec-path-from-shell-variables))
+  (exec-path-from-shell-copy-envs exec-path-from-shell-variables))
 
 
 (provide 'exec-path-from-shell)

Reply via email to