From 4beb850efb99b881fb8b648ad7bb43c6539a2431 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Tue, 24 Dec 2019 20:48:49 +0100 Subject: add native support to the build system --- lisp/emacs-lisp/autoload.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index 785e350e0e5..53d353858b3 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -1045,7 +1045,7 @@ write its autoloads into the specified file instead." ;; we don't want to depend on whether Emacs was ;; built with or without modules support, nor ;; what is the suffix for the underlying OS. - (unless (string-match "\\.\\(elc\\|so\\|dll\\)" suf) + (unless (string-match "\\.\\(elc\\|eln\\|so\\|dll\\)" suf) (push suf tmp))) (concat "^[^=.].*" (regexp-opt tmp t) "\\'"))) (files (apply #'nconc -- cgit v1.2.3 From 8db8c851ad1568d61ed50a4d087e6de2b475cf5f Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Tue, 14 Apr 2020 19:58:41 +0100 Subject: Always set `load-true-file-name' where `load-file-name' is set too. Fix bug#40620. * lisp/cus-dep.el (custom-make-dependencies): Set load-true-file-name. * lisp/emacs-lisp/package.el (package-quickstart-refresh): Likewise. * lisp/international/mule.el (load-with-code-conversion): Likewise. * lisp/loadup.el (load-true-file-name): Likewise. --- lisp/cus-dep.el | 1 + lisp/emacs-lisp/autoload.el | 4 +++- lisp/emacs-lisp/package.el | 3 ++- lisp/international/mule.el | 5 +++-- lisp/loadup.el | 1 + 5 files changed, 10 insertions(+), 4 deletions(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el index fd307a5c04e..e2c2ebe5f42 100644 --- a/lisp/cus-dep.el +++ b/lisp/cus-dep.el @@ -90,6 +90,7 @@ Usage: emacs -batch -l ./cus-dep.el -f custom-make-dependencies DIRS" (string-match "\\`\\(.*\\)\\.el\\'" file) (let ((name (or generated-autoload-load-name ; see bug#5277 (file-name-nondirectory (match-string 1 file)))) + (load-true-file-name file) (load-file-name file)) (if (save-excursion (re-search-forward diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index 6180bee2aa7..d9a43c23299 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -167,7 +167,9 @@ expression, in which case we want to handle forms differently." define-inline cl-defun cl-defmacro cl-defgeneric cl-defstruct pcase-defmacro)) (macrop car) - (setq expand (let ((load-file-name file)) (macroexpand form))) + (setq expand (let ((load-true-file-name file) + (load-file-name file)) + (macroexpand form))) (memq (car expand) '(progn prog1 defalias))) (make-autoload expand file 'expansion)) ;Recurse on the expansion. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 4312ab9ca9a..b33e4897a01 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -3965,7 +3965,8 @@ activations need to be changed, such as when `package-load-list' is modified." (let ((load-suffixes '(".el" ".elc"))) (locate-library (package--autoloads-file-name pkg)))) (pfile (prin1-to-string file))) - (insert "(let ((load-file-name " pfile "))\n") + (insert "(let ((load-true-file-name " pfile ")\ +(load-file-name " pfile "))\n") (insert-file-contents file) ;; Fixup the special #$ reader form and throw away comments. (while (re-search-forward "#\\$\\|^;\\(.*\n\\)" nil 'move) diff --git a/lisp/international/mule.el b/lisp/international/mule.el index 72e8cad9d62..363df13dfe6 100644 --- a/lisp/international/mule.el +++ b/lisp/international/mule.el @@ -320,8 +320,9 @@ Return t if file exists." (when purify-flag (push (purecopy file) preloaded-file-list)) (unwind-protect - (let ((load-file-name fullname) - (set-auto-coding-for-load t) + (let ((load-true-file-name fullname) + (load-file-name fullname) + (set-auto-coding-for-load t) (inhibit-file-name-operation nil)) (with-current-buffer buffer ;; So that we don't get completely screwed if the diff --git a/lisp/loadup.el b/lisp/loadup.el index 3cc47bc91fa..7cf2cb01c33 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -566,6 +566,7 @@ lost after dumping"))) ;; Don't keep `load-file-name' set during the top-level session! ;; Otherwise, it breaks a lot of code which does things like ;; (or load-file-name byte-compile-current-file). +(setq load-true-file-name nil) (setq load-file-name nil) (eval top-level) -- cgit v1.2.3 From a06fe08e8e8177ae3ccd6e2677b40237cd86ae9d Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Mon, 28 Sep 2020 17:20:55 +0200 Subject: Clean-up some now unnecessary diff against master * lisp/emacs-lisp/autoload.el (update-directory-autoloads): .eln files have been moved so remove the '.eln' match. * lisp/emacs-lisp/bytecomp.el (byte-compile-refresh-preloaded): Likewise. * lisp/emacs-lisp/find-func.el (find-library-suffixes): Clean-up as '.eln' is no more in `load-suffixes'. * lisp/help-fns.el (find-lisp-object-file-name): Clean-up as `symbol-file' will return the '.elc' file. * src/lread.c (Fget_load_suffixes): Remove logic as '.eln' is not anymore in load-suffixes. (openp): Two spaces. --- lisp/emacs-lisp/autoload.el | 2 +- lisp/emacs-lisp/bytecomp.el | 3 +-- lisp/emacs-lisp/find-func.el | 3 +-- lisp/help-fns.el | 11 +++-------- src/lread.c | 23 +++-------------------- 5 files changed, 9 insertions(+), 33 deletions(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index 4bdbc95081f..5ee0a14273f 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -1047,7 +1047,7 @@ write its autoloads into the specified file instead." ;; we don't want to depend on whether Emacs was ;; built with or without modules support, nor ;; what is the suffix for the underlying OS. - (unless (string-match "\\.\\(elc\\|eln\\|so\\|dll\\)" suf) + (unless (string-match "\\.\\(elc\\|so\\|dll\\)" suf) (push suf tmp))) (concat "\\`[^=.].*" (regexp-opt tmp t) "\\'"))) (files (apply #'nconc diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 4a2a8c62cbc..b0e3158df32 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -5180,8 +5180,7 @@ Use with caution." (message "Can't find %s to refresh preloaded Lisp files" argv0) (dolist (f (reverse load-history)) (setq f (car f)) - (when (string-match "el[cn]\\'" f) - (setq f (substring f 0 -1))) + (if (string-match "elc\\'" f) (setq f (substring f 0 -1))) (when (and (file-readable-p f) (file-newer-than-file-p f emacs-file) ;; Don't reload the source version of the files below diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index a4577a53164..9e4d8cf1aa8 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -167,8 +167,7 @@ See the functions `find-function' and `find-variable'." (defun find-library-suffixes () (let ((suffixes nil)) (dolist (suffix (get-load-suffixes) (nreverse suffixes)) - (unless (string-match "el[cn]" suffix) - (push suffix suffixes))))) + (unless (string-match "elc" suffix) (push suffix suffixes))))) (defun find-library--load-name (library) (let ((name library)) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 88984ec453e..9fee156f18f 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -323,17 +323,12 @@ found via `load-path'. The return value can also be `C-source', which means that OBJECT is a function or variable defined in C. If no suitable file is found, return nil." (let* ((autoloaded (autoloadp type)) - (true-name (or (and autoloaded (nth 1 type)) + (file-name (or (and autoloaded (nth 1 type)) (symbol-file ;; FIXME: Why do we have this weird "If TYPE is the ;; value returned by `symbol-function' for a function ;; symbol" exception? - object (or (if (symbolp type) type) 'defun)))) - (file-name (if (and true-name - (string-match "[.]eln\\'" true-name)) - (gethash (file-name-nondirectory true-name) - comp-eln-to-el-h) - true-name))) + object (or (if (symbolp type) type) 'defun))))) (cond (autoloaded ;; An autoloaded function: Locate the file since `symbol-function' @@ -392,7 +387,7 @@ suitable file is found, return nil." ((let ((lib-name (if (string-match "[.]elc\\'" file-name) (substring-no-properties file-name 0 -1) - file-name))) + file-name))) (or (and (file-readable-p lib-name) lib-name) ;; The library might be compressed. (and (file-readable-p (concat lib-name ".gz")) lib-name)))) diff --git a/src/lread.c b/src/lread.c index d32f5755e98..ea31131b755 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1056,25 +1056,8 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) { Lisp_Object exts = Vload_file_rep_suffixes; Lisp_Object suffix = XCAR (suffixes); - bool native_code_suffix = - NATIVE_COMP_FLAG - && strcmp (NATIVE_ELISP_SUFFIX, SSDATA (suffix)) == 0; - -#ifdef HAVE_MODULES - native_code_suffix = - native_code_suffix || strcmp (MODULES_SUFFIX, SSDATA (suffix)) == 0; -#ifdef MODULES_SECONDARY_SUFFIX - native_code_suffix = - native_code_suffix - || strcmp (MODULES_SECONDARY_SUFFIX, SSDATA (suffix)) == 0; -#endif -#endif - - if (native_code_suffix) - lst = Fcons (suffix, lst); - else - FOR_EACH_TAIL (exts) - lst = Fcons (concat2 (suffix, XCAR (exts)), lst); + FOR_EACH_TAIL (exts) + lst = Fcons (concat2 (suffix, XCAR (exts)), lst); } return Fnreverse (lst); } @@ -1698,6 +1681,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, int last_errno = ENOENT; int save_fd = -1; USE_SAFE_ALLOCA; + /* The last-modified time of the newest matching file found. Initialize it to something less than all valid timestamps. */ struct timespec save_mtime = make_timespec (TYPE_MINIMUM (time_t), -1); @@ -1898,7 +1882,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, /* We succeeded; return this descriptor and filename. */ if (storeptr) *storeptr = string; - SAFE_FREE (); return fd; } -- cgit v1.2.3 From 58e0c8ee86e2c36245f1c5a1483f1c73600b4914 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 14 Feb 2021 13:21:24 +0100 Subject: Extend the syntax of `interactive' to list applicable modes * doc/lispref/commands.texi (Using Interactive): Document the extended `interactive' form. * doc/lispref/loading.texi (Autoload): Document list-of-modes form. * lisp/emacs-lisp/autoload.el (make-autoload): Pick the list of modes from `interactive' out of the functions. * lisp/emacs-lisp/bytecomp.el (byte-compile-lambda): Allow for the extended `interactive' form. * src/callint.c (Finteractive): Document the extended form. * src/data.c (Finteractive_form): Return the interactive form in the old format (even when there's an extended `interactive') to avoid having other parts of Emacs be aware of this. (Fcommand_modes): New defun. * src/emacs-module.c (GCALIGNED_STRUCT): Allow for modules to return command modes. * src/lisp.h: New function module_function_command_modes. --- doc/lispref/commands.texi | 19 +++++++++- doc/lispref/loading.texi | 3 ++ etc/NEWS | 8 ++++ lisp/emacs-lisp/autoload.el | 15 ++++++-- lisp/emacs-lisp/bytecomp.el | 40 ++++++++++++-------- src/callint.c | 9 ++++- src/data.c | 92 ++++++++++++++++++++++++++++++++++++++++++--- src/emacs-module.c | 8 +++- src/eval.c | 9 ++++- src/lisp.h | 3 ++ src/lread.c | 1 + 11 files changed, 179 insertions(+), 28 deletions(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 3a2c7d019ef..d60745a825b 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -156,7 +156,7 @@ commands by adding the @code{interactive} form to them. makes a Lisp function an interactively-callable command, and how to examine a command's @code{interactive} form. -@defspec interactive arg-descriptor +@defspec interactive &optional arg-descriptor &rest modes This special form declares that a function is a command, and that it may therefore be called interactively (via @kbd{M-x} or by entering a key sequence bound to it). The argument @var{arg-descriptor} declares @@ -177,6 +177,23 @@ forms are executed; at this time, if the @code{interactive} form occurs within the body, the form simply returns @code{nil} without even evaluating its argument. +The @var{modes} list allows specifying which modes the command is +meant to be used in. This affects, for instance, completion in +@kbd{M-x} (commands won't be offered as completions if they don't +match (using @code{derived-mode-p}) the current major mode, or if the +mode is a minor mode, whether it's switched on in the current buffer). +This will also make @kbd{C-h m} list these commands (if they aren't +bound to any keys). + +For instance: + +@lisp +(interactive "p" dired-mode) +@end lisp + +This will mark the command as applicable for modes derived from +@code{dired-mode} only. + By convention, you should put the @code{interactive} form in the function body, as the first top-level form. If there is an @code{interactive} form in both the @code{interactive-form} symbol diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 33f37331947..8c6aeb04721 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -510,6 +510,9 @@ specification is not given here; it's not needed unless the user actually calls @var{function}, and when that happens, it's time to load the real definition. +If @var{interactive} is a list, it is interpreted as a list of modes +this command is applicable for. + You can autoload macros and keymaps as well as ordinary functions. Specify @var{type} as @code{macro} if @var{function} is really a macro. Specify @var{type} as @code{keymap} if @var{function} is really a diff --git a/etc/NEWS b/etc/NEWS index 08e1e94d83d..d8f0bc60726 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2266,6 +2266,14 @@ back in Emacs 23.1. The affected functions are: 'make-obsolete', * Lisp Changes in Emacs 28.1 ++++ +** The 'interactive' syntax has been extended to allow listing applicable modes. +Forms like '(interactive "p" dired-mode)' can be used to annotate the +commands as being applicable for modes derived from 'dired-mode', +or if the mode is a minor mode, that the current buffer has that +minor mode activated. Note that using this form will create byte code +that is not compatible with byte code in previous Emacs versions. + +++ ** New buffer-local variable 'minor-modes'. This permanently buffer-local variable holds a list of currently diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index ec7492dd4b1..ae17039645a 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -141,9 +141,12 @@ expression, in which case we want to handle forms differently." ((stringp (car-safe rest)) (car rest)))) ;; Look for an interactive spec. (interactive (pcase body - ((or `((interactive . ,_) . ,_) - `(,_ (interactive . ,_) . ,_)) - t)))) + ((or `((interactive . ,iargs) . ,_) + `(,_ (interactive . ,iargs) . ,_)) + ;; List of modes or just t. + (if (nthcdr 1 iargs) + (list 'quote (nthcdr 1 iargs)) + t))))) ;; Add the usage form at the end where describe-function-1 ;; can recover it. (when (consp args) (setq doc (help-add-fundoc-usage doc args))) @@ -207,7 +210,11 @@ expression, in which case we want to handle forms differently." easy-mmode-define-minor-mode define-minor-mode)) t) - (eq (car-safe (car body)) 'interactive)) + (and (eq (car-safe (car body)) 'interactive) + ;; List of modes or just t. + (or (if (nthcdr 1 (car body)) + (list 'quote (nthcdr 1 (car body))) + t)))) ,(if macrop ''macro nil)))) ;; For defclass forms, use `eieio-defclass-autoload'. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 89068a14f02..5c6b9c2e39a 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2939,7 +2939,8 @@ for symbols generated by the byte compiler itself." ;; unless it is the last element of the body. (if (cdr body) (setq body (cdr body)))))) - (int (assq 'interactive body))) + (int (assq 'interactive body)) + command-modes) (when lexical-binding (dolist (var arglistvars) (when (assq var byte-compile--known-dynamic-vars) @@ -2951,9 +2952,10 @@ for symbols generated by the byte compiler itself." (if (eq int (car body)) (setq body (cdr body))) (cond ((consp (cdr int)) - (if (cdr (cdr int)) - (byte-compile-warn "malformed interactive spec: %s" - (prin1-to-string int))) + (unless (seq-every-p #'symbolp (cdr (cdr int))) + (byte-compile-warn "malformed interactive specc: %s" + (prin1-to-string int))) + (setq command-modes (cdr (cdr int))) ;; If the interactive spec is a call to `list', don't ;; compile it, because `call-interactively' looks at the ;; args of `list'. Actually, compile it to get warnings, @@ -2964,14 +2966,15 @@ for symbols generated by the byte compiler itself." (while (consp (cdr form)) (setq form (cdr form))) (setq form (car form))) - (if (and (eq (car-safe form) 'list) - ;; For code using lexical-binding, form is not - ;; valid lisp, but rather an intermediate form - ;; which may include "calls" to - ;; internal-make-closure (Bug#29988). - (not lexical-binding)) - nil - (setq int `(interactive ,newform))))) + (setq int + (if (and (eq (car-safe form) 'list) + ;; For code using lexical-binding, form is not + ;; valid lisp, but rather an intermediate form + ;; which may include "calls" to + ;; internal-make-closure (Bug#29988). + (not lexical-binding)) + `(interactive ,form) + `(interactive ,newform))))) ((cdr int) (byte-compile-warn "malformed interactive spec: %s" (prin1-to-string int))))) @@ -3002,9 +3005,16 @@ for symbols generated by the byte compiler itself." (list (help-add-fundoc-usage doc arglist))) ((or doc int) (list doc))) - ;; optionally, the interactive spec. - (if int - (list (nth 1 int)))))))) + ;; optionally, the interactive spec (and the modes the + ;; command applies to). + (cond + ;; We have some command modes, so use the vector form. + (command-modes + (list (vector (nth 1 int) command-modes))) + ;; No command modes, use the simple form with just the + ;; interactive spec. + (int + (list (nth 1 int))))))))) (defvar byte-compile-reserved-constants 0) diff --git a/src/callint.c b/src/callint.c index d3f49bc35d1..18624637843 100644 --- a/src/callint.c +++ b/src/callint.c @@ -104,7 +104,14 @@ If the string begins with `^' and `shift-select-mode' is non-nil, Emacs first calls the function `handle-shift-selection'. You may use `@', `*', and `^' together. They are processed in the order that they appear, before reading any arguments. -usage: (interactive &optional ARG-DESCRIPTOR) */ + +If MODES is present, it should be a list of mode names (symbols) that +this command is applicable for. The main effect of this is that +`M-x TAB' (by default) won't list this command if the current buffer's +mode doesn't match the list. That is, if either the major mode isn't +derived from them, or (when it's a minor mode) the mode isn't in effect. + +usage: (interactive &optional ARG-DESCRIPTOR &rest MODES) */ attributes: const) (Lisp_Object args) { diff --git a/src/data.c b/src/data.c index 38cde0ff8b2..7bddc039f6f 100644 --- a/src/data.c +++ b/src/data.c @@ -904,7 +904,17 @@ Value, if non-nil, is a list (interactive SPEC). */) else if (COMPILEDP (fun)) { if (PVSIZE (fun) > COMPILED_INTERACTIVE) - return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE)); + { + Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE); + if (VECTORP (form)) + /* The vector form is the new form, where the first + element is the interactive spec, and the second is the + command modes. */ + return list2 (Qinteractive, AREF (form, 0)); + else + /* Old form -- just the interactive spec. */ + return list2 (Qinteractive, form); + } } #ifdef HAVE_MODULES else if (MODULE_FUNCTIONP (fun)) @@ -920,10 +930,80 @@ Value, if non-nil, is a list (interactive SPEC). */) else if (CONSP (fun)) { Lisp_Object funcar = XCAR (fun); - if (EQ (funcar, Qclosure)) - return Fassq (Qinteractive, Fcdr (Fcdr (XCDR (fun)))); - else if (EQ (funcar, Qlambda)) - return Fassq (Qinteractive, Fcdr (XCDR (fun))); + if (EQ (funcar, Qclosure) + || EQ (funcar, Qlambda)) + { + Lisp_Object form = Fcdr (XCDR (fun)); + if (EQ (funcar, Qclosure)) + form = Fcdr (form); + Lisp_Object spec = Fassq (Qinteractive, form); + if (NILP (Fcdr (Fcdr (spec)))) + return spec; + else + return list2 (Qinteractive, Fcar (Fcdr (spec))); + } + } + return Qnil; +} + +DEFUN ("command-modes", Fcommand_modes, Scommand_modes, 1, 1, 0, + doc: /* Return the modes COMMAND is defined for. +If COMMAND is not a command, the return value is nil. +The value, if non-nil, is a list of mode name symbols. */) + (Lisp_Object command) +{ + Lisp_Object fun = indirect_function (command); /* Check cycles. */ + + if (NILP (fun)) + return Qnil; + + fun = command; + while (SYMBOLP (fun)) + fun = Fsymbol_function (fun); + + if (SUBRP (fun)) + { + if (!NILP (XSUBR (fun)->command_modes)) + return XSUBR (fun)->command_modes; + } + else if (COMPILEDP (fun)) + { + Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE); + if (VECTORP (form)) + /* New form -- the second element is the command modes. */ + return AREF (form, 1); + else + /* Old .elc file -- no command modes. */ + return Qnil; + } +#ifdef HAVE_MODULES + else if (MODULE_FUNCTIONP (fun)) + { + Lisp_Object form + = module_function_command_modes (XMODULE_FUNCTION (fun)); + if (! NILP (form)) + return form; + } +#endif + else if (AUTOLOADP (fun)) + { + Lisp_Object modes = Fnth (make_int (3), fun); + if (CONSP (modes)) + return modes; + else + return Qnil; + } + else if (CONSP (fun)) + { + Lisp_Object funcar = XCAR (fun); + if (EQ (funcar, Qclosure) + || EQ (funcar, Qlambda)) + { + Lisp_Object form = Fcdr (XCDR (fun)); + if (EQ (funcar, Qclosure)) + form = Fcdr (form); + return Fcdr (Fcdr (Fassq (Qinteractive, form))); + } } return Qnil; } @@ -3908,6 +3988,7 @@ syms_of_data (void) defsubr (&Sindirect_variable); defsubr (&Sinteractive_form); + defsubr (&Scommand_modes); defsubr (&Seq); defsubr (&Snull); defsubr (&Stype_of); @@ -4030,6 +4111,7 @@ This variable cannot be set; trying to do so will signal an error. */); DEFSYM (Qunlet, "unlet"); DEFSYM (Qset, "set"); DEFSYM (Qset_default, "set-default"); + DEFSYM (Qcommand_modes, "command-modes"); defsubr (&Sadd_variable_watcher); defsubr (&Sremove_variable_watcher); defsubr (&Sget_variable_watchers); diff --git a/src/emacs-module.c b/src/emacs-module.c index 894dffcf21e..f8fb54c0728 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -549,7 +549,7 @@ struct Lisp_Module_Function union vectorlike_header header; /* Fields traced by GC; these must come first. */ - Lisp_Object documentation, interactive_form; + Lisp_Object documentation, interactive_form, command_modes; /* Fields ignored by GC. */ ptrdiff_t min_arity, max_arity; @@ -646,6 +646,12 @@ module_function_interactive_form (const struct Lisp_Module_Function *fun) return fun->interactive_form; } +Lisp_Object +module_function_command_modes (const struct Lisp_Module_Function *fun) +{ + return fun->command_modes; +} + static emacs_value module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs, emacs_value *args) diff --git a/src/eval.c b/src/eval.c index 91fc4e68377..542d7f686e6 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2080,14 +2080,21 @@ then strings and vectors are not accepted. */) DEFUN ("autoload", Fautoload, Sautoload, 2, 5, 0, doc: /* Define FUNCTION to autoload from FILE. FUNCTION is a symbol; FILE is a file name string to pass to `load'. + Third arg DOCSTRING is documentation for the function. -Fourth arg INTERACTIVE if non-nil says function can be called interactively. + +Fourth arg INTERACTIVE if non-nil says function can be called +interactively. If INTERACTIVE is a list, it is interpreted as a list +of modes the function is applicable for. + Fifth arg TYPE indicates the type of the object: nil or omitted says FUNCTION is a function, `keymap' says FUNCTION is really a keymap, and `macro' or t says FUNCTION is really a macro. + Third through fifth args give info about the real definition. They default to nil. + If FUNCTION is already defined other than as an autoload, this does nothing and returns nil. */) (Lisp_Object function, Lisp_Object file, Lisp_Object docstring, Lisp_Object interactive, Lisp_Object type) diff --git a/src/lisp.h b/src/lisp.h index 0847324d1ff..697dd89363c 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -2060,6 +2060,7 @@ struct Lisp_Subr const char *symbol_name; const char *intspec; EMACS_INT doc; + Lisp_Object command_modes; } GCALIGNED_STRUCT; union Aligned_Lisp_Subr { @@ -4221,6 +4222,8 @@ extern Lisp_Object module_function_documentation (struct Lisp_Module_Function const *); extern Lisp_Object module_function_interactive_form (const struct Lisp_Module_Function *); +extern Lisp_Object module_function_command_modes + (const struct Lisp_Module_Function *); extern module_funcptr module_function_address (struct Lisp_Module_Function const *); extern void *module_function_data (const struct Lisp_Module_Function *); diff --git a/src/lread.c b/src/lread.c index dea1b232fff..8b8ba93c607 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4467,6 +4467,7 @@ defsubr (union Aligned_Lisp_Subr *aname) XSETPVECTYPE (sname, PVEC_SUBR); XSETSUBR (tem, sname); set_symbol_function (sym, tem); + sname->command_modes = Qnil; } #ifdef NOTDEF /* Use fset in subr.el now! */ -- cgit v1.2.3 From 26b9564bd53685533f71e6e102f5bbf575e0c6af Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Mon, 5 Jul 2021 15:55:38 +0200 Subject: Propagate :safe properties when autoloading defcustoms * lisp/emacs-lisp/autoload.el (make-autoload): Propagate the :safe property to the loaddefs file (bug#28104). --- etc/NEWS | 3 +++ lisp/emacs-lisp/autoload.el | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/etc/NEWS b/etc/NEWS index 1a3130826a5..a62e9c86c93 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2914,6 +2914,9 @@ The former is now declared obsolete. * Lisp Changes in Emacs 28.1 +--- +*** :safe settings in 'defcustom' are now propagated to the loaddefs files. + +++ ** New function 'syntax-class-to-char'. This does almost the opposite of 'string-to-syntax' -- it returns the diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index b45984be1d5..9d1ae705976 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -250,7 +250,10 @@ expression, in which case we want to handle forms differently." (custom-autoload ',varname ,file ,(condition-case nil (null (plist-get props :set)) - (error nil)))))) + (error nil))) + ;; Propagate the :safe property to the loaddefs file. + ,@(when-let ((safe (plist-get props :safe))) + `((put ',varname 'safe-local-variable ,safe)))))) ((eq car 'defgroup) ;; In Emacs this is normally handled separately by cus-dep.el, but for -- cgit v1.2.3 From cd7eb4bee1805ca810332e495d566a555e2c9196 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sun, 1 Aug 2021 22:58:09 +0300 Subject: * lisp/emacs-lisp/autoload.el (autoload--make-defs-autoload): Display warning. https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00007.html --- lisp/emacs-lisp/autoload.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lisp/emacs-lisp/autoload.el') diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index 9d1ae705976..e9a20634af8 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -626,8 +626,8 @@ Don't try to split prefixes that are already longer than that.") (radix-tree-iter-mappings (cdr x) (lambda (s _) (push (concat prefix s) dropped))) - (message "Not registering prefix \"%s\" from %s. Affects: %S" - prefix file dropped) + (message "%s:0: Warning: Not registering prefix \"%s\". Affects: %S" + file prefix dropped) nil)))) prefixes))) `(register-definition-prefixes ,file ',(sort (delq nil strings) -- cgit v1.2.3