如何为Emacs的* Messages *缓冲区中的每个条目添加时间戳?


11

我非常依赖*Messages*缓冲区,但是条目没有时间戳记。

如何为Emacs的Messages缓冲区中的每个条目添加时间戳?

这样的事情:

Loading /Users/gsl/lisp.d/init.el (source)...
No outline structure detected
For information about GNU Emacs and the GNU system, type C-h C-a.
Loading /Users/gsl/lisp.d/var/recentf...done
Error running timer: (wrong-number-of-arguments (lambda nil (setq gc-cons-threshold (* 64 1024 1024)) (message "WARNING: gc-cons-threshold restored to %S")) 1)
[yas] Prepared just-in-time loading of snippets successfully.
M-] is undefined
CHILDREN [2 times]
‘show-all’ is an obsolete command (as of 25.1); use ‘outline-show-all’ instead.
Invalid face reference: nil [33 times]
Auto-saving...done
Saving file /Users/gsl/lisp.d/init.el...
Wrote /Users/gsl/lisp.d/init.el
mwheel-scroll: Beginning of buffer [5 times]
Mark set
previous-line: Beginning of buffer [10 times]
Quit [4 times]

会变成这样:

2017-02-14-18:50:01 Loading /Users/gsl/lisp.d/init.el (source)...
2017-02-14-18:50:02 No outline structure detected
2017-02-14-18:50:03 For information about GNU Emacs and the GNU system, type C-h C-a.
2017-02-14-18:50:05 Loading /Users/gsl/lisp.d/var/recentf...done
2017-02-14-18:50:10 Error running timer: (wrong-number-of-arguments (lambda nil (setq gc-cons-threshold (* 64 1024 1024)) (message "WARNING: gc-cons-threshold restored     to %S")) 1)
2017-02-14-18:50:12 [yas] Prepared just-in-time loading of snippets successfully.
2017-02-14-18:50:40 M-] is undefined
2017-02-14-18:50:41 CHILDREN [2 times]
2017-02-14-18:50:00 ‘show-all’ is an obsolete command (as of 25.1); use ‘outline-show-all’ instead.
2017-02-14-18:50:01 Invalid face reference: nil [33 times]
2017-02-14-18:51:01 Auto-saving...done
2017-02-14-18:51:03 Saving file /Users/gsl/lisp.d/init.el...
2017-02-14-18:51:06 Wrote /Users/gsl/lisp.d/init.el
2017-02-14-18:51:09 mwheel-scroll: Beginning of buffer [5 times]
2017-02-14-18:51:11 Mark set
2017-02-14-18:51:21 previous-line: Beginning of buffer [10 times]

我当然在EmacsWiki,Reddit和emacs.sx上搜索,但没有成功。

我知道command-log-mode,可以对其进行调整以记录时间戳,但它仅对交互式命令有用,而不对包括Emacs的“系统”在内的所有消息都有用。

而是,应记录每个记录到消息缓冲区的消息的时间戳。

如何才能时间戳添加到Emacs的每个条目消息缓冲区,不管它的来源?


2
这听起来像是对Emacs的功能要求。该message命令在C中实现,并且可能具有直接调用者,因此如果您不自行构建Emacs,则无法确保每个记录的消息都带有时间戳。也就是说,您可以建议message命令从Elisp调用时引入时间戳。需要注意一些事项:message可以在不使用参数,空格式字符串等的情况下调用。如果时间戳建议本身message在某些代码路径中调用,您还希望避免递归循环。
glucas


1
我倾向于使用after-change-functions(在消息缓冲区中)实现这一点。每当在缓冲区的末尾插入一些内容时,都要在其前面加上时间戳。
菲尔斯

1
@phils从gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html引用 。将消息输出到Messages缓冲区不会调用这些函数,某些内部缓冲区也不会更改,例如创建的缓冲区的更改由Emacs内部处理某些作业,这对Lisp程序不可见。
发堂

Answers:


7

我的init.el中包含以下代码段,该代码段是根据我在以下Reddit线程中找到的原始代码改编而成的:http : //www.reddit.com/r/emacs/comments/16tzu9/anyone_know_of_a_reasonable_way_to_timestamp/

(编辑:现代化为advice-add,并在@blujay的advice上删除了笨拙的只读缓冲区处理)

(defun sh/current-time-microseconds ()
  "Return the current time formatted to include microseconds."
  (let* ((nowtime (current-time))
         (now-ms (nth 2 nowtime)))
    (concat (format-time-string "[%Y-%m-%dT%T" nowtime) (format ".%d]" now-ms))))

(defun sh/ad-timestamp-message (FORMAT-STRING &rest args)
  "Advice to run before `message' that prepends a timestamp to each message.

Activate this advice with:
(advice-add 'message :before 'sh/ad-timestamp-message)"
  (unless (string-equal FORMAT-STRING "%s%s")
    (let ((deactivate-mark nil)
          (inhibit-read-only t))
      (with-current-buffer "*Messages*"
        (goto-char (point-max))
        (if (not (bolp))
          (newline))
        (insert (sh/current-time-microseconds) " ")))))

(advice-add 'message :before 'sh/ad-timestamp-message)

这导致* Messages *缓冲区的修饰如下:

[2017-06-13T07:21:13.270070] Turning on magit-auto-revert-mode...
[2017-06-13T07:21:13.467317] Turning on magit-auto-revert-mode...done
[2017-06-13T07:21:13.557918] For information about GNU Emacs and the GNU system, type C-h C-a.

3
我想知道为什么默认情况下不提供此选项。
bertfred

1
太棒了,这正是我想要的。谢谢。
gsl

2
@bertfred因为没人能实现。也许就是你吗?
菲尔勋爵

2
您可以使用重写建议advice-add吗?现在它是首选方法,因为它知道如何处理无法解决的情况defadvice。另外,您可能不应该这样做(read-only-mode 0),因为那可能是永久的。您可以绑定inhibit-read-onlyt修改缓冲区的代码周围。
blujay

2
我用你的代码,但显示许多消息只是一个时间戳
新发堂

5

@xinfatang将新advice-add语法作为该message函数的包装器的简单解决方案的翻译是:

(defun my-message-with-timestamp (old-func fmt-string &rest args)
   "Prepend current timestamp (with microsecond precision) to a message"
   (apply old-func
          (concat (format-time-string "[%F %T.%3N %Z] ")
                   fmt-string)
          args))

输出*Messages*如下:

[2018-02-25 10:13:45.442 PST] Mark set

添加:

 (advice-add 'message :around #'my-message-with-timestamp)

去除:

 (advice-remove 'message #'my-message-with-timestamp)

3
您也可以只过滤args,而不是使用周围的建议:(advice-add 'message :filter-args 'with-timestamp)可以使用以下功能:(defun with-timestamp (args) (push (concat (format-time-string "[%F %T.%3N] ") (car args)) (cdr args)))
glucas

1
@glucas不错!当我将鼠标悬停在微型缓冲区上时,我收到没有消息的时间戳。有办法避免这种情况吗?
AstroFloyd

3

https://www.emacswiki.org/emacs/DebugMessages参考:

(defadvice message (before when-was-that activate)
  "Add timestamps to `message' output."
  (ad-set-arg 0 (concat (format-time-string "[%Y-%m-%d %T %Z] ") 
                        (ad-get-arg 0)) ))

最后,我仍然喜欢Stuart Hickinbottom的答案,因为它避免了在minibuffer中显示时间戳,以下是我使用的修改版本,它忽略仅在回显区域中显示的消息(let message-log-maxnil消息函数调用之前)。

 (defun my/ad-timestamp-message (FORMAT-STRING &rest args)
   "Advice to run before `message' that prepends a timestamp to each message.
    Activate this advice with:
      (advice-add 'message :before 'my/ad-timestamp-message)
    Deactivate this advice with:
      (advice-remove 'message 'my/ad-timestamp-message)"
       (if message-log-max
           (let ((deactivate-mark nil)
                 (inhibit-read-only t))
             (with-current-buffer "*Messages*"
               (goto-char (point-max))
               (if (not (bolp))
                   (newline))
               (insert (format-time-string "[%F %T.%3N] "))))))
 (advice-add 'message :before 'my/ad-timestamp-message)

2
将时间戳记格式更改%F %T.%3N为显示微秒
xinfa tang
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.