commit 4396f6414c2fb82cb8cee68420b658e376bb4e01 (HEAD, refs/remotes/origin/master) Author: Vincenzo Pupillo Date: Mon Feb 3 22:14:44 2025 +0100 Correctly handled the local parser for jsdoc (bug#75456) As a result of recent patches to treesitter, local parsers must now be recognized by 'treesit-language-at-point' and have their own indentation rules. * lisp/progmodes/js.el (js--treesit-indent-rules): New rule for jsdoc. (js--treesit-language-at-point): New function. (js-ts-mode): Use the new function. diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 8029a304757..3168395acf1 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3490,7 +3490,10 @@ Check if a node type is available, then return the right indent rules." ((match "/" "jsx_self_closing_element") parent 0) ((parent-is "jsx_self_closing_element") parent js-indent-level) ;; FIXME(Theo): This no-node catch-all should be removed. When is it needed? - (no-node parent-bol 0))))) + (no-node parent-bol 0)) + (jsdoc + ((and (parent-is "document") c-ts-common-looking-at-star) + c-ts-common-comment-start-after-first-star -1))))) (defvar js--treesit-keywords '("as" "async" "await" "break" "case" "catch" "class" "const" "continue" @@ -3718,6 +3721,22 @@ Return nil if there is no name or if NODE is not a defun node." ("lexical_declaration" (treesit-node-top-level node)) (_ t))) +(defun js--treesit-language-at-point (point) + "Return the language at POINT." + (let* ((node (treesit-node-at point 'javascript)) + (node-type (treesit-node-type node)) + (node-start (treesit-node-start node)) + (node-end (treesit-node-end node))) + (if (not (treesit-ready-p 'jsdoc t)) + 'javascript + (if (equal node-type "comment") + (save-excursion + (goto-char node-start) + (if (search-forward "/**" node-end t) + 'jsdoc + 'javascript)) + 'javascript)))) + ;;; Main Function ;;;###autoload @@ -3927,6 +3946,7 @@ See `treesit-thing-settings' for more information.") ;; Tree-sitter setup. (setq-local treesit-primary-parser (treesit-parser-create 'javascript)) + (setq-local treesit-language-at-point-function #'js--treesit-language-at-point) ;; Indent. (setq-local treesit-simple-indent-rules js--treesit-indent-rules) commit 12a3145b3b9480e5e5993dac28df52a36cc7b95d Author: Yuan Fu Date: Tue Feb 4 23:35:37 2025 -0800 Make treesit-node-at more readable * lisp/treesit.el (treesit-node-at): Make the logic for finding the parser (and the root node) more explicit and straightforward. Don't use treesit-buffer-root-node; instead, find the parser and use treesit-parser-root-node directly. diff --git a/lisp/treesit.el b/lisp/treesit.el index e2fdfb7c1ef..9e3c75519f9 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -226,17 +226,35 @@ is nil, try to guess the language at POS using `treesit-language-at'. If there's a local parser at POS, the local parser takes priority unless PARSER-OR-LANG is a parser, or PARSER-OR-LANG is a language and doesn't match the language of the local parser." - (let* ((root (if (treesit-parser-p parser-or-lang) - (treesit-parser-root-node parser-or-lang) - (or (when-let* ((parser - (car (treesit-local-parsers-at - pos parser-or-lang)))) - (treesit-parser-root-node parser)) - (condition-case nil - (treesit-buffer-root-node - (or parser-or-lang - (treesit-language-at pos))) - (treesit-no-parser nil))))) + (let* ((root + ;; 1. Given a parser, just use the parser's root node. + (cond ((treesit-parser-p parser-or-lang) + (treesit-parser-root-node parser-or-lang)) + ;; 2. Given a language, try local parser, then global + ;; parser. + (parser-or-lang + (let* ((local-parser (car (treesit-local-parsers-at + pos parser-or-lang))) + (global-parser (car (treesit-parser-list + nil parser-or-lang))) + (parser (or local-parser global-parser))) + (when parser + (treesit-parser-root-node parser)))) + ;; 3. No given language, try to get a language at point. + ;; If we got a language, only use parser of that + ;; language, otherwise use any parser we can find. When + ;; finding parser, try local parser first, then global + ;; parser. + (t + ;; LANG can be nil. + (let* ((lang (treesit-language-at pos)) + (local-parser (car (treesit-local-parsers-at + pos lang))) + (global-parser (car (treesit-parser-list + nil lang))) + (parser (or local-parser global-parser))) + (when parser + (treesit-parser-root-node parser)))))) (node root) (node-before root) (pos-1 (max (1- pos) (point-min))) commit 4aab2f45b3dc39f4ebe4e09fd4e3b56b757843aa Author: Paul Eggert Date: Tue Feb 4 16:56:56 2025 -0800 Remove no-longer-needed delete_frame UNINIT * src/frame.c (delete_frame): Remove a local with UNINIT that is no longer needed now that GCC bug#85563 is fixed, as we don’t need to worry about porting --enable-gcc-warnings to older GCC. This change reverts this part of my commit “Port --enable-gcc-warnings to GCC 8” 8c3215e7a47e3caaa005bf573765ed63e0739b89 dated Sat Apr 28 16:49:24 2018 -0700. diff --git a/src/frame.c b/src/frame.c index cac9b0a4acd..6e125b9561c 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2481,7 +2481,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) else { Lisp_Object tail; - Lisp_Object frame1 UNINIT; /* This line works around GCC bug 85563. */ eassume (CONSP (Vframe_list)); /* Look for another visible frame on the same terminal. commit 999d054dc1e265f1a39c10035a3a3f7f75de8445 Author: kobarity Date: Wed Feb 5 00:02:05 2025 +0900 Make it configurable to highlight Python 2 builtins By default, Python 2-only builtins are not highlighted. * lisp/progmodes/python.el (python-2-support): New defcustom. (python-font-lock-builtin-types) (python-font-lock-builtins-python3) (python-font-lock-builtins-python2) (python-font-lock-builtins) (python-font-lock-special-attributes) (python-font-lock-builtin-exceptions-python3) (python-font-lock-builtin-exceptions-python2) (python-font-lock-builtin-exceptions): New variables. (python-font-lock-keywords-level-2) (python-font-lock-keywords-maximum-decoration) (python--treesit-builtin-types) (python--treesit-builtins) (python--treesit-special-attributes) (python--treesit-exceptions): Use new variables. Co-authored-by: Konstantin Kharlamov Co-authored-by: Stefan Kangas diff --git a/etc/NEWS b/etc/NEWS index 82e2462df6b..ade635aa924 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -988,6 +988,14 @@ exist. If "python" points to Python 2 on your system, you now have to customize these variables to "python3" if you want to use Python 3 instead. +--- +*** Python 2 support is now optional and disabled by default. +Since Python 2 EOL was over 5 years ago, this release removes Python +2-only builtins such as "file" from the default highlighting in +'python-mode' and 'python-ts-mode'. If you would like them highlighted, +customize the new user option `python-2-support' to a non-nil value and +restart Emacs. + --- *** Support of 'electric-layout-mode' added. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 3a297a3979c..8a99ff0434d 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -316,6 +316,16 @@ To customize the Python interpreter for interactive use, modify :version "30.1" :type 'string) +(defcustom python-2-support nil + "If non-nil, enable Python 2 support. +Currently only affects highlighting. + +After customizing this variable, you must restart Emacs for it to take +effect." + :version "31.1" + :type 'boolean + :safe 'booleanp) + ;;; Bindings @@ -689,6 +699,40 @@ the {...} holes that appear within f-strings." This is the minimum decoration level, including function and class declarations.") +(defvar python-font-lock-builtin-types + '("bool" "bytearray" "bytes" "complex" "dict" "float" "frozenset" + "int" "list" "memoryview" "range" "set" "str" "tuple")) + +(defvar python-font-lock-builtins-python3 + '("abs" "aiter" "all" "anext" "any" "ascii" "bin" "breakpoint" + "callable" "chr" "classmethod" "compile" "delattr" "dir" "divmod" + "enumerate" "eval" "exec" "filter" "format" "getattr" "globals" + "hasattr" "hash" "help" "hex" "id" "input" "isinstance" + "issubclass" "iter" "len" "locals" "map" "max" "min" "next" + "object" "oct" "open" "ord" "pow" "print" "property" "repr" + "reversed" "round" "setattr" "slice" "sorted" "staticmethod" "sum" + "super" "type" "vars" "zip" "__import__")) + +(defvar python-font-lock-builtins-python2 + '("basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce" + "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce" + "intern")) + +(defvar python-font-lock-builtins + (append python-font-lock-builtins-python3 + (when python-2-support + python-font-lock-builtins-python2))) + +(defvar python-font-lock-special-attributes + '(;; https://docs.python.org/3/reference/datamodel.html + "__annotations__" "__bases__" "__closure__" "__code__" + "__defaults__" "__dict__" "__doc__" "__firstlineno__" + "__globals__" "__kwdefaults__" "__name__" "__module__" + "__mro__" "__package__" "__qualname__" + "__static_attributes__" "__type_params__" + ;; Extras: + "__all__")) + (defvar python-font-lock-keywords-level-2 `(,@python-font-lock-keywords-level-1 ,(rx symbol-start @@ -711,33 +755,11 @@ class declarations.") "self") symbol-end) ;; Builtins - (,(rx symbol-start - (or - "abs" "all" "any" "bin" "bool" "callable" "chr" "classmethod" - "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" - "eval" "filter" "float" "format" "frozenset" "getattr" "globals" - "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" - "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview" - "min" "next" "object" "oct" "open" "ord" "pow" "print" "property" - "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" - "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip" - "__import__" - ;; Python 2: - "basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce" - "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce" - "intern" - ;; Python 3: - "aiter" "anext" "ascii" "breakpoint" "bytearray" "bytes" "exec" - ;; Special attributes: - ;; https://docs.python.org/3/reference/datamodel.html - "__annotations__" "__bases__" "__closure__" "__code__" - "__defaults__" "__dict__" "__doc__" "__firstlineno__" - "__globals__" "__kwdefaults__" "__name__" "__module__" - "__mro__" "__package__" "__qualname__" - "__static_attributes__" "__type_params__" - ;; Extras: - "__all__") - symbol-end) . font-lock-builtin-face)) + (,(rx-to-string `(seq symbol-start + (or ,@(append python-font-lock-builtin-types + python-font-lock-builtins + python-font-lock-special-attributes)) + symbol-end)) . font-lock-builtin-face)) "Font lock keywords to use in `python-mode' for level 2 decoration. This is the medium decoration level, including everything in @@ -759,6 +781,41 @@ sign in chained assignment." (equal (char-after) ?=)) return (progn (backward-char) t)))) +(defvar python-font-lock-builtin-exceptions-python3 + '(;; Python 2 and 3: + "ArithmeticError" "AssertionError" "AttributeError" "BaseException" + "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" + "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" + "GeneratorExit" "IOError" "ImportError" "ImportWarning" + "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" + "LookupError" "MemoryError" "NameError" "NotImplementedError" + "OSError" "OverflowError" "PendingDeprecationWarning" + "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" + "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" + "TypeError" "UnboundLocalError" "UnicodeDecodeError" + "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" + "UnicodeWarning" "UserWarning" "ValueError" "Warning" + "ZeroDivisionError" + ;; Python 3: + "BlockingIOError" "BrokenPipeError" "ChildProcessError" + "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" + "ConnectionResetError" "EncodingWarning" "FileExistsError" + "FileNotFoundError" "InterruptedError" "IsADirectoryError" + "NotADirectoryError" "ModuleNotFoundError" "PermissionError" + "ProcessLookupError" "PythonFinalizationError" "RecursionError" + "ResourceWarning" "StopAsyncIteration" "TimeoutError" + "BaseExceptionGroup" "ExceptionGroup" + ;; OS specific + "VMSError" "WindowsError")) + +(defvar python-font-lock-builtin-exceptions-python2 + '("StandardError")) + +(defvar python-font-lock-builtin-exceptions + (append python-font-lock-builtin-exceptions-python3 + (when python-2-support + python-font-lock-builtin-exceptions-python2))) + (defvar python-font-lock-keywords-maximum-decoration `((python--font-lock-f-strings) ,@python-font-lock-keywords-level-2 @@ -776,38 +833,9 @@ sign in chained assignment." (0+ "." (1+ (or word ?_))))) (1 font-lock-type-face)) ;; Builtin Exceptions - (,(rx symbol-start - (or - ;; Python 2 and 3: - "ArithmeticError" "AssertionError" "AttributeError" "BaseException" - "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" - "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" - "GeneratorExit" "IOError" "ImportError" "ImportWarning" - "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" - "LookupError" "MemoryError" "NameError" "NotImplementedError" - "OSError" "OverflowError" "PendingDeprecationWarning" - "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" - "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" - "TypeError" "UnboundLocalError" "UnicodeDecodeError" - "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" - "UnicodeWarning" "UserWarning" "ValueError" "Warning" - "ZeroDivisionError" - ;; Python 2: - "StandardError" - ;; Python 3: - "BlockingIOError" "BrokenPipeError" "ChildProcessError" - "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" - "ConnectionResetError" "EncodingWarning" "FileExistsError" - "FileNotFoundError" "InterruptedError" "IsADirectoryError" - "NotADirectoryError" "ModuleNotFoundError" "PermissionError" - "ProcessLookupError" "PythonFinalizationError" "RecursionError" - "ResourceWarning" "StopAsyncIteration" "TimeoutError" - "BaseExceptionGroup" "ExceptionGroup" - ;; OS specific - "VMSError" "WindowsError" - ) - symbol-end) - . font-lock-type-face) + (,(rx-to-string `(seq symbol-start + (or ,@python-font-lock-builtin-exceptions) + symbol-end)) . font-lock-type-face) ;; single assignment with/without type hints, e.g. ;; a: int = 5 ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo') @@ -1015,8 +1043,7 @@ It makes underscores and dots word constituent chars.") "and" "in" "is" "not" "or" "not in" "is not")) (defvar python--treesit-builtin-types - '("int" "float" "complex" "bool" "list" "tuple" "range" "str" - "bytes" "bytearray" "memoryview" "set" "frozenset" "dict")) + python-font-lock-builtin-types) (defvar python--treesit-type-regex (rx-to-string `(seq bol (or @@ -1025,17 +1052,7 @@ It makes underscores and dots word constituent chars.") eol))) (defvar python--treesit-builtins - (append python--treesit-builtin-types - '("abs" "aiter" "all" "anext" "any" "ascii" "bin" "breakpoint" - "callable" "chr" "classmethod" "compile" - "delattr" "dir" "divmod" "enumerate" "eval" "exec" - "filter" "format" "getattr" "globals" - "hasattr" "hash" "help" "hex" "id" "input" "isinstance" - "issubclass" "iter" "len" "locals" "map" "max" - "min" "next" "object" "oct" "open" "ord" "pow" - "print" "property" "repr" "reversed" "round" - "setattr" "slice" "sorted" "staticmethod" "sum" "super" - "type" "vars" "zip" "__import__"))) + python-font-lock-builtins) (defvar python--treesit-constants '("Ellipsis" "False" "None" "NotImplemented" "True" "__debug__" @@ -1047,42 +1064,10 @@ It makes underscores and dots word constituent chars.") ">>" ">>=" "|" "|=" "~" "@" "@=")) (defvar python--treesit-special-attributes - '("__annotations__" "__bases__" "__closure__" "__code__" - "__defaults__" "__dict__" "__doc__" "__firstlineno__" - "__globals__" "__kwdefaults__" "__name__" "__module__" - "__mro__" "__package__" "__qualname__" - "__static_attributes__" "__type_params__" - "__all__")) + python-font-lock-special-attributes) (defvar python--treesit-exceptions - '(;; Python 2 and 3: - "ArithmeticError" "AssertionError" "AttributeError" "BaseException" - "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" - "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" - "GeneratorExit" "IOError" "ImportError" "ImportWarning" - "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" - "LookupError" "MemoryError" "NameError" "NotImplementedError" - "OSError" "OverflowError" "PendingDeprecationWarning" - "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" - "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" - "TypeError" "UnboundLocalError" "UnicodeDecodeError" - "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" - "UnicodeWarning" "UserWarning" "ValueError" "Warning" - "ZeroDivisionError" - ;; Python 2: - "StandardError" - ;; Python 3: - "BlockingIOError" "BrokenPipeError" "ChildProcessError" - "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" - "ConnectionResetError" "EncodingWarning" "FileExistsError" - "FileNotFoundError" "InterruptedError" "IsADirectoryError" - "NotADirectoryError" "ModuleNotFoundError" "PermissionError" - "ProcessLookupError" "PythonFinalizationError" "RecursionError" - "ResourceWarning" "StopAsyncIteration" "TimeoutError" - "BaseExceptionGroup" "ExceptionGroup" - ;; OS specific - "VMSError" "WindowsError" - )) + python-font-lock-builtin-exceptions) (defun python--treesit-fontify-string (node override start end &rest _) "Fontify string. commit 7d85f678f33029cc874da2aaa89cf95a45403146 Author: Stefan Kangas Date: Tue Feb 4 02:53:53 2025 +0100 Avoid overly short timeout in ispell-help * lisp/textmodes/ispell.el (ispell-help): Avoid too short timeout by using at least 0.5 seconds. diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index f53732098ea..24d09c3e9bc 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -2512,7 +2512,7 @@ Selections are: (with-current-buffer buffer (insert (concat help-1 "\n" help-2 "\n" help-3))) (ispell-display-buffer buffer) - (sit-for ispell-help-timeout) + (sit-for (max 0.5 ispell-help-timeout)) (kill-buffer "*Ispell Help*")) (unwind-protect (let ((resize-mini-windows 'grow-only)) @@ -2522,7 +2522,7 @@ Selections are: ;;(set-minibuffer-window (selected-window)) (enlarge-window 2) (insert (concat help-1 "\n" help-2 "\n" help-3)) - (sit-for ispell-help-timeout)) + (sit-for (max 0.5 ispell-help-timeout))) (erase-buffer))))))) (define-obsolete-function-alias 'lookup-words 'ispell-lookup-words "24.4") commit 782ec71053d8535511522f27f28c11682ca0f40b Author: Paul Eggert Date: Tue Feb 4 11:43:58 2025 -0800 Improve bidi_get_time runtime checking * src/bidi.c (bidi_get_type): Improve runtime checking, by also aborting if the bidi_type_table entry is not a bidi_type_t value. diff --git a/src/bidi.c b/src/bidi.c index d8754e2db73..fd0bebb85e0 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -282,12 +282,6 @@ bidi_get_type (int ch, bidi_dir_t override) emacs_abort (); default_type = (bidi_type_t) XFIXNUM (CHAR_TABLE_REF (bidi_type_table, ch)); - /* Every valid character code, even those that are unassigned by the - UCD, have some bidi-class property, according to - DerivedBidiClass.txt file. Therefore, if we ever get UNKNOWN_BT - (= zero) code from CHAR_TABLE_REF, that's a bug. */ - if (default_type == UNKNOWN_BT) - emacs_abort (); switch (default_type) { @@ -303,13 +297,26 @@ bidi_get_type (int ch, bidi_dir_t override) case FSI: case PDI: return default_type; - default: + + case STRONG_L: case STRONG_R: + case WEAK_EN: case WEAK_AN: + case STRONG_AL: + case WEAK_ES: case WEAK_ET: case WEAK_CS: case WEAK_NSM: + case NEUTRAL_S: case NEUTRAL_WS: case NEUTRAL_ON: if (override == L2R) return STRONG_L; else if (override == R2L) return STRONG_R; else return default_type; + + case UNKNOWN_BT: + default: + /* Every valid character code, even those unassigned by the UCD, + have some bidi-class property, according to DerivedBidiClass.txt. + Therefore, if we ever get UNKNOWN_BT (= zero) or some unknown + code from CHAR_TABLE_REF, that's a bug. */ + emacs_abort (); } } commit 6842415577405adafcba16f8cbff02f35b5583f9 Author: Jim Porter Date: Tue Feb 4 09:25:17 2025 -0800 Improve calculation of indent prefixes when using text scaling Previously, the display spec for the "average space" was wrong. It used a plain number for the width of the specified space, which means "N times the normal character width for the buffer", but we want "N times the normal character width for the *current face*" (bug#76008). * lisp/visual-wrap.el (visual-wrap--content-prefix): Specify the width of the "average space" in terms of the average width of the current face. * lisp/net/shr.el (shr-indent): As above, and call 'string-pixel-width' without specifying the buffer, to match 'shr-string-pixel-width'. diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 8cc95ea6966..b25b6783066 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -1052,15 +1052,15 @@ When `shr-fill-text' is nil, only indent." (insert-char ?\s shr-indentation) (insert ?\s) ;; Set the specified space width in units of the average-width - ;; of the current font, like (N . width). That way, the + ;; of the current face, like (N . width). That way, the ;; indentation is calculated correctly when using ;; `text-scale-adjust'. (let ((avg-space (propertize (buffer-substring (1- (point)) (point)) - 'display '(space :width 1)))) + 'display '(space :width (1 . width))))) (put-text-property (1- (point)) (point) 'display `(space :width (,(/ (float shr-indentation) - (string-pixel-width avg-space (current-buffer))) + (string-pixel-width avg-space)) . width))))) (put-text-property start (+ (point) prefix) 'shr-prefix-length (+ prefix (- (point) start)))))) diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el index 1691ba9c500..f2a186ce320 100644 --- a/lisp/visual-wrap.el +++ b/lisp/visual-wrap.el @@ -164,7 +164,7 @@ PREFIX was empty." ;; units of the font's average-width) large enough to fit the ;; first-line prefix. (let ((avg-space (propertize (buffer-substring position (1+ position)) - 'display '(space :width 1)))) + 'display '(space :width (1 . width))))) ;; Remove any `min-width' display specs since we'll replace with ;; our own later in `visual-wrap--apply-to-line' (bug#73882). (add-display-text-property 0 (length prefix) 'min-width nil prefix) commit b685b21a33423018f3da7695919a4d1b1ef2c9cd Author: João Távora Date: Tue Feb 4 14:43:48 2025 +0000 Eglot: protect against nil jit-lock-context-unfontify-pos * lisp/progmodes/eglot.el (eglot-shutdown, eglot--update-hints): Rework. Github-reference: https://github.com/joaotavora/eglot/pull/1370 diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4a174d5db5c..7b1c174c4d7 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -4247,47 +4247,47 @@ If NOERROR, return predicate, else erroring function." (defvar-local eglot--outstanding-inlay-regions-timer nil "Helper timer for `eglot--update-hints'.") -(defun eglot--update-hints (from to) +(cl-defun eglot--update-hints (from to) "Jit-lock function for Eglot inlay hints." + ;; XXX: We're relying on knowledge of jit-lock internals here. + ;; Comparing `jit-lock-context-unfontify-pos' (if non-nil) to + ;; `point-max' tells us whether this call to `jit-lock-functions' + ;; happens after `jit-lock-context-timer' has just run. + (when (and jit-lock-context-unfontify-pos + (/= jit-lock-context-unfontify-pos (point-max))) + (cl-return-from eglot--update-hints)) (cl-symbol-macrolet ((region eglot--outstanding-inlay-hints-region) (last-region eglot--outstanding-inlay-hints-last-region) (timer eglot--outstanding-inlay-regions-timer)) (setcar region (min (or (car region) (point-max)) from)) (setcdr region (max (or (cdr region) (point-min)) to)) - ;; HACK: We're relying on knowledge of jit-lock internals here. The - ;; condition comparing `jit-lock-context-unfontify-pos' to - ;; `point-max' is a heuristic for telling whether this call to - ;; `jit-lock-functions' happens after `jit-lock-context-timer' has - ;; just run. Only after this delay should we start the smoothing - ;; timer that will eventually call `eglot--update-hints-1' with the - ;; coalesced region. I wish we didn't need the timer, but sometimes - ;; a lot of "non-contextual" calls come in all at once and do verify - ;; the condition. Notice it is a 0 second timer though, so we're - ;; not introducing any more delay over jit-lock's timers. - (when (= jit-lock-context-unfontify-pos (point-max)) - (if timer (cancel-timer timer)) - (let ((buf (current-buffer))) - (setq timer (run-at-time - 0 nil - (lambda () - (eglot--when-live-buffer buf - ;; HACK: In some pathological situations - ;; (Emacs's own coding.c, for example), - ;; jit-lock is calling `eglot--update-hints' - ;; repeatedly with same sequence of - ;; arguments, which leads to - ;; `eglot--update-hints-1' being called with - ;; the same region repeatedly. This happens - ;; even if the hint-painting code does - ;; nothing else other than widen, narrow, - ;; move point then restore these things. - ;; Possible Emacs bug, but this fixes it. - (unless (equal last-region region) - (eglot--update-hints-1 (max (car region) (point-min)) - (min (cdr region) (point-max))) - (setq last-region region)) - (setq region (cons nil nil) - timer nil))))))))) + ;; XXX: Then there is a smoothing timer. I wish we didn't need it, + ;; but sometimes a lot of calls come in all at once and do make it + ;; past the check above. Notice it is a 0 second timer though, so + ;; we're not introducing any more delay over jit-lock's timers. + (when timer (cancel-timer timer)) + (setq timer (run-at-time + 0 nil + (lambda (buf) + (eglot--when-live-buffer buf + ;; HACK: In some pathological situations + ;; (Emacs's own coding.c, for example), + ;; jit-lock is calling `eglot--update-hints' + ;; repeatedly with same sequence of + ;; arguments, which leads to + ;; `eglot--update-hints-1' being called with + ;; the same region repeatedly. This happens + ;; even if the hint-painting code does + ;; nothing else other than widen, narrow, + ;; move point then restore these things. + ;; Possible Emacs bug, but this fixes it. + (unless (equal last-region region) + (eglot--update-hints-1 (max (car region) (point-min)) + (min (cdr region) (point-max))) + (setq last-region region)) + (setq region (cons nil nil) + timer nil))) + (current-buffer))))) (defun eglot--update-hints-1 (from to) "Do most work for `eglot--update-hints', including LSP request." commit f9a1f449d9cbe57f7312a5327d08e28e71c16882 Author: Gerd Möllmann Date: Tue Feb 4 06:09:52 2025 +0100 Fix min-width display spec handling (bug#76014) * src/xdisp.c (display_min_width): Take into account that the output may already be longer than the specified min-width. diff --git a/src/xdisp.c b/src/xdisp.c index 36e82f873ab..804a19e048f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5646,7 +5646,7 @@ get_display_property (ptrdiff_t charpos, Lisp_Object prop, Lisp_Object object) /* Handle 'display' property '(min-width (WIDTH))' at CHARPOS in OBJECT. OBJECT can be a buffer (or nil, which means the current buffer) or a - string. MIN_WIDTH is the value of min-width spec that we expect to + string. WIDTH_SPEC is the value of min-width spec that we expect to process. */ static void display_min_width (struct it *it, ptrdiff_t charpos, @@ -5692,8 +5692,9 @@ display_min_width (struct it *it, ptrdiff_t charpos, a stretch that ends beyond the visible portion of the window if we are truncating screen lines. If we are requested to do that, some Lisp program went awry. */ - if (!(it->line_wrap == TRUNCATE - && it->current_x + width > it->last_visible_x)) + if (width > 0 + && !(it->line_wrap == TRUNCATE + && it->current_x + width > it->last_visible_x)) w = list1 (make_int (width)); } else @@ -5704,8 +5705,9 @@ display_min_width (struct it *it, ptrdiff_t charpos, NULL, true, NULL); width -= (it->current_x - it->min_width_start) / FRAME_COLUMN_WIDTH (it->f); - if (!(it->line_wrap == TRUNCATE - && it->current_x + width > it->last_visible_x)) + if (width > 0 + && !(it->line_wrap == TRUNCATE + && it->current_x + width > it->last_visible_x)) w = make_int (width); } commit 1e01ae335dda0ebcbca71c50c066a3072dd9d022 Author: Gerd Möllmann Date: Mon Jan 27 08:58:30 2025 +0100 Use read-key in read-multiple-choice (bug#75886) * lisp/emacs-lisp/rmc.el (read-multiple-choice--short-answers): Use read-key instead of read-event because read-event doesn't use input-decode-map. * test/lisp/emacs-lisp/rmc-tests.el: Use read-key instead of read-event. diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el index 27e5d6c612b..c4df8cf2f98 100644 --- a/lisp/emacs-lisp/rmc.el +++ b/lisp/emacs-lisp/rmc.el @@ -216,8 +216,14 @@ Usage example: (car elem))) prompt-choices))) (condition-case nil - (let ((cursor-in-echo-area t)) - (read-event)) + (let ((cursor-in-echo-area t) + ;; Do NOT use read-event here. That + ;; function does not consult + ;; input-decode-map (bug#75886). + (key (read-key))) + (when (eq key ?\C-g) + (signal 'quit nil)) + key) (error nil)))) (if (memq (car-safe tchar) '(touchscreen-begin touchscreen-end diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el index 1bc8c90cad6..0237bc3f9e5 100644 --- a/test/lisp/emacs-lisp/rmc-tests.el +++ b/test/lisp/emacs-lisp/rmc-tests.el @@ -61,7 +61,7 @@ (ert-deftest test-read-multiple-choice () (dolist (char '(?y ?n)) - (cl-letf* (((symbol-function #'read-event) (lambda () char)) + (cl-letf* (((symbol-function #'read-key) (lambda () char)) (str (if (eq char ?y) "yes" "no"))) (should (equal (list char str) (read-multiple-choice "Do it? " '((?y "yes") (?n "no")))))))) @@ -69,7 +69,7 @@ (ert-deftest test-read-multiple-choice-help () (let ((chars '(?o ?a)) help) - (cl-letf* (((symbol-function #'read-event) + (cl-letf* (((symbol-function #'read-key) (lambda () (message "chars %S" chars) (when (= 1 (length chars)) commit 4212b2630f7a9d754810c8c9641e766534b44098 Author: Eli Zaretskii Date: Tue Feb 4 16:01:47 2025 +0200 ; * test/src/editfns-tests.el (editfns-tests-styled-print): Fix last change. diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index b18111ad119..8d4e7bc48fa 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -536,7 +536,6 @@ (ert-deftest editfns-tests-styled-print () "Test bug#75754." - :expected-result :failed (let* ((print-unreadable-function (lambda (&rest _args) (garbage-collect) commit 2dbcabec78bac334d5928e3b7201c05adb30cc05 Merge: 2b1c25e62b3 2eb6171ec96 Author: Michael Albinus Date: Tue Feb 4 14:33:51 2025 +0100 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs commit 2b1c25e62b3ff1718cfebda9d0e6b670c903b4cd Author: Michael Albinus Date: Tue Feb 4 14:32:46 2025 +0100 Fix some checks in autorevert.el * lisp/autorevert.el (auto-revert-handler): Rework checks. (auto-revert-handler): Don't run `vc-refresh-state' in `auto-revert-tail-mode'. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index b6dd9fb9015..ddb116bb828 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -818,23 +818,22 @@ This is an internal function used by Auto-Revert Mode." (not (file-remote-p buffer-file-name))) (or (not auto-revert-notify-watch-descriptor) auto-revert-notify-modified-p) + (not (memq (current-buffer) inhibit-auto-revert-buffers)) (if auto-revert-tail-mode (and (file-readable-p buffer-file-name) (/= auto-revert-tail-pos (setq size (file-attribute-size (file-attributes buffer-file-name))))) - (and (not (memq (current-buffer) - inhibit-auto-revert-buffers)) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))) (and (or auto-revert-mode global-auto-revert-non-file-buffers) - (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))))) + (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t)))) eob eoblist) (setq auto-revert-notify-modified-p nil auto-revert--last-time (current-time)) @@ -869,7 +868,7 @@ This is an internal function used by Auto-Revert Mode." (set-window-point window (point-max))))) ;; `preserve-modes' avoids changing the (minor) modes. But we do ;; want to reset the mode for VC, so we do it manually. - (when (or revert auto-revert-check-vc-info) + (when (and (not auto-revert-tail-mode) (or revert auto-revert-check-vc-info)) (let ((revert-buffer-in-progress-p t)) (vc-refresh-state))))) commit 2eb6171ec96eac0c78cf20b3003fcbcb1206c8c7 Author: Andrew G Cohen Date: Wed Jul 5 15:21:16 2023 +0800 Don't use obsolete In-Reply-To format in messages (Bug#64454) When creating a new message, message-send-mail uses an obsolete format for the In-Reply-To header that includes additional information about the originating message. This patch changes the default to use the rfc5322 approved format, but allow the obsolete format through a defcustom. * lisp/gnus/message.el (message-make-in-reply-to): Return only the message-id of the originating message (the default) unless the new custom variable message-header-use-obsolete-in-reply-to is non-nil. * doc/misc/message.texi: Document the new custom variable message-header-use-obsolete-in-reply-to. * etc/NEWS: Update NEWS. diff --git a/doc/misc/message.texi b/doc/misc/message.texi index bd20aec5bc6..509bbd5b575 100644 --- a/doc/misc/message.texi +++ b/doc/misc/message.texi @@ -1791,6 +1791,12 @@ member list with elements @code{CC} and @code{To}, then @code{message-carefully-insert-headers} will not insert a @code{To} header when the message is already @code{CC}ed to the recipient. +@item message-header-use-obsolete-in-reply-to +@vindex message-header-use-obsolete-in-reply-to +When non-@code{nil}, use an obsolete form of the @code{In-Reply-To} +header that includes a parenthetical phrase with details of the +originating email following the message id. The default is @code{nil}. + @item message-syntax-checks @vindex message-syntax-checks Controls what syntax checks should not be performed on outgoing posts. diff --git a/etc/NEWS b/etc/NEWS index 8cf86d1375d..2e5022b4955 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -484,6 +484,16 @@ If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at Emacs exit. +** Message + +--- +*** In-Reply-To header contains only a message id. +The In-Reply-To header created when replying to a message now contains +only the originating message's id, conforming to RFC5322. The previous +behavior included additional information about the originating message. +The new variable 'message-header-use-obsolete-in-reply-to', nil by +default, can be set to a non-nil value to restore the previous behavior. + ** Gnus --- diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index b552b211eb8..7a84d6366db 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -113,6 +113,13 @@ :group 'message :group 'faces) +(defcustom message-header-use-obsolete-in-reply-to nil + "Include extra information in the In-Reply-To header. +This form has been obsolete since RFC 2822." + :group 'message-headers + :version "31.1" + :type 'boolean) + (defcustom message-directory "~/Mail/" "Directory from which all other mail file variables are derived." :group 'message-various @@ -5993,35 +6000,38 @@ In posting styles use `(\"Expires\" (make-expires-date 30))'." "Return the In-Reply-To header for this message." (when message-reply-headers (let ((from (mail-header-from message-reply-headers)) - (date (mail-header-date message-reply-headers)) - (msg-id (mail-header-id message-reply-headers))) + (date (mail-header-date message-reply-headers)) + (msg-id (mail-header-id message-reply-headers))) (when from - (let ((name (mail-extract-address-components from))) - (concat - msg-id (if msg-id " (") - (if (car name) - (if (string-match "[^[:ascii:]]" (car name)) - ;; Quote a string containing non-ASCII characters. - ;; It will make the RFC2047 encoder cause an error - ;; if there are special characters. - (mm-with-multibyte-buffer - (insert (car name)) - (goto-char (point-min)) - (while (search-forward "\"" nil t) - (when (prog2 - (backward-char) - (zerop (% (skip-chars-backward "\\\\") 2)) - (goto-char (match-beginning 0))) - (insert "\\")) - (forward-char)) - ;; Those quotes will be removed by the RFC2047 encoder. - (concat "\"" (buffer-string) "\"")) - (car name)) - (nth 1 name)) - "'s message of \"" - (if (or (not date) (string= date "")) - "(unknown date)" date) - "\"" (if msg-id ")"))))))) + (let ((name (mail-extract-address-components from))) + (concat + msg-id + (when message-header-use-obsolete-in-reply-to + (concat + (if msg-id " (") + (if (car name) + (if (string-match "[^[:ascii:]]" (car name)) + ;; Quote a string containing non-ASCII characters. + ;; It will make the RFC2047 encoder cause an error + ;; if there are special characters. + (mm-with-multibyte-buffer + (insert (car name)) + (goto-char (point-min)) + (while (search-forward "\"" nil t) + (when (prog2 + (backward-char) + (zerop (% (skip-chars-backward "\\\\") 2)) + (goto-char (match-beginning 0))) + (insert "\\")) + (forward-char)) + ;; Those quotes will be removed by the RFC2047 encoder. + (concat "\"" (buffer-string) "\"")) + (car name)) + (nth 1 name)) + "'s message of \"" + (if (or (not date) (string= date "")) + "(unknown date)" date) + "\"" (if msg-id ")"))))))))) (defun message-make-distribution () "Make a Distribution header." commit 9597881592049509d62f91139316ac0eba2fb19d Author: Michael Albinus Date: Tue Feb 4 14:09:52 2025 +0100 Add inhibit-auto-revert macro * doc/lispref/backups.texi (Reverting): Add inhibit-auto-revert-buffers and inhibit-auto-revert. * etc/NEWS: Add inhibit-auto-revert-buffers and inhibit-auto-revert. Fix typos. * lisp/autorevert.el (inhibit-auto-revert-buffers): New variable. (inhibit-auto-revert): New macro. (auto-revert-active-p, auto-revert-handler): Check `inhibit-auto-revert-buffers'. * lisp/dired.el (dired--inhibit-auto-revert): Remove. (dired-buffer-stale-p): Don't set it. (dired-map-over-marks, dired-internal-do-deletions): Use `inhibit-auto-revert. * test/lisp/autorevert-tests.el (auto-revert-test08-auto-revert-inhibit-auto-revert) (auto-revert-test08-auto-revert-inhibit-auto-revert-remote): New tests. diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index 50c7ace253c..f3f0902f364 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -852,6 +852,30 @@ It is important to assure that point does not continuously jump around as a consequence of auto-reverting. Of course, moving point might be inevitable if the buffer radically changes. +@defvar inhibit-auto-revert-buffers +When the current buffer is member of this variable (a list of buffers), +auto-reverting is suppressed for that buffer. This is useful if serious +changes are applied to that buffer which would be poisoned by an +unexpected auto-revert. After the change is finished, the buffer shall +be removed from @code{inhibit-auto-revert-buffers}. + +The check of membership in @code{inhibit-auto-revert-buffers} is applied +prior to the call of @code{buffer-stale-function}; any heavy check in +that function is avoided, therefore. + +If auto-reverting is triggered by file notification while +@code{inhibit-auto-revert-buffers} prevents this, auto-revert will +happen next time the buffer is polled for changes, unless +@code{auto-revert-avoid-polling} is non-@code{nil}. @pxref{(emacs) Auto +Revert}. +@end defvar + +@defmac inhibit-auto-revert &rest body +This macro adds the current buffer to +@code{inhibit-auto-revert-buffers}, runs @var{body}, and removes the +current buffer from @code{inhibit-auto-revert-buffers} afterwards. +@end defmac + You should make sure that the @code{revert-buffer-function} does not print messages that unnecessarily duplicate Auto Revert's own messages, displayed if @code{auto-revert-verbose} is @code{t}, and effectively diff --git a/etc/NEWS b/etc/NEWS index 8cf86d1375d..2464598c6d1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -41,12 +41,12 @@ incorrectly in rare cases. ** In compatible terminals, 'xterm-mouse-mode' is turned on by default. For these terminals the mouse will work by default. A compatible -terminal is one that supports Emacs seting and getting the OS selection +terminal is one that supports Emacs setting and getting the OS selection data (a.k.a. the clipboard) and mouse button and motion events. With -xterm-mouse-mode enabled, you must use Emacs keybindings to copy to the +'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the OS selection instead of terminal-specific keybindings. -You can keep the old behavior by putting `(xterm-mouse-mode -1)' in your +You can keep the old behavior by putting '(xterm-mouse-mode -1)' in your init file. @@ -75,7 +75,7 @@ In particular: To enable tooltips on TTY frames, call 'tty-tip-mode'. The presence of child frame support on TTY frames can be checked with -`(featurep 'tty-child-frames)'. +'(featurep 'tty-child-frames)'. Recent versions of Posframe and Corfu are known to use child frames on TTYs if they are supported. @@ -108,7 +108,7 @@ instead of its now-obsolete variable. ** Network Security Manager (NSM) is now more strict. *** NSM warns about TLS 1.1 by default. -It has been deprecated by RFC8996, published in 2021. +It has been deprecated by RFC 8996, published in 2021. *** NSM warns about DHE and RSA key exchange by default. Emacs now warns about ephemeral Diffie-Hellman key exchange, and static @@ -181,13 +181,9 @@ the "*Completions*" buffer is hidden. +++ *** New functions to modify window layout. Several functions to modify the window layout have been added: -'rotate-window-layout-clockwise' -'rotate-window-layout-anticlockwise' -'flip-window-layout-vertically' -'flip-window-layout-horizontally' -'transpose-window-layout' -'rotate-windows' -'rotate-windows-back' +'rotate-window-layout-clockwise', 'rotate-window-layout-anticlockwise', +'flip-window-layout-vertically', 'flip-window-layout-horizontally', +'transpose-window-layout', 'rotate-windows', and 'rotate-windows-back'. +++ *** New hook 'window-deletable-functions'. @@ -254,11 +250,11 @@ adjustment when a tab is restored, and avoids advice. *** New user option 'tab-bar-define-keys'. This controls which key bindings tab-bar creates. Values are t, the default, which defines all keys and is backwards compatible, 'numeric' -(tab number selection only), 'tab' (TAB and SHIFT-TAB keys only), nil +(tab number selection only), 'tab' ('TAB' and 'S-TAB' keys only), nil (which defines none). This is useful to avoid key binding conflicts, such as when folding in -outline mode using TAB keys, or when a user wants to define her own +outline mode using 'TAB' keys, or when a user wants to define her own tab-bar keys without first having to remove the defaults. --- @@ -386,13 +382,15 @@ modal editing packages. --- ** ASM mode + *** 'asm-mode-set-comment-hook' is obsolete. You can now set `asm-comment-char' from 'asm-mode-hook' instead. --- ** Ibuffer + *** New column 'recency' in Ibuffer display. -The variable 'ibuffer-formats' configures the Ibuffer formats. Add +The user option 'ibuffer-formats' configures the Ibuffer formats. Add 'recency' to the format to display the column. *** New value 'title' for the user option 'ibuffer-use-header-line'. @@ -404,11 +402,13 @@ When non-nil, buffer sizes are shown in human readable format. --- ** Buffer Menu + *** New user option 'Buffer-menu-human-readable-sizes'. When non-nil, buffer sizes are shown in human readable format. The default is nil, which retains the old format. ** Smerge + *** New command 'smerge-extend' extends a conflict over surrounding lines. ** Image Dired @@ -430,7 +430,7 @@ a web browser to load them. For example, it could be used like this: For better integration with the Qutebrowser, set 'browse-url(-secondary)-browser-function' to 'browse-url-qutebrowser'. -*** New GTK-native launch mode +*** New GTK-native launch mode. For better Wayland support, the pgtk toolkit exposes a new 'x-gtk-launch-uri' browse-url handler and uses it by default when URLs are browsed from a PGTK frame. For other frames, we fall back to the @@ -469,16 +469,15 @@ compatible. --- *** You can now regularly auto-save places. -Customize 'save-place-autosave-interval' to the number of seconds -between auto saving places. For example, to save places every 5 +Customize user option 'save-place-autosave-interval' to the number of +seconds between auto saving places. For example, to save places every 5 minutes: - M-x customize-option RET save-place-autosave-interval RET and set to - 300 seconds. + M-x customize-option RET save-place-autosave-interval RET 300 -Or in elisp: +Or in Elisp: - (setopt save-place-autosave-interval (* 60 5)) + (setopt save-place-autosave-interval (* 60 5)) If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at @@ -680,7 +679,6 @@ build tags for the test commands. The 'go-ts-mode-test-flags' user option is available to set a list of additional flags to pass to the go test command line. - ** C-ts mode +++ @@ -901,13 +899,13 @@ the 'grep' results editable. The edits will be reflected in the buffer visiting the originating file. Typing 'C-c C-c' will leave the Grep Edit mode. -** time-stamp +** Time Stamp --- *** 'time-stamp' can up-case, capitalize and down-case date words. This control can be useful in languages in which days of the week and/or month names are capitalized only at the beginning of a sentence. For -details, see the built-in documentation for variable 'time-stamp-format'. +details, see the built-in documentation for user option 'time-stamp-format'. Because this feature is new in Emacs 31.1, do not use it in the local variables section of any file that might be edited by an older version @@ -915,12 +913,12 @@ of Emacs. --- *** Some historical 'time-stamp' conversions now warn. -'time-stamp-pattern' and 'time-stamp-format' had quietly -accepted several 'time-stamp' conversions (e.g., "%:y") that -have been deprecated since Emacs 27.1 (released in 2020). -These now generate a warning with a suggested migration. +'time-stamp-pattern' and 'time-stamp-format' had quietly accepted +several 'time-stamp' conversions (e.g., "%:y") that have been deprecated +since Emacs 27.1. These now generate a warning with a suggested +migration. -Merely having "(add-hook 'before-save-hook 'time-stamp)" +Merely having '(add-hook 'before-save-hook 'time-stamp)' in your Emacs init file does not expose you to this change. However, if you set 'time-stamp-format' or 'time-stamp-pattern' with a file-local variable, you may be asked to update the value. @@ -1076,6 +1074,19 @@ destination window is chosen using 'display-buffer-alist'. Example: display-buffer-use-some-window) (some-window . mru)))) +** Autorevert + ++++ +*** New variable 'inhibit-auto-revert-buffers'. +While a buffer is member of this variable, a list of buffers, +auto-reverting of this buffer is suppressed. + ++++ +*** New macro 'inhibit-auto-revert'. +This macro adds the current buffer to 'inhibit-auto-revert-buffers', +runs its body, and removes the current buffer from +'inhibit-auto-revert-buffers' afterwards. + * New Modes and Packages in Emacs 31.1 @@ -1085,7 +1096,7 @@ destination window is chosen using 'display-buffer-alist'. Example: ** Nested backquotes are not supported any more in Pcase patterns. --- -** The obsolete variable `redisplay-dont-pause' has been removed. +** The obsolete variable 'redisplay-dont-pause' has been removed. ** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. An old alternative name (without the first 'e') has been removed. @@ -1161,7 +1172,7 @@ authorize the invoked D-Bus method (for example via polkit). ** The customization group 'wp' has been removed. It has been obsolete since Emacs 26.1. Use the group 'text' instead. -** Changes in tree-sitter modes. +** Changes in tree-sitter modes +++ *** Indirect buffers can have their own parser list. @@ -1186,7 +1197,7 @@ override flag by 'treesit-font-lock-setting-query', 'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable', and 'treesit-font-lock-setting-override'. -*** New treesit thing 'list'. +*** New tree-sitter thing 'list'. Unlike the existing thing 'sexp' that defines both lists and atoms, 'list' defines only lists to be navigated by 'forward-sexp'. The new function 'treesit-forward-sexp-list' uses 'list' @@ -1209,9 +1220,9 @@ used to communicate the tree-sitter parsing results to *** Tree-sitter enabled modes now properly support 'hs-minor-mode'. All commands from hideshow.el can selectively display blocks -defined by the new treesit thing 'list'. +defined by the new tree-sitter thing 'list'. -*** New treesit thing 'comment'. +*** New tree-sitter thing 'comment'. The new variable 'forward-comment-function' is set to the new function 'treesit-forward-comment' if a major mode defines the thing 'comment'. @@ -1223,26 +1234,26 @@ variable 'treesit-language-display-name-alist' holds the translations of language symbols where that translation is not trivial. +++ -*** New command 'treesit-explore' +*** New command 'treesit-explore'. This command replaces 'treesit-explore-mode'. It turns on 'treesit-explore-mode' if it’s not on, and pops up the explorer buffer if it’s already on. +++ -*** 'treesit-explore-mode' now supports local parsers +*** 'treesit-explore-mode' now supports local parsers. Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser rather than a language, and it’s now possible to select a local parser at point to explore. +++ -*** New variable 'treesit-aggregated-simple-imenu-settings' +*** New variable 'treesit-aggregated-simple-imenu-settings'. This variable allows major modes to setup Imenu for multiple languages. -*** New function 'treesit-add-simple-indent-rules' +*** New function 'treesit-add-simple-indent-rules'. This new function makes it easier to customize indent rules for tree-sitter modes. -*** New variable 'treesit-simple-indent-override-rules' +*** New variable 'treesit-simple-indent-override-rules'. Users can customize this variable to add simple custom indentation rules for tree-sitter major modes. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 1dcfe8e911f..b6dd9fb9015 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -772,11 +772,37 @@ If the buffer needs to be reverted, do it now." (when auto-revert-notify-modified-p (auto-revert-handler))))) +;;;###autoload +(progn + (defvar inhibit-auto-revert-buffers nil + "A list of buffers with suppressed auto-revert.") + + (defmacro inhibit-auto-revert (&rest body) + "Deactivate auto-reverting of current buffer temporarily. +Run BODY." + (declare (indent 0) (debug ((form body) body))) + `(progn + ;; Cleanup. + (dolist (buf inhibit-auto-revert-buffers) + (unless (buffer-live-p buf) + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))) + (let ((buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (current-buffer)))) + (unwind-protect + (progn + (when buf (add-to-list 'inhibit-auto-revert-buffers buf)) + ,@body) + (when buf + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))))))) + (defun auto-revert-active-p () "Check if auto-revert is active in current buffer." - (or auto-revert-mode - auto-revert-tail-mode - auto-revert--global-mode)) + (and (or auto-revert-mode + auto-revert-tail-mode + auto-revert--global-mode) + (not (memq (current-buffer) inhibit-auto-revert-buffers)))) (defun auto-revert-handler () "Revert current buffer, if appropriate. @@ -798,14 +824,17 @@ This is an internal function used by Auto-Revert Mode." (setq size (file-attribute-size (file-attributes buffer-file-name))))) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))) + (and (not (memq (current-buffer) + inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t)))) (and (or auto-revert-mode global-auto-revert-non-file-buffers) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))))) eob eoblist) (setq auto-revert-notify-modified-p nil auto-revert--last-time (current-time)) diff --git a/lisp/dired.el b/lisp/dired.el index 2eb6546107a..91163186443 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -944,9 +944,6 @@ Return value is the number of files marked, or nil if none were marked." "")))) (and (> count 0) count))) -(defvar-local dired--inhibit-auto-revert nil - "A non-nil value prevents `auto-revert-mode' from reverting the buffer.") - (defmacro dired-map-over-marks (body arg &optional show-progress distinguish-one-marked) "Eval BODY with point on each marked line. Return a list of BODY's results. @@ -983,48 +980,48 @@ marked file, return (t FILENAME) instead of (FILENAME)." ;;endless loop. ;;This warning should not apply any longer, sk 2-Sep-1991 14:10. `(prog1 - (let ((dired--inhibit-auto-revert t) - (inhibit-read-only t) - case-fold-search found results) - (if (and ,arg (not (eq ,arg 'marked))) - (if (integerp ,arg) - (progn ;; no save-excursion, want to move point. - (dired-repeat-over-lines - ,arg - (lambda () - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)))) - (when (< ,arg 0) - (setq results (nreverse results))) - results) - ;; non-nil, non-integer, non-marked ARG means use current file: - (list ,body)) - (let ((regexp (dired-marker-regexp)) next-position) - (save-excursion - (goto-char (point-min)) - ;; remember position of next marked file before BODY - ;; can insert lines before the just found file, - ;; confusing us by finding the same marked file again - ;; and again and... - (setq next-position (and (re-search-forward regexp nil t) - (point-marker)) - found (not (null next-position))) - (while next-position - (goto-char next-position) - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)) - ;; move after last match - (goto-char next-position) - (forward-line 1) - (set-marker next-position nil) - (setq next-position (and (re-search-forward regexp nil t) - (point-marker))))) - (if (and ,distinguish-one-marked (= (length results) 1)) - (setq results (cons t results))) - (if found - results - (unless (eq ,arg 'marked) - (list ,body)))))) + (inhibit-auto-revert + (let ((inhibit-read-only t) + case-fold-search found results) + (if (and ,arg (not (eq ,arg 'marked))) + (if (integerp ,arg) + (progn ;; no save-excursion, want to move point. + (dired-repeat-over-lines + ,arg + (lambda () + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)))) + (when (< ,arg 0) + (setq results (nreverse results))) + results) + ;; non-nil, non-integer, non-marked ARG means use current file: + (list ,body)) + (let ((regexp (dired-marker-regexp)) next-position) + (save-excursion + (goto-char (point-min)) + ;; remember position of next marked file before BODY + ;; can insert lines before the just found file, + ;; confusing us by finding the same marked file again + ;; and again and... + (setq next-position (and (re-search-forward regexp nil t) + (point-marker)) + found (not (null next-position))) + (while next-position + (goto-char next-position) + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)) + ;; move after last match + (goto-char next-position) + (forward-line 1) + (set-marker next-position nil) + (setq next-position (and (re-search-forward regexp nil t) + (point-marker))))) + (if (and ,distinguish-one-marked (= (length results) 1)) + (setq results (cons t results))) + (if found + results + (unless (eq ,arg 'marked) + (list ,body))))))) ;; save-excursion loses, again (dired-move-to-filename))) @@ -1294,12 +1291,6 @@ This feature is used by Auto Revert mode." ;; Do not auto-revert when the dired buffer can be currently ;; written by the user as in `wdired-mode'. buffer-read-only - ;; When a dired operation using dired-map-over-marks is in - ;; progress, dired--inhibit-auto-revert is bound to some - ;; non-nil value and we must not auto-revert because that could - ;; change the order of files leading to skipping or - ;; double-processing (see bug#75626). - (not dired--inhibit-auto-revert) (dired-directory-changed-p dirname)))) (defcustom dired-auto-revert-buffer nil @@ -4089,26 +4080,26 @@ non-empty directories is allowed." (while l (goto-char (marker-position (cdr (car l)))) (dired-move-to-filename) - (let ((inhibit-read-only t) - ;; Temporarily prevent auto-revert while deleting - ;; entry in the dired buffer (bug#71264). - (dired--inhibit-auto-revert t)) - (condition-case err - (let ((fn (car (car l)))) - (dired-delete-file fn dired-recursive-deletes trash) - ;; if we get here, removing worked - (setq succ (1+ succ)) - (progress-reporter-update progress-reporter succ) - (dired-fun-in-all-buffers - (file-name-directory fn) (file-name-nondirectory fn) - #'dired-delete-entry fn) - ;; For when FN's directory name is different - ;; from the current buffer's dired-directory. - (dired-delete-entry fn)) - (quit (throw '--delete-cancel (message "OK, canceled"))) - (error ;; catch errors from failed deletions - (dired-log "%s: %s\n" (car err) (error-message-string err)) - (setq failures (cons (car (car l)) failures))))) + ;; Temporarily prevent auto-revert while deleting entry in + ;; the dired buffer (bug#71264). + (inhibit-auto-revert + (let ((inhibit-read-only t)) + (condition-case err + (let ((fn (car (car l)))) + (dired-delete-file fn dired-recursive-deletes trash) + ;; if we get here, removing worked + (setq succ (1+ succ)) + (progress-reporter-update progress-reporter succ) + (dired-fun-in-all-buffers + (file-name-directory fn) (file-name-nondirectory fn) + #'dired-delete-entry fn) + ;; For when FN's directory name is different + ;; from the current buffer's dired-directory. + (dired-delete-entry fn)) + (quit (throw '--delete-cancel (message "OK, canceled"))) + (error ;; catch errors from failed deletions + (dired-log "%s: %s\n" (car err) (error-message-string err)) + (setq failures (cons (car (car l)) failures)))))) (setq l (cdr l))) (if (not failures) (progress-reporter-done progress-reporter) diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index 5e46216cc42..319f3285d2d 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el @@ -687,6 +687,41 @@ This expects `auto-revert--messages' to be bound by (auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers "Check autorevert for several buffers visiting the same remote file.") +(ert-deftest auto-revert-test08-auto-revert-inhibit-auto-revert () + "Check the power of `inhibit-auto-revert'." + ;; `auto-revert-buffers' runs every 5". And we must wait, until the + ;; file has been reverted. + (with-auto-revert-test + (ert-with-temp-file tmpfile + (let ((times '(60 30 15)) + buf) + (unwind-protect + (progn + (auto-revert-tests--write-file "any text" tmpfile (pop times)) + (setq buf (find-file-noselect tmpfile)) + (with-current-buffer buf + (ert-with-message-capture auto-revert--messages + (inhibit-auto-revert + (auto-revert-mode 1) + (should auto-revert-mode) + + (auto-revert-tests--write-file "another text" tmpfile (pop times)) + ;; Check, that the buffer hasn't been reverted. + (auto-revert--wait-for-revert buf) + (should-not (string-match "another text" (buffer-string)))) + + ;; Check, that the buffer has been reverted. + (auto-revert--wait-for-revert buf) + (should (string-match "another text" (buffer-string)))))) + + ;; Exit. + (ignore-errors + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf))))))) + +(auto-revert--deftest-remote auto-revert-test08-auto-revert-inhibit-auto-revert + "Check the power of `inhibit-auto-revert' on a remote file.") + ;; Mark all tests as unstable on Cygwin (bug#49665). (when (eq system-type 'cygwin) (dolist (test (apropos-internal "^auto-revert" #'ert-test-boundp)) commit 40e38a681dafb02f71d741338e9c3c5ff99c734e Author: Eli Zaretskii Date: Tue Feb 4 14:18:38 2025 +0200 ; * test/src/editfns-tests.el (editfns-tests-styled-print): New test. diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 9fff4255b57..b18111ad119 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -534,4 +534,15 @@ 'utf-8 nil (current-buffer)) (should (null (sanity-check-change-functions-errors)))))) +(ert-deftest editfns-tests-styled-print () + "Test bug#75754." + :expected-result :failed + (let* ((print-unreadable-function + (lambda (&rest _args) + (garbage-collect) + (make-string 100 ?Ā t))) + (str "\"[1] ĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀ\"")) + (should (string= (format "%S" (format "%S %S" [1] (symbol-function '+))) + str)))) + ;;; editfns-tests.el ends here commit 164da071e07cf162bfe166908dedc82da44ef634 Author: João Távora Date: Tue Feb 4 12:02:06 2025 +0000 Eglot: avoid 'null' as params to 'shutdown' request (bug#66144) Doing so confuses some servers. It used to be needed for the gopls server, but according to https://debbugs.gnu.org/cgi/bugreport.cgi?bug=66144#32 that has been fixed. Thanks to Javier Olaechea * lisp/progmodes/eglot.el (eglot-shutdown): Use eglot--{}. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4114f21bc75..4a174d5db5c 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1246,7 +1246,7 @@ SERVER." (unwind-protect (progn (setf (eglot--shutdown-requested server) t) - (eglot--request server :shutdown nil :timeout (or timeout 1.5)) + (eglot--request server :shutdown eglot--{} :timeout (or timeout 1.5)) (jsonrpc-notify server :exit nil)) ;; Now ask jsonrpc.el to shut down the server. (jsonrpc-shutdown server (not preserve-buffers))