mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
* src/fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
(Qsubstitute_env_in_file_name): New var. (syms_of_fileio): Define it. * lisp/env.el (substitute-env-in-file-name): New function. (substitute-env-vars): Extend the meaning of the optional arg.
This commit is contained in:
parent
00036e1dd2
commit
ee041f2d07
4 changed files with 57 additions and 145 deletions
|
|
@ -1,3 +1,8 @@
|
|||
2013-10-10 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* env.el (substitute-env-in-file-name): New function.
|
||||
(substitute-env-vars): Extend the meaning of the optional arg.
|
||||
|
||||
2013-10-10 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* term/w32-win.el (dynamic-library-alist): Define separate lists
|
||||
|
|
|
|||
30
lisp/env.el
30
lisp/env.el
|
|
@ -1,4 +1,4 @@
|
|||
;;; env.el --- functions to manipulate environment variables
|
||||
;;; env.el --- functions to manipulate environment variables -*- lexical-binding:t -*-
|
||||
|
||||
;; Copyright (C) 1991, 1994, 2000-2013 Free Software Foundation, Inc.
|
||||
|
||||
|
|
@ -60,30 +60,46 @@ If it is also not t, RET does not exit if it does non-null completion."
|
|||
(defconst env--substitute-vars-regexp
|
||||
"\\$\\(?:\\(?1:[[:alnum:]_]+\\)\\|{\\(?1:[^{}]+\\)}\\|\\$\\)")
|
||||
|
||||
(defun substitute-env-vars (string &optional only-defined)
|
||||
(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
|
||||
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 ONLY-DEFINED is nil, references to undefined environment variables
|
||||
are replaced by the empty string; if it is non-nil, they are left unchanged.
|
||||
|
||||
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 env--substitute-vars-regexp string start)
|
||||
(cond ((match-beginning 1)
|
||||
(let ((value (getenv (match-string 1 string))))
|
||||
(if (and (null value) only-defined)
|
||||
(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)
|
||||
(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.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
2013-10-10 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* fileio.c (Fsubstitute_in_file_name): Use substitute-env-in-file-name.
|
||||
(Qsubstitute_env_in_file_name): New var.
|
||||
(syms_of_fileio): Define it.
|
||||
|
||||
2013-10-10 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* xdisp.c (deep_copy_glyph_row): Assert that the 'used' counts of
|
||||
|
|
|
|||
161
src/fileio.c
161
src/fileio.c
|
|
@ -143,6 +143,8 @@ static Lisp_Object Qcopy_directory;
|
|||
/* Lisp function for recursively deleting directories. */
|
||||
static Lisp_Object Qdelete_directory;
|
||||
|
||||
static Lisp_Object Qsubstitute_env_in_file_name;
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
#endif
|
||||
|
||||
|
|
@ -1664,10 +1666,8 @@ If `//' appears, everything up to and including the first of
|
|||
those `/' is discarded. */)
|
||||
(Lisp_Object filename)
|
||||
{
|
||||
char *nm, *s, *p, *o, *x, *endp;
|
||||
char *target = NULL;
|
||||
ptrdiff_t total = 0;
|
||||
bool substituted = 0;
|
||||
char *nm, *p, *x, *endp;
|
||||
bool substituted = false;
|
||||
bool multibyte;
|
||||
char *xnm;
|
||||
Lisp_Object handler;
|
||||
|
|
@ -1708,66 +1708,19 @@ those `/' is discarded. */)
|
|||
return Fsubstitute_in_file_name
|
||||
(make_specified_string (p, -1, endp - p, multibyte));
|
||||
|
||||
/* See if any variables are substituted into the string
|
||||
and find the total length of their values in `total'. */
|
||||
/* See if any variables are substituted into the string. */
|
||||
|
||||
for (p = nm; p != endp;)
|
||||
if (*p != '$')
|
||||
p++;
|
||||
else
|
||||
{
|
||||
p++;
|
||||
if (p == endp)
|
||||
goto badsubst;
|
||||
else if (*p == '$')
|
||||
{
|
||||
/* "$$" means a single "$". */
|
||||
p++;
|
||||
total -= 1;
|
||||
substituted = 1;
|
||||
continue;
|
||||
}
|
||||
else if (*p == '{')
|
||||
{
|
||||
o = ++p;
|
||||
p = memchr (p, '}', endp - p);
|
||||
if (! p)
|
||||
goto missingclose;
|
||||
s = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
o = p;
|
||||
while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
|
||||
s = p;
|
||||
}
|
||||
|
||||
/* Copy out the variable name. */
|
||||
target = alloca (s - o + 1);
|
||||
memcpy (target, o, s - o);
|
||||
target[s - o] = 0;
|
||||
#ifdef DOS_NT
|
||||
strupr (target); /* $home == $HOME etc. */
|
||||
#endif /* DOS_NT */
|
||||
|
||||
/* Get variable value. */
|
||||
o = egetenv (target);
|
||||
if (o)
|
||||
{
|
||||
/* Don't try to guess a maximum length - UTF8 can use up to
|
||||
four bytes per character. This code is unlikely to run
|
||||
in a situation that requires performance, so decoding the
|
||||
env variables twice should be acceptable. Note that
|
||||
decoding may cause a garbage collect. */
|
||||
Lisp_Object orig, decoded;
|
||||
orig = build_unibyte_string (o);
|
||||
decoded = DECODE_FILE (orig);
|
||||
total += SBYTES (decoded);
|
||||
substituted = 1;
|
||||
}
|
||||
else if (*p == '}')
|
||||
goto badvar;
|
||||
}
|
||||
if (!NILP (Ffboundp (Qsubstitute_env_in_file_name)))
|
||||
{
|
||||
Lisp_Object name
|
||||
= (!substituted ? filename
|
||||
: make_specified_string (nm, -1, endp - nm, multibyte));
|
||||
Lisp_Object tmp = call1 (Qsubstitute_env_in_file_name, name);
|
||||
CHECK_STRING (tmp);
|
||||
if (!EQ (tmp, name))
|
||||
substituted = true;
|
||||
filename = tmp;
|
||||
}
|
||||
|
||||
if (!substituted)
|
||||
{
|
||||
|
|
@ -1778,73 +1731,9 @@ those `/' is discarded. */)
|
|||
return filename;
|
||||
}
|
||||
|
||||
/* If substitution required, recopy the string and do it. */
|
||||
/* Make space in stack frame for the new copy. */
|
||||
xnm = alloca (SBYTES (filename) + total + 1);
|
||||
x = xnm;
|
||||
|
||||
/* Copy the rest of the name through, replacing $ constructs with values. */
|
||||
for (p = nm; *p;)
|
||||
if (*p != '$')
|
||||
*x++ = *p++;
|
||||
else
|
||||
{
|
||||
p++;
|
||||
if (p == endp)
|
||||
goto badsubst;
|
||||
else if (*p == '$')
|
||||
{
|
||||
*x++ = *p++;
|
||||
continue;
|
||||
}
|
||||
else if (*p == '{')
|
||||
{
|
||||
o = ++p;
|
||||
p = memchr (p, '}', endp - p);
|
||||
if (! p)
|
||||
goto missingclose;
|
||||
s = p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
o = p;
|
||||
while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
|
||||
s = p;
|
||||
}
|
||||
|
||||
/* Copy out the variable name. */
|
||||
target = alloca (s - o + 1);
|
||||
memcpy (target, o, s - o);
|
||||
target[s - o] = 0;
|
||||
|
||||
/* Get variable value. */
|
||||
o = egetenv (target);
|
||||
if (!o)
|
||||
{
|
||||
*x++ = '$';
|
||||
strcpy (x, target); x+= strlen (target);
|
||||
}
|
||||
else
|
||||
{
|
||||
Lisp_Object orig, decoded;
|
||||
ptrdiff_t orig_length, decoded_length;
|
||||
orig_length = strlen (o);
|
||||
orig = make_unibyte_string (o, orig_length);
|
||||
decoded = DECODE_FILE (orig);
|
||||
decoded_length = SBYTES (decoded);
|
||||
memcpy (x, SDATA (decoded), decoded_length);
|
||||
x += decoded_length;
|
||||
|
||||
/* If environment variable needed decoding, return value
|
||||
needs to be multibyte. */
|
||||
if (decoded_length != orig_length
|
||||
|| memcmp (SDATA (decoded), o, orig_length))
|
||||
multibyte = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*x = 0;
|
||||
|
||||
xnm = SSDATA (filename);
|
||||
x = xnm + SBYTES (filename);
|
||||
|
||||
/* If /~ or // appears, discard everything through first slash. */
|
||||
while ((p = search_embedded_absfilename (xnm, x)) != NULL)
|
||||
/* This time we do not start over because we've already expanded envvars
|
||||
|
|
@ -1862,14 +1751,9 @@ those `/' is discarded. */)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
return make_specified_string (xnm, -1, x - xnm, multibyte);
|
||||
|
||||
badsubst:
|
||||
error ("Bad format environment-variable substitution");
|
||||
missingclose:
|
||||
error ("Missing \"}\" in environment-variable substitution");
|
||||
badvar:
|
||||
error ("Substituting nonexistent environment variable \"%s\"", target);
|
||||
return (xnm == SSDATA (filename)
|
||||
? filename
|
||||
: make_specified_string (xnm, -1, x - xnm, multibyte));
|
||||
}
|
||||
|
||||
/* A slightly faster and more convenient way to get
|
||||
|
|
@ -6108,6 +5992,7 @@ This includes interactive calls to `delete-file' and
|
|||
DEFSYM (Qmove_file_to_trash, "move-file-to-trash");
|
||||
DEFSYM (Qcopy_directory, "copy-directory");
|
||||
DEFSYM (Qdelete_directory, "delete-directory");
|
||||
DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
|
||||
|
||||
defsubr (&Sfind_file_name_handler);
|
||||
defsubr (&Sfile_name_directory);
|
||||
|
|
|
|||
Loading…
Reference in a new issue