Bagaimana cara menambahkan stempel waktu untuk setiap entri dalam buffer * Pesan * Emacs?

11

Saya banyak bergantung pada *Messages*buffer, tetapi entri tidak diberi cap waktu.

Bagaimana cara menambahkan cap waktu untuk setiap entri di buffer Pesan Emacs ?

Sehingga kira-kira seperti ini:

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]

akan menjadi sesuatu seperti ini:

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]

Saya mencari di EmacsWiki, Reddit dan emacs.sx tentu saja, tidak berhasil.

Saya tahu command-log-mode, yang dapat disesuaikan untuk masuk dengan stempel waktu, tetapi hanya berguna untuk perintah interaktif, tidak semua pesan, termasuk yang "sistem" Emacs.

Sebaliknya, setiap pesan yang masuk ke buffer Pesan harus diberi cap waktu.

Bagaimana cara menambahkan cap waktu untuk setiap entri di buffer Pesan Emacs , terlepas dari sumbernya?

gsl
sumber
2
Ini terdengar seperti permintaan fitur untuk Emacs. The messageperintah diimplementasikan dalam C dan kemungkinan memiliki penelepon langsung, sehingga Anda tidak akan dapat memastikan setiap pesan yang ditebang mendapat cap tanpa membangun Emacs sendiri. Yang mengatakan, Anda mungkin dapat menyarankan messageperintah untuk memperkenalkan cap waktu ketika itu dipanggil dari Elisp. Dibutuhkan kehati-hatian: messagedapat dipanggil tanpa argumen, string format kosong, dll. Anda juga ingin menghindari loop rekursif jika saran cap waktu Anda sendiri memanggil messagebeberapa jalur kode.
glukas
1
Saya belum mencobanya tetapi sepertinya Anda harus dapat memberikan saran ke pesan emacswiki.org/emacs/AdvisingFuncaps stackoverflow.com/questions/21524488/… superuser.com/questions/669701/…
eflanigan00
1
Saya akan cenderung menggunakan after-change-functions(di buffer pesan) untuk mengimplementasikannya. Setiap kali sesuatu dimasukkan di akhir buffer, awali stempel waktu untuk itu.
phils
1
@phils Rujuk dari gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html Output pesan ke dalam buffer Pesan tidak memanggil fungsi-fungsi ini, dan tidak juga melakukan perubahan buffer internal tertentu, seperti perubahan buffer yang dibuat oleh Emacs secara internal untuk pekerjaan tertentu, yang seharusnya tidak terlihat oleh program Lisp.
xinfa tang

Jawaban:

7

Saya memiliki cuplikan berikut di init.el saya, yang diadaptasi dari aslinya yang saya temukan di utas Reddit berikut: http://www.reddit.com/r/emacs/comments/16tzu9/anyone_know_of_a_reasonable_way_to_timestamp/

(EDIT: dimodernisasi untuk saran-tambah dan hapus penanganan buffer read-only yang kikuk atas saran @blujay)

(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)

Ini menghasilkan dekorasi penyangga * Pesan * sebagai berikut:

[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.
Stuart Hickinbottom
sumber
3
Saya ingin tahu mengapa ini tidak disediakan sebagai opsi secara default.
bertfred
1
Cemerlang, ini persis apa yang saya cari. Terima kasih.
gsl
2
@bertfred Karena belum ada yang mewujudkannya. Mungkin itu kamu?
Phil Lord
2
Bisakah Anda menulis ulang saran menggunakan advice-add? Ini metode yang disukai sekarang, karena ia tahu bagaimana menangani situasi yang defadvicetidak bisa. Juga, Anda mungkin tidak boleh melakukannya (read-only-mode 0), karena itu mungkin permanen. Anda dapat mengikat inhibit-read-onlyuntuk tseluruh kode yang memodifikasi buffer.
blujay
2
Saya menggunakan kode Anda, tetapi menampilkan banyak pesan hanya cap waktu
xinfa tang
5

Terjemahan dari solusi sederhana @ xinfatang ke advice-addsintaks baru sebagai pembungkus messagefungsi adalah:

(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))

Output *Messages*seperti:

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

Menambahkan:

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

Untuk menghapus:

 (advice-remove 'message #'my-message-with-timestamp)
mithos
sumber
3
Anda juga bisa hanya memfilter argumen, daripada menggunakan saran sekitar: (advice-add 'message :filter-args 'with-timestamp)akan bekerja dengan fungsi seperti ini:(defun with-timestamp (args) (push (concat (format-time-string "[%F %T.%3N] ") (car args)) (cdr args)))
glucas
1
@glucas Bagus! Saya mendapat cap waktu tanpa pesan ketika saya mengarahkan mouse ke minibuffer. Apakah ada cara untuk menghindarinya?
AstroFloyd
3

Rujuk dari 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)) ))

Akhirnya saya masih seperti Stuart Hickinbottom jawaban 's, karena menghindari acara timestamp di minibuffer, berikut ini adalah versi modifikasi yang saya gunakan, itu mengabaikan pesan hanya menunjukkan di daerah echo (oleh let message-log-maxuntuk nilsebelum fungsi pesan panggilan):

 (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)
xinfa tang
sumber
2
Ubah format cap waktu menjadi %F %T.%3Nuntuk menunjukkan mikrodetik
xinfa tang