diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 6ea7b5783c2..879967ddfb2 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -716,8 +716,14 @@ use @kbd{C-h l} (@code{view-lossage}). @kbd{C-h l} displays your last input keystrokes and the commands they invoked. By default, Emacs stores the last 300 keystrokes; if you wish, you can change this number with the command @code{lossage-size}. -If you see commands that you are not familiar with, you can use @kbd{C-h k} or -@kbd{C-h f} to find out what they do. +If you see commands that you are not familiar with, use +@kbd{C-h k}, or press @kbd{RET} or click on them to find out what they do. + +@vindex view-lossage-auto-refresh +By default, after the lossage buffer is displayed it will not show the +most recent keystroke and command that you are currently typing, to +change this set the variable @code{view-lossage-auto-refresh} to +@code{t}. @kindex C-h e @findex view-echo-area-messages diff --git a/etc/NEWS b/etc/NEWS index 81117951302..7345c08218b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -690,6 +690,12 @@ or strings. If set to 'on-mismatch', mismatched parens inside comments and strings will not be highlighted. If set to nil (the default), highlight the parens wherever they are. ++++ +** New user option 'view-lossage-auto-refresh'. +If this option is non-nil, the lossage buffer in 'view-lossage' will be +refreshed automatically for each new input keystroke and command +performed. + ** Change in SVG foreground color handling. SVG images no longer have the 'fill' attribute set to the value of ':foreground' or the current text foreground color. The 'currentcolor' diff --git a/lisp/help.el b/lisp/help.el index 4ba99868c4a..8cf91faf174 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -517,6 +517,67 @@ If that doesn't give a function, return nil." (setq sym (intern-soft (match-string 1 str))) (and (fboundp sym) sym)))))))) + +;;; Lossage + +(defcustom view-lossage-auto-refresh nil + "Whether to auto-refresh the lossage buffer. +If non-nil, the lossage buffer will be refreshed automatically for each +new input keystroke and command performed." + :type 'boolean + :group 'help + :version "31.1") + +(defvar-local help--lossage-update nil + "Variable used to determine if lossage buffer should be refreshed.") + +(defun help--lossage-make-recent-keys (&optional most-recent) + "Return a string containing all the recent keys and its commands. +If MOST-RECENT is non-nil, only return the most recent key and its +command." + (let ((keys + (if most-recent + `[,@(this-single-command-raw-keys) (nil . ,this-command)] + (recent-keys 'include-cmds)))) + (mapconcat + (lambda (key) + (cond + ((and (consp key) (null (car key))) + (concat + ";; " + (if (symbolp (cdr key)) + (buttonize + (symbol-name (cdr key)) + (lambda (&rest _) + (interactive) + (describe-function (cdr key))) + "mouse-1: go to the documentation for this command.") + (propertize "anonymous-command" 'face 'shadow)) + "\n")) + ((or (integerp key) (symbolp key) (listp key)) + (propertize (single-key-description key) + 'face 'help-key-binding + 'rear-nonsticky t)) + (t + (propertize (prin1-to-string key nil) + 'face 'help-key-binding + 'rear-nonsticky t)))) + keys + " "))) + +(defun help--refresh-lossage-buffer () + (if-let* ((buf (get-buffer "*Help*")) + (_ (buffer-local-value 'help--lossage-update buf))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (save-excursion + (goto-char (point-max)) + (insert-before-markers + (concat " " (help--lossage-make-recent-keys :most-recent))) + (forward-line -1) + (comment-indent)))) + (remove-hook 'post-command-hook #'help--refresh-lossage-buffer))) + ;;; `User' help functions @@ -692,43 +753,50 @@ the variable `message-log-max'." (interactive) (info "(efaq)Packages that do not come with Emacs")) -(defun view-lossage () +(defun view-lossage (&optional auto-refresh) "Display last few input keystrokes and the commands run. For convenience this uses the same format as `edit-last-kbd-macro'. See `lossage-size' to update the number of recorded keystrokes. +With argument, auto-refresh the lossage buffer for each new input +keystroke, see also `view-lossage-auto-refresh'. + To record all your input, use `open-dribble-file'." - (interactive) - (let ((help-buffer-under-preparation t)) - (help-setup-xref (list #'view-lossage) - (called-interactively-p 'interactive)) + (interactive "P") + (let ((help-buffer-under-preparation t) + (view-lossage-auto-refresh + (if auto-refresh t view-lossage-auto-refresh))) + (unless view-lossage-auto-refresh + ;; `view-lossage-auto-refresh' conflicts with xref buttons, add + ;; them if `view-lossage-auto-refresh' is nil. + (help-setup-xref (list #'view-lossage) + (called-interactively-p 'interactive))) (with-help-window (help-buffer) (princ " ") - (princ (mapconcat (lambda (key) - (cond - ((and (consp key) (null (car key))) - (format ";; %s\n" (if (symbolp (cdr key)) (cdr key) - "anonymous-command"))) - ((or (integerp key) (symbolp key) (listp key)) - (single-key-description key)) - (t - (prin1-to-string key nil)))) - (recent-keys 'include-cmds) - " ")) + (insert (help--lossage-make-recent-keys)) (with-current-buffer standard-output (goto-char (point-min)) - (let ((comment-start ";; ") - ;; Prevent 'comment-indent' from handling a single - ;; semicolon as the beginning of a comment. - (comment-start-skip ";; ") - (comment-use-syntax nil) - (comment-column 24)) - (while (not (eobp)) - (comment-indent) - (forward-line 1))) + (setq-local comment-start ";; " + ;; Prevent 'comment-indent' from handling a single + ;; semicolon as the beginning of a comment. + comment-start-skip ";; " + comment-use-syntax nil + comment-column 24) + (while (not (eobp)) + (comment-indent) + (forward-line 1)) ;; Show point near the end of "lossage", as we did in Emacs 24. - (set-marker help-window-point-marker (point)))))) + (set-marker help-window-point-marker (point)) + + (when view-lossage-auto-refresh + (setq-local help--lossage-update t) + (add-hook 'post-command-hook #'help--refresh-lossage-buffer)))) + + ;; `help-make-xrefs' adds a newline at the end of the buffer, which + ;; makes impossible to reposition point in `with-help-window'. + (when view-lossage-auto-refresh + (set-window-point (get-buffer-window (help-buffer)) (point-max))))) ;; Key bindings