基本上我想让*Messages*缓冲区在有新消息到来时始终滚动到底部。
我可以这样做吗?
我找到了auto-revert-tail-mode
,但它仅适用于正在访问文件的缓冲区。
当我在Messages缓冲区中尝试使用它时,它弹出了一个错误:
auto-revert-tail-mode:该缓冲区没有访问文件
基本上我想让*Messages*缓冲区在有新消息到来时始终滚动到底部。
我可以这样做吗?
我找到了auto-revert-tail-mode
,但它仅适用于正在访问文件的缓冲区。
当我在Messages缓冲区中尝试使用它时,它弹出了一个错误:
auto-revert-tail-mode:该缓冲区没有访问文件
对于多个框架,您可能需要:
(defadvice message (after message-tail activate)
"goto point max after a message"
(with-current-buffer "*Messages*"
(goto-char (point-max))
(walk-windows (lambda (window)
(if (string-equal (buffer-name (window-buffer window)) "*Messages*")
(set-window-point window (point-max))))
nil
t)))
get-buffer-window-list
而不是walk-windows
加过滤器。 - ClémentM->
而不仅仅是其他光标移动来将点放在 point-max
上。 - Drewwindow-point
。在这种情况下,@Peter的回答或类似的回答是相关的。我刚刚提交了Emacs错误(增强请求)# 36343 ,建议用户可以选择自动执行此操作。 (Bug#36343本身实际上是关于C-h e
的。) - Drew这段代码看起来有点复杂,但是简单的(goto-char (point-max))
对我来说并不能正常工作:
(defadvice message (after message-tail activate)
"goto point max after a message"
(with-current-buffer "*Messages*"
(goto-char (point-max))
(let ((windows (get-buffer-window-list (current-buffer) nil t)))
(while windows
(set-window-point (car windows) (point-max))
(setq windows (cdr windows))))))
(while windows ...)
最好像 walk-windows
版本一样写成 (mapc (lambda (w) (set-window-point w (point-max))) windows)
。 - ntc2(defun message-buffer-goto-end-of-buffer (&rest args)
(let* ((win (get-buffer-window "*Messages*"))
(buf (and win (window-buffer win))))
(and win (not (equal (current-buffer) buf))
(set-window-point
win (with-current-buffer buf (point-max))))))
(advice-add 'message :after 'message-buffer-goto-end-of-buffer)
我运行23.3版本,但是仍然有太多情况下内置的"解决方案"和消息函数的原始defadvice无法满足需求,所以我将代码包装在列表/切换/定时器设置中,现在工作得非常好——在调试时不再感到沮丧!
它是通用的,因此可以在任何缓冲区上使用,尽管我只在实际使用中使用它…
(toggle-buffer-tail "*Messages*" "on")
希望对某些人有用。
;alist of 'buffer-name / timer' items
(defvar buffer-tail-alist nil)
(defun buffer-tail (name)
"follow buffer tails"
(cond ((or (equal (buffer-name (current-buffer)) name)
(string-match "^ \\*Minibuf.*?\\*$" (buffer-name (current-buffer)))))
((get-buffer name)
(with-current-buffer (get-buffer name)
(goto-char (point-max))
(let ((windows (get-buffer-window-list (current-buffer) nil t)))
(while windows (set-window-point (car windows) (point-max))
(with-selected-window (car windows) (recenter -3)) (setq windows (cdr windows))))))))
(defun toggle-buffer-tail (name &optional force)
"toggle tailing of buffer NAME. when called non-interactively, a FORCE arg of 'on' or 'off' can be used to to ensure a given state for buffer NAME"
(interactive (list (cond ((if name name) (read-from-minibuffer
(concat "buffer name to tail"
(if buffer-tail-alist (concat " (" (caar buffer-tail-alist) ")") "") ": ")
(if buffer-tail-alist (caar buffer-tail-alist)) nil nil
(mapcar '(lambda (x) (car x)) buffer-tail-alist)
(if buffer-tail-alist (caar buffer-tail-alist)))) nil)))
(let ((toggle (cond (force force) ((assoc name buffer-tail-alist) "off") (t "on")) ))
(if (not (or (equal toggle "on") (equal toggle "off")))
(error "invalid 'force' arg. required 'on'/'off'")
(progn
(while (assoc name buffer-tail-alist)
(cancel-timer (cdr (assoc name buffer-tail-alist)))
(setq buffer-tail-alist (remove* name buffer-tail-alist :key 'car :test 'equal)))
(if (equal toggle "on")
(add-to-list 'buffer-tail-alist (cons name (run-at-time t 1 'buffer-tail name))))
(message "toggled 'tail buffer' for '%s' %s" name toggle)))))
编辑:将功能更改为在窗口底部显示尾行
这里是对 Peter / Trey 解决方案的修正
(defun modi/messages-auto-tail (&rest _)
"Make *Messages* buffer auto-scroll to the end after each message."
(let* ((buf-name "*Messages*")
;; Create *Messages* buffer if it does not exist
(buf (get-buffer-create buf-name)))
;; Activate this advice only if the point is _not_ in the *Messages* buffer
;; to begin with. This condition is required; otherwise you will not be
;; able to use `isearch' and other stuff within the *Messages* buffer as
;; the point will keep moving to the end of buffer :P
(when (not (string= buf-name (buffer-name)))
;; Go to the end of buffer in all *Messages* buffer windows that are
;; *live* (`get-buffer-window-list' returns a list of only live windows).
(dolist (win (get-buffer-window-list buf-name nil :all-frames))
(with-selected-window win
(goto-char (point-max))))
;; Go to the end of the *Messages* buffer even if it is not in one of
;; the live windows.
(with-current-buffer buf
(goto-char (point-max))))))
(advice-add 'message :after #'modi/messages-auto-tail)
auto-revert-tail-mode
似乎没有明显不同的作用。 - phils