commit ce7f2b93bb4dc17ae083ca33327c618a2038f420 (HEAD, refs/remotes/origin/master) Author: Stefan Monnier Date: Thu Oct 16 12:37:14 2025 -0400 lisp/emacs-lisp/rx.el ( rx): Workaround for bug#79634 diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 229f1dbb57b..617a0fb1d40 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1685,6 +1685,10 @@ following constructs: REF can be a number, as usual, or a name introduced by a previous (let REF ...) construct." + ;; FIXME: We can't rely on the surrounding lexical context because + ;; `pcase-defmacro' wraps this function inside an `eval-and-compile', + ;; so we have to repeat the (defvar rx--pcase-vars). + (defvar rx--pcase-vars) (let* ((rx--pcase-vars nil) (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps))))) `(and (pred stringp) commit 7de5a6d1f71ebd359202ae45635b1f2c3f2c184c Author: Przemysław Alexander Kamiński Date: Fri Oct 17 11:24:31 2025 +0100 Release NS objects (bug#79023) * src/nsterm.m (ns_free_frame_resources): Release the NSView. ([EmacsView dealloc]): Release the EmacsLayer and menu. ([EmacsWindow dealloc]): Fix the toolbar release. Co-authored-by: Rudolf Adamkovič diff --git a/src/nsterm.m b/src/nsterm.m index 5127739e2d9..74ee1219bbc 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1637,6 +1637,7 @@ Hide the window (X11 semantics) [[view window] close]; [view removeFromSuperview]; + [view release]; xfree (f->output_data.ns); f->output_data.ns = NULL; @@ -6844,6 +6845,14 @@ - (void)dealloc if (fs_state == FULLSCREEN_BOTH) [nonfs_window release]; + +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 + /* Release layer and menu */ + EmacsLayer *layer = (EmacsLayer *)[self layer]; + [layer release]; +#endif + + [[self menu] release]; [super dealloc]; } @@ -9599,8 +9608,9 @@ - (void)dealloc NSTRACE ("[EmacsWindow dealloc]"); /* We need to release the toolbar ourselves. */ - [self setToolbar: nil]; [[self toolbar] release]; + [self setToolbar: nil]; + /* Also the last button press event . */ if (last_drag_event) commit ba8752cae9c61a0c18422627aa4cbda7cb06b43a Author: Sean Whitton Date: Fri Oct 17 15:06:11 2025 +0100 Replace recent fix for vc-auto-revert-mode autoload problem * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Wrap references to MODE-variable in bound-and-true-p. * lisp/vc/vc-hooks.el (auto-revert-mode): Restore to compilation declaration only. diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 0aa1fe2ce9d..e87b9269188 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -567,7 +567,7 @@ Disable the mode if ARG is a negative number.\n\n" (dolist (buf (buffer-list)) (with-current-buffer buf (if ,global-mode (funcall ,turn-on-function) - (when ,MODE-variable (,mode -1))))) + (when (bound-and-true-p ,MODE-variable) (,mode -1))))) ,@body) ,(when predicate @@ -629,7 +629,7 @@ list." ;; If one of them declines to turn the minor mode on, ;; that should not mean the others can't. (,MODE-suppress-set-explicitly t)) - (if ,MODE-variable + (if (bound-and-true-p ,MODE-variable) (progn (,mode -1) (funcall ,turn-on-function)) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index a082270563b..32586f57804 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -210,10 +210,7 @@ VC commands are globally reachable under the prefix \\[vc-prefix-map]: \\{vc-prefix-map}" nil) -;; A compiler declaration (defvar auto-revert-mode) is not enough here -;; because `define-globalized-minor-mode' wants to check the variable's -;; value before causing autorevert.el to be autoloaded. -(defvar-local auto-revert-mode nil) +(defvar auto-revert-mode) (define-globalized-minor-mode vc-auto-revert-mode auto-revert-mode vc-turn-on-auto-revert-mode-for-tracked-files :group 'vc commit d587ce8c65a0e22ab0a63ef2873a3dfcfbeba166 Author: Eli Zaretskii Date: Fri Oct 17 14:15:41 2025 +0300 Support Tree-sitter version 0.26 and later * src/treesit.c (init_treesit_functions) [TREE_SITTER_LANGUAGE_VERSION >= 15]: Define prototype for, and load 'ts_language_abi_version' instead of the deprecated (and removed in tree-sitter 0.26) 'ts_language_version'. (ts_language_abi_version) [TREE_SITTER_LANGUAGE_VERSION >= 15]: Define on WINDOWSNT, instead of 'ts_language_version'. (treesit_language_abi_version): New compatibility function. (treesit_load_language, Ftreesit_language_abi_version): Use 'treesit_language_abi_version' instead of 'ts_language_version'. (Bug#79627) diff --git a/src/treesit.c b/src/treesit.c index bf982de580b..69751b5ea10 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -35,7 +35,11 @@ along with GNU Emacs. If not, see . */ # include "w32common.h" /* In alphabetical order. */ +#if TREE_SITTER_LANGUAGE_VERSION >= 15 +#undef ts_language_abi_version +#else #undef ts_language_version +#endif #undef ts_node_child #undef ts_node_child_by_field_name #undef ts_node_child_count @@ -90,7 +94,11 @@ along with GNU Emacs. If not, see . */ #undef ts_tree_get_changed_ranges #undef ts_tree_root_node +#if TREE_SITTER_LANGUAGE_VERSION >= 15 +DEF_DLL_FN (uint32_t, ts_language_abi_version, (const TSLanguage *)); +#else DEF_DLL_FN (uint32_t, ts_language_version, (const TSLanguage *)); +#endif DEF_DLL_FN (TSNode, ts_node_child, (TSNode, uint32_t)); DEF_DLL_FN (TSNode, ts_node_child_by_field_name, (TSNode, const char *, uint32_t)); @@ -167,7 +175,11 @@ init_treesit_functions (void) if (!library) return false; +#if TREE_SITTER_LANGUAGE_VERSION >= 15 + LOAD_DLL_FN (library, ts_language_abi_version); +#else LOAD_DLL_FN (library, ts_language_version); +#endif LOAD_DLL_FN (library, ts_node_child); LOAD_DLL_FN (library, ts_node_child_by_field_name); LOAD_DLL_FN (library, ts_node_child_count); @@ -225,7 +237,11 @@ init_treesit_functions (void) return true; } +#if TREE_SITTER_LANGUAGE_VERSION >= 15 +#define ts_language_abi_version fn_ts_language_abi_version +#else #define ts_language_version fn_ts_language_version +#endif #define ts_node_child fn_ts_node_child #define ts_node_child_by_field_name fn_ts_node_child_by_field_name #define ts_node_child_count fn_ts_node_child_count @@ -711,6 +727,22 @@ treesit_load_language_push_for_each_suffix (Lisp_Object lib_base_name, } } +/* This function is a compatibility shim. Tree-sitter 0.25 introduced + ts_language_abi_version as a replacement for ts_language_version, and + tree-sitter 0.26 removed ts_language_version. Here we use the fact + that 0.25 bumped TREE_SITTER_LANGUAGE_VERSION to 15, to use the new + function instead of the old one, when Emacs is compiled against + tree-sitter version 0.25 or newer. */ +static uint32_t +treesit_language_abi_version (const TSLanguage *ts_lang) +{ +#if TREE_SITTER_LANGUAGE_VERSION >= 15 + return ts_language_abi_version (ts_lang); +#else + return ts_language_version (ts_lang); +#endif +} + /* Load the dynamic library of LANGUAGE_SYMBOL and return the pointer to the language definition. @@ -832,7 +864,7 @@ treesit_load_language (Lisp_Object language_symbol, build_string ("%s's ABI version is %d, but supported versions are %d-%d"); Lisp_Object formatted_msg = CALLN (Fformat_message, fmt, loaded_lib, - make_fixnum (ts_language_version (lang)), + make_fixnum (treesit_language_abi_version (lang)), make_fixnum (TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION), make_fixnum (TREE_SITTER_LANGUAGE_VERSION)); *signal_symbol = Qtreesit_load_language_error; @@ -914,7 +946,7 @@ Return nil if a grammar library for LANGUAGE is not available. */) TSLanguage *ts_language = lang.lang; if (ts_language == NULL) return Qnil; - uint32_t version = ts_language_version (ts_language); + uint32_t version = treesit_language_abi_version (ts_language); return make_fixnum((ptrdiff_t) version); } } commit bd0a141d094315663731420043936293f566f510 Author: Eli Zaretskii Date: Fri Oct 17 13:41:15 2025 +0300 ; * doc/lispref/windows.texi (Window Hooks): Fix markup. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 893726d30da..e042418634d 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -7426,20 +7426,23 @@ temporarily current. If you are using the buffer-local version of this hook, you may want to discern the case where the buffer was removed from a window from the -case where the buffer is now shown in that window. Let @code{window} -denote the window argument passed to a function on this hook: To detect -the case where the buffer was removed from @code{window} use the idiom +case where the buffer is now shown in that window. If @var{window} +denotes the window argument passed to a function on this hook, then to +detect the case where the buffer was removed from @var{window} use the +idiom @example -(eq (window-old-buffer window) (current-buffer)) +(eq (window-old-buffer @var{window}) (current-buffer)) @end example -while to detect whether the buffer is now shown in @code{window} use +@noindent +while to detect whether the buffer is now shown in @var{window} use @example -(eq (window-buffer window) (current-buffer)) +(eq (window-buffer @var{window}) (current-buffer)) @end example +@noindent instead. Functions specified by the default value are called for a frame if at commit 3fd24aee7e593ad37f9cd8ca59964a9db2c4fb44 Author: Martin Rudalics Date: Fri Oct 17 10:24:53 2025 +0200 Clarify buffer-local behavior of 'window-buffer-change-functions' * doc/lispref/windows.texi (Window Hooks): Explain how to discern calls for 'window-buffer-change-functions' where a buffer was removed from the window from those where a buffer is now shown in that window. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 48f1b878bfd..893726d30da 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -7424,6 +7424,24 @@ once for the buffer currently shown in the window. In either case the window is passed as argument and the respective buffer is made temporarily current. +If you are using the buffer-local version of this hook, you may want to +discern the case where the buffer was removed from a window from the +case where the buffer is now shown in that window. Let @code{window} +denote the window argument passed to a function on this hook: To detect +the case where the buffer was removed from @code{window} use the idiom + +@example +(eq (window-old-buffer window) (current-buffer)) +@end example + +while to detect whether the buffer is now shown in @code{window} use + +@example +(eq (window-buffer window) (current-buffer)) +@end example + +instead. + Functions specified by the default value are called for a frame if at least one window on that frame has been added, deleted or assigned another buffer since the last time window change functions were run. commit 3e78f6487d86d14340686942480202161f703e40 Author: Helmut Eller Date: Thu Oct 16 20:24:43 2025 +0200 Add some tests for weak hashtables Also add ft- as shorthand for fns-tests-. * test/src/fns-tests.el (ft-hash-table-weakness, ft-weak-key-removal) (ft-weak-value-removal, ft-weak-and-removal, ft-weak-or-removal): New tests. (ft--test-weak-removal, ft--gc, ft--check-entries, ft--check-entry) (ft--hash-table-entries, ft--populate-hashtable, ft--component-num) (ft--parse-component, ft--dead-component, ft--format-component) (ft--init-rng, ft--nentries): New helpers. diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 6f0155cd5df..e0467c0b871 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -1209,6 +1209,129 @@ (should-not (eq h1 h2)) (should (equal (gethash 'foo h2) '(bar baz))))) +(ert-deftest ft-hash-table-weakness () + (dolist (w '(nil key value key-or-value key-and-value t)) + (let* ((h (make-hash-table :weakness w)) + (w2 (hash-table-weakness h))) + (cond ((eq w t) + (should (eq w2 'key-and-value))) + (t + (should (eq w2 w))))))) + + +;;; Weak hashtable tests + +(defun ft--init-rng () (random "weak-hashtable-tests")) +(defun ft--nentries () 50) + +(defun ft--format-component (num key? dead?) + (format "%02d-%s-%s" num (if key? "key" "val") (if dead? "dead" "alive"))) + +(defun ft--parse-component (string) + (or (string-match "^\\([0-9]+\\)-\\(key\\|val\\)-\\(dead\\|alive\\)$" + string) + (error "Invalid argument: %S" string)) + (vector (string-to-number (match-string 1 string)) + (equal (match-string 2 string) "key") + (equal (match-string 3 string) "dead"))) + +(defun ft--component-num (string) (aref (ft--parse-component string) 0)) + +(defun ft--dead-component (string key?) + (ft--format-component (ft--component-num string) key? t)) + +;; Create NENTRIES pairs of strings and put them into TABLE. Randomly +;; select a subset of the strings as "dead". Return the list of pairs +;; where the "dead" strings are replaced the with nil. +(defun ft--populate-hashtable (table nentries) + (let ((pairs '())) + (dotimes (i nentries) + (let* ((r (random 4)) + (key (cl-ecase r + ((0 2) (ft--format-component i t nil)) + ((1 3) (ft--format-component i t t)))) + (val (cl-ecase r + ((0 1) (ft--format-component i nil nil)) + ((2 3) (ft--format-component i nil t))))) + (puthash key val table) + (cl-ecase r + (0 (push (cons key val) pairs)) + (1 (push (cons nil val) pairs)) + (2 (push (cons key nil) pairs)) + (3 )))) + (nreverse pairs))) + +(defun ft--hash-table-entries (table) + (let ((entries '())) + (maphash (lambda (k v) (push (cons k v) entries)) + table) + entries)) + +(defun ft--check-entry (weakness key1 val1 key2 val2) + (cl-ecase weakness + (key + (should (eq key1 key2)) + (cond (val1 (should (eq val1 val2))) + (t (should (equal (ft--dead-component key1 nil) + val2))))) + (value + (should (eq val1 val2)) + (cond (key1 (should (eq key1 key2))) + (t (should (equal (ft--dead-component val1 t) + key2))))) + (key-and-value + (should (eq key1 key2)) + (should (eq val1 val2))) + (key-or-value + (cond (key1 (should (eq key1 key2))) + (t (should (equal (ft--dead-component val1 t) + key2)))) + (cond (val1 (should (eq val1 val2))) + (t (should (equal (ft--dead-component key1 nil) + val2))))))) + +(defun ft--check-entries (table pairs) + (let* ((w (hash-table-weakness table)) + (expected (cl-ecase w + (key (cl-remove nil pairs :key #'car)) + (value (cl-remove nil pairs :key #'cdr)) + (key-and-value + (cl-remove-if (lambda (e) + (not (and (car e) (cdr e)))) + pairs)) + (key-or-value + (cl-remove-if (lambda (e) + (not (or (car e) (cdr e)))) + pairs)))) + (actual (sort (ft--hash-table-entries table) + :key #'car :lessp #'string<))) + (cl-loop for (k1 . v1) in expected + for (k2 . v2) in actual + do (ft--check-entry w k1 v1 k2 v2)) + (should (= (length expected) (length actual))))) + +(defun ft--gc () (garbage-collect)) + +;; Test that weakly held objects are no longer in a hash table after a +;; GC cycle. +(defun ft--test-weak-removal (weakness) + ;; Use a separate thread to avoid stray references on the stack. + (unless (featurep 'threads) + (ert-skip '(not (featurep 'threads)))) + (let* ((_ (ft--init-rng)) + (table (make-hash-table :weakness weakness)) + (f (lambda () (ft--populate-hashtable table (ft--nentries)))) + (pairs (thread-join (make-thread f)))) + (ft--gc) + (ft--check-entries table pairs))) + +(ert-deftest ft-weak-key-removal () (ft--test-weak-removal 'key)) +(ert-deftest ft-weak-value-removal () (ft--test-weak-removal 'value)) +(ert-deftest ft-weak-and-removal () (ft--test-weak-removal 'key-and-value)) +(ert-deftest ft-weak-or-removal () (ft--test-weak-removal 'key-or-value)) + + + (ert-deftest test-hash-function-that-mutates-hash-table () (define-hash-table-test 'badeq 'eq 'bad-hash) (let ((h (make-hash-table :test 'badeq :size 1 :rehash-size 1))) @@ -1893,4 +2016,8 @@ ;; Undo the flip. (aset b i val))))))))))) +;; Local Variables: +;; read-symbol-shorthands: (("ft-" . "fns-tests-")) +;; End: + ;;; fns-tests.el ends here commit 90ec5ef01bb227ec69f4d41f9554ee0cde8421fb Author: Stephen Gildea Date: Thu Oct 16 17:29:01 2025 -0700 Manual pages: use a showcase time-stamp-pattern * doc/man/ebrowse.1: * doc/man/emacs.1.in: * doc/man/emacsclient.1: * doc/man/etags.1: Loosen the time-stamp-pattern used so that it is not specific to each file. These files now provide readable examples that will work with most man pages. diff --git a/doc/man/ebrowse.1 b/doc/man/ebrowse.1 index 312947c2e99..8c96088e5ae 100644 --- a/doc/man/ebrowse.1 +++ b/doc/man/ebrowse.1 @@ -101,6 +101,6 @@ in a translation approved by the Free Software Foundation. .\" Local Variables: .\" eval: (add-hook 'before-save-hook 'time-stamp nil t) -.\" time-stamp-pattern: "3/.TH EBROWSE 1 \"%Y-%02m-%02d\" \"GNU Emacs\" \"GNU\"$" +.\" time-stamp-pattern: "^\\.TH [^ ]+ [^ ]+ \"?%Y-%m-%d\\_>" .\" time-stamp-time-zone: "UTC0" .\" End: diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in index bbd8b552a9a..bd8d6ed9835 100644 --- a/doc/man/emacs.1.in +++ b/doc/man/emacs.1.in @@ -685,6 +685,6 @@ There is NO WARRANTY, to the extent permitted by law. .\" Local Variables: .\" eval: (add-hook 'before-save-hook 'time-stamp nil t) -.\" time-stamp-pattern: "3/.TH EMACS 1 \"%Y-%02m-%02d\" \"GNU Emacs @version@\" \"GNU\"$" +.\" time-stamp-pattern: "^\\.TH [^ ]+ [^ ]+ \"?%Y-%m-%d\\_>" .\" time-stamp-time-zone: "UTC0" .\" End: diff --git a/doc/man/emacsclient.1 b/doc/man/emacsclient.1 index 0174b27e3e4..0b338ae155c 100644 --- a/doc/man/emacsclient.1 +++ b/doc/man/emacsclient.1 @@ -194,6 +194,6 @@ This manual page is in the public domain. .\" Local Variables: .\" eval: (add-hook 'before-save-hook 'time-stamp nil t) -.\" time-stamp-pattern: "3/.TH EMACSCLIENT 1 \"%Y-%02m-%02d\" \"GNU Emacs\" \"GNU\"$" +.\" time-stamp-pattern: "^\\.TH [^ ]+ [^ ]+ \"?%Y-%m-%d\\_>" .\" time-stamp-time-zone: "UTC0" .\" End: diff --git a/doc/man/etags.1 b/doc/man/etags.1 index 5c416a17f43..3921a60361b 100644 --- a/doc/man/etags.1 +++ b/doc/man/etags.1 @@ -329,6 +329,6 @@ in a translation approved by the Free Software Foundation. .\" Local Variables: .\" eval: (add-hook 'before-save-hook 'time-stamp nil t) -.\" time-stamp-pattern: "3/.TH ETAGS 1 \"%Y-%02m-%02d\" \"GNU Tools\" \"GNU\"$" +.\" time-stamp-pattern: "^\\.TH [^ ]+ [^ ]+ \"?%Y-%m-%d\\_>" .\" time-stamp-time-zone: "UTC0" .\" End: commit d208502e4c83b2509be84f334f4d3bc11aecbf7c Author: Stephen Gildea Date: Thu Oct 16 15:22:36 2025 -0700 time-stamp: padding composed characters * lisp/time-stamp.el (time-stamp-string-preprocess): Use 'string-width' instead of 'length' to calculate needed padding. Thanks to Stefan Monnier for the suggestion. diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index 1280c86bcbe..2a6079a9fa2 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -779,7 +779,8 @@ and all `time-stamp-format' compatibility." (format (format "%%%sd" field-width) (or field-result ""))) (let* ((field-width-num (string-to-number field-width)) - (needed-padding (- field-width-num (length field-result)))) + (needed-padding (- field-width-num + (string-width (or field-result ""))))) (if (> needed-padding 0) (concat (make-string needed-padding ?\s) field-result) field-result))) commit 888a910bc9a840ea8007abe04d610b66e8de56db Author: Eshel Yaron Date: Thu Oct 16 19:20:14 2025 +0200 ; elisp-scope.el: Standardize copyright notice. Suggested by Arash Esbati . diff --git a/lisp/emacs-lisp/elisp-scope.el b/lisp/emacs-lisp/elisp-scope.el index 7f182bc73f0..f717a5f4070 100644 --- a/lisp/emacs-lisp/elisp-scope.el +++ b/lisp/emacs-lisp/elisp-scope.el @@ -1,22 +1,24 @@ ;;; elisp-scope.el --- Semantic analysis for Elisp symbols -*- lexical-binding: t; -*- -;; Copyright (C) 2025 Free Software Foundation, Inc. +;; Copyright (C) 2025 Free Software Foundation, Inc. ;; Author: Eshel Yaron ;; Keywords: lisp, languages -;; This program is free software; you can redistribute it and/or modify +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. -;; This program is distributed in the hope that it will be useful, +;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: commit 17ac50ea9e105527753722b508ca44c58cbc892f Author: Spencer Baugh Date: Wed Sep 3 08:48:05 2025 -0400 Return case common to all completions in try-completion When completion-ignore-case is non-nil, if all completions share a common prefix ignoring case, try-completion has always returned that. Now, if all completions also share a common prefix including case, try-completion includes that common prefix in its return value (bug#79377). * lisp/minibuffer.el (completion-pcm--merge-completions): Always use return value from try-completion, which may change case. * src/minibuf.c (Ftry_completion): Return the common prefix which changes case. * test/lisp/minibuffer-tests.el (completion-pcm-bug4219) (completion-substring-test-5): New tests. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index edc8e87fec0..4e4622fa7f9 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -4763,7 +4763,7 @@ the same set of elements." ;; `prefix' only wants to include the fixed part before the ;; wildcard, not the result of growing that fixed part. (when (seq-some (lambda (elem) (eq elem 'prefix)) wildcards) - (setq prefix fixed)) + (setq prefix (substring prefix 0 (length fixed)))) (push prefix res) ;; Push all the wildcards in this stretch, to preserve `point' and ;; `star' wildcards before ELEM. diff --git a/src/minibuf.c b/src/minibuf.c index 6d96160a851..53bc905af6f 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1820,12 +1820,6 @@ or from one of the possible completions. */) if (NILP (bestmatch)) return Qnil; /* No completions found. */ - /* If we are ignoring case, and there is no exact match, - and no additional text was supplied, - don't change the case of what the user typed. */ - if (completion_ignore_case && bestmatchsize == SCHARS (string) - && SCHARS (bestmatch) > bestmatchsize) - return string; /* Return t if the supplied string is an exact match (counting case); it does not require any change to be made. */ diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el index 03e8ea24018..c7b24a4928d 100644 --- a/test/lisp/minibuffer-tests.el +++ b/test/lisp/minibuffer-tests.el @@ -345,7 +345,34 @@ (should (equal (let ((completion-ignore-case t)) (completion-pcm-try-completion "a" '("ABC" "ABD") nil 1)) - '("AB" . 2)))) + '("AB" . 2))) + ;; Even when the text isn't growing. + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm-try-completion "ab" '("ABC" "ABD") nil 2)) + '("AB" . 2))) + ;; Or when point is in the middle of the region changing case. + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm-try-completion "ab" '("ABC" "ABD") nil 1)) + '("AB" . 2))) + ;; Even when the existing minibuffer contents has mixed case. + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm-try-completion "Ab" '("ABC" "ABD") nil 1)) + '("AB" . 2))) + ;; But not if the completions don't actually all have the same case. + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm-try-completion "Ab" '("abc" "ABD") nil 1)) + '("Ab" . 2))) + ;; We don't change case if it doesn't match all of the completions, though. + (should (equal + (let ((completion-ignore-case t)) (try-completion "a" '("ax" "Ay"))) + "a")) + (should (equal + (let ((completion-ignore-case t)) (try-completion "a" '("Ay" "ax"))) + "a"))) (ert-deftest completion-substring-test-1 () ;; One third of a match! @@ -409,6 +436,15 @@ (should (equal (completion-pcm--merge-try '("a" prefix "b") '("axb" "ayb") "" "") '("ab" . 2))) + ;; Letter-casing from the completions on the common prefix is still applied. + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm--merge-try '("a" prefix "b") '("Axb" "Ayb") "" "")) + '("Ab" . 2))) + (should (equal + (let ((completion-ignore-case t)) + (completion-pcm--merge-try '("a" prefix "b") '("AAxb" "AAyb") "" "")) + '("Ab" . 2))) ;; substring completion should successfully complete the entire string (should (equal (completion-substring-try-completion "b" '("ab" "ab") nil 0) commit b0078bfa15029a2072bd762e32f472031700fe18 Author: Juri Linkov Date: Thu Oct 16 20:05:41 2025 +0300 Improve color contrast of refine-related diff faces on dark backgrounds * lisp/vc/diff-mode.el (diff-refine-removed, diff-refine-added): * lisp/vc/ediff-init.el (ediff-fine-diff-A, ediff-fine-diff-B): * lisp/vc/smerge-mode.el (smerge-refined-removed, smerge-refined-added): Lower the dominant component of RGB colors from "aa" to "88" (bug#79633). diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 2fb552597fd..c6c6233485f 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2471,7 +2471,7 @@ With non-nil prefix arg, re-diff all the hunks." (((class color) (min-colors 88) (background light)) :background "#ffbbbb") (((class color) (min-colors 88) (background dark)) - :background "#aa2222")) + :background "#882222")) "Face used for removed characters shown by `diff-refine-hunk'." :version "24.3") @@ -2483,7 +2483,7 @@ With non-nil prefix arg, re-diff all the hunks." (((class color) (min-colors 88) (background light)) :background "#aaffaa") (((class color) (min-colors 88) (background dark)) - :background "#22aa22")) + :background "#228822")) "Face used for added characters shown by `diff-refine-hunk'." :version "24.3") diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el index 12b94e81489..7254b32e41e 100644 --- a/lisp/vc/ediff-init.el +++ b/lisp/vc/ediff-init.el @@ -856,7 +856,7 @@ this variable represents.") '((((class color) (min-colors 88) (background light)) :background "#ffbbbb") (((class color) (min-colors 88) (background dark)) - :background "#aa2222") + :background "#882222") (((class color) (min-colors 16)) (:foreground "Navy" :background "sky blue")) (((class color)) @@ -876,7 +876,7 @@ this variable represents.") '((((class color) (min-colors 88) (background light)) :background "#aaffaa") (((class color) (min-colors 88) (background dark)) - :background "#22aa22") + :background "#228822") (((class color) (min-colors 16)) (:foreground "Black" :background "cyan")) (((class color)) diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el index 0a9e07cf78b..173b67e1983 100644 --- a/lisp/vc/smerge-mode.el +++ b/lisp/vc/smerge-mode.el @@ -126,7 +126,7 @@ Used in `smerge-diff-base-upper' and related functions." (((class color) (min-colors 88) (background light)) :background "#ffbbbb") (((class color) (min-colors 88) (background dark)) - :background "#aa2222") + :background "#882222") (t :inverse-video t)) "Face used for removed characters shown by `smerge-refine'." :version "24.3") @@ -137,7 +137,7 @@ Used in `smerge-diff-base-upper' and related functions." (((class color) (min-colors 88) (background light)) :background "#aaffaa") (((class color) (min-colors 88) (background dark)) - :background "#22aa22") + :background "#228822") (t :inverse-video t)) "Face used for added characters shown by `smerge-refine'." :version "24.3") commit bbbad934981cb9b8bf840c6c16301f8091363e70 Author: Juri Linkov Date: Thu Oct 16 19:40:21 2025 +0300 * lisp/treesit.el: Small fixes in navigation functions. (treesit-up-list): Better handle multi-language buffers. (treesit-hs-find-next-block): Fix off-by-one error. diff --git a/lisp/treesit.el b/lisp/treesit.el index 36d6c875d45..69abe869cd8 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -3209,6 +3209,10 @@ ARG is described in the docstring of `up-list'." (or (when (and (null (or treesit-sexp-thing-up-list treesit-sexp-thing)) default-pos + ;; The default function returns wrong results + ;; when crossing multi-language boundaries: + (eq (treesit-language-at default-pos) + (treesit-language-at (point))) (or (null parent) (if (> arg 0) (<= default-pos (treesit-node-end parent)) @@ -4207,7 +4211,7 @@ For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in (comment-p (and comment-thing (eq beg (treesit-node-start comment-thing)))) (thing (if comment-p comment-thing list-thing)) (end (if thing (min (1+ (treesit-node-start thing)) (point-max))))) - (when (and end (< end maxp)) + (when (and end (<= end maxp)) (goto-char end) (set-match-data (if (and comments comment-p) commit 208241aa83820ce154b918ccb1044838f4fe6fbf Author: Sean Whitton Date: Thu Oct 16 17:19:43 2025 +0100 Update VC-Dir contents upon revert-buffer * lisp/vc/vc-hooks.el (vc-after-revert): New function. (after-revert-hook): Add it. diff --git a/lisp/files.el b/lisp/files.el index 114ff9edaa8..0017d7bf87b 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7212,23 +7212,24 @@ preserve markers and overlays, at the price of being slower." The arguments IGNORE-AUTO and NOCONFIRM are as described for `revert-buffer'. Runs the hooks `before-revert-hook' and `after-revert-hook' at the start and end. -The function returns non-nil if it reverts the buffer; signals -an error if the buffer is not associated with a file. +The function returns non-nil if it reverts the buffer, and signals an +error if the buffer is not associated with a file. Calls `revert-buffer-insert-file-contents-function' to reread the contents of the visited file, with two arguments: the first is the file name, the second is non-nil if reading an auto-save file. This function handles only buffers that are visiting files. -Non-file buffers need a custom function." +Non-file buffers need a custom `revert-buffer-function'; see +`revert-buffer'." (with-current-buffer (or (buffer-base-buffer (current-buffer)) (current-buffer)) (let* ((auto-save-p (and (not ignore-auto) (recent-auto-save-p) buffer-auto-save-file-name (file-readable-p buffer-auto-save-file-name) - (y-or-n-p - "Buffer has been auto-saved recently. Revert from auto-save file? "))) + (y-or-n-p "Buffer has been auto-saved recently. \ +Revert from auto-save file? "))) (file-name (if auto-save-p buffer-auto-save-file-name buffer-file-name))) @@ -7254,8 +7255,8 @@ Non-file buffers need a custom function." ;; Effectively copy the after-revert-hook status, ;; since after-find-file will clobber it. (let ((global-hook (default-value 'after-revert-hook)) - (local-hook (when (local-variable-p 'after-revert-hook) - after-revert-hook)) + (local-hook (and (local-variable-p 'after-revert-hook) + after-revert-hook)) (inhibit-read-only t)) ;; FIXME: Throw away undo-log when preserve-modes is nil? (funcall @@ -7270,8 +7271,7 @@ Non-file buffers need a custom function." ;; Run after-revert-hook as it was before we reverted. (setq-default revert-buffer-internal-hook global-hook) (if local-hook - (setq-local revert-buffer-internal-hook - local-hook) + (setq-local revert-buffer-internal-hook local-hook) (kill-local-variable 'revert-buffer-internal-hook)) (run-hooks 'revert-buffer-internal-hook)) t))))) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 60aa0cf9927..a082270563b 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -751,6 +751,14 @@ Before doing that, check if there are any old backups and get rid of them." (when vc-dir-buffers (vc-dir-resynch-file file)))) +(defun vc-after-revert () + "Update VC-Dir contents after reverting a buffer from disk." + (when-let* (vc-dir-buffers + (backend (vc-backend buffer-file-name))) + (vc-dir-resynch-file buffer-file-name))) + +(add-hook 'after-revert-hook #'vc-after-revert) + (defvar vc-menu-entry '(menu-item "Version Control" vc-menu-map :filter vc-menu-map-filter)) commit d0d6e5ce659c00b6cb04839e13700c018200eabb Author: Sean Whitton Date: Thu Oct 16 16:56:47 2025 +0100 vc-auto-revert-mode: Fix an autoload problem * lisp/vc/vc-hooks.el (auto-revert-mode): Replace compiler declaration for this variable with a full defvar-local. diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index e03313b5730..60aa0cf9927 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -210,7 +210,10 @@ VC commands are globally reachable under the prefix \\[vc-prefix-map]: \\{vc-prefix-map}" nil) -(defvar auto-revert-mode) +;; A compiler declaration (defvar auto-revert-mode) is not enough here +;; because `define-globalized-minor-mode' wants to check the variable's +;; value before causing autorevert.el to be autoloaded. +(defvar-local auto-revert-mode nil) (define-globalized-minor-mode vc-auto-revert-mode auto-revert-mode vc-turn-on-auto-revert-mode-for-tracked-files :group 'vc commit f36ed942b1971e99ed344e3ed7501638a7cb7610 Author: Sean Whitton Date: Thu Oct 16 16:56:00 2025 +0100 autorevert: Use defvar-local for the -mode variables * lisp/autorevert.el (auto-revert-mode, auto-revert-tail-mode): Use defvar-local not defvar. New comment explaining why these duplicate definitions of the variables are present. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index ccedaa759cb..3bb40c13b4d 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -126,12 +126,16 @@ Global Auto-Revert Mode does so in all buffers." ;; Variables: -(defvar auto-revert-mode nil +;; These two variables are defined here in addition to within the +;; `define-minor-mode' forms below because the modes are mutually +;; self-referential. + +(defvar-local auto-revert-mode nil "Non-nil when Auto-Revert Mode is active. Never set this variable directly, use the command `auto-revert-mode' instead.") (put 'auto-revert-mode 'permanent-local t) -(defvar auto-revert-tail-mode nil +(defvar-local auto-revert-tail-mode nil "Non-nil when Auto-Revert Tail Mode is active. Never set this variable directly, use the command `auto-revert-tail-mode' instead.") commit 8aeb4f82d915c6f7b552347ed93ed21d93afae07 Author: Martin Rudalics Date: Thu Oct 16 10:17:29 2025 +0200 ; * lisp/minibuffer.el (minibuffer--nonselected-check): Fix typos. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 0c06760a678..edc8e87fec0 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -5655,7 +5655,7 @@ Used by `minibuffer-nonselected-mode'.") "Check if active minibuffer window is no longer selected. Use overlay to highlight its contents when another window is selected. But don't highlight when the *Completions* window is selected or the -buffer-loval value of `completion-reference-buffer' in the selected +buffer-local value of `completion-reference-buffer' in the selected window's buffer equals the buffer of the active minibuffer window." (let* ((active-minibuffer-window (active-minibuffer-window)) (active-minibuffer (when active-minibuffer-window @@ -5669,7 +5669,7 @@ window's buffer equals the buffer of the active minibuffer window." active-minibuffer)) ;; When there's no active minibuffer window or either the ;; minibuffer or the *Completions* window is selected or the - ;; buffer-loval value of 'completion-reference-buffer' in the + ;; buffer-local value of 'completion-reference-buffer' in the ;; selected window's buffer equals the buffer of the active ;; minibuffer window, remove the overlay if it exists. (when minibuffer--nonselected-overlay commit 85a9189dbba9a21b1f79e9a1b65eb82e16a60eba Author: Martin Rudalics Date: Thu Oct 16 09:59:15 2025 +0200 In 'minibuffer--nonselected-check' consult 'completion-reference-buffer' * lisp/minibuffer.el (minibuffer--nonselected-check): Don't highlight when the selected window's buffer has 'completion-reference-buffer' set. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index d92dc6615ca..0c06760a678 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -5654,17 +5654,24 @@ Used by `minibuffer-nonselected-mode'.") (defun minibuffer--nonselected-check (_frame) "Check if active minibuffer window is no longer selected. Use overlay to highlight its contents when another window is selected. -But don't highlight when the *Completions* window is selected." +But don't highlight when the *Completions* window is selected or the +buffer-loval value of `completion-reference-buffer' in the selected +window's buffer equals the buffer of the active minibuffer window." (let* ((active-minibuffer-window (active-minibuffer-window)) (active-minibuffer (when active-minibuffer-window (window-buffer active-minibuffer-window)))) (cond ((or (not active-minibuffer-window) (eq active-minibuffer-window (selected-window)) - (equal (buffer-name (window-buffer)) "*Completions*")) + (equal (buffer-name (window-buffer)) "*Completions*") + (eq (buffer-local-value + 'completion-reference-buffer (window-buffer)) + active-minibuffer)) ;; When there's no active minibuffer window or either the - ;; minibuffer or *the Completions* window is selected, remove the - ;; overlay if it exists. + ;; minibuffer or the *Completions* window is selected or the + ;; buffer-loval value of 'completion-reference-buffer' in the + ;; selected window's buffer equals the buffer of the active + ;; minibuffer window, remove the overlay if it exists. (when minibuffer--nonselected-overlay (delete-overlay minibuffer--nonselected-overlay))) ((not minibuffer--nonselected-overlay) commit 0a4503de3a5a94fda8a81c8847a5cc4bf8bbe545 Author: Juri Linkov Date: Thu Oct 16 09:43:30 2025 +0300 Check if treesit-major-mode-remap-alist is bound in ts-modes autoload forms * lisp/progmodes/c-ts-mode.el: * lisp/progmodes/cmake-ts-mode.el: * lisp/progmodes/csharp-mode.el: * lisp/progmodes/dockerfile-ts-mode.el: * lisp/progmodes/elixir-ts-mode.el: * lisp/progmodes/go-ts-mode.el: * lisp/progmodes/heex-ts-mode.el: * lisp/progmodes/java-ts-mode.el: * lisp/progmodes/js.el: * lisp/progmodes/json-ts-mode.el: * lisp/progmodes/lua-ts-mode.el: * lisp/progmodes/php-ts-mode.el: * lisp/progmodes/python.el: * lisp/progmodes/ruby-ts-mode.el: * lisp/progmodes/rust-ts-mode.el: * lisp/progmodes/sh-script.el: * lisp/progmodes/typescript-ts-mode.el: * lisp/textmodes/css-mode.el: * lisp/textmodes/markdown-ts-mode.el: * lisp/textmodes/mhtml-ts-mode.el: * lisp/textmodes/toml-ts-mode.el: * lisp/textmodes/yaml-ts-mode.el: In autoload forms replace '(treesit-available-p)' with (boundp 'treesit-major-mode-remap-alist). Calling 'treesit-available-p' in loaddefs.el is too early since the tree-sitter library might not be loaded yet. Checking if 'treesit-major-mode-remap-alist' is bound is equivalent to checking if Emacs is compiled with tree-sitter support. (bug#79622) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 20694c4abcf..e17f388216e 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -1674,8 +1674,7 @@ the code is C or C++, and based on that chooses whether to enable (funcall (major-mode-remap mode)))) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(c-mode . c-ts-mode)) (add-to-list 'treesit-major-mode-remap-alist diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index 9625b0f0330..60d03f50a12 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -284,11 +284,10 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . cmake-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(cmake-mode . cmake-ts-mode))) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 236354ece27..86b925afa7d 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -1287,8 +1287,7 @@ Key bindings: (derived-mode-add-parents 'csharp-ts-mode '(csharp-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(csharp-mode . csharp-ts-mode))) diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el index f02f97b6eb1..c2e8b1f3264 100644 --- a/lisp/progmodes/dockerfile-ts-mode.el +++ b/lisp/progmodes/dockerfile-ts-mode.el @@ -215,7 +215,7 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist ;; NOTE: We can't use `rx' here, as it breaks bootstrap. ;; (rx (or (and (or "Dockerfile" "Containerfile") @@ -225,7 +225,6 @@ is t or contains the mode name." '("\\(?:\\(?:\\(?:Contain\\|Dock\\)erfile\\)\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" . dockerfile-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(dockerfile-mode . dockerfile-ts-mode))) diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index b6828a3d09c..1b57f4bb34d 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -815,13 +815,12 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.elixir\\'" . elixir-ts-mode-maybe)) (add-to-list 'auto-mode-alist '("\\.ex\\'" . elixir-ts-mode-maybe)) (add-to-list 'auto-mode-alist '("\\.exs\\'" . elixir-ts-mode-maybe)) (add-to-list 'auto-mode-alist '("mix\\.lock" . elixir-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(elixir-mode . elixir-ts-mode))) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 91664a4de48..484c87fed9f 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -380,10 +380,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(go-mode . go-ts-mode))) @@ -658,10 +657,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(go-mod-mode . go-mod-ts-mode))) @@ -763,10 +761,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("/go\\.work\\'" . go-work-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(go-work-mode . go-work-ts-mode))) diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index e9626e32f33..2cdec337821 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -278,12 +278,11 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) ;; Both .heex and the deprecated .leex files should work ;; with the tree-sitter-heex grammar. (add-to-list 'auto-mode-alist '("\\.[hl]?eex\\'" . heex-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(heex-mode . heex-ts-mode))) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index f8c486e1bea..5e45c55f42d 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -533,8 +533,7 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'java-ts-mode '(java-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(java-mode . java-ts-mode))) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 5e54383cd9f..1a81fa6c7fa 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -4106,8 +4106,7 @@ See `treesit-thing-settings' for more information.") (derived-mode-add-parents 'js-ts-mode '(js-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(javascript-mode . js-ts-mode))) diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index a08e9a29fe8..2e823c11cee 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -182,8 +182,7 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'json-ts-mode '(json-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(js-json-mode . json-ts-mode))) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 35700255ba4..8cbd2efda70 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -773,8 +773,7 @@ Calls REPORT-FN directly." (derived-mode-add-parents 'lua-ts-mode '(lua-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(lua-mode . lua-ts-mode))) diff --git a/lisp/progmodes/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index fd5727b0f00..2c04c8cdeea 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el @@ -1994,7 +1994,7 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.\\(?:php[s345]?\\|phtml\\)\\'" . php-ts-mode-maybe)) (add-to-list @@ -2005,7 +2005,6 @@ is t or contains the mode name." 'interpreter-mode-alist (cons "php\\(?:-?[34578]\\(?:\\.[0-9]+\\)*\\)?" 'php-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(php-mode . php-ts-mode))) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f06d58a6c20..5a96972caa7 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -7442,8 +7442,7 @@ implementations: `python-mode' and `python-ts-mode'." (derived-mode-add-parents 'python-ts-mode '(python-mode))) ;;;###autoload -(when (and (fboundp 'treesit-available-p) (treesit-available-p) - (boundp 'treesit-major-mode-remap-alist)) ; Emacs 31.1 +(when (boundp 'treesit-major-mode-remap-alist) ; Emacs 31.1 (add-to-list 'treesit-major-mode-remap-alist '(python-mode . python-ts-mode))) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 742331ccddb..03ea6616ae1 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1278,8 +1278,7 @@ leading double colon is not added." (derived-mode-add-parents 'ruby-ts-mode '(ruby-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(ruby-mode . ruby-ts-mode))) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index a98d621af65..cbd489c5e2c 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -668,10 +668,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(rust-mode . rust-ts-mode))) diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 3b2601d251d..097cbaa0d6e 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -1649,8 +1649,7 @@ not written in Bash or sh." (derived-mode-add-parents 'bash-ts-mode '(sh-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(sh-mode . bash-ts-mode))) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index e83ee70d7e9..848093e7d60 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -735,10 +735,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(typescript-mode . typescript-ts-mode))) @@ -872,10 +871,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(tsx-mode . tsx-ts-mode))) diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index ffecc86cbe0..a83dc28dc15 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -1916,8 +1916,7 @@ can also be used to fill comments. (derived-mode-add-parents 'css-ts-mode '(css-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(css-mode . css-ts-mode))) diff --git a/lisp/textmodes/markdown-ts-mode.el b/lisp/textmodes/markdown-ts-mode.el index 4929f2d91ee..7e579f41628 100644 --- a/lisp/textmodes/markdown-ts-mode.el +++ b/lisp/textmodes/markdown-ts-mode.el @@ -422,10 +422,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(markdown-mode . markdown-ts-mode))) diff --git a/lisp/textmodes/mhtml-ts-mode.el b/lisp/textmodes/mhtml-ts-mode.el index 355c3201946..b97555de2fc 100644 --- a/lisp/textmodes/mhtml-ts-mode.el +++ b/lisp/textmodes/mhtml-ts-mode.el @@ -599,8 +599,7 @@ Powered by tree-sitter." (derived-mode-add-parents 'mhtml-ts-mode '(css-mode js-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(mhtml-mode . mhtml-ts-mode))) diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el index f85ded35968..f52f7de7b42 100644 --- a/lisp/textmodes/toml-ts-mode.el +++ b/lisp/textmodes/toml-ts-mode.el @@ -173,8 +173,7 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'toml-ts-mode '(toml-mode)) ;;;###autoload -(when (treesit-available-p) - (defvar treesit-major-mode-remap-alist) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(conf-toml-mode . toml-ts-mode))) diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index 61c70340f8e..c50daf8cead 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -240,10 +240,9 @@ is t or contains the mode name." (fundamental-mode))) ;;;###autoload -(when (treesit-available-p) +(when (boundp 'treesit-major-mode-remap-alist) (add-to-list 'auto-mode-alist '("\\.ya?ml\\'" . yaml-ts-mode-maybe)) ;; To be able to toggle between an external package and core ts-mode: - (defvar treesit-major-mode-remap-alist) (add-to-list 'treesit-major-mode-remap-alist '(yaml-mode . yaml-ts-mode))) commit 88c18efb3a1b9e48a5fb72b80cc7cdd5d03fa894 Author: Stephen Gildea Date: Wed Oct 15 20:42:07 2025 -0700 time-stamp: padding with mixed uni- and multibyte * lisp/time-stamp.el (time-stamp-string-preprocess): Use 'length' instead of 'format' to calculate string padding, so that we consistently count characters, not bytes. diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index faf5d51d441..1280c86bcbe 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -769,16 +769,21 @@ and all `time-stamp-format' compatibility." (eq cur-char ?X)) ;full system name, experimental (system-name)) )) - (and (numberp field-result) - (= colon-cnt 0) - (or (string-equal field-width "") - (string-equal field-width "0")) - ;; no width provided; set width for default - (setq field-width "02")) - (format (format "%%%s%c" - field-width - (if (numberp field-result) ?d ?s)) - (or field-result "")))))) ;end of handle-one-conversion + (if (numberp field-result) + (progn + (and (= colon-cnt 0) + (or (string-equal field-width "") + (string-equal field-width "0")) + ;; no width provided; set width for default + (setq field-width "02")) + (format (format "%%%sd" field-width) + (or field-result ""))) + (let* ((field-width-num (string-to-number field-width)) + (needed-padding (- field-width-num (length field-result)))) + (if (> needed-padding 0) + (concat (make-string needed-padding ?\s) field-result) + field-result))) + )))) ;end of handle-one-conversion ;; iterate over the format string (while (< ind fmt-len) (setq cur-char (aref format ind)) commit 39d711696ae61c72711789417983c43df3dc34b1 Author: Stefan Monnier Date: Wed Oct 15 16:30:59 2025 -0400 (remote-shell-program): Simplify * lisp/files.el (remote-shell-program): Don't bother looking for the full file name of the `ssh` executable, since all users end up looking it up in `load-path` anyway. diff --git a/lisp/files.el b/lisp/files.el index 98e723aa2e1..114ff9edaa8 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1445,13 +1445,9 @@ Tip: You can use this expansion of remote identifier components ;; Probably this entire variable should be obsolete now, in favor of ;; something Tramp-related (?). It is not used in many places. -;; It's not clear what the best file for this to be in is, but given -;; it uses custom-initialize-delay, it is easier if it is preloaded -;; rather than autoloaded. -(defcustom remote-shell-program (or (executable-find "ssh") "ssh") +(defcustom remote-shell-program "ssh" "Program to use to execute commands on a remote host (i.e. ssh)." - :version "29.1" - :initialize #'custom-initialize-delay + :version "31.1" :group 'environment :type 'file) commit cb4d9efbd43e4b5657926b365a325165bdcf2c8b Author: Eshel Yaron Date: Wed Oct 15 19:03:24 2025 +0200 ; elisp-scope.el: Rename some private symbols as such Also add a few missing docstrings. * lisp/emacs-lisp/elisp-scope.el (elisp-scope-symbol-role-p) (elisp-scope-read-symbol-role, elisp-scope-special-variables) (elisp-scope-let, elisp-scope-let*): Add docstring. (elisp-scope-counter, elisp-scope-callback) (elisp-scope-current-let-alist-form, elisp-scope-local-new) (elisp-scope-sym-pos, elisp-scope-sym-bare) (elisp-scope-report, elisp-scope-special-variable-p) (elisp-scope-let-1, elisp-scope-variable) (elisp-scope-binding, elisp-scope-symbol): Rename, replace 'elisp-scope-' prefix with 'elisp-scope--' to indicate that these are private. Update all references. diff --git a/lisp/emacs-lisp/elisp-scope.el b/lisp/emacs-lisp/elisp-scope.el index 5230da17cc4..7f182bc73f0 100644 --- a/lisp/emacs-lisp/elisp-scope.el +++ b/lisp/emacs-lisp/elisp-scope.el @@ -183,11 +183,14 @@ symbol role properties." ;;;###autoload (defun elisp-scope-symbol-role-p (sym) + "Check whether a symbol SYM is the name of a \"symbol role\"." (or (get sym 'elisp-scope-parent-roles) (get sym 'elisp-scope-role-properties))) (defvar elisp-scope-read-symbol-role-history nil) (defun elisp-scope-read-symbol-role (prompt &optional default) + "Prompt with PROMPT for a symbol role. +DEFAULT is the minibuffer default argument." (completing-read (format-prompt prompt default) obarray #'elisp-scope-symbol-role-p 'confirm @@ -564,7 +567,7 @@ Interactively, prompt for ROLE." :face 'elisp-completion-category-definition :help "Completion category definition") -(defvar elisp-scope-counter nil) +(defvar elisp-scope--counter nil) (defvar elisp-scope-local-bindings nil "Alist of locally bound variables. @@ -579,97 +582,102 @@ is the buffer position in which BOUND is bound, such as a surrounding "Output spec of the form currently analyzed, or nil if unknown. See `elisp-scope-1' for possible values.") -(defvar elisp-scope-callback #'ignore) +(defvar elisp-scope--callback #'ignore + "Function to call to report information about each analyzed symbol.") -(defvar elisp-scope-current-let-alist-form nil) +(defvar elisp-scope--current-let-alist-form nil) -(defsubst elisp-scope-local-new (sym pos &optional local) +(defsubst elisp-scope--local-new (sym pos &optional local) "Return new local context with SYM bound at POS. Optional argument LOCAL is a local context to extend." - (cons (cons sym (or pos (cons 'gen (incf elisp-scope-counter)))) local)) + (cons (cons sym (or pos (cons 'gen (incf elisp-scope--counter)))) local)) -(defsubst elisp-scope-sym-pos (sym) +(defsubst elisp-scope--sym-pos (sym) (when (symbol-with-pos-p sym) (symbol-with-pos-pos sym))) -(defsubst elisp-scope-sym-bare (sym) +(defsubst elisp-scope--sym-bare (sym) (cond ((symbolp sym) sym) ((symbol-with-pos-p sym) (bare-symbol sym)))) (defvar elisp-scope--quoted nil) -(defsubst elisp-scope-report (role beg len &optional id def) - (funcall elisp-scope-callback role beg len id (or def (and (numberp id) id)))) +(defsubst elisp-scope--report (role beg len &optional id def) + (funcall elisp-scope--callback role beg len id (or def (and (numberp id) id)))) -(defvar elisp-scope-special-variables nil) +(defvar elisp-scope-special-variables nil + "List of symbols that are special variables in the current analysis context.") -(defun elisp-scope-special-variable-p (sym) +(defun elisp-scope--special-variable-p (sym) + "Check whether SYM is a special variable in the current analysis context." (or (memq sym elisp-scope-special-variables) (special-variable-p sym))) -(defun elisp-scope-variable (sym beg len id) - (elisp-scope-report - (if id (if (elisp-scope-special-variable-p sym) 'shadowed-variable 'bound-variable) 'free-variable) +(defun elisp-scope--variable (sym beg len id) + (elisp-scope--report + (if id (if (elisp-scope--special-variable-p sym) 'shadowed-variable 'bound-variable) 'free-variable) beg len id)) -(defun elisp-scope-binding (sym beg len) - (elisp-scope-report - (if (elisp-scope-special-variable-p sym) 'shadowing-variable 'binding-variable) +(defun elisp-scope--binding (sym beg len) + (elisp-scope--report + (if (elisp-scope--special-variable-p sym) 'shadowing-variable 'binding-variable) beg len beg)) -(defun elisp-scope-s (sym) - (let* ((beg (elisp-scope-sym-pos sym)) - (bare (elisp-scope-sym-bare sym)) +(defun elisp-scope--symbol (sym) + (let* ((beg (elisp-scope--sym-pos sym)) + (bare (elisp-scope--sym-bare sym)) (name (symbol-name bare)) (len (length name))) (when (and beg (not (booleanp bare))) (cond - ((keywordp bare) (elisp-scope-report 'constant beg len)) - ((and elisp-scope-current-let-alist-form (= (aref name 0) ?.)) + ((keywordp bare) (elisp-scope--report 'constant beg len)) + ((and elisp-scope--current-let-alist-form (= (aref name 0) ?.)) (if (and (length> name 1) (= (aref name 1) ?.)) ;; Double dot escapes `let-alist'. (let* ((unescaped (intern (substring name 1)))) - (elisp-scope-variable unescaped beg len (alist-get unescaped elisp-scope-local-bindings))) - (elisp-scope-report 'bound-variable beg len - (list 'let-alist (car elisp-scope-current-let-alist-form) bare) - (cdr elisp-scope-current-let-alist-form)))) - (t (elisp-scope-variable bare beg len (alist-get bare elisp-scope-local-bindings))))))) + (elisp-scope--variable unescaped beg len (alist-get unescaped elisp-scope-local-bindings))) + (elisp-scope--report 'bound-variable beg len + (list 'let-alist (car elisp-scope--current-let-alist-form) bare) + (cdr elisp-scope--current-let-alist-form)))) + (t (elisp-scope--variable bare beg len (alist-get bare elisp-scope-local-bindings))))))) -(defun elisp-scope-let-1 (local bindings body) +(defun elisp-scope--let-1 (local bindings body) (if bindings (let* ((binding (ensure-list (car bindings))) (sym (car binding)) - (bare (elisp-scope-sym-bare sym)) + (bare (elisp-scope--sym-bare sym)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos sym))) - (when beg (elisp-scope-binding bare beg len)) + (beg (elisp-scope--sym-pos sym))) + (when beg (elisp-scope--binding bare beg len)) (elisp-scope-1 (cadr binding)) - (elisp-scope-let-1 (if bare (elisp-scope-local-new bare beg local) local) - (cdr bindings) body)) + (elisp-scope--let-1 (if bare (elisp-scope--local-new bare beg local) local) + (cdr bindings) body)) (let ((elisp-scope-local-bindings local)) (elisp-scope-n body elisp-scope-output-spec)))) (defun elisp-scope-let (bindings body) - (elisp-scope-let-1 elisp-scope-local-bindings bindings body)) + "Analyze BINDINGS and BODY of a `let' form (let BINDINGS . BODY)." + (elisp-scope--let-1 elisp-scope-local-bindings bindings body)) (defun elisp-scope-let* (bindings body) + "Analyze BINDINGS and BODY of a `let*' form (let* BINDINGS . BODY)." (if bindings (let* ((binding (ensure-list (car bindings))) (sym (car binding)) (bare (bare-symbol sym)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos sym))) - (when beg (elisp-scope-binding bare beg len)) + (beg (elisp-scope--sym-pos sym))) + (when beg (elisp-scope--binding bare beg len)) (elisp-scope-1 (cadr binding)) - (let ((elisp-scope-local-bindings (elisp-scope-local-new bare beg elisp-scope-local-bindings))) + (let ((elisp-scope-local-bindings (elisp-scope--local-new bare beg elisp-scope-local-bindings))) (elisp-scope-let* (cdr bindings) body))) (elisp-scope-n body elisp-scope-output-spec))) (defun elisp-scope-interactive (intr spec modes) (when (symbol-with-pos-p intr) - (elisp-scope-report 'special-form - (symbol-with-pos-pos intr) - (length (symbol-name (elisp-scope-sym-bare intr))))) + (elisp-scope--report 'special-form + (symbol-with-pos-pos intr) + (length (symbol-name (elisp-scope--sym-bare intr))))) (elisp-scope-1 spec) (mapc #'elisp-scope-major-mode-name modes)) @@ -678,16 +686,16 @@ Optional argument LOCAL is a local context to extend." (when (listp args) (dolist (arg args) (when-let* ((bare (bare-symbol arg)) - (beg (elisp-scope-sym-pos arg))) + (beg (elisp-scope--sym-pos arg))) (unless (memq bare '(&optional &rest)) - (setq l (elisp-scope-local-new bare beg l)))))) + (setq l (elisp-scope--local-new bare beg l)))))) ;; Handle docstring. (cond ((and (consp (car body)) (or (symbol-with-pos-p (caar body)) (symbolp (caar body))) (eq (bare-symbol (caar body)) :documentation)) - (elisp-scope-s (caar body)) + (elisp-scope--symbol (caar body)) (elisp-scope-1 (cadar body)) (setq body (cdr body))) ((stringp (car body)) (setq body (cdr body)))) @@ -698,24 +706,24 @@ Optional argument LOCAL is a local context to extend." (symbolp decl))) ((eq (bare-symbol decl) 'declare))) (when (symbol-with-pos-p decl) - (elisp-scope-report 'macro - (symbol-with-pos-pos decl) - (length (symbol-name (bare-symbol decl))))) + (elisp-scope--report 'macro + (symbol-with-pos-pos decl) + (length (symbol-name (bare-symbol decl))))) (dolist (spec (cdr form)) (when-let* ((head (car-safe spec)) - (bare (elisp-scope-sym-bare head))) + (bare (elisp-scope--sym-bare head))) (when (symbol-with-pos-p head) - (elisp-scope-report 'function-property-declaration - (symbol-with-pos-pos head) - (length (symbol-name bare)))) + (elisp-scope--report 'function-property-declaration + (symbol-with-pos-pos head) + (length (symbol-name bare)))) (cl-case bare (completion (elisp-scope-sharpquote (cadr spec))) (interactive-only - (when-let* ((bare (elisp-scope-sym-bare (cadr spec))) + (when-let* ((bare (elisp-scope--sym-bare (cadr spec))) ((not (eq bare t)))) (elisp-scope-sharpquote (cadr spec)))) (obsolete - (when-let* ((bare (elisp-scope-sym-bare (cadr spec)))) + (when-let* ((bare (elisp-scope--sym-bare (cadr spec)))) (elisp-scope-sharpquote (cadr spec)))) ((compiler-macro gv-expander gv-setter) ;; Use the extended lexical environment `l'. @@ -725,7 +733,7 @@ Optional argument LOCAL is a local context to extend." (interactive-args (dolist (arg-form (cdr spec)) (when-let* ((arg (car-safe arg-form))) - (let ((elisp-scope-local-bindings l)) (elisp-scope-s arg)) + (let ((elisp-scope-local-bindings l)) (elisp-scope--symbol arg)) (when (consp (cdr arg-form)) (elisp-scope-1 (cadr arg-form))))))))) (setq body (cdr body))) @@ -746,19 +754,19 @@ Optional argument LOCAL is a local context to extend." (len (length (symbol-name bare)))) (when (and beg (not (eq bare '_))) (if (memq bare '(&optional &rest)) - (elisp-scope-report 'ampersand beg len) - (elisp-scope-report 'binding-variable beg len beg))))))) + (elisp-scope--report 'ampersand beg len) + (elisp-scope--report 'binding-variable beg len beg))))))) ;; Handle BODY. (let ((elisp-scope-local-bindings l)) (elisp-scope-n body outspec)))) (defun elisp-scope-defun (name args body) - (when-let* ((beg (elisp-scope-sym-pos name)) - (bare (elisp-scope-sym-bare name))) - (elisp-scope-report + (when-let* ((beg (elisp-scope--sym-pos name)) + (bare (elisp-scope--sym-bare name))) + (elisp-scope--report (let ((tmp body)) (when (stringp (car-safe tmp)) (pop tmp)) - (when (eq 'declare (elisp-scope-sym-bare (car-safe (car-safe tmp)))) (pop tmp)) - (if (eq 'interactive (elisp-scope-sym-bare (car-safe (car-safe tmp)))) + (when (eq 'declare (elisp-scope--sym-bare (car-safe (car-safe tmp)))) (pop tmp)) + (if (eq 'interactive (elisp-scope--sym-bare (car-safe (car-safe tmp)))) 'defcmd 'defun)) beg (length (symbol-name bare)))) @@ -766,12 +774,14 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-setq (args) (elisp-scope-n args elisp-scope-output-spec)) -(defvar elisp-scope-local-definitions nil) +(defvar elisp-scope-local-definitions nil + "Alist associating (local) analyzer functions to function/macro names.") -(defmacro elisp-scope-with-local-definition (sym def &rest body) +(defmacro elisp-scope-with-local-definition (sym af &rest body) + "Execute BODY with analyzer function AF associated to function/macro SYM." (declare (indent 2) (debug t)) `(let ((elisp-scope-local-definitions - (cons (cons ,sym ,def) elisp-scope-local-definitions))) + (cons (cons ,sym ,af) elisp-scope-local-definitions))) ,@body)) (defun elisp-scope-flet (defs body outspec) @@ -779,18 +789,18 @@ Optional argument LOCAL is a local context to extend." (let* ((def (car defs)) (func (car def)) (exps (cdr def)) - (beg (elisp-scope-sym-pos func)) + (beg (elisp-scope--sym-pos func)) (bare (bare-symbol func)) (len (length (symbol-name bare)))) (when beg ;; TODO: Use a bespoke 'local-function-definition' role. - (elisp-scope-report 'function beg len beg)) + (elisp-scope--report 'function beg len beg)) (if (cdr exps) ;; def is (FUNC ARGLIST BODY...) (elisp-scope-cl-lambda (car exps) (cdr exps)) ;; def is (FUNC EXP) (elisp-scope-1 (car exps))) - (let ((pos (or beg (cons 'gen (incf elisp-scope-counter))))) + (let ((pos (or beg (cons 'gen (incf elisp-scope--counter))))) (elisp-scope-with-local-definition bare (elisp-scope--local-function-analyzer pos) (elisp-scope-flet (cdr defs) body outspec)))) @@ -799,10 +809,10 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope--local-function-analyzer (pos) (lambda (f &rest args) (when (symbol-with-pos-p f) - (elisp-scope-report 'function - (symbol-with-pos-pos f) - (length (symbol-name (bare-symbol f))) - pos)) + (elisp-scope--report 'function + (symbol-with-pos-pos f) + (length (symbol-name (bare-symbol f))) + pos)) (elisp-scope-n args))) (defun elisp-scope-labels (defs forms outspec) @@ -811,12 +821,12 @@ Optional argument LOCAL is a local context to extend." (func (car def)) (args (cadr def)) (body (cddr def)) - (beg (elisp-scope-sym-pos func)) + (beg (elisp-scope--sym-pos func)) (bare (bare-symbol func)) (len (length (symbol-name bare)))) (when beg - (elisp-scope-report 'function beg len beg)) - (let ((pos (or beg (cons 'gen (incf elisp-scope-counter))))) + (elisp-scope--report 'function beg len beg)) + (let ((pos (or beg (cons 'gen (incf elisp-scope--counter))))) (elisp-scope-with-local-definition bare (elisp-scope--local-function-analyzer pos) (elisp-scope-lambda args body) @@ -827,19 +837,19 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-block (name body) (if name - (let* ((beg (elisp-scope-sym-pos name)) + (let* ((beg (elisp-scope--sym-pos name)) (bare (bare-symbol name))) (when beg - (elisp-scope-report 'block beg (length (symbol-name bare)) beg)) - (let ((elisp-scope-block-alist (elisp-scope-local-new bare beg elisp-scope-block-alist))) + (elisp-scope--report 'block beg (length (symbol-name bare)) beg)) + (let ((elisp-scope-block-alist (elisp-scope--local-new bare beg elisp-scope-block-alist))) (elisp-scope-n body))) (elisp-scope-n body))) (defun elisp-scope-return-from (name result) (when-let* ((bare (and (symbol-with-pos-p name) (bare-symbol name))) (pos (alist-get bare elisp-scope-block-alist))) - (elisp-scope-report 'block - (symbol-with-pos-pos name) (length (symbol-name bare)) pos)) + (elisp-scope--report 'block + (symbol-with-pos-pos name) (length (symbol-name bare)) pos)) (elisp-scope-1 result)) (defvar elisp-scope-assume-func nil) @@ -857,7 +867,7 @@ Optional argument LOCAL is a local context to extend." ((consp arg) (elisp-scope-1 arg)))) (defun elisp-scope-loop-for-and (rest) - (if (eq (elisp-scope-sym-bare (car rest)) 'and) + (if (eq (elisp-scope--sym-bare (car rest)) 'and) (elisp-scope-loop-for elisp-scope-local-bindings (cadr rest) (cddr rest)) (elisp-scope-loop rest))) @@ -868,7 +878,7 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-for-to (local expr rest) (elisp-scope-1 expr) - (when-let* ((bare (elisp-scope-sym-bare (car rest))) + (when-let* ((bare (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (cond ((eq bare 'by) @@ -878,7 +888,7 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-for-from (local expr rest) (elisp-scope-1 expr) - (when-let* ((bare (elisp-scope-sym-bare (car rest))) + (when-let* ((bare (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (cond ((memq bare '(to upto downto below above)) @@ -890,7 +900,7 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-for-= (local expr rest) (elisp-scope-1 expr) - (when-let* ((bare (elisp-scope-sym-bare (car rest))) + (when-let* ((bare (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (cond ((eq bare 'then) @@ -900,15 +910,15 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-for-being-the-hash-keys-of-using (form rest) (let* ((var (cadr form)) - (bare (elisp-scope-sym-bare var)) - (beg (elisp-scope-sym-pos var))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) - (let ((elisp-scope-local-bindings (elisp-scope-local-new bare beg elisp-scope-local-bindings))) + (bare (elisp-scope--sym-bare var)) + (beg (elisp-scope--sym-pos var))) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) + (let ((elisp-scope-local-bindings (elisp-scope--local-new bare beg elisp-scope-local-bindings))) (elisp-scope-loop-for-and rest)))) (defun elisp-scope-loop-for-being-the-hash-keys-of (local expr rest) (elisp-scope-1 expr) - (when-let* ((bare (elisp-scope-sym-bare (car rest))) + (when-let* ((bare (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (let ((elisp-scope-local-bindings local)) (cond @@ -917,13 +927,13 @@ Optional argument LOCAL is a local context to extend." (t (elisp-scope-loop-for-and rest)))))) (defun elisp-scope-loop-for-being-the-hash-keys (local word rest) - (when-let* ((bare (elisp-scope-sym-bare word))) + (when-let* ((bare (elisp-scope--sym-bare word))) (cond ((eq bare 'of) (elisp-scope-loop-for-being-the-hash-keys-of local (car rest) (cdr rest)))))) (defun elisp-scope-loop-for-being-the (local word rest) - (when-let* ((bare (elisp-scope-sym-bare word))) + (when-let* ((bare (elisp-scope--sym-bare word))) (cond ((memq bare '(buffer buffers)) (let ((elisp-scope-local-bindings local)) @@ -937,7 +947,7 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-for-being (local next rest) (elisp-scope-loop-for-being-the local (car rest) - (if (memq (elisp-scope-sym-bare next) '(the each)) (cdr rest) rest))) + (if (memq (elisp-scope--sym-bare next) '(the each)) (cdr rest) rest))) (defun elisp-scope-loop-for (local vars rest) (if vars @@ -945,10 +955,10 @@ Optional argument LOCAL is a local context to extend." ;; `cl-macs-loop-destructure-cons' test in cl-macs-tests.el. (let* ((var (car (ensure-list vars))) (bare (bare-symbol var)) - (beg (elisp-scope-sym-pos var))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) - (elisp-scope-loop-for (elisp-scope-local-new bare beg local) (cdr-safe vars) rest)) - (when-let* ((bare (elisp-scope-sym-bare (car rest))) + (beg (elisp-scope--sym-pos var))) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) + (elisp-scope-loop-for (elisp-scope--local-new bare beg local) (cdr-safe vars) rest)) + (when-let* ((bare (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (cond ((memq bare '(from upfrom downfrom)) @@ -972,34 +982,34 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop-collect (expr rest) (elisp-scope-1 expr) - (let ((bw (elisp-scope-sym-bare (car rest))) + (let ((bw (elisp-scope--sym-bare (car rest))) (more (cdr rest))) (if (eq bw 'into) (let* ((var (car more)) - (bare (elisp-scope-sym-bare var)) - (beg (elisp-scope-sym-pos var))) + (bare (elisp-scope--sym-bare var)) + (beg (elisp-scope--sym-pos var))) (if (memq bare elisp-scope-loop-into-vars) (progn - (elisp-scope-s var) + (elisp-scope--symbol var) (elisp-scope-loop (cdr more))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) (let ((elisp-scope-loop-into-vars (cons bare elisp-scope-loop-into-vars)) - (elisp-scope-local-bindings (elisp-scope-local-new bare beg elisp-scope-local-bindings))) + (elisp-scope-local-bindings (elisp-scope--local-new bare beg elisp-scope-local-bindings))) (elisp-scope-loop (cdr more))))) (elisp-scope-loop rest)))) (defun elisp-scope-loop-with-and (rest) - (if (eq (elisp-scope-sym-bare (car rest)) 'and) + (if (eq (elisp-scope--sym-bare (car rest)) 'and) (elisp-scope-loop-with (cadr rest) (cddr rest)) (elisp-scope-loop rest))) (defun elisp-scope-loop-with (var rest) - (let* ((bare (elisp-scope-sym-bare var)) + (let* ((bare (elisp-scope--sym-bare var)) (beg (symbol-with-pos-pos var)) - (l (elisp-scope-local-new bare beg elisp-scope-local-bindings)) + (l (elisp-scope--local-new bare beg elisp-scope-local-bindings)) (eql (car rest))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) - (if (eq (elisp-scope-sym-bare eql) '=) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) + (if (eq (elisp-scope--sym-bare eql) '=) (let* ((val (cadr rest)) (more (cddr rest))) (elisp-scope-1 val) (let ((elisp-scope-local-bindings l)) @@ -1014,29 +1024,29 @@ Optional argument LOCAL is a local context to extend." (elisp-scope-loop rest))) (defun elisp-scope-loop-named (name rest) - (let* ((beg (elisp-scope-sym-pos name)) - (bare (elisp-scope-sym-bare name))) + (let* ((beg (elisp-scope--sym-pos name)) + (bare (elisp-scope--sym-bare name))) (when beg - (elisp-scope-report 'block beg (length (symbol-name bare)) beg)) - (let ((elisp-scope-block-alist (elisp-scope-local-new bare beg elisp-scope-block-alist))) + (elisp-scope--report 'block beg (length (symbol-name bare)) beg)) + (let ((elisp-scope-block-alist (elisp-scope--local-new bare beg elisp-scope-block-alist))) (elisp-scope-loop rest)))) (defun elisp-scope-loop-finally (next rest) - (if-let* ((bare (elisp-scope-sym-bare next))) + (if-let* ((bare (elisp-scope--sym-bare next))) (cond ((eq bare 'do) (elisp-scope-loop-do (car rest) (cdr rest))) ((eq bare 'return) (elisp-scope-1 (car rest)) (elisp-scope-loop (cdr rest)))) - (if (eq (elisp-scope-sym-bare (car-safe next)) 'return) + (if (eq (elisp-scope--sym-bare (car-safe next)) 'return) (progn (elisp-scope-1 (cadr next)) (elisp-scope-loop (cdr rest))) (elisp-scope-loop-do next rest)))) (defun elisp-scope-loop-initially (next rest) - (if (eq (elisp-scope-sym-bare next) 'do) + (if (eq (elisp-scope--sym-bare next) 'do) (elisp-scope-loop-do (car rest) (cdr rest)) (elisp-scope-loop-do next rest))) @@ -1047,7 +1057,7 @@ Optional argument LOCAL is a local context to extend." (let ((elisp-scope-loop-if-depth (1+ elisp-scope-loop-if-depth)) (elisp-scope-local-bindings ;; `if' binds `it'. - (elisp-scope-local-new 'it (elisp-scope-sym-pos keyword) elisp-scope-local-bindings))) + (elisp-scope--local-new 'it (elisp-scope--sym-pos keyword) elisp-scope-local-bindings))) (elisp-scope-loop rest))) (defun elisp-scope-loop-end (rest) @@ -1061,7 +1071,7 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-loop (forms) (when forms (let* ((kw (car forms)) - (bare (elisp-scope-sym-bare kw)) + (bare (elisp-scope--sym-bare kw)) (rest (cdr forms))) (cond ((memq bare '(for as)) @@ -1082,22 +1092,22 @@ Optional argument LOCAL is a local context to extend." ((memq bare '(and else)) (elisp-scope-loop-and rest)))))) (defun elisp-scope-named-let (name bindings body &optional outspec) - (let ((bare (elisp-scope-sym-bare name)) - (beg (elisp-scope-sym-pos name))) + (let ((bare (elisp-scope--sym-bare name)) + (beg (elisp-scope--sym-pos name))) (when beg - (elisp-scope-report 'function beg (length (symbol-name bare)) beg)) + (elisp-scope--report 'function beg (length (symbol-name bare)) beg)) (dolist (binding bindings) (let* ((sym (car (ensure-list binding))) (beg (symbol-with-pos-pos sym)) (bare (bare-symbol sym))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) (elisp-scope-1 (cadr binding)))) (let ((l elisp-scope-local-bindings)) (dolist (binding bindings) (when-let* ((sym (car (ensure-list binding))) - (bare (elisp-scope-sym-bare sym))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos sym) l)))) - (let ((pos (or beg (cons 'gen (incf elisp-scope-counter))))) + (bare (elisp-scope--sym-bare sym))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos sym) l)))) + (let ((pos (or beg (cons 'gen (incf elisp-scope--counter))))) (elisp-scope-with-local-definition bare (elisp-scope--local-function-analyzer pos) (let ((elisp-scope-local-bindings l)) (elisp-scope-n body outspec))))))) @@ -1110,11 +1120,11 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-rx-1 (regexp) (if (consp regexp) (let* ((head (car regexp)) - (bare (elisp-scope-sym-bare head))) + (bare (elisp-scope--sym-bare head))) (when (and bare (symbol-with-pos-p head)) - (elisp-scope-report 'rx-construct - (symbol-with-pos-pos head) (length (symbol-name bare)) - (alist-get bare elisp-scope-rx-alist))) + (elisp-scope--report 'rx-construct + (symbol-with-pos-pos head) (length (symbol-name bare)) + (alist-get bare elisp-scope-rx-alist))) (cond ((memq bare '(literal regex regexp eval)) (elisp-scope-1 (cadr regexp))) @@ -1129,15 +1139,15 @@ Optional argument LOCAL is a local context to extend." group-n submatch-n)) (elisp-scope-rx (cdr regexp))))) (when-let* (((symbol-with-pos-p regexp)) - (bare (elisp-scope-sym-bare regexp))) - (elisp-scope-report 'rx-construct - (symbol-with-pos-pos regexp) (length (symbol-name bare)) - (alist-get bare elisp-scope-rx-alist))))) + (bare (elisp-scope--sym-bare regexp))) + (elisp-scope--report 'rx-construct + (symbol-with-pos-pos regexp) (length (symbol-name bare)) + (alist-get bare elisp-scope-rx-alist))))) (defun elisp-scope-rx-define (name rest) - (when-let* ((bare (elisp-scope-sym-bare name))) - (elisp-scope-report 'rx-construct - (symbol-with-pos-pos name) (length (symbol-name bare)) nil)) + (when-let* ((bare (elisp-scope--sym-bare name))) + (elisp-scope--report 'rx-construct + (symbol-with-pos-pos name) (length (symbol-name bare)) nil)) (if (not (cdr rest)) (elisp-scope-rx-1 (car rest)) (let ((l elisp-scope-rx-alist) @@ -1150,23 +1160,23 @@ Optional argument LOCAL is a local context to extend." (len (length (symbol-name bare)))) (when beg (if (memq (bare-symbol arg) '(&optional &rest _)) - (elisp-scope-report 'ampersand beg len) - (elisp-scope-report 'rx-construct beg len beg)))))) + (elisp-scope--report 'ampersand beg len) + (elisp-scope--report 'rx-construct beg len beg)))))) (dolist (arg args) (when-let* ((bare (bare-symbol arg)) - (beg (elisp-scope-sym-pos arg))) + (beg (elisp-scope--sym-pos arg))) (unless (memq bare '(&optional &rest)) - (setq l (elisp-scope-local-new bare beg l))))) + (setq l (elisp-scope--local-new bare beg l))))) (let ((elisp-scope-rx-alist l)) (elisp-scope-rx-1 rx))))) (defun elisp-scope-rx-let (bindings body) (if-let* ((binding (car bindings))) (let ((name (car binding)) (rest (cdr binding))) - (when-let* ((bare (elisp-scope-sym-bare name)) + (when-let* ((bare (elisp-scope--sym-bare name)) (beg (symbol-with-pos-pos name))) - (elisp-scope-report 'rx-construct - beg (length (symbol-name bare)) beg)) + (elisp-scope--report 'rx-construct + beg (length (symbol-name bare)) beg)) (if (cdr rest) (let ((l elisp-scope-rx-alist) (args (car rest)) @@ -1178,67 +1188,67 @@ Optional argument LOCAL is a local context to extend." (len (length (symbol-name bare)))) (when beg (if (memq (bare-symbol arg) '(&optional &rest _)) - (elisp-scope-report 'ampersand beg len) - (elisp-scope-report 'rx-construct beg len beg)))))) + (elisp-scope--report 'ampersand beg len) + (elisp-scope--report 'rx-construct beg len beg)))))) (dolist (arg args) (when-let* ((bare (bare-symbol arg)) - (beg (elisp-scope-sym-pos arg))) + (beg (elisp-scope--sym-pos arg))) (unless (memq bare '(&optional &rest)) - (setq l (elisp-scope-local-new bare beg l))))) + (setq l (elisp-scope--local-new bare beg l))))) (let ((elisp-scope-rx-alist l)) (elisp-scope-rx-1 rx)) - (let ((elisp-scope-rx-alist (elisp-scope-local-new (elisp-scope-sym-bare name) - (elisp-scope-sym-pos name) - elisp-scope-rx-alist))) + (let ((elisp-scope-rx-alist (elisp-scope--local-new (elisp-scope--sym-bare name) + (elisp-scope--sym-pos name) + elisp-scope-rx-alist))) (elisp-scope-rx-let (cdr bindings) body))) (elisp-scope-rx-1 (car rest)) - (let ((elisp-scope-rx-alist (elisp-scope-local-new (elisp-scope-sym-bare name) - (elisp-scope-sym-pos name) - elisp-scope-rx-alist))) + (let ((elisp-scope-rx-alist (elisp-scope--local-new (elisp-scope--sym-bare name) + (elisp-scope--sym-pos name) + elisp-scope-rx-alist))) (elisp-scope-rx-let (cdr bindings) body)))) (elisp-scope-n body))) (defun elisp-scope-gv-define-expander (name handler) - (when-let* ((beg (elisp-scope-sym-pos name)) (bare (elisp-scope-sym-bare name))) - (elisp-scope-report 'defun beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos name)) (bare (elisp-scope--sym-bare name))) + (elisp-scope--report 'defun beg (length (symbol-name bare)))) (elisp-scope-1 handler)) (defun elisp-scope-gv-define-simple-setter (name setter rest) - (when-let* ((beg (elisp-scope-sym-pos name)) (bare (elisp-scope-sym-bare name))) - (elisp-scope-report 'defun beg (length (symbol-name bare)))) - (when-let* ((beg (elisp-scope-sym-pos setter)) (bare (elisp-scope-sym-bare setter))) - (elisp-scope-report 'function beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos name)) (bare (elisp-scope--sym-bare name))) + (elisp-scope--report 'defun beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos setter)) (bare (elisp-scope--sym-bare setter))) + (elisp-scope--report 'function beg (length (symbol-name bare)))) (elisp-scope-n rest)) (defun elisp-scope-face (face) - (if (or (elisp-scope-sym-bare face) - (keywordp (elisp-scope-sym-bare (car-safe face)))) + (if (or (elisp-scope--sym-bare face) + (keywordp (elisp-scope--sym-bare (car-safe face)))) (elisp-scope-face-1 face) (mapc #'elisp-scope-face-1 face))) (defun elisp-scope-face-1 (face) (cond ((symbol-with-pos-p face) - (when-let* ((beg (elisp-scope-sym-pos face)) (bare (elisp-scope-sym-bare face))) - (elisp-scope-report 'face beg (length (symbol-name bare))))) - ((keywordp (elisp-scope-sym-bare (car-safe face))) + (when-let* ((beg (elisp-scope--sym-pos face)) (bare (elisp-scope--sym-bare face))) + (elisp-scope--report 'face beg (length (symbol-name bare))))) + ((keywordp (elisp-scope--sym-bare (car-safe face))) (let ((l face)) (while l (let ((kw (car l)) (vl (cadr l))) (setq l (cddr l)) - (when-let* ((bare (elisp-scope-sym-bare kw)) + (when-let* ((bare (elisp-scope--sym-bare kw)) ((keywordp bare))) - (when-let* ((beg (elisp-scope-sym-pos kw)) + (when-let* ((beg (elisp-scope--sym-pos kw)) (len (length (symbol-name bare)))) - (elisp-scope-report 'constant beg len)) + (elisp-scope--report 'constant beg len)) (when (eq bare :inherit) - (when-let* ((beg (elisp-scope-sym-pos vl)) (fbare (elisp-scope-sym-bare vl))) - (elisp-scope-report 'face beg (length (symbol-name fbare)))))))))))) + (when-let* ((beg (elisp-scope--sym-pos vl)) (fbare (elisp-scope--sym-bare vl))) + (elisp-scope--report 'face beg (length (symbol-name fbare)))))))))))) (defun elisp-scope-deftype (name args body) - (when-let* ((beg (elisp-scope-sym-pos name)) (bare (elisp-scope-sym-bare name))) - (elisp-scope-report 'deftype beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos name)) (bare (elisp-scope--sym-bare name))) + (elisp-scope--report 'deftype beg (length (symbol-name bare)))) (elisp-scope-lambda args body)) (defun elisp-scope-defmethod-1 (local args body) @@ -1249,55 +1259,55 @@ Optional argument LOCAL is a local context to extend." (let* ((var (car arg)) (spec (cadr arg))) (cond - ((setq bare (elisp-scope-sym-bare var)) - (when-let* ((beg (elisp-scope-sym-pos var)) + ((setq bare (elisp-scope--sym-bare var)) + (when-let* ((beg (elisp-scope--sym-pos var)) (len (length (symbol-name bare)))) - (elisp-scope-binding bare beg len)) + (elisp-scope--binding bare beg len)) (cond ((consp spec) (let ((head (car spec)) (form (cadr spec))) - (and (eq 'eql (elisp-scope-sym-bare head)) + (and (eq 'eql (elisp-scope--sym-bare head)) (not (or (symbolp form) (symbol-with-pos-p form))) (elisp-scope-1 form)))) ((symbol-with-pos-p spec) (when-let* ((beg (symbol-with-pos-pos spec)) (bare (bare-symbol spec)) (len (length (symbol-name bare)))) - (elisp-scope-report 'type beg len)))) - (elisp-scope-defmethod-1 (elisp-scope-local-new bare (elisp-scope-sym-pos var) local) - (cdr args) body))))) - ((setq bare (elisp-scope-sym-bare arg)) + (elisp-scope--report 'type beg len)))) + (elisp-scope-defmethod-1 (elisp-scope--local-new bare (elisp-scope--sym-pos var) local) + (cdr args) body))))) + ((setq bare (elisp-scope--sym-bare arg)) (cond ((memq bare '(&optional &rest &body _)) - (when-let* ((beg (elisp-scope-sym-pos arg))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos arg))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (elisp-scope-defmethod-1 local (cdr args) body)) ((eq bare '&context) (let* ((expr-type (cadr args)) (expr (car expr-type)) (spec (cadr expr-type)) (more (cddr args))) - (when-let* ((beg (elisp-scope-sym-pos arg))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos arg))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (elisp-scope-1 expr) (cond ((consp spec) (let ((head (car spec)) (form (cadr spec))) - (and (eq 'eql (elisp-scope-sym-bare head)) + (and (eq 'eql (elisp-scope--sym-bare head)) (not (or (symbolp form) (symbol-with-pos-p form))) (elisp-scope-1 form)))) ((symbol-with-pos-p spec) (when-let* ((beg (symbol-with-pos-pos spec)) (bare (bare-symbol spec)) (len (length (symbol-name bare)))) - (elisp-scope-report 'type beg len beg)))) + (elisp-scope--report 'type beg len beg)))) (elisp-scope-defmethod-1 local more body))) (t - (when-let* ((beg (elisp-scope-sym-pos arg)) + (when-let* ((beg (elisp-scope--sym-pos arg)) (len (length (symbol-name bare)))) - (elisp-scope-binding bare beg len)) - (elisp-scope-defmethod-1 (elisp-scope-local-new bare (elisp-scope-sym-pos arg) local) - (cdr args) body)))))) + (elisp-scope--binding bare beg len)) + (elisp-scope-defmethod-1 (elisp-scope--local-new bare (elisp-scope--sym-pos arg) local) + (cdr args) body)))))) (let ((elisp-scope-local-bindings local)) (elisp-scope-n body)))) @@ -1312,24 +1322,24 @@ Optional argument LOCAL is a local context to extend." ;; (if (stringp (cadr rest)) (cddr rest) (cdr rest)))) (defun elisp-scope-defmethod (name rest) - (when-let* ((beg (elisp-scope-sym-pos name)) (bare (elisp-scope-sym-bare name))) - (elisp-scope-report 'defun beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos name)) (bare (elisp-scope--sym-bare name))) + (elisp-scope--report 'defun beg (length (symbol-name bare)))) ;; [EXTRA] - (when (eq (elisp-scope-sym-bare (car rest)) :extra) - (elisp-scope-s (car rest)) + (when (eq (elisp-scope--sym-bare (car rest)) :extra) + (elisp-scope--symbol (car rest)) (setq rest (cddr rest))) ;; [QUALIFIER] - (when (keywordp (elisp-scope-sym-bare (car rest))) - (elisp-scope-s (car rest)) + (when (keywordp (elisp-scope--sym-bare (car rest))) + (elisp-scope--symbol (car rest)) (setq rest (cdr rest))) ;; ARGUMENTS (elisp-scope-defmethod-1 elisp-scope-local-bindings (car rest) (cdr rest))) (defun elisp-scope-cl-defun (name arglist body) - (let ((beg (elisp-scope-sym-pos name)) - (bare (elisp-scope-sym-bare name))) - (when beg (elisp-scope-report 'defun beg (length (symbol-name bare)))) - (let ((elisp-scope-block-alist (elisp-scope-local-new bare beg elisp-scope-block-alist))) + (let ((beg (elisp-scope--sym-pos name)) + (bare (elisp-scope--sym-bare name))) + (when beg (elisp-scope--report 'defun beg (length (symbol-name bare)))) + (let ((elisp-scope-block-alist (elisp-scope--local-new bare beg elisp-scope-block-alist))) (elisp-scope-cl-lambda arglist body)))) (defun elisp-scope-cl-lambda (arglist body) @@ -1342,11 +1352,11 @@ Optional argument LOCAL is a local context to extend." (let ((head (car arglist))) (if (consp head) (elisp-scope-cl-lambda-1 head (cons (cdr arglist) more) body) - (let ((bare (elisp-scope-sym-bare head))) + (let ((bare (elisp-scope--sym-bare head))) (if (memq bare '(&optional &rest &body &key &aux &whole &cl-defs &cl-quote)) (progn - (when-let* ((beg (elisp-scope-sym-pos head))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos head))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (cl-case bare (&optional (elisp-scope-cl-lambda-optional (cadr arglist) (cddr arglist) more body)) (&cl-defs (elisp-scope-cl-lambda-defs (cadr arglist) (cddr arglist) more body)) @@ -1354,9 +1364,11 @@ Optional argument LOCAL is a local context to extend." (&key (elisp-scope-cl-lambda-key (cadr arglist) (cddr arglist) more body)) (&aux (elisp-scope-cl-lambda-aux (cadr arglist) (cddr arglist) more body)) (&whole (elisp-scope-cl-lambda-1 (cdr arglist) more body)))) - (when-let* ((beg (elisp-scope-sym-pos head))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (let ((elisp-scope-local-bindings (elisp-scope-local-new bare (elisp-scope-sym-pos head) elisp-scope-local-bindings))) + (when-let* ((beg (elisp-scope--sym-pos head))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (let ((elisp-scope-local-bindings + (elisp-scope--local-new bare (elisp-scope--sym-pos head) + elisp-scope-local-bindings))) (elisp-scope-cl-lambda-1 (cdr arglist) more body)))))) (elisp-scope-cl-lambda-1 (list '&rest arglist) more body))) (more (elisp-scope-cl-lambda-1 (car more) (cdr more) body)) @@ -1380,25 +1392,25 @@ Optional argument LOCAL is a local context to extend." (if (consp var) (let ((elisp-scope-local-bindings l)) (elisp-scope-cl-lambda-1 var (cons (append (when svar (list svar)) - (cons '&optional arglist)) - more) - body)) - (when-let* ((bare (elisp-scope-sym-bare svar))) - (when-let* ((beg (elisp-scope-sym-pos svar))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos svar) l))) - (when-let* ((bare (elisp-scope-sym-bare var))) - (when-let* ((beg (elisp-scope-sym-pos var))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos var) l))) + (cons '&optional arglist)) + more) + body)) + (when-let* ((bare (elisp-scope--sym-bare svar))) + (when-let* ((beg (elisp-scope--sym-pos svar))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos svar) l))) + (when-let* ((bare (elisp-scope--sym-bare var))) + (when-let* ((beg (elisp-scope--sym-pos var))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos var) l))) (cond (arglist (let ((head (car arglist))) - (if-let* ((bare (elisp-scope-sym-bare head)) + (if-let* ((bare (elisp-scope--sym-bare head)) ((memq bare '(&rest &body &key &aux)))) (progn - (when-let* ((beg (elisp-scope-sym-pos head))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos head))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (cl-case bare ((&rest &body) (let ((elisp-scope-local-bindings l)) @@ -1418,18 +1430,18 @@ Optional argument LOCAL is a local context to extend." (let* ((l elisp-scope-local-bindings)) (if (consp var) (elisp-scope-cl-lambda-1 var (cons arglist more) body) - (when-let* ((bare (elisp-scope-sym-bare var))) - (when-let* ((beg (elisp-scope-sym-pos var))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos var) l))) + (when-let* ((bare (elisp-scope--sym-bare var))) + (when-let* ((beg (elisp-scope--sym-pos var))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos var) l))) (cond (arglist (let ((head (car arglist))) - (if-let* ((bare (elisp-scope-sym-bare head)) + (if-let* ((bare (elisp-scope--sym-bare head)) ((memq bare '(&key &aux)))) (progn - (when-let* ((beg (elisp-scope-sym-pos head))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos head))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (cl-case bare (&key (let ((elisp-scope-local-bindings l)) @@ -1457,33 +1469,33 @@ Optional argument LOCAL is a local context to extend." (not (cddr var)) ;; VAR is (KEYWORD VAR) (setq var (cadr var))) - (when-let* ((bare (elisp-scope-sym-bare kw)) + (when-let* ((bare (elisp-scope--sym-bare kw)) ((keywordp bare))) - (when-let* ((beg (elisp-scope-sym-pos kw))) - (elisp-scope-report 'constant beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos svar) l))) + (when-let* ((beg (elisp-scope--sym-pos kw))) + (elisp-scope--report 'constant beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos svar) l))) (if (consp var) (let ((elisp-scope-local-bindings l)) (elisp-scope-cl-lambda-1 var (cons (append (when svar (list svar)) - (cons '&key arglist)) - more) - body)) - (when-let* ((bare (elisp-scope-sym-bare svar))) - (when-let* ((beg (elisp-scope-sym-pos svar))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos svar) l))) - (when-let* ((bare (elisp-scope-sym-bare var))) - (when-let* ((beg (elisp-scope-sym-pos var))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos var) l))) + (cons '&key arglist)) + more) + body)) + (when-let* ((bare (elisp-scope--sym-bare svar))) + (when-let* ((beg (elisp-scope--sym-pos svar))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos svar) l))) + (when-let* ((bare (elisp-scope--sym-bare var))) + (when-let* ((beg (elisp-scope--sym-pos var))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos var) l))) (cond (arglist (let ((head (car arglist))) - (if-let* ((bare (elisp-scope-sym-bare head)) + (if-let* ((bare (elisp-scope--sym-bare head)) ((memq bare '(&aux &allow-other-keys)))) (progn - (when-let* ((beg (elisp-scope-sym-pos head))) - (elisp-scope-report 'ampersand beg (length (symbol-name bare)))) + (when-let* ((beg (elisp-scope--sym-pos head))) + (elisp-scope--report 'ampersand beg (length (symbol-name bare)))) (cl-case bare (&aux (let ((elisp-scope-local-bindings l)) @@ -1507,10 +1519,10 @@ Optional argument LOCAL is a local context to extend." (if (consp var) (let ((elisp-scope-local-bindings l)) (elisp-scope-cl-lambda-1 var (cons arglist more) body)) - (when-let* ((bare (elisp-scope-sym-bare var))) - (when-let* ((beg (elisp-scope-sym-pos var))) - (elisp-scope-binding bare beg (length (symbol-name bare)))) - (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos var) l))) + (when-let* ((bare (elisp-scope--sym-bare var))) + (when-let* ((beg (elisp-scope--sym-pos var))) + (elisp-scope--binding bare beg (length (symbol-name bare)))) + (setq l (elisp-scope--local-new bare (elisp-scope--sym-pos var) l))) (let ((elisp-scope-local-bindings l)) (cond (arglist (elisp-scope-cl-lambda-aux (car arglist) (cdr arglist) more body)) @@ -1523,26 +1535,26 @@ Optional argument LOCAL is a local context to extend." (arglist (cadr b)) (mbody (cddr b))) (elisp-scope-cl-lambda arglist mbody) - (when-let* ((bare (elisp-scope-sym-bare name)) + (when-let* ((bare (elisp-scope--sym-bare name)) (len (length (symbol-name bare)))) - (let ((beg (elisp-scope-sym-pos name))) + (let ((beg (elisp-scope--sym-pos name))) ;; TODO: Use a bespoke 'local-macro-definition' role. - (when beg (elisp-scope-report 'macro beg len beg)) - (let ((pos (or beg (cons 'gen (incf elisp-scope-counter))))) + (when beg (elisp-scope--report 'macro beg len beg)) + (let ((pos (or beg (cons 'gen (incf elisp-scope--counter))))) (elisp-scope-with-local-definition bare (lambda (f &rest _) (when (symbol-with-pos-p f) - (elisp-scope-report 'macro (symbol-with-pos-pos f) len pos))) + (elisp-scope--report 'macro (symbol-with-pos-pos f) len pos))) (elisp-scope-cl-macrolet (cdr bindings) body outspec)))))) (elisp-scope-n body outspec))) (defun elisp-scope-define-minor-mode (mode _doc body) (let ((explicit-var nil) (command t)) (while-let ((kw (car-safe body)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) - (when-let* ((beg (elisp-scope-sym-pos kw))) - (elisp-scope-report 'constant beg (length (symbol-name bkw)))) + (when-let* ((beg (elisp-scope--sym-pos kw))) + (elisp-scope--report 'constant beg (length (symbol-name bkw)))) (cl-case bkw ((:init-value :keymap :after-hook :initialize) (elisp-scope-1 (cadr body))) @@ -1566,30 +1578,30 @@ Optional argument LOCAL is a local context to extend." (elisp-scope-global-minor-mode-predicate (cadr body))) ((:on :off) (let ((obod (cdr body))) - (while (and obod (not (keywordp (elisp-scope-sym-bare (car obod))))) + (while (and obod (not (keywordp (elisp-scope--sym-bare (car obod))))) (elisp-scope-1 (pop obod))) (setq body (cons bkw (cons nil obod)))))) (setq body (cddr body))) - (when-let* ((bare (elisp-scope-sym-bare mode)) (beg (elisp-scope-sym-pos mode)) + (when-let* ((bare (elisp-scope--sym-bare mode)) (beg (elisp-scope--sym-pos mode)) (typ (if command 'defcmd 'defun))) - (elisp-scope-report typ beg (length (symbol-name bare))) + (elisp-scope--report typ beg (length (symbol-name bare))) (unless explicit-var - (elisp-scope-report 'defvar beg (length (symbol-name bare))))) + (elisp-scope--report 'defvar beg (length (symbol-name bare))))) (elisp-scope-n body))) (defun elisp-scope-global-minor-mode-predicate (pred) (if (consp pred) - (if (eq 'not (elisp-scope-sym-bare (car pred))) + (if (eq 'not (elisp-scope--sym-bare (car pred))) (mapc #'elisp-scope-global-minor-mode-predicate (cdr pred)) (mapc #'elisp-scope-global-minor-mode-predicate pred)) (elisp-scope-major-mode-name pred))) (defun elisp-scope-major-mode-name (mode) - (when-let* ((beg (elisp-scope-sym-pos mode)) + (when-let* ((beg (elisp-scope--sym-pos mode)) (bare (bare-symbol mode)) ((not (booleanp bare))) (len (length (symbol-name bare)))) - (elisp-scope-report 'major-mode beg len))) + (elisp-scope--report 'major-mode beg len))) (defun elisp-scope-mode-line-construct (format) (elisp-scope-mode-line-construct-1 format)) @@ -1597,16 +1609,16 @@ Optional argument LOCAL is a local context to extend." (defun elisp-scope-mode-line-construct-1 (format) (cond ((symbol-with-pos-p format) - (elisp-scope-report 'free-variable - (symbol-with-pos-pos format) - (length (symbol-name (bare-symbol format))))) + (elisp-scope--report 'free-variable + (symbol-with-pos-pos format) + (length (symbol-name (bare-symbol format))))) ((consp format) (let ((head (car format))) (cond ((or (stringp head) (consp head) (integerp head)) (mapc #'elisp-scope-mode-line-construct-1 format)) ((or (symbolp head) (symbol-with-pos-p head)) - (elisp-scope-s head) + (elisp-scope--symbol head) (cl-case (bare-symbol head) (:eval (elisp-scope-1 (cadr format))) @@ -1656,6 +1668,8 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (defvar warning-minimum-log-level) (defmacro elisp-scope-define-analyzer (fsym args &rest body) + "Define an analyzer function for function/macro FSYM. +ARGS is the arguments list of the analyzer function, and BODY is its body." (declare (indent defun)) (let ((analyzer (intern (concat "elisp-scope--analyze-" (symbol-name fsym))))) `(progn @@ -1672,10 +1686,18 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (apply #',helper args))))) (defmacro elisp-scope-define-function-analyzer (fsym args &rest body) + "Define an analyzer function for function FSYM. +The analyzer function analyzes occurrences of FSYM as a function call, +and it analyzes the arguments in calls to FSYM by executing BODY with +ARGS bound to the analyzed arguments." (declare (indent defun)) `(elisp-scope--define-function-analyzer ,fsym ,args function ,@body)) (defmacro elisp-scope-define-macro-analyzer (fsym args &rest body) + "Define an analyzer function for macro FSYM. +The analyzer function analyzes occurrences of FSYM as a macro call, and +it analyzes the arguments in calls to FSYM by executing BODY with ARGS +bound to the analyzed arguments." (declare (indent defun)) (let ((helper (intern (concat "elisp-scope--analyze-" (symbol-name fsym) "-1")))) `(progn @@ -1685,6 +1707,10 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (apply #',helper args))))) (defmacro elisp-scope-define-special-form-analyzer (fsym args &rest body) + "Define an analyzer function for special form FSYM. +The analyzer function analyzes occurrences of FSYM as a special form, +and it analyzes the arguments in calls to FSYM by executing BODY with +ARGS bound to the analyzed arguments." (declare (indent defun)) (let ((helper (intern (concat "elisp-scope--analyze-" (symbol-name fsym) "-1")))) `(progn @@ -1694,7 +1720,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (apply #',helper args))))) (defun elisp-scope--unquote (form) - (when (memq (elisp-scope-sym-bare (car-safe form)) '(quote function \`)) + (when (memq (elisp-scope--sym-bare (car-safe form)) '(quote function \`)) (cadr form))) (elisp-scope-define-analyzer with-suppressed-warnings (f warnings &rest body) @@ -1736,7 +1762,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (cons (symbol . slot) . (plist (:type . cl-type)))))) (while-let ((kw (car-safe props)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr props) (when (eq bkw :predicate) '(symbol . defun))) @@ -1863,7 +1889,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 default) (elisp-scope-1 doc) (while-let ((kw (car-safe args)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr args) @@ -1878,7 +1904,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 members) (elisp-scope-1 doc '(symbol . defgroup)) (while-let ((kw (car-safe args)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr args) (when (eq bkw :group) '(symbol . group))) @@ -1893,7 +1919,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 spec)) (elisp-scope-1 doc) (while-let ((kw (car-safe args)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr args) (when (eq bkw :group) '(symbol . group))) @@ -1935,8 +1961,8 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 ov) (elisp-scope-1 prop) ;TODO: Recognize overlay props. (if-let* ((q (elisp-scope--unquote prop)) - ((eq (elisp-scope-sym-bare q) 'face)) - (face (elisp-scope--unquote val))) + ((eq (elisp-scope--sym-bare q) 'face)) + (face (elisp-scope--unquote val))) ;; TODO: Use `elisp-scope-1' with an appropriate outspec. (elisp-scope-face face) (elisp-scope-1 val))) @@ -2001,9 +2027,9 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 beg) (elisp-scope-1 end) (elisp-scope-1 prop) - (if-let* (((memq (elisp-scope-sym-bare (elisp-scope--unquote prop)) - '(mouse-face face))) - (q (elisp-scope--unquote val))) + (if-let* (((memq (elisp-scope--sym-bare (elisp-scope--unquote prop)) + '(mouse-face face))) + (q (elisp-scope--unquote val))) ;; TODO: Use `elisp-scope-1' with an appropriate outspec. (elisp-scope-face q) (elisp-scope-1 val)) @@ -2015,7 +2041,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 string) (while props (elisp-scope-1 (car props)) - (cl-case (elisp-scope-sym-bare (elisp-scope--unquote (car props))) + (cl-case (elisp-scope--sym-bare (elisp-scope--unquote (car props))) ((face mouse-face) (if-let* ((q (elisp-scope--unquote (cadr props)))) ;; TODO: Use `elisp-scope-1' with an appropriate outspec. @@ -2031,18 +2057,18 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 superclasses '(repeat . (symbol . type))) (elisp-scope-1 slots '(repeat - cons - (symbol . slot) - plist - (:initform . code) - (:initarg . (symbol . constant)) - (:accessor . (symbol . defun)) - (:allocation . code) - (:writer . (symbol . function)) - (:reader . (symbol . function)) - (:type . cl-type) - ;; TODO: add (:custom . custom-type) - )) + cons + (symbol . slot) + plist + (:initform . code) + (:initarg . (symbol . constant)) + (:accessor . (symbol . defun)) + (:allocation . code) + (:writer . (symbol . function)) + (:reader . (symbol . function)) + (:type . cl-type) + ;; TODO: add (:custom . custom-type) + )) (elisp-scope-1 options)) (elisp-scope-define-function-analyzer cl-struct-define @@ -2062,7 +2088,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 class '(symbol . widget-type)) (elisp-scope-1 doc) (while-let ((kw (car-safe args)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr args) @@ -2138,7 +2164,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (if-let* ((q (elisp-scope--unquote kws))) (progn (while-let ((kw (car-safe q)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (elisp-scope-1 (cadr q) (when (eq bkw :group) '(symbol . group))) @@ -2169,7 +2195,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (defun elisp-scope--easy-menu-do-define-menu (menu) (let ((items (cdr menu))) (while-let ((kw (car-safe items)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (cl-case bkw @@ -2184,7 +2210,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (let ((it (cddr (append item nil)))) (elisp-scope-1 (car it)) (while-let ((kw (car-safe it)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (cl-case bkw @@ -2207,11 +2233,11 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (if-let* ((q (elisp-scope--unquote def))) ;; TODO: Use `elisp-scope-1' with an appropriate outspec. (cond - ((eq (elisp-scope-sym-bare (car-safe q)) 'menu-item) + ((eq (elisp-scope--sym-bare (car-safe q)) 'menu-item) (let ((fn (caddr q)) (it (cdddr q))) (elisp-scope-sharpquote fn) (while-let ((kw (car-safe it)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (cl-case bkw @@ -2244,13 +2270,13 @@ property, or if the current buffer is trusted (see `trusted-content-p')." binding)) (form (when (consp binding) (if (cdr binding) (cadr binding) (car binding)))) - (bare (elisp-scope-sym-bare sym)) + (bare (elisp-scope--sym-bare sym)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos sym))) - (when beg (elisp-scope-binding bare beg len)) + (beg (elisp-scope--sym-pos sym))) + (when beg (elisp-scope--binding bare beg len)) (when form (elisp-scope-1 form)) (let ((elisp-scope-local-bindings - (elisp-scope-local-new bare beg elisp-scope-local-bindings))) + (elisp-scope--local-new bare beg elisp-scope-local-bindings))) (elisp-scope-if-let (cdr bindings) then else outspec))) (elisp-scope-1 then outspec) (elisp-scope-n else outspec))) @@ -2266,7 +2292,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-mode-line-construct name) (when (stringp (car body)) (pop body)) (while-let ((kw (car-safe body)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (cl-case bkw @@ -2282,13 +2308,13 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (if bindings (let* ((binding (ensure-list (car bindings))) (sym (car binding)) - (bare (elisp-scope-sym-bare sym)) + (bare (elisp-scope--sym-bare sym)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos sym))) - (when beg (elisp-scope-binding bare beg len)) + (beg (elisp-scope--sym-pos sym))) + (when beg (elisp-scope--binding bare beg len)) (elisp-scope-1 (cadr binding)) (elisp-scope-oclosure-lambda-1 - (if bare (elisp-scope-local-new bare beg local) local) + (if bare (elisp-scope--local-new bare beg local) local) (cdr bindings) args body)) (let ((elisp-scope-local-bindings local)) (elisp-scope-lambda args body)))) @@ -2352,22 +2378,22 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (defun elisp-scope-cl-tagbody (labels statements) (if labels (let* ((label (car labels)) - (bare (elisp-scope-sym-bare label))) - (when-let* ((beg (elisp-scope-sym-pos label))) - (elisp-scope-report 'label beg (length (symbol-name bare)) beg)) + (bare (elisp-scope--sym-bare label))) + (when-let* ((beg (elisp-scope--sym-pos label))) + (elisp-scope--report 'label beg (length (symbol-name bare)) beg)) (let ((elisp-scope-label-alist (if bare - (elisp-scope-local-new bare (elisp-scope-sym-pos label) elisp-scope-label-alist) + (elisp-scope--local-new bare (elisp-scope--sym-pos label) elisp-scope-label-alist) elisp-scope-label-alist))) (elisp-scope-cl-tagbody (cdr labels) statements))) (elisp-scope-n statements))) (elisp-scope-define-macro-analyzer go (label) ;; TODO: Change to a local macro defintion induced by `cl-tagbody'. - (when-let* ((bare (elisp-scope-sym-bare label)) + (when-let* ((bare (elisp-scope--sym-bare label)) (pos (alist-get bare elisp-scope-label-alist)) - (beg (elisp-scope-sym-pos label))) - (elisp-scope-report 'label beg (length (symbol-name bare)) pos))) + (beg (elisp-scope--sym-pos label))) + (elisp-scope--report 'label beg (length (symbol-name bare)) pos))) (elisp-scope-define-macro-analyzer rx-define (name &rest rest) (elisp-scope-rx-define name rest)) @@ -2395,8 +2421,8 @@ property, or if the current buffer is trusted (see `trusted-content-p')." ;; Unsafe macro! (let* ((bare (bare-symbol backend)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos backend))) - (when beg (elisp-scope-report 'nnoo-backend beg len)))) + (beg (elisp-scope--sym-pos backend))) + (when beg (elisp-scope--report 'nnoo-backend beg len)))) (elisp-scope-define-macro-analyzer gv-define-expander (name handler) (elisp-scope-gv-define-expander name handler)) @@ -2433,7 +2459,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-report-s name 'symbol-role-definition) (dolist (parent parents) (elisp-scope-report-s parent 'symbol-role)) (while-let ((kw (car-safe props)) - (bkw (elisp-scope-sym-bare kw)) + (bkw (elisp-scope--sym-bare kw)) ((keywordp bkw))) (elisp-scope-report-s kw 'constant) (cl-case bkw @@ -2450,9 +2476,9 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (if (or (symbol-with-pos-p place) (symbolp place)) (let* ((bare (bare-symbol place)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos place))) - (when beg (elisp-scope-binding bare beg len)) - (setq l (elisp-scope-local-new bare beg l))) + (beg (elisp-scope--sym-pos place))) + (when beg (elisp-scope--binding bare beg len)) + (setq l (elisp-scope--local-new bare beg l))) (elisp-scope-1 place)) (elisp-scope-1 (cadr binding)))) (let ((elisp-scope-local-bindings l)) (elisp-scope-n body elisp-scope-output-spec)))) @@ -2501,21 +2527,21 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-1 sequence) (let ((l elisp-scope-local-bindings)) (dolist (arg args) - (let* ((bare (elisp-scope-sym-bare arg)) + (let* ((bare (elisp-scope--sym-bare arg)) (len (length (symbol-name bare))) - (beg (elisp-scope-sym-pos arg))) + (beg (elisp-scope--sym-pos arg))) (if (eq bare '&rest) - (elisp-scope-report 'ampersand beg len) - (when beg (elisp-scope-binding bare beg len)) - (setq l (elisp-scope-local-new bare beg l))))) + (elisp-scope--report 'ampersand beg len) + (when beg (elisp-scope--binding bare beg len)) + (setq l (elisp-scope--local-new bare beg l))))) (let ((elisp-scope-local-bindings l)) (elisp-scope-n body)))) (elisp-scope-define-analyzer let-alist (f alist &rest body) (elisp-scope-report-s f 'macro) (elisp-scope-1 alist) - (let ((elisp-scope-current-let-alist-form - (cons (or (elisp-scope-sym-pos f) (cons 'gen (incf elisp-scope-counter))) - (elisp-scope-sym-pos f)))) + (let ((elisp-scope--current-let-alist-form + (cons (or (elisp-scope--sym-pos f) (cons 'gen (incf elisp-scope--counter))) + (elisp-scope--sym-pos f)))) (elisp-scope-n body))) (elisp-scope-define-macro-analyzer define-obsolete-face-alias (&optional obs cur when) @@ -2573,18 +2599,18 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (elisp-scope-define-special-form-analyzer condition-case (var bodyform &rest handlers) (let* ((bare (bare-symbol var)) (beg (when (symbol-with-pos-p var) (symbol-with-pos-pos var))) - (l (elisp-scope-local-new bare beg elisp-scope-local-bindings))) - (when beg (elisp-scope-binding bare beg (length (symbol-name bare)))) + (l (elisp-scope--local-new bare beg elisp-scope-local-bindings))) + (when beg (elisp-scope--binding bare beg (length (symbol-name bare)))) (elisp-scope-1 bodyform elisp-scope-output-spec) (dolist (handler handlers) (dolist (cond-name (ensure-list (car-safe handler))) - (when-let* ((cbeg (elisp-scope-sym-pos cond-name)) - (cbare (elisp-scope-sym-bare cond-name)) + (when-let* ((cbeg (elisp-scope--sym-pos cond-name)) + (cbare (elisp-scope--sym-bare cond-name)) (clen (length (symbol-name cbare)))) (cond ((booleanp cbare)) - ((keywordp cbare) (elisp-scope-report 'constant cbeg clen)) - (t (elisp-scope-report 'condition cbeg clen))))) + ((keywordp cbare) (elisp-scope--report 'constant cbeg clen)) + (t (elisp-scope--report 'condition cbeg clen))))) (let ((elisp-scope-local-bindings l)) (elisp-scope-n (cdr handler) elisp-scope-output-spec))))) @@ -2622,7 +2648,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (cl-defmethod elisp-scope--handle-quoted ((_spec (eql 'code)) arg) (let ((elisp-scope-local-bindings nil) - (elisp-scope-current-let-alist-form nil) + (elisp-scope--current-let-alist-form nil) (elisp-scope-local-definitions nil) (elisp-scope-block-alist nil) (elisp-scope-label-alist nil) @@ -2740,7 +2766,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (let ((res nil) (go t)) (while (and arg go) (let* ((key (car arg)) - (bkw (elisp-scope-sym-bare key)) + (bkw (elisp-scope--sym-bare key)) (val (cadr arg))) (push (if (keywordp bkw) '(symbol . constant) t) res) (push (setq go (elisp-scope--match-spec-to-arg (alist-get bkw (cdr spec) t) val)) res)) @@ -2764,7 +2790,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." (res nil) (go t) bkw) - (while (and go (keywordp (setq bkw (elisp-scope-sym-bare (car arg))))) + (while (and go (keywordp (setq bkw (elisp-scope--sym-bare (car arg))))) (push '(symbol . constant) res) (setq go (elisp-scope--match-spec-to-arg (alist-get bkw val-spec-alist t) (cadr arg))) (push go res) @@ -2802,8 +2828,8 @@ property, or if the current buffer is trusted (see `trusted-content-p')." "Report that symbol SYM has role ROLE. If SYM is not a symbol with position information, do nothing." - (when-let* ((beg (elisp-scope-sym-pos sym)) (bare (bare-symbol sym))) - (elisp-scope-report role beg (length (symbol-name bare))))) + (when-let* ((beg (elisp-scope--sym-pos sym)) (bare (bare-symbol sym))) + (elisp-scope--report role beg (length (symbol-name bare))))) (defvar-local elisp-scope-buffer-file-name nil) @@ -2858,7 +2884,7 @@ See also `elisp-scope-analyze-form' for an details about how subforms are analyzed." (cond ((consp form) - (let* ((f (car form)) (bare (elisp-scope-sym-bare f)) + (let* ((f (car form)) (bare (elisp-scope--sym-bare f)) (forms (cdr form)) (this nil)) (when bare (cond @@ -2883,7 +2909,7 @@ are analyzed." (t (elisp-scope-report-s f 'unknown) (when elisp-scope-assume-func (elisp-scope-n forms))))))) - ((symbol-with-pos-p form) (elisp-scope-s form)))) + ((symbol-with-pos-p form) (elisp-scope--symbol form)))) (defun elisp-scope-n (forms &optional outspec) "Analyze FORMS as evaluated forms. @@ -2937,8 +2963,8 @@ for the `identity' function: (lambda (fsym arg) (elisp-scope-report-s fsym \\='function) (elisp-scope-1 arg elisp-scope-output-spec))" - (let ((elisp-scope-counter 0) - (elisp-scope-callback callback) + (let ((elisp-scope--counter 0) + (elisp-scope--callback callback) (read-symbol-shorthands nil) (max-lisp-eval-depth 32768)) (elisp-scope-1 (read-positioning-symbols (or stream (current-buffer)))))) commit f37a150a5fb3be1718fedc8fdf77d624edbc4a8a Author: Stefan Monnier Date: Wed Oct 15 15:21:06 2025 -0400 doc/emacs/display.texi (Semantic Font Lock): Simplify diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index b982a39a980..3f72a9416c1 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1214,7 +1214,7 @@ visit in the future in the same session. @subsection Semantic Font Lock @cindex semantic highlighting -@dfn{Semantic highlighting} is a semi-advanced editor feature in which +@dfn{Semantic highlighting} is feature in which an editor uses some kind of semantic analysis to understand a program's source code, and communicates useful information about the meaning of different tokens to the user by highlighting these tokens according to commit b25d9d20813a22d5049adb19aea875e361ddaeae Author: Stefan Monnier Date: Wed Oct 15 14:36:04 2025 -0400 (easy-mmode--less-selective-first): Uncomment the test * test/lisp/emacs-lisp/easy-mmode-tests.el (easy-mmode--less-selective-first): Mark it as failing, instead. diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el b/test/lisp/emacs-lisp/easy-mmode-tests.el index a12b9b8adb0..2ee849f6e9d 100644 --- a/test/lisp/emacs-lisp/easy-mmode-tests.el +++ b/test/lisp/emacs-lisp/easy-mmode-tests.el @@ -131,19 +131,19 @@ after-change-major-mode-hook))) (easy-mmode--test-two-globalized-modes)) -;; FIXME: This case is broken by the introduction of the -;; MODE-suppress-set-explicitly mechanism. -;; This test should be re-enabled as part of resolving bug#79624. - -;; (ert-deftest easy-mmode--less-selective-first () -;; "Test with the less selective globalized mode going first." -;; (easy-mmode-test-globalized-mode-1 -1) -;; (easy-mmode-test-globalized-mode-2 -1) -;; (easy-mmode-test-globalized-mode-1 1) -;; (easy-mmode-test-globalized-mode-2 1) -;; (should (memq 'easy-mmode-test-globalized-mode-1-enable-in-buffer -;; (memq 'easy-mmode-test-globalized-mode-2-enable-in-buffer -;; after-change-major-mode-hook))) -;; (easy-mmode--test-two-globalized-modes)) +(ert-deftest easy-mmode--less-selective-first () + "Test with the less selective globalized mode going first." + ;; FIXME: This case is broken by the introduction of the + ;; MODE-suppress-set-explicitly mechanism. + ;; This test should be re-enabled as part of resolving bug#79624. + :expected-result :failed + (easy-mmode-test-globalized-mode-1 -1) + (easy-mmode-test-globalized-mode-2 -1) + (easy-mmode-test-globalized-mode-1 1) + (easy-mmode-test-globalized-mode-2 1) + (should (memq 'easy-mmode-test-globalized-mode-1-enable-in-buffer + (memq 'easy-mmode-test-globalized-mode-2-enable-in-buffer + after-change-major-mode-hook))) + (easy-mmode--test-two-globalized-modes)) ;;; easy-mmode-tests.el ends here commit eb9a93b22180dc29bebe4dad014b958213eb6027 Author: Juri Linkov Date: Wed Oct 15 20:14:43 2025 +0300 * lisp/minibuffer.el: Fix recent change of scrolling truncated completions (completion--lazy-insert-strings-on-scroll): Don't move to the last completion candidate since this is what happens when scrolling without truncated completions buffer (bug#79506). diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index b002087d14d..d92dc6615ca 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2346,10 +2346,7 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a (when track-eob (with-selected-window window (goto-char (point-max)) - (previous-completion 1) - (recenter -1) - (when cursor-face-highlight-mode - (redisplay--update-cursor-face-highlight window)))))) + (recenter -1))))) (remove-hook 'window-scroll-functions 'completion--lazy-insert-strings-on-scroll t)) commit c4490084fc6957c317cce5ad54f6dc23d22ae592 Author: Juri Linkov Date: Wed Oct 15 19:08:48 2025 +0300 ; * lisp/progmodes/c-ts-mode.el (c-ts-mode, c++-ts-mode): Improve docstrings. Add mentions of `treesit-enabled-modes' to the docstrings (bug#79627). diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 174eb47cb3a..20694c4abcf 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -1468,7 +1468,7 @@ To use tree-sitter C/C++ modes by default, evaluate (add-to-list \\='major-mode-remap-alist \\='(c-or-c++-mode . c-or-c++-ts-mode)) -in your init files." +in your init files, or customize `treesit-enabled-modes'." :group 'c :after-hook (c-ts-mode-set-modeline) @@ -1543,7 +1543,7 @@ To use tree-sitter C/C++ modes by default, evaluate (add-to-list \\='major-mode-remap-alist \\='(c-or-c++-mode . c-or-c++-ts-mode)) -in your init files. +in your init files, or customize `treesit-enabled-modes'. Since this mode uses a parser, unbalanced brackets might cause some breakage in indentation/fontification. Therefore, it's commit 6cb7fa36ad0a1608c81ee0b0bd8f731adcfa03e1 Author: Sean Whitton Date: Wed Oct 15 16:20:46 2025 +0100 New tests for multiple globalized minor modes * test/lisp/emacs-lisp/easy-mmode-tests.el (easy-mmode-test-mode): Mark permanent-local. (easy-mmode--test-two-globalized-modes): New function. (easy-mmode--more-selective-first) (easy-mmode--less-selective-first): New tests. diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el b/test/lisp/emacs-lisp/easy-mmode-tests.el index dc3386e0b3e..a12b9b8adb0 100644 --- a/test/lisp/emacs-lisp/easy-mmode-tests.el +++ b/test/lisp/emacs-lisp/easy-mmode-tests.el @@ -60,4 +60,90 @@ (easy-mmode-test-mode 'toggle) (should (eq easy-mmode-test-mode t)))) + +;;;; Globalized minor modes + +;; Globalized minor modes can either enable or decline to enable their +;; minor mode for a given buffer. That means you can have more than one +;; globalized version of a single minor mode, where they enable it in +;; different buffers. This combination is legitimate because globalized +;; minor modes don't ever *disable* the minor mode in a buffer, so the +;; only possibilities are that either one or more of them enable the +;; minor mode, or none of them do. +;; +;; We have had problems with a particular case of this with two +;; globalized versions of a minor mode where the buffers in which one +;; globalized mode enables the minor mode are a strict superset of the +;; buffers in which the other globalized mode enables the minor mode: +;; `magit-auto-revert-mode' enables `auto-revert-mode' for all +;; Git-managed files and `vc-auto-revert-mode' enables it for all VCS +;; managed files with any VC backend. These tests are to assert that +;; this combination still works. +;; +;; As an additional complication, `auto-revert-mode' is marked +;; permanent-local, so we involve that in the test, again to assert that +;; the combination still works. + +(put 'easy-mmode-test-mode 'permanent-local t) + +(with-suppressed-warnings ((redefine easy-mmode-test-mode--set-explicitly)) + + ;; More selective globalized major mode: like `magit-auto-revert-mode'. + (define-globalized-minor-mode easy-mmode-test-globalized-mode-1 + easy-mmode-test-mode + (lambda () + (when (string-search "both" (buffer-name)) + (easy-mmode-test-mode 1))) + :group 'test-group) + + ;; Less selective globalized major mode: like `vc-auto-revert-mode'. + (define-globalized-minor-mode easy-mmode-test-globalized-mode-2 + easy-mmode-test-mode + (lambda () + (when (string-match "both\\|only" (buffer-name)) + (easy-mmode-test-mode 1))) + :group 'test-group)) + +(defun easy-mmode--test-two-globalized-modes () + (let ((only-file (expand-file-name (make-temp-name "only") + temporary-file-directory)) + (both-file (expand-file-name (make-temp-name "both") + temporary-file-directory))) + (unwind-protect + (progn + (with-current-buffer (find-file-noselect only-file) + (should easy-mmode-test-mode)) + (with-current-buffer (find-file-noselect both-file) + (should easy-mmode-test-mode))) + (delete-file only-file) + (delete-file both-file)))) + +;; This is the case that the introduction of the +;; MODE-suppress-set-explicitly mechanism was intended to fix. +(ert-deftest easy-mmode--more-selective-first () + "Test with the more selective globalized mode going first." + (easy-mmode-test-globalized-mode-1 -1) + (easy-mmode-test-globalized-mode-2 -1) + (easy-mmode-test-globalized-mode-2 1) + (easy-mmode-test-globalized-mode-1 1) + (should (memq 'easy-mmode-test-globalized-mode-2-enable-in-buffer + (memq 'easy-mmode-test-globalized-mode-1-enable-in-buffer + after-change-major-mode-hook))) + (easy-mmode--test-two-globalized-modes)) + +;; FIXME: This case is broken by the introduction of the +;; MODE-suppress-set-explicitly mechanism. +;; This test should be re-enabled as part of resolving bug#79624. + +;; (ert-deftest easy-mmode--less-selective-first () +;; "Test with the less selective globalized mode going first." +;; (easy-mmode-test-globalized-mode-1 -1) +;; (easy-mmode-test-globalized-mode-2 -1) +;; (easy-mmode-test-globalized-mode-1 1) +;; (easy-mmode-test-globalized-mode-2 1) +;; (should (memq 'easy-mmode-test-globalized-mode-1-enable-in-buffer +;; (memq 'easy-mmode-test-globalized-mode-2-enable-in-buffer +;; after-change-major-mode-hook))) +;; (easy-mmode--test-two-globalized-modes)) + ;;; easy-mmode-tests.el ends here commit 11b7cd7ebe19aafcc5566fad224bee114925d24e Author: Stefan Monnier Date: Wed Oct 15 09:31:05 2025 -0400 (xdg-mime-apps): Restore corner case and simplify * lisp/xdg.el (xdg-mime-apps): Return nil if that's what the table holds, like we did before commit f60fc1287d49. Consolidate the three (assoc type xdg-mime-table) and shrink the scope of `files`. diff --git a/lisp/xdg.el b/lisp/xdg.el index 1e1495f8c7f..56a5efa7720 100644 --- a/lisp/xdg.el +++ b/lisp/xdg.el @@ -372,8 +372,7 @@ an absolute file name of a readable file. Results are cached in `xdg-mime-table'." (pcase-let ((`(,type ,subtype) (split-string mime "/")) (xdg-data-dirs (xdg-data-dirs)) - (caches (xdg-mime-apps-files)) - (files ())) + (caches (xdg-mime-apps-files))) (let ((mtim1 (get 'xdg-mime-table 'mtime)) (mtim2 (cl-loop for f in caches when (file-readable-p f) maximize (float-time @@ -382,21 +381,21 @@ Results are cached in `xdg-mime-table'." ;; If one of the MIME/Desktop cache files has been modified: (when (or (null mtim1) (time-less-p mtim1 mtim2)) (setq xdg-mime-table nil))) - (when (null (assoc type xdg-mime-table)) - (push (cons type (make-hash-table :test #'equal)) xdg-mime-table)) - (if (let ((table (cdr (assoc type xdg-mime-table)))) - (and (hash-table-contains-p subtype table) - (setq files (gethash subtype table)))) - files - (and files (setq files nil)) - (let ((dirs (mapcar (lambda (dir) (expand-file-name "applications" dir)) - (cons (xdg-data-home) xdg-data-dirs)))) - ;; Not being particular about desktop IDs - (dolist (f (nreverse (xdg-mime-collect-associations mime caches))) - (push (locate-file f dirs) files)) - (when files - (put 'xdg-mime-table 'mtime (current-time))) - (puthash subtype (delq nil files) (cdr (assoc type xdg-mime-table))))))) + (let ((table (cdr (or (assoc type xdg-mime-table) + (let ((p (cons type (make-hash-table :test #'equal)))) + (push p xdg-mime-table) + p))))) + (if (hash-table-contains-p subtype table) + (gethash subtype table) + (let ((files ()) + (dirs (mapcar (lambda (dir) (expand-file-name "applications" dir)) + (cons (xdg-data-home) xdg-data-dirs)))) + ;; Not being particular about desktop IDs + (dolist (f (nreverse (xdg-mime-collect-associations mime caches))) + (push (locate-file f dirs) files)) + (when files + (put 'xdg-mime-table 'mtime (current-time))) + (puthash subtype (delq nil files) table)))))) ;; Unofficial extension from systemd. commit eeaa9421479de0ceefbbb90a7b7bd750c3e00f4b Author: Eshel Yaron Date: Wed Oct 15 12:21:19 2025 +0200 ; Refine a few 'elisp-*' faces for dark backgrounds * lisp/progmodes/elisp-mode.el (elisp-major-mode-name) (elisp-symbol-role, elisp-symbol-role-definition, elisp-rx): Use a lighter foreground color when background color is dark to improve legibility. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 87c7a53b057..af7c8b96555 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -321,18 +321,26 @@ code analysis." "Face for highlighting `condition-case' conditions in Emacs Lisp code." :version "31.1") -(defface elisp-major-mode-name '((t :foreground "#006400")) +(defface elisp-major-mode-name + '((((background light)) :foreground "#006400") + (((background dark)) :foreground "#4ade80")) "Face for highlighting major mode names in Emacs Lisp code.") (defface elisp-face '((t :inherit font-lock-type-face)) "Face for highlighting face names in Emacs Lisp code." :version "31.1") -(defface elisp-symbol-role '((t :foreground "#00008b" :inherit font-lock-function-call-face)) +(defface elisp-symbol-role + '((default :inherit font-lock-function-call-face) + (((background light)) :foreground "#00008b") + (((background dark)) :foreground "#5c9cff")) "Face for highlighting symbol role names in Emacs Lisp code." :version "31.1") -(defface elisp-symbol-role-definition '((t :foreground "#00008b" :inherit font-lock-function-name-face)) +(defface elisp-symbol-role-definition + '((default :inherit font-lock-function-name-face) + (((background light)) :foreground "#00008b") + (((background dark)) :foreground "#5c9cff")) "Face for highlighting symbol role definitions in Emacs Lisp code." :version "31.1") @@ -367,7 +375,9 @@ code analysis." "Face for highlighting feature names in Emacs Lisp code." :version "31.1") -(defface elisp-rx '((t :foreground "#00008b")) +(defface elisp-rx + '((((background light)) :foreground "#00008b") + (((background dark)) :foreground "#5c9cff")) "Face for highlighting `rx' constructs in Emacs Lisp code." :version "31.1") commit 53fa2b72183e110cc6da3ce172c48e40d3fea3c7 Author: Michael Albinus Date: Wed Oct 15 10:30:29 2025 +0200 Add support for su-rs and sudo-rs programs * doc/misc/tramp.texi (Inline methods): Add "surs" and "sudors" methods. * etc/NEWS: Add optional "surs" and "sudors" Tramp methods. Presentational fixes and improvements. * lisp/net/tramp-cmds.el (tramp-file-name-with-method): Add "surs" and "sudors" to :type. Adapt :version. * lisp/net/tramp-sh.el (tramp-enable-surs-method) (tramp-enable-sudors-method): New defuns (tramp-sh-handle-expand-file-name): Add "surs" and "sudors" in check. * lisp/net/tramp.el (tramp-methods): Adapt docstring. * lisp/comint.el (comint-password-prompt-regexp): * test/lisp/comint-tests.el (comint-testsuite-password-strings): Add su-rs and sudo-rs password prompts. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 5ce41091048..7b3a4808a45 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -852,12 +852,20 @@ as the @option{rsh} method. @cindex method @option{su} @cindex @option{su} method @item @option{su} +@cindex method @option{surs} +@cindex @option{surs} method +@item @option{surs} Instead of connecting to a remote host, @command{su} program allows editing as another user. The host can be either @samp{localhost} or the host returned by the function @command{(system-name)}. @xref{Multi-hops}, for an exception to this behavior. +Method @option{surs} is the same like method @option{su}, but it uses +the modern @command{su-rs} program. It can be used instead wherever +method @option{su} is mentioned in this manual. @option{surs} is an +optional method, @pxref{Optional methods}. + @cindex method @option{androidsu} @cindex @option{androidsu} method @item @option{androidsu} @@ -876,6 +884,9 @@ default on @code{android} systems only. @cindex method @option{sudo} @cindex @option{sudo} method @item @option{sudo} +@cindex method @option{sudors} +@cindex @option{sudors} method +@item @option{sudors} Similar to @option{su} method, @option{sudo} uses @command{sudo}. @command{sudo} must have sufficient rights to start a shell. @@ -884,6 +895,11 @@ For security reasons, a @option{sudo} connection is disabled after a predefined timeout (5 minutes by default). This can be changed, @pxref{Predefined connection information}. +Method @option{sudors} is the same like method @option{sudo}, but it +uses the modern @command{sudo-rs} program. It can be used instead +wherever method @option{sudo} is mentioned in this manual. +@option{sudors} is an optional method, @pxref{Optional methods}. + @cindex method @option{doas} @cindex @option{doas} method @item @option{doas} diff --git a/etc/NEWS b/etc/NEWS index 4e27d6fc44e..0b8d624d923 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -327,13 +327,13 @@ deleted implicitly by functions like 'kill-buffer', 'bury-buffer' and +++ *** Buffer-local window change functions run in their buffers now. Running the buffer-local version of each of the abnormal hooks -'window-buffer-change-functions', 'window-size-change-functions' +'window-buffer-change-functions', 'window-size-change-functions', 'window-selection-change-functions' and 'window-state-change-functions' will make the respective buffer temporarily current for running the -hook.' +hook. +++ -*** 'window-buffer-change-functions' is run for removed buffer too. +*** 'window-buffer-change-functions' is run for removed buffers too. The buffer-local version of 'window-buffer-change-functions' may be run twice now: Once for the buffer removed from the respective window and once for the buffer now shown in that window. @@ -1882,6 +1882,11 @@ default, "sudo". +++ *** 'tramp-file-name-with-method' can now be set as connection-local variable. ++++ +*** New optional connection methods "surs" and "sudors". +These connection methods are similar to "su" and "sudo", but they use +the modern 'su-rs' and 'sudo-rs' commands. + +++ *** Connection method "kubernetes" supports now optional namespace. The host name for Kubernetes connections can be of kind @@ -3320,10 +3325,10 @@ The column number is no longer available; the line number will be removed in next Emacs release. +++ -** defvar-keymap can now take a ':prefix t' option. +** 'defvar-keymap' can now take a ':prefix t' option. This is an abbreviation for using the name of the keymap as the prefix -command name. E.g. (defvar-keymap foo-map :prefix t) is equivalent to -(defvar-keymap foo-map :prefix 'foo-map). +command name. E.g., '(defvar-keymap foo-map :prefix t)' is equivalent +to '(defvar-keymap foo-map :prefix 'foo-map)'. * Changes in Emacs 31.1 on Non-Free Operating Systems diff --git a/lisp/comint.el b/lisp/comint.el index c7315a90181..b7c609ed469 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -408,7 +408,8 @@ This variable is buffer-local." "Vault" "SSH" "BECOME" "Enter Auth" "enter auth" "Old" "old" "New" "new" "login" "Kerberos" "CVS" "UNIX" " SMB" "LDAP" "PEM" "SUDO" - "[sudo]" "doas" "Repeat" "Bad" "Retype" "Verify") + "[sudo]" "[sudo: authenticate]" "[su: authenticate]" + "doas" "Repeat" "Bad" "Retype" "Verify") t) ;; Allow for user name to precede password equivalent (Bug#31075). " +.*\\)" diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 6042209d4f0..a4f74383325 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -631,9 +631,9 @@ For details, see `tramp-rename-files'." (defcustom tramp-file-name-with-method "sudo" "Which method to be used in `tramp-file-name-with-sudo'." :group 'tramp - :version "30.1" - :type '(choice (const "su") - (const "sudo") + :version "31.1" + :type '(choice (const "su") (const "surs") + (const "sudo") (const "sudors") (const "doas") (const "run0") (const "ksu")) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 8922adb7586..98e3cae5a79 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -521,6 +521,42 @@ The string is used in `tramp-methods'.") (tramp-set-completion-function "nc" tramp-completion-function-alist-telnet)) +;;;###tramp-autoload +(defun tramp-enable-surs-method () + "Enable \"surs\" method." + (add-to-list 'tramp-methods + `("surs" + (tramp-login-program "su-rs") + (tramp-login-args (("-") ("%u"))) + (tramp-remote-shell ,tramp-default-remote-shell) + (tramp-remote-shell-login ("-l")) + (tramp-remote-shell-args ("-c")) + (tramp-connection-timeout 10))) + + (add-to-list 'tramp-default-user-alist + `(,(rx bos "surs" eos) nil ,tramp-root-id-string)) + + (tramp-set-completion-function "surs" tramp-completion-function-alist-su)) + +;;;###tramp-autoload +(defun tramp-enable-sudors-method () + "Enable \"sudors\" method." + (add-to-list 'tramp-methods + `("sudors" + (tramp-login-program "sudo-rs") + (tramp-login-args (("-u" "%u") ("-s") ("%l"))) + (tramp-remote-shell ,tramp-default-remote-shell) + (tramp-remote-shell-login ("-l")) + (tramp-remote-shell-args ("-c")) + (tramp-connection-timeout 10) + (tramp-session-timeout 300) + (tramp-password-previous-hop t))) + + (add-to-list 'tramp-default-user-alist + `(,(rx bos "sudors" eos) nil ,tramp-root-id-string)) + + (tramp-set-completion-function "sudors" tramp-completion-function-alist-su)) + ;;;###tramp-autoload (defun tramp-enable-run0-method () "Enable \"run0\" method." @@ -2964,7 +3000,10 @@ the result will be a local, non-Tramp, file name." ;; use a user name from the config file. (when (and (tramp-string-empty-or-nil-p uname) (string-match-p - (rx bos (| "su" "sudo" "doas" "run0" "ksu") eos) method)) + (rx bos + (| "su" "surs" "sudo" "sudors" "doas" "run0" "ksu") + eos) + method)) (setq uname user)) (when (setq hname (tramp-get-home-directory v uname)) (setq localname (concat hname fname))))) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 546ffa5d638..ec57aca0568 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -418,12 +418,12 @@ Notes: All these arguments can be overwritten by connection properties. See Info node `(tramp) Predefined connection information'. -When using `su', `sudo' or `doas' the phrase \"open connection to -a remote host\" sounds strange, but it is used nevertheless, for -consistency. No connection is opened to a remote host, but `su', -`sudo' or `doas' is started on the local host. You should -specify a remote host `localhost' or the name of the local host. -Another host name is useful only in combination with +When using `su', `surs', `sg', `sudo', `sudors', `doas', `run0' or `ksu' +the phrase \"open connection to a remote host\" sounds strange, but it +is used nevertheless, for consistency. No connection is opened to a +remote host, but the respective command is started on the local host. +You should specify a remote host `localhost' or the name of the local +host. Another host name is useful only in combination with `tramp-default-proxies-alist'.") (defcustom tramp-default-method @@ -5239,10 +5239,11 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") vec "Method `%s' is not supported for multi-hops" (tramp-file-name-method item))))) - ;; Some methods ("su", "sg", "sudo", "doas", "run0", "ksu") do - ;; not use the host name in their command template. In this - ;; case, the remote file name must use either a local host name - ;; (first hop), or a host name matching the previous hop. + ;; Some methods ("su", "surs", "sg", "sudo", "sudors", "doas", + ;; "run0", "ksu") do not use the host name in their command + ;; template. In this case, the remote file name must use either + ;; a local host name (first hop), or a host name matching the + ;; previous hop. (let ((previous-host (or tramp-local-host-regexp ""))) (setq choices target-alist) (while (setq item (pop choices)) diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el index d981aad7198..0ae5daa70ca 100644 --- a/test/lisp/comint-tests.el +++ b/test/lisp/comint-tests.el @@ -38,6 +38,8 @@ "Enter your password: " ; python3 -m twine ... Bug#37636 "Passphrase for key root@GNU.ORG: " ; plink "[sudo] password for user:" ; Ubuntu sudo + "[sudo: authenticate] Password:" ; sudo-rs + "[su: authenticate] Password:" ; su-rs "[sudo] user 的密码:" ; localized "doas (user@host) password:" ; OpenBSD doas "PIN for user:" ; Bug#35523 commit 7845936cbbf8c56a4d57700fbd10246b7288aa01 Author: Stefan Monnier Date: Tue Oct 14 21:51:04 2025 -0400 (font-lock-defaults): Clarify the use of SYNTAX-ALIST (bug#79586) * doc/lispref/modes.texi (Font Lock Basics): * lisp/font-core.el (font-lock-defaults): Document when SYNTAX-ALIST is used and how it interacts with syntactic fontification. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index d98d8b21807..8c8cbf32b61 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3322,12 +3322,22 @@ Font Lock mode ignores case during search-based fontification. If the fourth element, @var{syntax-alist}, is non-@code{nil}, it should be a list of cons cells of the form @code{(@var{char-or-string} -. @var{string})}. These are used to set up a syntax table for syntactic +. @var{string})}. These are used to set up a syntax table during fontification; the resulting syntax table is stored in @code{font-lock-syntax-table}. If @var{syntax-alist} is omitted or -@code{nil}, syntactic fontification uses the syntax table returned by +@code{nil}, fontification uses the syntax table returned by the @code{syntax-table} function. @xref{Syntax Table Functions}. +The most common uses of @var{syntax-alist} simply change the syntax of +a few chars from symbol constituent to word constituent so that the +fontification rules can use regexp operators based on word boundaries. +When @var{syntax-alist} describes more intrusive changes that can change +what is recognized as a string or a comment, this prevents an important +optimization in syntactic fontification, so it's better to either +refrain from using such settings or to additionally set +@code{syntax-ppss-table} to a non-@code{nil} value, which takes +precedence during syntactic fontification. + All the remaining elements (if any) are collectively called @var{other-vars}. Each of these elements should have the form @code{(@var{variable} . @var{value})}---which means, make diff --git a/lisp/font-core.el b/lisp/font-core.el index 04a2056d9f7..7c8230f54e7 100644 --- a/lisp/font-core.el +++ b/lisp/font-core.el @@ -44,8 +44,10 @@ comments) is not performed. If CASE-FOLD is non-nil, the case of the keywords is ignored when fontifying. If SYNTAX-ALIST is non-nil, it should be a list of cons pairs of the form -\(CHAR-OR-STRING . STRING) used to set the local Font Lock syntax table, for -keyword and syntactic fontification (see `modify-syntax-entry'). +\(CHAR-OR-STRING . STRING) used to modify the syntax table used during Font +Lock (see `modify-syntax-entry'). +For performance reasons, if `syntax-ppss-table' is not set, make sure the +changes described by SYNTAX-ALIST cannot affect syntactic fontification. These item elements are used by Font Lock mode to set the variables `font-lock-keywords', `font-lock-keywords-only', commit 8c19b71660e44c31b57c741a7d748ce1e80fb513 Author: Stefan Monnier Date: Tue Oct 14 11:58:08 2025 -0400 (rx): Remove the `rx--pcase-expand` middle man * lisp/emacs-lisp/rx.el (rx): Remove the `rx--pcase-expand` middle man, now that `loaddefs-gen.el` expands the `pcase-defmacro` for us. diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 58f95c7d89a..229f1dbb57b 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1685,12 +1685,6 @@ following constructs: REF can be a number, as usual, or a name introduced by a previous (let REF ...) construct." - (rx--pcase-expand regexps)) - -;; Autoloaded because it's referred to by the pcase rx macro above, -;; whose body ends up in loaddefs.el. -;;;###autoload -(defun rx--pcase-expand (regexps) (let* ((rx--pcase-vars nil) (regexp (rx--to-expr (rx--pcase-transform (cons 'seq regexps))))) `(and (pred stringp) @@ -1726,7 +1720,7 @@ following constructs: (reverse rx--pcase-vars)))))))))) ;; Obsolete internal symbol, used in old versions of the `flycheck' package. -(define-obsolete-function-alias 'rx-submatch-n 'rx-to-string "27.1") +(define-obsolete-function-alias 'rx-submatch-n #'rx-to-string "27.1") (provide 'rx) commit 171c7fd6df861ab71f6cc8faedb8ff68bfac4bae Author: Stefan Monnier Date: Tue Oct 14 11:21:29 2025 -0400 (define-minor-mode): Update `global-minor-modes` if init-value is non-nil When a global minor mode is enabled by init-value rather than by calling the major mode function, we failed to register it in `global-minor-modes` (bug#79518). * lisp/emacs-lisp/easy-mmode.el (define-minor-mode): Register ourselves in `global-minor-modes` at top-level for global modes with a non-nil init-value. Also in the `modefun`, simply the code with `not` and `add-to-list` and consolidate the local/global paths to update `*-minor-modes`. * lisp/simple.el (global-minor-modes): Move to... * lisp/subr.el (global-minor-modes): ...here so it's defined early enough for `auto-compression-mode` to register itself. diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 25e4f882295..0aa1fe2ce9d 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -332,12 +332,16 @@ for a description of this minor mode." Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `%s'.")))) - `(defcustom ,mode ,init-value - ,(format base-doc-string pretty-name mode mode) - ,@set - ,@initialize - ,@type - ,@(nreverse extra-keywords))))) + `(progn + (defcustom ,mode ,init-value + ,(format base-doc-string pretty-name mode mode) + ,@set + ,@initialize + ,@type + ,@(nreverse extra-keywords)) + ,(when init-value + `(when (bound-and-true-p ,mode) + (add-to-list 'global-minor-modes ',modefun))))))) ;; The actual function. ,(funcall @@ -360,30 +364,21 @@ or call the function `%s'.")))) 'toggle))))) (let ((,last-message (current-message))) (,@setter - (cond ((eq arg 'toggle) - (not ,getter)) - ((and (numberp arg) - (< arg 1)) - nil) - (t - t))) + (cond ((eq arg 'toggle) (not ,getter)) + (t (not (and (numberp arg) (< arg 1)))))) ;; Keep minor modes list up to date. - ,@(if globalp - ;; When running this byte-compiled code in earlier - ;; Emacs versions, these variables may not be defined - ;; there. So check defensively, even if they're - ;; always defined in Emacs 28 and up. - `((when (boundp 'global-minor-modes) - (setq global-minor-modes - (delq ',modefun global-minor-modes)) - (when ,getter - (push ',modefun global-minor-modes)))) - ;; Ditto check. - `((when (boundp 'local-minor-modes) - (setq local-minor-modes - (delq ',modefun local-minor-modes)) - (when ,getter - (push ',modefun local-minor-modes))))) + ,(let ((minor-modes-var (if globalp + 'global-minor-modes + 'local-minor-modes))) + ;; When running this byte-compiled code in earlier + ;; Emacs versions, these variables may not be defined + ;; there. So check defensively, even if they're + ;; always defined in Emacs 28 and up. + `(when (boundp ',minor-modes-var) + (if ,getter + (add-to-list ',minor-modes-var ',modefun) + (setq ,minor-modes-var + (delq ',modefun ,minor-modes-var))))) ,@body ;; The on/off hooks are here for backward compatibility only. (run-hooks ',hook (if ,getter ',hook-on ',hook-off)) diff --git a/lisp/simple.el b/lisp/simple.el index 824f7c5a1a0..589b136a008 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -157,10 +157,6 @@ messages are highlighted; this helps to see what messages were visited." nil "Overlay highlighting the current error message in the `next-error' buffer.") -(defvar global-minor-modes nil - "A list of the currently enabled global minor modes. -This is a list of symbols.") - (defcustom next-error-hook nil "List of hook functions run by `next-error' after visiting source file." :type 'hook diff --git a/lisp/subr.el b/lisp/subr.el index 9f1680f3896..891663f7640 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3064,6 +3064,10 @@ though trying to avoid AVOIDED-MODES." hs-minor-mode) "List of all minor mode functions.") +(defvar global-minor-modes nil + "A list of the currently enabled global minor modes. +This is a list of symbols.") + (defun add-minor-mode (toggle name &optional keymap after toggle-fun) "Register a new minor mode. commit 3aae55acfc5b43ebe436dfc57937db217ccc0891 Author: Michael Albinus Date: Tue Oct 14 12:58:27 2025 +0200 Fix Tramp customization Do not use the ;;;###tramp-autoload cookie for defcustoms. This damages the customisation when Tramp is autoloaded. Reported by Joel Reicher . * lisp/net/tramp-cache.el (tramp-verbose): Declare. (tramp-connection-properties): * lisp/net/tramp-message.el (tramp-verbose): Remove ;;;###tramp-autoload cookie. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index eedb5a3e9ba..c8223d859c7 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -90,6 +90,7 @@ (require 'time-stamp) (declare-function tramp-get-method-parameter "tramp") +(defvar tramp-verbose) ;;; -- Cache -- @@ -97,7 +98,6 @@ (defvar tramp-cache-data (make-hash-table :test #'equal) "Hash table for remote files properties.") -;;;###tramp-autoload (defcustom tramp-connection-properties nil "List of static connection properties. Every entry has the form (REGEXP PROPERTY VALUE). The regexp diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el index a328183e184..d349179d0e6 100644 --- a/lisp/net/tramp-message.el +++ b/lisp/net/tramp-message.el @@ -56,7 +56,6 @@ (defvar tramp-repository-branch) (defvar tramp-repository-version) -;;;###tramp-autoload (defcustom tramp-verbose 3 "Verbosity level for Tramp messages. Any level x includes messages for all levels 1 .. x-1. The levels are commit bcc33e300a77750a30ab5d6aa60f1fa101f93501 Author: Eli Zaretskii Date: Tue Oct 14 12:47:57 2025 +0300 Extend Tree-sitter support on MS-Windows to v0.26.x * lisp/term/w32-nt.el (dynamic-library-alist): Support Tree-sitter DLLs for versions upto 0.26.x. diff --git a/lisp/term/w32-nt.el b/lisp/term/w32-nt.el index e40afcb7c94..83116419774 100644 --- a/lisp/term/w32-nt.el +++ b/lisp/term/w32-nt.el @@ -117,7 +117,9 @@ '(tree-sitter "libtree-sitter-0.24.dll" "libtree-sitter.dll" "libtree-sitter-0.dll") - '(tree-sitter "libtree-sitter-0.25.dll")))) + ;; Supported ABI 13..15 + '(tree-sitter "libtree-sitter-0.26.dll" + "libtree-sitter-0.25.dll")))) ;;;; Selections