* bug#50042: 26.3; Post-command hooks slow with M-x commands @ 2021-08-13 11:52 ` Simon Katz 2021-08-13 12:27 ` Lars Ingebrigtsen [not found] ` <handler.50042.C.162902754922550.notifdonectrl.0@debbugs.gnu.org> 0 siblings, 2 replies; 15+ messages in thread From: Simon Katz @ 2021-08-13 11:52 UTC (permalink / raw) To: 50042 [-- Attachment #1: Type: text/plain, Size: 5161 bytes --] Post-command hooks are slow to run for commands invoked using `M-x ...`. I'm using Emacs 26.3 (which produced this bug report), but I've checked with 27.2.2 and I get the same behaviour. Here's a startup file that can be used to show this (also at https://github.com/simon-katz/demo-post-command-hook-slow-with-m-x-commands.el/blob/8e7b96fc322f6372fb1531f04ab6008d59ab9b9e/demo-post-command-hook-slow-with-m-x-commands.el#L1 ). ;;; demo-post-command-hook-slow-with-m-x-commands.el --- Demo that post-sommand hooks are slow with M-x commands -*- lexical-binding: t; -*- ;; This demonstrates an issue with `(add-hook 'post-command-hook ...)`. ;; To reproduce the problem: ;; - Run `emacs -q -l demo-post-command-hook-slow-with-m-x-commands.el` (that's ;; this file). ;; - Enter `M-x next-line`. ;; - Observe that the message displayed by the `say-something` function ;; takes a while to appear. ;; - Contrast with hitting the down-arrow key, when the message appears ;; immediately. ;;; Code: (require 'package) (setq debug-on-error t no-byte-compile t package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/")) package-user-dir (expand-file-name (make-temp-name "flycheck-tmp-elpa") user-emacs-directory) custom-file (expand-file-name "custom.el" package-user-dir)) (defun say-something () (let ((inhibit-message t)) (message "With `M-x next-line` (for example), this message is slow to appear"))) (add-hook 'post-command-hook 'say-something) (display-buffer "*Messages*") (provide 'demo-post-command-hook-slow-with-m-x-commands) ;;; demo-post-command-hook-slow-with-m-x-commands.el ends here In GNU Emacs 26.3 (build 1, x86_64-apple-darwin18.2.0, NS appkit-1671.20 Version 10.14.3 (Build 18D109)) of 2019-09-02 built on builder10-14.porkrind.org Windowing system distributor 'Apple', version 10.3.1894 Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. With ‘M-x next-line‘ (for example), this message is slow to appear [13 times] You can run the command ‘next-line’ with C-n With ‘M-x next-line‘ (for example), this message is slow to appear [10 times] Quit With ‘M-x next-line‘ (for example), this message is slow to appear [7 times] Making completion list... With ‘M-x next-line‘ (for example), this message is slow to appear [6 times] Configured using: 'configure --with-ns '--enable-locallisppath=/Library/Application Support/Emacs/${version}/site-lisp:/Library/Application Support/Emacs/site-lisp' --with-modules' Configured features: NOTIFY ACL GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS MODULES THREADS Important settings: value of $LANG: en_GB.UTF-8 locale-coding-system: utf-8-unix Major mode: Fundamental Minor modes in effect: tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t buffer-read-only: t line-number-mode: t transient-mark-mode: t Load-path shadows: None found. Features: (shadow sort map mail-extr emacsbug message rmc puny dired dired-loaddefs format-spec rfc822 mml mml-sec epa derived epg gnus-util rmail rmail-loaddefs mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils demo-post-command-hook-slow-with-m-x-commands package easymenu epg-config url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs eieio-loaddefs password-cache url-vars seq byte-opt gv bytecomp byte-compile cconv cl-loaddefs cl-lib elec-pair time-date tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel term/ns-win ns-win ucs-normalize mule-util term/common-win tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow isearch timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote threads kqueue cocoa ns multi-tty make-network-process emacs) Memory information: ((conses 16 213714 7973) (symbols 48 21049 1) (miscs 40 83 191) (strings 32 31839 1672) (string-bytes 1 863206) (vectors 16 36747) (vector-slots 8 745240 8812) (floats 8 57 65) (intervals 56 214 0) (buffers 992 13)) [-- Attachment #2: Type: text/html, Size: 6001 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-13 11:52 ` bug#50042: 26.3; Post-command hooks slow with M-x commands Simon Katz @ 2021-08-13 12:27 ` Lars Ingebrigtsen 2021-08-13 12:40 ` Simon Katz 2021-08-14 16:36 ` Lars Ingebrigtsen [not found] ` <handler.50042.C.162902754922550.notifdonectrl.0@debbugs.gnu.org> 1 sibling, 2 replies; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-13 12:27 UTC (permalink / raw) To: Simon Katz; +Cc: 50042 Simon Katz <sk@nomistech.com> writes: > Here's a startup file that can be used to show this (also at Simpler repro: (add-hook 'post-command-hook (lambda () (let ((inhibit-message t)) (message "foo: %s" this-command)))) (display-buffer "*Messages*") M-x previous-line I think this has something to do with the You can run the command ‘previous-line’ with C-p stuff -- if the `M-x' command in question isn't bound to anything, `post-command-hook' is run immediately instead of after a two-second timeout. Hm... yup: `execute-extended-command' ends with (when binding (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))) (sit-for (if (numberp suggest-key-bindings) suggest-key-bindings 2)))))))) So presumably `post-command-hook' isn't run after that timeout has completed. Uhm... anybody got any ideas how to fix this? I mean, in one way it's behaving as it's supposed to -- the command really isn't finished after this sit-for has finished. On the other hand, it's pretty awkward. Could we yank this out of the flow and run it from a timer (fired immediately) instead? -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-13 12:27 ` Lars Ingebrigtsen @ 2021-08-13 12:40 ` Simon Katz 2021-08-14 16:36 ` Lars Ingebrigtsen 1 sibling, 0 replies; 15+ messages in thread From: Simon Katz @ 2021-08-13 12:40 UTC (permalink / raw) To: Lars Ingebrigtsen; +Cc: 50042 [-- Attachment #1: Type: text/plain, Size: 274 bytes --] It's probably worth me giving a bit more context… I'm using `lsp-ui`, and that's using post-command hooks to update the UI. If I use `M-x flycheck-next-error` (for example), it takes time for the UI to update. See https://github.com/emacs-lsp/lsp-ui/issues/647 [-- Attachment #2: Type: text/html, Size: 468 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-13 12:27 ` Lars Ingebrigtsen 2021-08-13 12:40 ` Simon Katz @ 2021-08-14 16:36 ` Lars Ingebrigtsen 2021-08-14 20:52 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-14 16:36 UTC (permalink / raw) To: Simon Katz; +Cc: 50042, Stefan Monnier Lars Ingebrigtsen <larsi@gnus.org> writes: > Simpler repro: > > (add-hook 'post-command-hook > (lambda () > (let ((inhibit-message t)) > (message "foo: %s" this-command)))) > (display-buffer "*Messages*") > > M-x previous-line [...] > `execute-extended-command' ends with > > (when binding > (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))) > (sit-for (if (numberp suggest-key-bindings) > suggest-key-bindings > 2)))))))) > > So presumably `post-command-hook' isn't run after that timeout has > completed. [...] > Could we yank this out of the flow and run it from a timer (fired > immediately) instead? Stefan, I forgot to put you on the CCs here -- I wondered whether you had any ideas here. I think lifting this out of `execute-extended-command' should be possible -- either by doing something a la (run-at-time 0 nil (lambda () (with-temp-message "The binding is foo" (sit-for 1)))) or making `execute-extended-command' set a variable and do the messaging from the "command loop" after running post-command-hook. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-14 16:36 ` Lars Ingebrigtsen @ 2021-08-14 20:52 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2021-08-15 11:38 ` Lars Ingebrigtsen 0 siblings, 1 reply; 15+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2021-08-14 20:52 UTC (permalink / raw) To: Lars Ingebrigtsen; +Cc: 50042, Simon Katz >> `execute-extended-command' ends with >> >> (when binding >> (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))) >> (sit-for (if (numberp suggest-key-bindings) >> suggest-key-bindings >> 2)))))))) Indeed this `sit-for` is a problem because it delays running the `post-command-hook`. [ We have a few other such problems, tho I sadly didn't bother to keep track of them. ] > Stefan, I forgot to put you on the CCs here -- I wondered whether you > had any ideas here. I think lifting this out of > `execute-extended-command' should be possible -- either by doing > something a la > > (run-at-time 0 nil (lambda () > (with-temp-message "The binding is foo" > (sit-for 1)))) > > or making `execute-extended-command' set a variable and do the messaging > from the "command loop" after running post-command-hook. Using a timer might be a good option, indeed. Stefan ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-14 20:52 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2021-08-15 11:38 ` Lars Ingebrigtsen 2021-08-17 0:41 ` Dmitry Gutov 0 siblings, 1 reply; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-15 11:38 UTC (permalink / raw) To: Stefan Monnier; +Cc: 50042, Simon Katz Stefan Monnier <monnier@iro.umontreal.ca> writes: > Using a timer might be a good option, indeed. OK; I've now implemented a solution based on `run-at-time', and after using it for a bit, I'm not seeing any glitches usage-wise, so I'm pushing it. But I realise that there might be some peculiarities in this area, so we'll see... -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: 26.3; Post-command hooks slow with M-x commands 2021-08-15 11:38 ` Lars Ingebrigtsen @ 2021-08-17 0:41 ` Dmitry Gutov 0 siblings, 0 replies; 15+ messages in thread From: Dmitry Gutov @ 2021-08-17 0:41 UTC (permalink / raw) To: Lars Ingebrigtsen, Stefan Monnier; +Cc: 50042, Simon Katz On 15.08.2021 14:38, Lars Ingebrigtsen wrote: > OK; I've now implemented a solution based on `run-at-time', and after > using it for a bit, I'm not seeing any glitches usage-wise, so I'm > pushing it. Thanks for this change, it's been a long time coming. ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <handler.50042.C.162902754922550.notifdonectrl.0@debbugs.gnu.org>]
* bug#50042: acknowledged by developer (control message for bug #50042) [not found] ` <handler.50042.C.162902754922550.notifdonectrl.0@debbugs.gnu.org> @ 2021-08-18 15:27 ` Simon Katz 2021-08-18 15:33 ` Simon Katz 2021-08-18 15:37 ` Simon Katz 0 siblings, 2 replies; 15+ messages in thread From: Simon Katz @ 2021-08-18 15:27 UTC (permalink / raw) To: 50042 Hi Lars, Thanks for fixing the bug I reported. You mentioned that there might be some peculiarities in this area, and indeed that seems to be the case. I still have a problem. If you are interested in what I am trying to fix, see https://github.com/emacs-lsp/lsp-ui/issues/647 Note that everything is fine if I set `suggest-key-bindings` to `nil`. The problems seem to be with commands that both (a) write messages to the echo area, and (b) have key bindings. The code below reproduces the problem. See the comments at the beginning for instructions. -------------------------------------------------------------------------------- ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el --- Demo that post-command hooks are slow with M-x commands -*- lexical-binding: t; -*- ;; This demonstrates an issue with: ;; `(add-hook 'post-command-hook ...)`. ;; It's a follow-up to an already-reported and partially-fixed problem -- see ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=50042 ;; To reproduce the problem: ;; ;; - Run `emacs -q -l <this-file>` ;; ;; - Enter `M-x **-msg-cmd-without-key-binding`. ;; - Observe that it takes many seconds (~15 for me) to produce output to the ;; "my-output" buffer, and that the "*Messages*" buffer has the message: ;; You can run the command ‘**-msg-cmd-without-key-binding’ with M-x -witho RET ;; ;; - Enter `M-x **-msg-cmd-without-key-binding` again. ;; - Observe that both the "*Messages*" buffer and the "my-output" buffer update ;; immediately. ;; - Repeatedly enter `M-x **-msg-cmd-without-key-binding` and observe the same ;; - result. ;; ;; - Enter `M-x **-msg-cmd-with-key-binding`. ;; - Observe that it takes 2 seconds for output to appear in the "my-output" ;; buffer. ;; - Observe that the behaviour is the same if the command is repeated. ;; ;; - Use the `C-c C-c` key binding, to invoke `**-msg-cmd-with-key-binding`. ;; - Observe that there are no delays. ;; Emacs displays the "*GNU Emacs*" buffer after loading this file, so use ;; `run-at-time` to delay setting up which buffers are displayed. (run-at-time 1 nil (lambda () (switch-to-buffer "*Messages*" nil t) (display-buffer (generate-new-buffer "my-output")) ;; Arrange things so that we see the output as it appears: (select-window (get-buffer-window "my-output")))) (defun date-time () (format-time-string "%Y-%m-%d %H:%M:%S")) (defun post-command-message () (when (member this-command '(**-msg-cmd-with-key-binding **-msg-cmd-without-key-binding)) (with-current-buffer "my-output" (goto-char (point-max)) (insert (date-time) " The command `" (format "%s" this-command) "` was executed\n") (goto-char (point-max))))) (add-hook 'post-command-hook 'post-command-message) (defun **-msg-cmd-without-key-binding () (interactive) (message "%s Hello from `**-msg-cmd-without-key-binding`" (date-time))) (defun **-msg-cmd-with-key-binding () (interactive) (message "%s Hello from `**-msg-cmd-with-key-binding`" (date-time))) (define-key global-map (kbd "C-c C-c") '**-msg-cmd-with-key-binding) (setq suggest-key-bindings nil) (when t ; Whether to load the changes in Emacs commit 42a98feb5b (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 <aaron.s.hawley(at)gmail.com> 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'." (declare (interactive-only command-execute)) ;; FIXME: Remember the actual text typed by the user before completion, ;; so that we don't later on suggest the same shortening. (interactive (let ((execute-extended-command--last-typed nil)) (list current-prefix-arg (read-extended-command) execute-extended-command--last-typed))) ;; Emacs<24 calling-convention was with a single `prefixarg' argument. (unless command-name (let ((current-prefix-arg prefixarg) ; for prompt (execute-extended-command--last-typed nil)) (setq command-name (read-extended-command)) (setq typed execute-extended-command--last-typed))) (let* ((function (and (stringp command-name) (intern-soft command-name))) (binding (and suggest-key-bindings (not executing-kbd-macro) (where-is-internal function overriding-local-map t)))) (unless (commandp function) (error "`%s' is not a valid command name" command-name)) ;; Some features, such as novice.el, rely on this-command-keys ;; including M-x COMMAND-NAME RET. (set--this-command-keys (concat "\M-x" (symbol-name function) "\r")) (setq this-command function) ;; Normally `real-this-command' should never be changed, but here we really ;; want to pretend that M-x <cmd> RET is nothing more than a "key ;; binding" for <cmd>, so the command the user really wanted to run is ;; `function' and not `execute-extended-command'. The difference is ;; visible in cases such as M-x <cmd> RET and then C-x z (bug#11506). (setq real-this-command function) (let ((prefix-arg prefixarg)) (command-execute function 'record)) ;; If enabled, show which key runs this command. ;; But first wait, and skip the message if there is input. (let* ((waited ;; If this command displayed something in the echo area; ;; wait a few seconds, then display our suggestion message. ;; FIXME: Wait *after* running post-command-hook! ;; FIXME: If execute-extended-command--shorter were ;; faster, we could compute the result here first too. (when (and suggest-key-bindings (or binding (and extended-command-suggest-shorter typed))) (sit-for (cond ((zerop (length (current-message))) 0) ((numberp suggest-key-bindings) suggest-key-bindings) (t 2)))))) (when (and waited (not (consp unread-command-events))) (unless (or (not extended-command-suggest-shorter) binding executing-kbd-macro (not (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. ;; FIXME: Can be slow. Cache it maybe? (while-no-input (setq binding (execute-extended-command--shorter (symbol-name function) typed)))) (when binding ;; This is normally not necessary -- the timer should run ;; immediately, but be defensive and ensure that we never ;; have two of these timers in flight. (when execute-extended-command--binding-timer (cancel-timer execute-extended-command--binding-timer)) (setq execute-extended-command--binding-timer (run-at-time 0 nil (lambda () (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))) (sit-for (if (numberp suggest-key-bindings) suggest-key-bindings 2)))))))))))) (provide 'demo-post-command-hook-slow-with-m-x-commands-v2) ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el ends here -------------------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-18 15:27 ` bug#50042: acknowledged by developer (control message for bug #50042) Simon Katz @ 2021-08-18 15:33 ` Simon Katz 2021-08-18 15:37 ` Simon Katz 1 sibling, 0 replies; 15+ messages in thread From: Simon Katz @ 2021-08-18 15:33 UTC (permalink / raw) To: 50042 Oh, I'm really sorry… I was playing around and I accidentally left in the `(setq suggest-key-bindings nil)` form. Please remove that in order to reproduce the problem! On Wed, 18 Aug 2021 at 16:27, Simon Katz <sk@nomistech.com> wrote: > > Hi Lars, > > Thanks for fixing the bug I reported. > > You mentioned that there might be some peculiarities in this > area, and indeed that seems to be the case. > > I still have a problem. If you are interested in what I am trying > to fix, see https://github.com/emacs-lsp/lsp-ui/issues/647 > > Note that everything is fine if I set `suggest-key-bindings` to > `nil`. > > The problems seem to be with commands that both (a) write > messages to the echo area, and (b) have key bindings. > > The code below reproduces the problem. See the comments at the > beginning for instructions. > > > -------------------------------------------------------------------------------- > > ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el --- Demo that > post-command hooks are slow with M-x commands -*- > lexical-binding: t; -*- > > ;; This demonstrates an issue with: > ;; `(add-hook 'post-command-hook ...)`. > ;; It's a follow-up to an already-reported and partially-fixed problem -- see > ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=50042 > > ;; To reproduce the problem: > ;; > ;; - Run `emacs -q -l <this-file>` > ;; > ;; - Enter `M-x **-msg-cmd-without-key-binding`. > ;; - Observe that it takes many seconds (~15 for me) to produce output to the > ;; "my-output" buffer, and that the "*Messages*" buffer has the message: > ;; You can run the command ‘**-msg-cmd-without-key-binding’ with > M-x -witho RET > ;; > ;; - Enter `M-x **-msg-cmd-without-key-binding` again. > ;; - Observe that both the "*Messages*" buffer and the "my-output" buffer update > ;; immediately. > ;; - Repeatedly enter `M-x **-msg-cmd-without-key-binding` and observe the same > ;; - result. > ;; > ;; - Enter `M-x **-msg-cmd-with-key-binding`. > ;; - Observe that it takes 2 seconds for output to appear in the "my-output" > ;; buffer. > ;; - Observe that the behaviour is the same if the command is repeated. > ;; > ;; - Use the `C-c C-c` key binding, to invoke `**-msg-cmd-with-key-binding`. > ;; - Observe that there are no delays. > > > ;; Emacs displays the "*GNU Emacs*" buffer after loading this file, so use > ;; `run-at-time` to delay setting up which buffers are displayed. > (run-at-time 1 > nil > (lambda () > (switch-to-buffer "*Messages*" nil t) > (display-buffer (generate-new-buffer "my-output")) > ;; Arrange things so that we see the output as it appears: > (select-window (get-buffer-window "my-output")))) > > (defun date-time () > (format-time-string "%Y-%m-%d %H:%M:%S")) > > (defun post-command-message () > (when (member this-command > '(**-msg-cmd-with-key-binding > **-msg-cmd-without-key-binding)) > (with-current-buffer "my-output" > (goto-char (point-max)) > (insert (date-time) > " The command `" > (format "%s" this-command) > "` was executed\n") > (goto-char (point-max))))) > > (add-hook 'post-command-hook 'post-command-message) > > (defun **-msg-cmd-without-key-binding () > (interactive) > (message "%s Hello from `**-msg-cmd-without-key-binding`" > (date-time))) > > (defun **-msg-cmd-with-key-binding () > (interactive) > (message "%s Hello from `**-msg-cmd-with-key-binding`" > (date-time))) > > (define-key global-map (kbd "C-c C-c") '**-msg-cmd-with-key-binding) > > (setq suggest-key-bindings nil) > > (when t ; Whether to load the changes in Emacs commit 42a98feb5b > > (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 <aaron.s.hawley(at)gmail.com> 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'." > (declare (interactive-only command-execute)) > ;; FIXME: Remember the actual text typed by the user before completion, > ;; so that we don't later on suggest the same shortening. > (interactive > (let ((execute-extended-command--last-typed nil)) > (list current-prefix-arg > (read-extended-command) > execute-extended-command--last-typed))) > ;; Emacs<24 calling-convention was with a single `prefixarg' argument. > (unless command-name > (let ((current-prefix-arg prefixarg) ; for prompt > (execute-extended-command--last-typed nil)) > (setq command-name (read-extended-command)) > (setq typed execute-extended-command--last-typed))) > (let* ((function (and (stringp command-name) (intern-soft command-name))) > (binding (and suggest-key-bindings > (not executing-kbd-macro) > (where-is-internal function overriding-local-map t)))) > (unless (commandp function) > (error "`%s' is not a valid command name" command-name)) > ;; Some features, such as novice.el, rely on this-command-keys > ;; including M-x COMMAND-NAME RET. > (set--this-command-keys (concat "\M-x" (symbol-name function) "\r")) > (setq this-command function) > ;; Normally `real-this-command' should never be changed, but > here we really > ;; want to pretend that M-x <cmd> RET is nothing more than a "key > ;; binding" for <cmd>, so the command the user really wanted to run is > ;; `function' and not `execute-extended-command'. The difference is > ;; visible in cases such as M-x <cmd> RET and then C-x z (bug#11506). > (setq real-this-command function) > (let ((prefix-arg prefixarg)) > (command-execute function 'record)) > ;; If enabled, show which key runs this command. > ;; But first wait, and skip the message if there is input. > (let* ((waited > ;; If this command displayed something in the echo area; > ;; wait a few seconds, then display our suggestion message. > ;; FIXME: Wait *after* running post-command-hook! > ;; FIXME: If execute-extended-command--shorter were > ;; faster, we could compute the result here first too. > (when (and suggest-key-bindings > (or binding > (and extended-command-suggest-shorter typed))) > (sit-for (cond > ((zerop (length (current-message))) 0) > ((numberp suggest-key-bindings) suggest-key-bindings) > (t 2)))))) > (when (and waited (not (consp unread-command-events))) > (unless (or (not extended-command-suggest-shorter) > binding executing-kbd-macro (not (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. > ;; FIXME: Can be slow. Cache it maybe? > (while-no-input > (setq binding (execute-extended-command--shorter > (symbol-name function) typed)))) > (when binding > ;; This is normally not necessary -- the timer should run > ;; immediately, but be defensive and ensure that we never > ;; have two of these timers in flight. > (when execute-extended-command--binding-timer > (cancel-timer execute-extended-command--binding-timer)) > (setq execute-extended-command--binding-timer > (run-at-time > 0 nil > (lambda () > (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))) > (sit-for (if (numberp suggest-key-bindings) > suggest-key-bindings > 2)))))))))))) > > (provide 'demo-post-command-hook-slow-with-m-x-commands-v2) > ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el ends here > > -------------------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-18 15:27 ` bug#50042: acknowledged by developer (control message for bug #50042) Simon Katz 2021-08-18 15:33 ` Simon Katz @ 2021-08-18 15:37 ` Simon Katz 2021-08-19 13:07 ` Lars Ingebrigtsen 1 sibling, 1 reply; 15+ messages in thread From: Simon Katz @ 2021-08-18 15:37 UTC (permalink / raw) To: 50042 (Just so that you see the new part of the previous message -- apologies for my cack-handedness at driving Gmail with plain text!) Oh, I'm really sorry… I was playing around and I accidentally left in the `(setq suggest-key-bindings nil)` form. Please remove that in order to reproduce the problem! ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-18 15:37 ` Simon Katz @ 2021-08-19 13:07 ` Lars Ingebrigtsen 2021-08-19 14:55 ` Simon Katz 0 siblings, 1 reply; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-19 13:07 UTC (permalink / raw) To: Simon Katz; +Cc: 50042 Simon Katz <sk@nomistech.com> writes: > (Just so that you see the new part of the previous > message -- apologies for my cack-handedness at > driving Gmail with plain text!) > > Oh, I'm really sorry… > > I was playing around and I accidentally left in the > `(setq suggest-key-bindings nil)` form. > > Please remove that in order to reproduce the problem! The file for reproducing the problem was apparently mangled during transmission, too. Can you re-send the file as an attachment? -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-19 13:07 ` Lars Ingebrigtsen @ 2021-08-19 14:55 ` Simon Katz 2021-08-20 13:09 ` Lars Ingebrigtsen 0 siblings, 1 reply; 15+ messages in thread From: Simon Katz @ 2021-08-19 14:55 UTC (permalink / raw) To: Lars Ingebrigtsen; +Cc: 50042 [-- Attachment #1: Type: text/plain, Size: 166 bytes --] > The file for reproducing the problem was apparently mangled during > transmission, too. Can you re-send the file as an attachment? Sure. Please find it attached. [-- Attachment #2: demo-post-command-hook-slow-with-m-x-commands-v2.el --] [-- Type: application/octet-stream, Size: 7514 bytes --] ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el --- Demo that post-command hooks are slow with M-x commands -*- lexical-binding: t; -*- ;; This demonstrates an issue with: ;; `(add-hook 'post-command-hook ...)`. ;; It's a follow-up to an already-reported and partially-fixed problem -- see ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=50042 ;; To reproduce the problem: ;; ;; - Run `emacs -q -l <this-file>` ;; ;; - Enter `M-x **-msg-cmd-without-key-binding`. ;; - Observe that it takes many seconds (~15 for me) to produce output to the ;; "my-output" buffer, and that the "*Messages*" buffer has the message: ;; You can run the command ‘**-msg-cmd-without-key-binding’ with M-x -witho RET ;; ;; - Enter `M-x **-msg-cmd-without-key-binding` again. ;; - Observe that both the "*Messages*" buffer and the "my-output" buffer update ;; immediately. ;; - Repeatedly enter `M-x **-msg-cmd-without-key-binding` and observe the same ;; - result. ;; ;; - Enter `M-x **-msg-cmd-with-key-binding`. ;; - Observe that it takes 2 seconds for output to appear in the "my-output" ;; buffer. ;; - Observe that the behaviour is the same if the command is repeated. ;; ;; - Use the `C-c C-c` key binding, to invoke `**-msg-cmd-with-key-binding`. ;; - Observe that there are no delays. ;; Emacs displays the "*GNU Emacs*" buffer after loading this file, so use ;; `run-at-time` to delay setting up which buffers are displayed. (run-at-time 1 nil (lambda () (switch-to-buffer "*Messages*" nil t) (display-buffer (generate-new-buffer "my-output")) ;; Arrange things so that we see the output as it appears: (select-window (get-buffer-window "my-output")))) (defun date-time () (format-time-string "%Y-%m-%d %H:%M:%S")) (defun post-command-message () (when (member this-command '(**-msg-cmd-with-key-binding **-msg-cmd-without-key-binding)) (with-current-buffer "my-output" (goto-char (point-max)) (insert (date-time) " The command `" (format "%s" this-command) "` was executed\n") (goto-char (point-max))))) (add-hook 'post-command-hook 'post-command-message) (defun **-msg-cmd-without-key-binding () (interactive) (message "%s Hello from `**-msg-cmd-without-key-binding`" (date-time))) (defun **-msg-cmd-with-key-binding () (interactive) (message "%s Hello from `**-msg-cmd-with-key-binding`" (date-time))) (define-key global-map (kbd "C-c C-c") '**-msg-cmd-with-key-binding) (when t ; Whether to load the changes in Emacs commit 42a98feb5b (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 <aaron.s.hawley(at)gmail.com> 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'." (declare (interactive-only command-execute)) ;; FIXME: Remember the actual text typed by the user before completion, ;; so that we don't later on suggest the same shortening. (interactive (let ((execute-extended-command--last-typed nil)) (list current-prefix-arg (read-extended-command) execute-extended-command--last-typed))) ;; Emacs<24 calling-convention was with a single `prefixarg' argument. (unless command-name (let ((current-prefix-arg prefixarg) ; for prompt (execute-extended-command--last-typed nil)) (setq command-name (read-extended-command)) (setq typed execute-extended-command--last-typed))) (let* ((function (and (stringp command-name) (intern-soft command-name))) (binding (and suggest-key-bindings (not executing-kbd-macro) (where-is-internal function overriding-local-map t)))) (unless (commandp function) (error "`%s' is not a valid command name" command-name)) ;; Some features, such as novice.el, rely on this-command-keys ;; including M-x COMMAND-NAME RET. (set--this-command-keys (concat "\M-x" (symbol-name function) "\r")) (setq this-command function) ;; Normally `real-this-command' should never be changed, but here we really ;; want to pretend that M-x <cmd> RET is nothing more than a "key ;; binding" for <cmd>, so the command the user really wanted to run is ;; `function' and not `execute-extended-command'. The difference is ;; visible in cases such as M-x <cmd> RET and then C-x z (bug#11506). (setq real-this-command function) (let ((prefix-arg prefixarg)) (command-execute function 'record)) ;; If enabled, show which key runs this command. ;; But first wait, and skip the message if there is input. (let* ((waited ;; If this command displayed something in the echo area; ;; wait a few seconds, then display our suggestion message. ;; FIXME: Wait *after* running post-command-hook! ;; FIXME: If execute-extended-command--shorter were ;; faster, we could compute the result here first too. (when (and suggest-key-bindings (or binding (and extended-command-suggest-shorter typed))) (sit-for (cond ((zerop (length (current-message))) 0) ((numberp suggest-key-bindings) suggest-key-bindings) (t 2)))))) (when (and waited (not (consp unread-command-events))) (unless (or (not extended-command-suggest-shorter) binding executing-kbd-macro (not (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. ;; FIXME: Can be slow. Cache it maybe? (while-no-input (setq binding (execute-extended-command--shorter (symbol-name function) typed)))) (when binding ;; This is normally not necessary -- the timer should run ;; immediately, but be defensive and ensure that we never ;; have two of these timers in flight. (when execute-extended-command--binding-timer (cancel-timer execute-extended-command--binding-timer)) (setq execute-extended-command--binding-timer (run-at-time 0 nil (lambda () (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))) (sit-for (if (numberp suggest-key-bindings) suggest-key-bindings 2)))))))))))) (provide 'demo-post-command-hook-slow-with-m-x-commands-v2) ;;; demo-post-command-hook-slow-with-m-x-commands-v2.el ends here ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-19 14:55 ` Simon Katz @ 2021-08-20 13:09 ` Lars Ingebrigtsen 2021-08-20 16:14 ` Simon Katz 0 siblings, 1 reply; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-20 13:09 UTC (permalink / raw) To: Simon Katz; +Cc: 50042 [-- Attachment #1: Type: text/plain, Size: 1314 bytes --] Simon Katz <sk@nomistech.com> writes: >> The file for reproducing the problem was apparently mangled during >> transmission, too. Can you re-send the file as an attachment? > > Sure. Please find it attached. Thanks. When I hoisted the final waiting from the command, I totally didn't notice that there was even more waiting there (in the case of a command that had displayed a message). I've now tweaked this further, and it now seems to work correctly in all the message/no keybinding/keybinding cases, I think... Can you test this, too, to see if I got all the cases right? That is, it shouldn't display anything if you do anything else before the suggestion triggers, and it shouldn't inhibit entering other commands, and... er... no other peculiarities. One thing that is peculiar, but no more than before, is this bit: ;; FIXME: Can be slow. Cache it maybe? (setq binding (execute-extended-command--shorter (symbol-name function) typed)))) It takes five seconds on my laptop, which means that these suggestion arrive five seconds after I did the `M-x'. But that hasn't changed since before these patches. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no [-- Attachment #2: demo-post-command-hook-slow-with-m-x-commands-v2.el --] [-- Type: application/emacs-lisp, Size: 1439 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-20 13:09 ` Lars Ingebrigtsen @ 2021-08-20 16:14 ` Simon Katz 2021-08-21 12:55 ` Lars Ingebrigtsen 0 siblings, 1 reply; 15+ messages in thread From: Simon Katz @ 2021-08-20 16:14 UTC (permalink / raw) To: Lars Ingebrigtsen; +Cc: 50042 Lars Ingebrigtsen <larsi <at> gnus.org> writes: > Can you test this, too, to see if I got all the cases right? That is, > it shouldn't display anything if you do anything else before the > suggestion triggers, and it shouldn't inhibit entering other commands, > and... er... no other peculiarities. I'm using the version of `execute-extended-command` in commit 00a9c50ad7, and everything is behaving as I would expect. Thanks! > One thing that is peculiar, but no more than before, is this bit: > > ;; FIXME: Can be slow. Cache it maybe? > (setq binding (execute-extended-command--shorter > (symbol-name function) typed)))) > > It takes five seconds on my laptop, which means that these suggestion > arrive five seconds after I did the `M-x'. But that hasn't changed > since before these patches. FWIW, I haven't looked at this -- I'm not sure when it comes into play. But I guess it's a separate issue. Thanks again. ^ permalink raw reply [flat|nested] 15+ messages in thread
* bug#50042: acknowledged by developer (control message for bug #50042) 2021-08-20 16:14 ` Simon Katz @ 2021-08-21 12:55 ` Lars Ingebrigtsen 0 siblings, 0 replies; 15+ messages in thread From: Lars Ingebrigtsen @ 2021-08-21 12:55 UTC (permalink / raw) To: Simon Katz; +Cc: 50042 Simon Katz <sk@nomistech.com> writes: > Lars Ingebrigtsen <larsi <at> gnus.org> writes: > >> Can you test this, too, to see if I got all the cases right? That is, >> it shouldn't display anything if you do anything else before the >> suggestion triggers, and it shouldn't inhibit entering other commands, >> and... er... no other peculiarities. > > I'm using the version of `execute-extended-command` in commit > 00a9c50ad7, and everything is behaving as I would expect. Thanks for checking. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2021-08-21 12:55 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <878s13os3a.fsf@gnus.org> 2021-08-13 11:52 ` bug#50042: 26.3; Post-command hooks slow with M-x commands Simon Katz 2021-08-13 12:27 ` Lars Ingebrigtsen 2021-08-13 12:40 ` Simon Katz 2021-08-14 16:36 ` Lars Ingebrigtsen 2021-08-14 20:52 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2021-08-15 11:38 ` Lars Ingebrigtsen 2021-08-17 0:41 ` Dmitry Gutov [not found] ` <handler.50042.C.162902754922550.notifdonectrl.0@debbugs.gnu.org> 2021-08-18 15:27 ` bug#50042: acknowledged by developer (control message for bug #50042) Simon Katz 2021-08-18 15:33 ` Simon Katz 2021-08-18 15:37 ` Simon Katz 2021-08-19 13:07 ` Lars Ingebrigtsen 2021-08-19 14:55 ` Simon Katz 2021-08-20 13:09 ` Lars Ingebrigtsen 2021-08-20 16:14 ` Simon Katz 2021-08-21 12:55 ` Lars Ingebrigtsen
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).