According to my understanding of the post-command-hook from the documentation (https://www.gnu.org/software/emacs/manual/html_node/elisp/Command-Overview.html): the post-command-hook is executed after any and every interactive method completes (i.e. which is almost everything in Emacs ranging from typing a character, scrolling, clicking, etc.). This means that it executes after each interactive method either fully completes or runs into a non-standard exit (i.e. quitting, thrown exception, etc.). This seem to be logical and make sense on the surface as we would expect it to be invoked as the very last statement of an interactive method, something similar to following:
(prog1 (<your_interactive_method>) (run-hooks 'post-command-hook) ) However, based on my testing, it doesn't seem that the post-command-hook is executed that way, in a similar execution lifecycle. Meaning it doesn't wait on being invoked when there is a user-blocking event occurring in the middle of a method.
Put simply, say you have a method my_command_method that has invocations to read-string (or any other similar method that requests user input), it is expected that the post-command-hook is NOT executed, for the my_command_method invocation, until after ALL method invocations complete in my_command_method or there is a non-standard exiting of the method (i.e. quitting, thrown exception, etc.).
However, this seems to be false and the hook is just immediately executed in the method without waiting for it to be completed (in whatever way) and all of its internal methods invoked.
The code example that re-produces the issue:
(progn (defun my_command_method() "Insert text entered by the user in the current buffer." (interactive) (let* ((user_text (read-string "Say something: "))) (if user_text (insert user_text)))) (let* ((post_command_printer (lambda(&rest arguments) (if (symbolp this-command) (progn ; Just for clarity/testing (if (s-contains-p "my_command_method" (symbol-name this-command)) (progn (message "Post-Hook: This Command = %S" (symbol-name this-command)) (message "Post-Hook (This-Command): Buffer Contents = %S" (buffer-substring-no-properties (point-min) (point-max))) ; Should have the user's inserted text since this should only run _AFTER_ the method fully completes ... but it does NOT )))) (if (symbolp last-command) (progn ; Just for clarity/testing (if (s-contains-p "my_command_method" (symbol-name last-command)) (progn (message "Post-Hook: Last Command = %S" (symbol-name last-command)) (message "Post-Hook (Last-Command): Buffer Contents = %S" (buffer-substring-no-properties (point-min) (point-max))) ; Should have the user's inserted text since this should only run _AFTER_ the method fully completes ... but it does NOT ))))))) (add-hook 'post-command-hook post_command_printer))) Invoking my_command_method via M-x causes the hook to immediately fire off before the user has a chance to enter anything into the prompt for read-string. When I do enter some text for read-string and the method completes successfully, the hook does NOT execute again since it already executed. This overall behavior cannot be correct.
Could someone explain why this is?
How can we achieve the desired effect (i.e. only execute after the method completes entirely) via post-command-hook?
Standard environment disclosure:
- OS: MacOS
- Chip: Intel
- Emacs Version: 27.2.1
- Port: Mitsuharu Yamamoto / Railwaycat
- Other Notes: - No special distributions / etc.
- Relevant Common Packages Used:
- Standard internal Emacs packages
- s.el (String Library)