mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
* lisp/custom.el: Avoid adding vars to load-history multiple times
Avoid the abuse of (eval `(defvar ...)) which tends to end up adding redundant entries in `load-history`, as discussed in https://lists.gnu.org/r/help-gnu-emacs/2019-03/msg00237.html (custom-initialize-default): Don't add to load-history. (custom-declare-variable): Use internal--define-uninitialized-variable and only add the var to load-history once. Do it before calling `initialize` so the special-variable-p flag is set. * src/eval.c (Finternal__define_uninitialized_variable): New function. (Fdefvar, Fdefconst): Use it. (syms_of_eval): Defsubr' it.
This commit is contained in:
parent
f0c0b2cea3
commit
6309131349
2 changed files with 39 additions and 32 deletions
|
|
@ -56,8 +56,14 @@ Otherwise, if symbol has a `saved-value' property, it will evaluate
|
|||
the car of that and use it as the default binding for symbol.
|
||||
Otherwise, EXP will be evaluated and used as the default binding for
|
||||
symbol."
|
||||
(eval `(defvar ,symbol ,(let ((sv (get symbol 'saved-value)))
|
||||
(if sv (car sv) exp)))))
|
||||
(condition-case nil
|
||||
(default-toplevel-value symbol) ;Test presence of default value.
|
||||
(void-variable
|
||||
;; The var is not initialized yet.
|
||||
(set-default-toplevel-value
|
||||
symbol (eval (let ((sv (get symbol 'saved-value)))
|
||||
(if sv (car sv) exp))
|
||||
t)))))
|
||||
|
||||
(defun custom-initialize-set (symbol exp)
|
||||
"Initialize SYMBOL based on EXP.
|
||||
|
|
@ -188,18 +194,13 @@ set to nil, as the value is no longer rogue."
|
|||
(t
|
||||
(custom-handle-keyword symbol keyword value
|
||||
'custom-variable))))))
|
||||
;; Set the docstring, record the var on load-history, as well
|
||||
;; as set the special-variable-p flag.
|
||||
(internal--define-uninitialized-variable symbol doc)
|
||||
(put symbol 'custom-requests requests)
|
||||
;; Do the actual initialization.
|
||||
(unless custom-dont-initialize
|
||||
(funcall initialize symbol default)))
|
||||
;; Use defvar to set the docstring as well as the special-variable-p flag.
|
||||
;; FIXME: We should reproduce more of `defvar's behavior, such as the warning
|
||||
;; when the var is currently let-bound.
|
||||
(if (not (default-boundp symbol))
|
||||
;; Don't use defvar to avoid setting a default-value when undesired.
|
||||
(when doc (put symbol 'variable-documentation doc))
|
||||
(eval `(defvar ,symbol nil ,@(when doc (list doc)))))
|
||||
(push symbol current-load-list)
|
||||
(run-hooks 'custom-define-hook)
|
||||
symbol)
|
||||
|
||||
|
|
|
|||
50
src/eval.c
50
src/eval.c
|
|
@ -715,6 +715,25 @@ DEFUN ("set-default-toplevel-value", Fset_default_toplevel_value,
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("internal--define-uninitialized-variable",
|
||||
Finternal__define_uninitialized_variable,
|
||||
Sinternal__define_uninitialized_variable, 1, 2, 0,
|
||||
doc: /* Define SYMBOL as a variable, with DOC as its docstring.
|
||||
This is like `defvar' and `defconst' but without affecting the variable's
|
||||
value. */)
|
||||
(Lisp_Object symbol, Lisp_Object doc)
|
||||
{
|
||||
XSYMBOL (symbol)->u.s.declared_special = true;
|
||||
if (!NILP (doc))
|
||||
{
|
||||
if (!NILP (Vpurify_flag))
|
||||
doc = Fpurecopy (doc);
|
||||
Fput (symbol, Qvariable_documentation, doc);
|
||||
}
|
||||
LOADHIST_ATTACH (symbol);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
|
||||
doc: /* Define SYMBOL as a variable, and return SYMBOL.
|
||||
You are not required to define a variable in order to use it, but
|
||||
|
|
@ -754,32 +773,25 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
|
|||
{
|
||||
if (!NILP (XCDR (tail)) && !NILP (XCDR (XCDR (tail))))
|
||||
error ("Too many arguments");
|
||||
Lisp_Object exp = XCAR (tail);
|
||||
|
||||
tem = Fdefault_boundp (sym);
|
||||
tail = XCDR (tail);
|
||||
|
||||
/* Do it before evaluating the initial value, for self-references. */
|
||||
XSYMBOL (sym)->u.s.declared_special = true;
|
||||
Finternal__define_uninitialized_variable (sym, CAR (tail));
|
||||
|
||||
if (NILP (tem))
|
||||
Fset_default (sym, eval_sub (XCAR (tail)));
|
||||
Fset_default (sym, eval_sub (exp));
|
||||
else
|
||||
{ /* Check if there is really a global binding rather than just a let
|
||||
binding that shadows the global unboundness of the var. */
|
||||
union specbinding *binding = default_toplevel_binding (sym);
|
||||
if (binding && EQ (specpdl_old_value (binding), Qunbound))
|
||||
{
|
||||
set_specpdl_old_value (binding, eval_sub (XCAR (tail)));
|
||||
set_specpdl_old_value (binding, eval_sub (exp));
|
||||
}
|
||||
}
|
||||
tail = XCDR (tail);
|
||||
tem = Fcar (tail);
|
||||
if (!NILP (tem))
|
||||
{
|
||||
if (!NILP (Vpurify_flag))
|
||||
tem = Fpurecopy (tem);
|
||||
Fput (sym, Qvariable_documentation, tem);
|
||||
}
|
||||
LOADHIST_ATTACH (sym);
|
||||
}
|
||||
else if (!NILP (Vinternal_interpreter_environment)
|
||||
&& (SYMBOLP (sym) && !XSYMBOL (sym)->u.s.declared_special))
|
||||
|
|
@ -827,19 +839,12 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */)
|
|||
docstring = XCAR (XCDR (XCDR (args)));
|
||||
}
|
||||
|
||||
Finternal__define_uninitialized_variable (sym, docstring);
|
||||
tem = eval_sub (XCAR (XCDR (args)));
|
||||
if (!NILP (Vpurify_flag))
|
||||
tem = Fpurecopy (tem);
|
||||
Fset_default (sym, tem);
|
||||
XSYMBOL (sym)->u.s.declared_special = true;
|
||||
if (!NILP (docstring))
|
||||
{
|
||||
if (!NILP (Vpurify_flag))
|
||||
docstring = Fpurecopy (docstring);
|
||||
Fput (sym, Qvariable_documentation, docstring);
|
||||
}
|
||||
Fput (sym, Qrisky_local_variable, Qt);
|
||||
LOADHIST_ATTACH (sym);
|
||||
Fset_default (sym, tem); /* FIXME: set-default-toplevel-value? */
|
||||
Fput (sym, Qrisky_local_variable, Qt); /* FIXME: Why? */
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
|
@ -4198,6 +4203,7 @@ alist of active lexical bindings. */);
|
|||
defsubr (&Sdefvaralias);
|
||||
DEFSYM (Qdefvaralias, "defvaralias");
|
||||
defsubr (&Sdefconst);
|
||||
defsubr (&Sinternal__define_uninitialized_variable);
|
||||
defsubr (&Smake_var_non_special);
|
||||
defsubr (&Slet);
|
||||
defsubr (&SletX);
|
||||
|
|
|
|||
Loading…
Reference in a new issue