Package: emacs;
Reported by: Jonas Bernoulli <jonas <at> bernoul.li>
Date: Mon, 30 Jan 2023 15:08:01 UTC
Severity: normal
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Jonas Bernoulli <jonas <at> bernoul.li> To: bug-gnu-emacs <at> gnu.org Subject: post-command-hook is not run if minibuffer input is aborted Date: Mon, 30 Jan 2023 16:07:30 +0100
> -- Variable: post-command-hook > This normal hook is run by the editor command loop after it > executes each command (including commands terminated prematurely by > quitting or by errors). At that time, ‘this-command’ refers to the > command that just ran, and ‘last-command’ refers to the command > before that. > > This hook is also run when Emacs first enters the command loop (at > which point ‘this-command’ and ‘last-command’ are both ‘nil’). - post-command-hook is run even if a command is "terminated prematurely by quitting or by errors". This is very useful when it is crucial that some cleanup is run even when something goes wrong. - When a command uses the minibuffer, then post-command-hook is additionally run when the minibuffer is setup, with this-command being the command that uses the minibuffer. This happens before minibuffer-setup-hook is run. This is surprising, because undocumented, but easy to detect, because at this time this-command-keys-vector returns an empty vector. Never- the-less this should be documented (instead of being "fixed"; I depend on this behavior, and so might others). - However, when the command reads from the minibuffer and the user aborts that, then post-command-hook is NOT run a second time AFTER the command. This is extremely inconvenient. IMO, the fact that this hook is documented to run even if the command "terminated prematurely by quitting or by errors", implies that the hook is run even if the quitting is done intentionally by the user. This could be fixed simply by running post-command-hook in this case as well. If that is considered a dangerous change in behavior, then maybe a very similar hook --say unwind-command-hook-- could be added. Cheers, Jonas Oh -- here's some code that can be used to observe this behavior: (keymap-global-set "<f1>" '-command) (keymap-global-set "<f2>" '-prepare) (keymap-global-set "<f3>" '-cleanup) (defun -prepare () (interactive) (add-hook 'post-command-hook '-post) (add-hook 'minibuffer-setup-hook '-setup) (add-hook 'minibuffer-exit-hook '-exit)) (defun -cleanup () (interactive) (remove-hook 'post-command-hook '-post) (remove-hook 'minibuffer-setup-hook '-setup) (remove-hook 'minibuffer-exit-hook '-exit)) (defun -post () (message ";; -post (%-10s %s)" (this-command-keys-vector) this-command)) (defun -setup () (message ";; -setup (%-10s %s)" (this-command-keys-vector) this-command)) (defun -exit () (message ";; -exit (%-10s %s)" (this-command-keys-vector) this-command)) (defun -command () (interactive) (message ";; -command")) ;; -command ;; -post ([f1] -command) (defun -command () (interactive) (message ";; -command") (error "error in command")) ;; -command ;; -command: error in command ;; -post ([] -command) (defun -command () (interactive (error "error in interactive")) (message ";; -command")) ;; call-interactively: error in interactive ;; -post ([] -command) (defun -command (arg) (interactive (list (read-string ": "))) (message ";; -command")) ;; -setup ([f1] -command) ;; -post ([] -command) ;; -post ([97] self-insert-command) ;; -exit ([return] exit-minibuffer) ;; -command ;; -post ([f1] -command) ;; -setup ([f1] -command) ;; -post ([] -command) ;; -exit ([7] abort-minibuffers) ;; Quit ;; -post ([] abort-minibuffers) (defun -command () (interactive) (message ";; -command") (read-string "-command: ")) ;; -setup ([f1] -command) ;; -post ([] -command) ;; -post ([97] self-insert-command) ;; -exit ([return] exit-minibuffer) ;; -post ([f1] exit-minibuffer) ;; -setup ([f1] -command) ;; -post ([] -command) ;; -exit ([return] exit-minibuffer) ;; -post ([f1] exit-minibuffer) (defun -command (arg) (interactive (list (read-from-minibuffer ": " nil (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (define-key map "a" (lambda () (interactive) (error "error in minibuffer"))) map)))) (message ";; -command")) ;; -setup ([f1] -command) ;; -post ([] -command) ;; (lambda nil (interactive) (error error in minibuffer)): error in minibuffer ;; -post ([] (lambda nil (interactive) (error error in minibuffer))) ;; -exit ([return] exit-minibuffer) ;; -command ;; -post ([f1] -command)
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.