commit 83a497ee879959cd1b052fa9138adb79b480394d (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Mon Nov 14 14:07:04 2022 +0800 Prevent crashes upon trying to focus a child frame on click * src/xterm.c (handle_one_xevent): Do not try to activate override-redirect frames. Explain why. (x_focus_frame): Catch errors around XSetInputFocus. diff --git a/src/xterm.c b/src/xterm.c index 48ddd17568..7a1fd6086c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -21135,8 +21135,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) { + x_ignore_errors_for_next_request (dpyinfo); XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), RevertToParent, event->xbutton.time); + x_stop_ignoring_errors (dpyinfo); + if (FRAME_PARENT_FRAME (f)) XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); } @@ -22838,9 +22841,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #else /* Non-no toolkit builds without GTK 3 use core - events to handle focus. */ + events to handle focus. Errors are still + caught here in case the window is not + viewable. */ + x_ignore_errors_for_next_request (dpyinfo); XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), RevertToParent, xev->time); + x_stop_ignoring_errors (dpyinfo); #endif if (FRAME_PARENT_FRAME (f)) XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); @@ -27602,6 +27609,10 @@ x_focus_frame (struct frame *f, bool noactivate) else { if (!noactivate + /* If F is override-redirect, use SetInputFocus instead. + Override-redirect frames are not subject to window + management. */ + && !FRAME_OVERRIDE_REDIRECT (f) /* If F is a child frame, use SetInputFocus instead. This may not work if its parent is not activated. */ && !FRAME_PARENT_FRAME (f) commit c0474ca21dd76cafbd1a04fd32d4a0bd42de6351 Author: Dmitry Gutov Date: Mon Nov 14 02:18:56 2022 +0200 Hardcode "-name" instead of using find-name-arg * lisp/progmodes/project.el (project--files-in-directory): Hardcode "-name" instead of using find-name-arg (bug#59023). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index d2ce684c1b..ed26872ae7 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1,7 +1,7 @@ ;;; project.el --- Operations on the current project -*- lexical-binding: t; -*- ;; Copyright (C) 2015-2022 Free Software Foundation, Inc. -;; Version: 0.8.2 +;; Version: 0.8.3 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0")) ;; This is a GNU ELPA :core package. Avoid using functionality that @@ -296,7 +296,6 @@ to find the list of ignores for each directory." (defun project--files-in-directory (dir ignores &optional files) (require 'find-dired) (require 'xref) - (defvar find-name-arg) (let* ((default-directory dir) ;; Make sure ~/ etc. in local directory name is ;; expanded and not left for the shell command @@ -308,11 +307,11 @@ to find the list of ignores for each directory." (xref--find-ignores-arguments ignores "./") (if files (concat (shell-quote-argument "(") - " " find-name-arg " " + " -name " (mapconcat #'shell-quote-argument (split-string files) - (concat " -o " find-name-arg " ")) + (concat " -o -name ")) " " (shell-quote-argument ")")) ""))) commit 9d5fc2c7eb3cfc2ae36cdc750a4605b4b08771b8 Author: Juri Linkov Date: Sun Nov 13 20:57:50 2022 +0200 * lisp/minibuffer.el (set-message-functions): New user option. (set-message-function): Change the default from 'set-minibuffer-message' to 'set-message-functions'. 'set-minibuffer-message' is set as the default value of the user option 'set-message-functions'. (set-message-functions): New function. (inhibit-message-regexps): New customizable variable (bug#52314). (inhibit-message): New function. (multi-message-timeout, multi-message-max): New defcustoms. (multi-message-separator, multi-message-list): New variables. (set-multi-message): New function. diff --git a/etc/NEWS b/etc/NEWS index 0b8f4539f9..7cd192b9d3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -712,6 +712,15 @@ part of the buffer. +++ ** 'count-words' will now report sentence count when used interactively. +** New user option 'set-message-functions'. +It allows selecting more functions for 'set-message-function' +in addition to the default function that handles messages +in the active minibuffer. The most useful are 'inhibit-message' +that allows specifying a list of messages to inhibit via +'inhibit-message-regexps', and 'set-multi-message' that +accumulates recent messages and displays them stacked +in the echo area. + --- ** New user option 'find-library-include-other-files'. If set to nil, commands like 'find-library' will only include library diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 4898dfdb98..6bb0fa3ae9 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -850,7 +850,88 @@ via `set-message-function'." ;; was handled specially by this function. t)))) -(setq set-message-function 'set-minibuffer-message) +(setq set-message-function 'set-message-functions) + +(defcustom set-message-functions '(set-minibuffer-message) + "List of functions to handle display of echo-area messages. +Each function is called with one argument that is the text of a message. +If a function returns nil, a previous message string is given to the +next function in the list, and if the last function returns nil, the +last message string is displayed in the echo area. +If a function returns a string, the returned string is given to the +next function in the list, and if the last function returns a string, +it's displayed in the echo area. +If a function returns any other non-nil value, no more functions are +called from the list, and no message will be displayed in the echo area." + :type '(choice (const :tag "No special message handling" nil) + (repeat + (choice (function-item :tag "Inhibit some messages" + inhibit-message) + (function-item :tag "Accumulate messages" + set-multi-message) + (function-item :tag "Handle minibuffer" + set-minibuffer-message) + (function :tag "Custom function")))) + :version "29.1") + +(defun set-message-functions (message) + (run-hook-wrapped 'set-message-functions + (lambda (fun) + (when (stringp message) + (let ((ret (funcall fun message))) + (when ret (setq message ret)))) + nil)) + message) + +(defcustom inhibit-message-regexps nil + "List of regexps that inhibit messages by the function `inhibit-message'." + :type '(repeat regexp) + :version "29.1") + +(defun inhibit-message (message) + "Don't display MESSAGE when it matches the regexp `inhibit-message-regexps'. +This function is intended to be added to `set-message-functions'." + (or (and (consp inhibit-message-regexps) + (string-match-p (mapconcat #'identity inhibit-message-regexps "\\|") + message)) + message)) + +(defcustom multi-message-timeout 2 + "Number of seconds between messages before clearing the accumulated list." + :type 'number + :version "29.1") + +(defcustom multi-message-max 8 + "Max size of the list of accumulated messages." + :type 'number + :version "29.1") + +(defvar multi-message-separator "\n") + +(defvar multi-message-list nil) + +(defun set-multi-message (message) + "Return recent messages as one string to display in the echo area. +Note that this feature works best only when `resize-mini-windows' +is at its default value `grow-only'." + (let ((last-message (car multi-message-list))) + (unless (and last-message (equal message (aref last-message 1))) + (when last-message + (cond + ((> (float-time) (+ (aref last-message 0) multi-message-timeout)) + (setq multi-message-list nil)) + ((or + ;; `message-log-max' was nil, potential clutter. + (aref last-message 2) + ;; Remove old message that is substring of the new message + (string-prefix-p (aref last-message 1) message)) + (setq multi-message-list (cdr multi-message-list))))) + (push (vector (float-time) message (not message-log-max)) multi-message-list) + (when (> (length multi-message-list) multi-message-max) + (setf (nthcdr multi-message-max multi-message-list) nil))) + (mapconcat (lambda (m) (aref m 1)) + (reverse multi-message-list) + multi-message-separator))) (defun clear-minibuffer-message () "Clear minibuffer message. commit a5bf6fb526692e21b270145070a9e5f321f9eca7 Author: Stefan Kangas Date: Sun Nov 13 19:46:02 2022 +0100 Fix suggest-key-bindings displaying key as command * lisp/simple.el (execute-extended-command--describe-binding-msg): New function factored out from... (execute-extended-command): ...here. Fix bug where a key binding was displayed as a command with 'suggest-key-bindings'. (Bug#59247) * test/lisp/simple-tests.el (simple-execute-extended-command--describe-binding-msg): New test. diff --git a/lisp/simple.el b/lisp/simple.el index 35fe130ab9..a53b7b1d0d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2491,6 +2491,13 @@ Also see `suggest-key-bindings'." (defvar execute-extended-command--binding-timer nil) +(defun execute-extended-command--describe-binding-msg (function binding shorter) + (format-message "You can run the command `%s' with %s" + function + (cond (shorter (concat "M-x " shorter)) + ((stringp binding) binding) + (t (key-description binding))))) + (defun execute-extended-command (prefixarg &optional command-name typed) "Read a command name, then read the arguments and call the command. To pass a prefix argument to the command you are @@ -2514,7 +2521,7 @@ invoking, give a prefix argument to `execute-extended-command'." (not executing-kbd-macro) (where-is-internal function overriding-local-map t))) (delay-before-suggest 0) - (find-shorter nil)) + find-shorter shorter) (unless (commandp function) (error "`%s' is not a valid command name" command-name)) ;; If we're executing a command that's remapped, we can't actually @@ -2568,15 +2575,12 @@ invoking, give a prefix argument to `execute-extended-command'." (when find-shorter (while-no-input ;; FIXME: Can be slow. Cache it maybe? - (setq binding (execute-extended-command--shorter + (setq shorter (execute-extended-command--shorter (symbol-name function) typed)))) - (when binding + (when (or binding shorter) (with-temp-message - (format-message "You can run the command `%s' with %s" - function - (if (stringp binding) - (concat "M-x " binding " RET") - (key-description binding))) + (execute-extended-command--describe-binding-msg + function binding shorter) (sit-for (if (numberp suggest-key-bindings) suggest-key-bindings 2)))))))))))) diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index acb417b80b..d067f3e586 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -84,6 +84,17 @@ "display-line") "di-n"))) +(ert-deftest simple-execute-extended-command--describe-binding-msg () + (should (equal (execute-extended-command--describe-binding-msg + 'foo "m" nil) + "You can run the command ‘foo’ with m")) + (should (equal (execute-extended-command--describe-binding-msg + 'foo [14] nil) + "You can run the command ‘foo’ with C-n")) + (should (equal (execute-extended-command--describe-binding-msg + 'display-line-numbers-mode nil "di-n") + "You can run the command ‘display-line-numbers-mode’ with M-x di-n"))) + ;;; `transpose-sexps' (defmacro simple-test--transpositions (&rest body) commit 443bd35e86b63fdd8b0ab96ab78abd801e644066 Author: Juri Linkov Date: Sun Nov 13 20:16:17 2022 +0200 * lisp/tab-bar.el: More improvements for tab-bar-auto-width (bug#59208) (tab-bar-auto-width): Use add-face-text-property instead of propertize. Prevent from going into infinite loops. More optimizations. (tab-bar-format-align-right): Use add-face-text-property, not propertize. diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 19451b4e72..eb4cec4861 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -933,7 +933,9 @@ when the tab is current. Return the result as a keymap." (let* ((rest (cdr (memq 'tab-bar-format-align-right tab-bar-format))) (rest (tab-bar-format-list rest)) (rest (mapconcat (lambda (item) (nth 2 item)) rest "")) - (hpos (string-pixel-width (propertize rest 'face 'tab-bar))) + (hpos (progn + (add-face-text-property 0 (length rest) 'tab-bar t rest) + (string-pixel-width rest))) (str (propertize " " 'display `(space :align-to (- right (,hpos)))))) `((align-right menu-item ,str ignore)))) @@ -1048,9 +1050,9 @@ tab bar might wrap to the second line when it shouldn't.") (unless (eq (nth 0 item) 'align-right) (setq non-tabs (concat non-tabs (nth 2 item))))))) (when tabs + (add-face-text-property 0 (length non-tabs) 'tab-bar t non-tabs) (setq width (/ (- (frame-inner-width) - (string-pixel-width - (propertize non-tabs 'face 'tab-bar))) + (string-pixel-width non-tabs)) (length tabs))) (when tab-bar-auto-width-min (setq width (max width (if window-system @@ -1068,28 +1070,39 @@ tab bar might wrap to the second line when it shouldn't.") (let* ((name (nth 2 item)) (len (length name)) (close-p (get-text-property (1- len) 'close-tab name)) - (pixel-width (string-pixel-width - (propertize name 'face 'tab-bar-tab)))) + (continue t) + (prev-width (string-pixel-width name)) + curr-width) (cond - ((< pixel-width width) - (let* ((space (apply 'propertize " " (text-properties-at 0 name))) - (space-width (string-pixel-width (propertize space 'face 'tab-bar))) - (ins-pos (- len (if close-p 1 0)))) - (while (<= (+ pixel-width space-width) width) + ((< prev-width width) + (let* ((space (apply 'propertize " " + (text-properties-at 0 name))) + (ins-pos (- len (if close-p 1 0))) + (prev-name name)) + (while continue (setf (substring name ins-pos ins-pos) space) - (setq pixel-width (string-pixel-width - (propertize name 'face 'tab-bar-tab)))))) - ((> pixel-width width) - (let (del-pos) - (while (> pixel-width width) - (setq len (length name) - del-pos (- len (if close-p 1 0))) - (setf (substring name (1- del-pos) del-pos) "") - (setq pixel-width (string-pixel-width - (propertize name 'face 'tab-bar-tab)))) - (add-face-text-property (max (- del-pos 3) 1) - (1- del-pos) - 'shadow nil name)))) + (setq curr-width (string-pixel-width name)) + (if (and (< curr-width width) + (not (eq curr-width prev-width))) + (setq prev-width curr-width + prev-name name) + ;; Set back a shorter name + (setq name prev-name + continue nil))))) + ((> prev-width width) + (let ((del-pos1 (if close-p -2 -1)) + (del-pos2 (if close-p -1 nil))) + (while continue + (setf (substring name del-pos1 del-pos2) "") + (setq curr-width (string-pixel-width name)) + (if (and (> curr-width width) + (not (eq curr-width prev-width))) + (setq prev-width curr-width) + (setq continue nil))) + (let* ((len (length name)) + (pos (- len (if close-p 1 0)))) + (add-face-text-property + (max 0 (- pos 2)) (max 0 pos) 'shadow nil name))))) name))))) items)) commit 7d53164162b3e36b53f52f4132cea3202919f749 Author: Ingo Lohmar Date: Sun Nov 13 17:27:12 2022 +0100 Eglot: fix null scopeUri regression in workspace/configuration * lisp/progmodes/eglot.el (eglot-handle-request): Commit 1a2d603bb3938ff68ed1a5412d131b41efd40a24 changed `eglot--uri-to-path' to return a nil uri untouched. (Before, `url-unhex-string' turned the parsed all-nil uri record into the empty string.) A nil return value must now be handled in the caller, do that for the workspace/configuration handler to avoid an uncaught error. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 98d5281d2c..12808e80c4 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2368,10 +2368,11 @@ When called interactively, use the currently active server" (with-temp-buffer (let* ((uri-path (eglot--uri-to-path scopeUri)) (default-directory - (if (and (not (string-empty-p uri-path)) - (file-directory-p uri-path)) - (file-name-as-directory uri-path) - (project-root (eglot--project server))))) + (if (and uri-path + (not (string-empty-p uri-path)) + (file-directory-p uri-path)) + (file-name-as-directory uri-path) + (project-root (eglot--project server))))) (setq-local major-mode (car (eglot--major-modes server))) (hack-dir-local-variables-non-file-buffer) (cl-loop for (wsection o) commit ae1a6b5bdf112716aa4bf08cbb723dc3d393f6ed Author: Stefan Kangas Date: Sun Nov 13 15:58:48 2022 +0100 ; * lisp/simple.el (execute-extended-command): Improve comments. diff --git a/lisp/simple.el b/lisp/simple.el index 5f676ea50d..35fe130ab9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2492,8 +2492,6 @@ Also see `suggest-key-bindings'." (defvar execute-extended-command--binding-timer nil) (defun execute-extended-command (prefixarg &optional command-name typed) - ;; Based on Fexecute_extended_command in keyboard.c of Emacs. - ;; Aaron S. Hawley 2009-08-24 "Read a command name, then read the arguments and call the command. To pass a prefix argument to the command you are invoking, give a prefix argument to `execute-extended-command'." @@ -2540,11 +2538,11 @@ invoking, give a prefix argument to `execute-extended-command'." ;; flight. (when execute-extended-command--binding-timer (cancel-timer execute-extended-command--binding-timer)) - ;; If this command displayed something in the echo area, then - ;; postpone the display of our suggestion message a bit. (when (and suggest-key-bindings (or binding (and extended-command-suggest-shorter typed))) + ;; If this command displayed something in the echo area, then + ;; postpone the display of our suggestion message a bit. (setq delay-before-suggest (cond ((zerop (length (current-message))) 0) @@ -2556,7 +2554,7 @@ invoking, give a prefix argument to `execute-extended-command'." (symbolp function) (> (length (symbol-name function)) 2)) ;; There's no binding for CMD. Let's try and find the shortest - ;; string to use in M-x. + ;; string to use in M-x. But don't actually do anything yet. (setq find-shorter t)) (when (or binding find-shorter) (setq execute-extended-command--binding-timer commit 90a7dee79d0b99131ba97d05acc4bf8c9294fc15 Author: Stefan Kangas Date: Sun Nov 13 15:34:02 2022 +0100 New test for execute-extended-command helper defun * test/lisp/simple-tests.el (simple-execute-extended-command--shorter): New test. diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index 97f425f6f4..acb417b80b 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -72,6 +72,18 @@ (insert "あ\nい\nう\nえ\nお\n") (should (= (count-lines (point) (point)) 0)))) + +;;; `execute-extended-command' + +(ert-deftest simple-execute-extended-command--shorter () + ;; This test can be flaky with completion frameworks other than the + ;; default, so just skip it in interactive sessions. + (skip-unless noninteractive) + (should (equal (execute-extended-command--shorter + "display-line-numbers-mode" + "display-line") + "di-n"))) + ;;; `transpose-sexps' (defmacro simple-test--transpositions (&rest body) commit 73c03d64cec9869951ff0d52571671429032c7ca Author: Stefan Kangas Date: Sat Nov 12 21:14:23 2022 +0100 Prefer defvar-keymap in sql.el * lisp/progmodes/sql.el (sql-interactive-mode-map, sql-mode-map): Prefer defvar-keymap. diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index 4121e4dc3c..a1c0aa76de 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el @@ -1358,37 +1358,33 @@ specified, it's `sql-product' or `sql-connection' must match." ;; Keymap for sql-interactive-mode. -(defvar sql-interactive-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map comint-mode-map) - (define-key map (kbd "C-j") 'sql-accumulate-and-indent) - (define-key map (kbd "C-c C-w") 'sql-copy-column) - (define-key map (kbd "O") 'sql-magic-go) - (define-key map (kbd "o") 'sql-magic-go) - (define-key map (kbd ";") 'sql-magic-semicolon) - (define-key map (kbd "C-c C-l a") 'sql-list-all) - (define-key map (kbd "C-c C-l t") 'sql-list-table) - map) - "Mode map used for `sql-interactive-mode'. -Based on `comint-mode-map'.") +(defvar-keymap sql-interactive-mode-map + :doc "Mode map used for `sql-interactive-mode'. +Based on `comint-mode-map'." + :parent comint-mode-map + "C-j" #'sql-accumulate-and-indent + "C-c C-w" #'sql-copy-column + "O" #'sql-magic-go + "o" #'sql-magic-go + ";" #'sql-magic-semicolon + "C-c C-l a" #'sql-list-all + "C-c C-l t" #'sql-list-table) ;; Keymap for sql-mode. -(defvar sql-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-c") 'sql-send-paragraph) - (define-key map (kbd "C-c C-r") 'sql-send-region) - (define-key map (kbd "C-c C-s") 'sql-send-string) - (define-key map (kbd "C-c C-b") 'sql-send-buffer) - (define-key map (kbd "C-c C-n") 'sql-send-line-and-next) - (define-key map (kbd "C-c C-i") 'sql-product-interactive) - (define-key map (kbd "C-c C-z") 'sql-show-sqli-buffer) - (define-key map (kbd "C-c C-l a") 'sql-list-all) - (define-key map (kbd "C-c C-l t") 'sql-list-table) - (define-key map [remap beginning-of-defun] 'sql-beginning-of-statement) - (define-key map [remap end-of-defun] 'sql-end-of-statement) - map) - "Mode map used for `sql-mode'.") +(defvar-keymap sql-mode-map + :doc "Mode map used for `sql-mode'." + "C-c C-c" #'sql-send-paragraph + "C-c C-r" #'sql-send-region + "C-c C-s" #'sql-send-string + "C-c C-b" #'sql-send-buffer + "C-c C-n" #'sql-send-line-and-next + "C-c C-i" #'sql-product-interactive + "C-c C-z" #'sql-show-sqli-buffer + "C-c C-l a" #'sql-list-all + "C-c C-l t" #'sql-list-table + " " #'sql-beginning-of-statement + " " #'sql-end-of-statement) ;; easy menu for sql-mode. commit ae9e4414159b974e299f891a4edb46c89ca5b7ba Author: Davide Masserut Date: Sun Nov 13 12:30:43 2022 +0100 Add new Go modes to eglot-server-programs * lisp/progmodes/eglot.el (eglot-server-programs): Add new major modes for Go to be used with gopls. (Bug#59245) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 97c674f7aa..98d5281d2c 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -206,7 +206,7 @@ language-server/bin/php-language-server.php")) (elm-mode . ("elm-language-server")) (mint-mode . ("mint" "ls")) (kotlin-mode . ("kotlin-language-server")) - (go-mode . ("gopls")) + ((go-mode go-dot-mod-mode go-dot-work-mode) . ("gopls")) ((R-mode ess-r-mode) . ("R" "--slave" "-e" "languageserver::run()")) (java-mode . ("jdtls")) commit 7a9beac46142eb70061c45ef222d72f84b7b18ab Author: Po Lu Date: Sun Nov 13 17:30:37 2022 +0800 Fix bug#59075 * src/nsimage.m (ns_can_use_native_image_api): Do not use native image APIs for SVG images when RSVG is present. (bug#59075) diff --git a/src/nsimage.m b/src/nsimage.m index 9cb5090dd0..dd8768664a 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -74,8 +74,10 @@ Updated by Christian Limpach (chris@nice.ch) imageType = @"com.compuserve.gif"; else if (EQ (type, Qtiff)) imageType = @"public.tiff"; +#ifndef HAVE_RSVG else if (EQ (type, Qsvg)) imageType = @"public.svg-image"; +#endif else if (EQ (type, Qheic)) imageType = @"public.heic";