]> code.delx.au - gnu-emacs/blobdiff - lisp/env.el
; Spelling fixes
[gnu-emacs] / lisp / env.el
index 06ee533d74c092f84140ecd5135beb52304162bd..6c39f825c3c775176a1ba7ca2310bfc16ccbcfd1 100644 (file)
@@ -1,10 +1,10 @@
-;;; env.el --- functions to manipulate environment variables
+;;; env.el --- functions to manipulate environment variables  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1991, 1994, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 2000-2016 Free Software Foundation, Inc.
 
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: processes, unix
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
@@ -34,8 +34,6 @@
 
 ;;; Code:
 
-(eval-when-compile (require 'cl))
-
 ;; History list for environment variable names.
 (defvar read-envvar-name-history nil)
 
@@ -59,8 +57,10 @@ If it is also not t, RET does not exit if it does non-null completion."
 ;; History list for VALUE argument to setenv.
 (defvar setenv-history nil)
 
+(defconst env--substitute-vars-regexp
+  "\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)")
 
-(defun substitute-env-vars (string)
+(defun substitute-env-vars (string &optional when-undefined)
   "Substitute environment variables referred to in STRING.
 `$FOO' where FOO is an environment variable name means to substitute
 the value of that variable.  The variable name should be terminated
@@ -68,27 +68,38 @@ with a character not a letter, digit or underscore; otherwise, enclose
 the entire variable name in braces.  For instance, in `ab$cd-x',
 `$cd' is treated as an environment variable.
 
+If WHEN-DEFINED is nil, references to undefined environment variables
+are replaced by the empty string; if it is a function, the function is called
+with the variable name as argument and should return the text with which
+to replace it or nil to leave it unchanged.
+If it is non-nil and not a function, references to undefined variables are
+left unchanged.
+
 Use `$$' to insert a single dollar sign."
   (let ((start 0))
-    (while (string-match
-           (eval-when-compile
-             (rx (or (and "$" (submatch (1+ (regexp "[[:alnum:]_]"))))
-                     (and "${" (submatch (minimal-match (0+ anything))) "}")
-                     "$$")))
-           string start)
+    (while (string-match env--substitute-vars-regexp string start)
       (cond ((match-beginning 1)
-            (let ((value (getenv (match-string 1 string))))
-              (setq string (replace-match (or value "") t t string)
-                    start (+ (match-beginning 0) (length value)))))
-           ((match-beginning 2)
-            (let ((value (getenv (match-string 2 string))))
-              (setq string (replace-match (or value "") t t string)
-                    start (+ (match-beginning 0) (length value)))))
+            (let* ((var (match-string 1 string))
+                    (value (getenv var)))
+               (if (and (null value)
+                        (if (functionp when-undefined)
+                            (null (setq value (funcall when-undefined var)))
+                          when-undefined))
+                   (setq start (match-end 0))
+                 (setq string (replace-match (or value "") t t string)
+                       start (+ (match-beginning 0) (length value))))))
            (t
             (setq string (replace-match "$" t t string)
                   start (+ (match-beginning 0) 1)))))
     string))
 
+(defun substitute-env-in-file-name (filename)
+  (substitute-env-vars filename
+                       ;; How 'bout we lookup other tables than the env?
+                       ;; E.g. we could accept bookmark names as well!
+                       (if (memq system-type '(windows-nt ms-dos))
+                           (lambda (var) (getenv (upcase var)))
+                         t)))
 
 (defun setenv-internal (env variable value keep-empty)
   "Set VARIABLE to VALUE in ENV, adding empty entries if KEEP-EMPTY.
@@ -187,7 +198,7 @@ VARIABLE should be a string.  Value is nil if VARIABLE is undefined in
 the environment.  Otherwise, value is a string.
 
 If optional parameter FRAME is non-nil, then it should be a
-frame.  This function will look up VARIABLE in its 'environment
+frame.  This function will look up VARIABLE in its `environment'
 parameter.
 
 Otherwise, this function searches `process-environment' for
@@ -198,62 +209,15 @@ in the environment list of the selected frame."
                                    (encode-coding-string
                                     variable locale-coding-system)
                                  variable)
-                               frame)))
+                               (and frame
+                                    (assq 'environment
+                                          (frame-parameters frame))))))
     (if (and enable-multibyte-characters value)
        (setq value (decode-coding-string value locale-coding-system)))
-    (when (interactive-p)
+    (when (called-interactively-p 'interactive)
       (message "%s" (if value value "Not set")))
     value))
 
-(defun environment (&optional frame)
-  "Return a list of environment variables with their values.
-Each entry in the list is a string of the form NAME=VALUE.
-
-The returned list can not be used to change environment
-variables, only read them.  See `setenv' to do that.
-
-If optional parameter FRAME is non-nil, then it should be a
-frame.  The function returns the environment of that frame.
-
-The list is constructed by concatenating the elements of
-`process-environment' and the 'environment parameter of the
-selected frame, and removing duplicated and empty values.
-
-Non-ASCII characters are encoded according to the initial value of
-`locale-coding-system', i.e. the elements must normally be decoded for use.
-See `setenv' and `getenv'."
-  (let* ((env (append process-environment
-                      ;; (frame-environment frame)
-                     nil))
-        (scan env)
-        prev seen)
-    ;; Remove unset variables from the beginning of the list.
-    (while (and env
-               (or (not (stringp (car env)))
-                   (not (string-match "=" (car env)))))
-      (or (member (car env) seen)
-         (setq seen (cons (car env) seen)))
-      (setq env (cdr env)
-           scan env))
-    (let (name)
-      (while scan
-       (cond ((or (not (stringp (car scan)))
-                  (not (string-match "=" (car scan))))
-              ;; Unset variable.
-              (or (member (car scan) seen)
-                  (setq seen (cons (car scan) seen)))
-              (setcdr prev (cdr scan)))
-             ((member (setq name (substring (car scan) 0 (string-match "=" (car scan)))) seen)
-              ;; Duplicated variable.
-              (setcdr prev (cdr scan)))
-             (t
-              ;; New variable.
-              (setq seen (cons name seen))))
-       (setq prev scan
-             scan (cdr scan))))
-    env))
-
 (provide 'env)
 
-;; arch-tag: b7d6a8f7-bc81-46db-8e39-8d721d4ed0b8
 ;;; env.el ends here