(Fload, Feval_buffer): Emit a warning when lexbind is unset (bug#74145)
This emits a warning at run-time rather than at compile time. * src/lread.c (get_lexical_binding): New function. (Fload, Feval_buffer): Use it. (syms_of_lread): New var `internal--get-default-lexical-binding-function`. * lisp/files.el: Set it. (internal--get-default-lexical-binding): New function.
This commit is contained in:
parent
9663c959c7
commit
9f25d46568
3 changed files with 50 additions and 11 deletions
7
etc/NEWS
7
etc/NEWS
|
@ -1828,14 +1828,19 @@ Like 'static-if', these macros evaluate their condition at
|
|||
macro-expansion time and are useful for writing code that can work
|
||||
across different Emacs versions.
|
||||
|
||||
** Lexical binding
|
||||
|
||||
---
|
||||
** You can change the default value of 'lexical-binding'.
|
||||
*** You can change the default value of 'lexical-binding'.
|
||||
While the default is still the use of dynamic binding dialect of Elisp
|
||||
in those places that don't explicitly set 'lexical-binding' you can
|
||||
change it globally with:
|
||||
|
||||
(set-default-toplevel-value 'lexical-binding t)
|
||||
|
||||
---
|
||||
*** Loading a file displays a warning if there is no 'lexical-binding' cookie.
|
||||
|
||||
+++
|
||||
** New macros 'incf' and 'decf'.
|
||||
They increment or decrement the value stored in a variable (a symbol),
|
||||
|
|
|
@ -4277,6 +4277,30 @@ all the specified local variables, but ignores any settings of \"mode:\"."
|
|||
(push elem file-local-variables-alist)))
|
||||
(hack-local-variables-apply))))))
|
||||
|
||||
(defun internal--get-default-lexical-binding (from)
|
||||
(let ((mib (lambda (node) (buttonize node (lambda (_) (info node))))))
|
||||
(or (and (bufferp from) (zerop (buffer-size from)))
|
||||
(and (stringp from)
|
||||
(eql 0 (file-attribute-size (file-attributes from))))
|
||||
(display-warning
|
||||
'(files missing-lexbind-cookie)
|
||||
(format-message "Missing `lexical-binding' cookie in %S.
|
||||
You can add one with `M-x elisp-enable-lexical-binding RET'.
|
||||
See `%s' and `%s'
|
||||
for more information."
|
||||
(if (not (and (bufferp from)
|
||||
(equal (buffer-name from) " *load*")
|
||||
load-file-name))
|
||||
from
|
||||
(abbreviate-file-name load-file-name))
|
||||
(funcall mib "(elisp)Selecting Lisp Dialect")
|
||||
(funcall mib "(elisp)Converting to Lexical Binding"))
|
||||
:warning))
|
||||
(default-toplevel-value 'lexical-binding)))
|
||||
|
||||
(setq internal--get-default-lexical-binding-function
|
||||
#'internal--get-default-lexical-binding)
|
||||
|
||||
(defun hack-local-variables--find-variables (&optional handle-mode)
|
||||
"Return all local variables in the current buffer.
|
||||
If HANDLE-MODE is nil, we gather all the specified local
|
||||
|
|
30
src/lread.c
30
src/lread.c
|
@ -1271,6 +1271,18 @@ close_file_unwind_android_fd (void *ptr)
|
|||
|
||||
#endif
|
||||
|
||||
static Lisp_Object
|
||||
get_lexical_binding (Lisp_Object stream, Lisp_Object from)
|
||||
{
|
||||
lexical_cookie_t lexc = lisp_file_lexical_cookie (stream);
|
||||
return (lexc == Cookie_Lex ? Qt
|
||||
: lexc == Cookie_Dyn ? Qnil
|
||||
: (NILP (from) /* Loading a byte-compiled file. */
|
||||
|| NILP (Vinternal__get_default_lexical_binding_function)
|
||||
? Fdefault_toplevel_value (Qlexical_binding)
|
||||
: calln (Vinternal__get_default_lexical_binding_function, from)));
|
||||
}
|
||||
|
||||
DEFUN ("load", Fload, Sload, 1, 5, 0,
|
||||
doc: /* Execute a file of Lisp code named FILE.
|
||||
First try FILE with `.elc' appended, then try with `.el', then try
|
||||
|
@ -1720,11 +1732,8 @@ Return t if the file exists and loads successfully. */)
|
|||
}
|
||||
else
|
||||
{
|
||||
lexical_cookie_t lexc = lisp_file_lexical_cookie (Qget_file_char);
|
||||
Fset (Qlexical_binding,
|
||||
(lexc == Cookie_Lex ? Qt
|
||||
: lexc == Cookie_Dyn ? Qnil
|
||||
: Fdefault_toplevel_value (Qlexical_binding)));
|
||||
get_lexical_binding (Qget_file_char, compiled ? Qnil : file));
|
||||
|
||||
if (! version || version >= 22)
|
||||
readevalloop (Qget_file_char, &input, hist_file_name,
|
||||
|
@ -2609,11 +2618,7 @@ This function preserves the position of point. */)
|
|||
specbind (Qstandard_output, tem);
|
||||
record_unwind_protect_excursion ();
|
||||
BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
|
||||
lexical_cookie_t lexc = lisp_file_lexical_cookie (buf);
|
||||
specbind (Qlexical_binding,
|
||||
lexc == Cookie_Lex ? Qt
|
||||
: lexc == Cookie_Dyn ? Qnil
|
||||
: Fdefault_toplevel_value (Qlexical_binding));
|
||||
specbind (Qlexical_binding, get_lexical_binding (buf, buf));
|
||||
BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
|
||||
readevalloop (buf, 0, filename,
|
||||
!NILP (printflag), unibyte, Qnil, Qnil, Qnil);
|
||||
|
@ -5169,7 +5174,7 @@ obarray_index (struct Lisp_Obarray *oa, const char *str, ptrdiff_t size_byte)
|
|||
return knuth_hash (reduce_emacs_uint_to_hash_hash (hash), oa->size_bits);
|
||||
}
|
||||
|
||||
/* Return the symbol in OBARRAY whose names matches the string
|
||||
/* Return the symbol in OBARRAY whose name matches the string
|
||||
of SIZE characters (SIZE_BYTE bytes) at PTR.
|
||||
If there is no such symbol, return the integer bucket number of
|
||||
where the symbol would be if it were present.
|
||||
|
@ -6145,6 +6150,11 @@ through `require'. */);
|
|||
|
||||
DEFSYM (Qchar_from_name, "char-from-name");
|
||||
|
||||
DEFVAR_LISP ("internal--get-default-lexical-binding-function",
|
||||
Vinternal__get_default_lexical_binding_function,
|
||||
doc: /* Function to decide default lexical-binding. */);
|
||||
Vinternal__get_default_lexical_binding_function = Qnil;
|
||||
|
||||
DEFVAR_LISP ("read-symbol-shorthands", Vread_symbol_shorthands,
|
||||
doc: /* Alist of known symbol-name shorthands.
|
||||
This variable's value can only be set via file-local variables.
|
||||
|
|
Loading…
Add table
Reference in a new issue