Wie füge ich jedem Eintrag im * Nachrichten * -Puffer von Emacs einen Zeitstempel hinzu?

11

Ich bin sehr vom *Messages*Puffer abhängig , aber die Einträge sind nicht mit einem Zeitstempel versehen.

Wie kann man jedem Eintrag im Nachrichtenpuffer von Emacs einen Zeitstempel hinzufügen ?

So dass so etwas:

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]

wird so etwas werden:

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]

Ich habe natürlich vergeblich nach EmacsWiki, Reddit und emacs.sx gesucht.

Mir ist bekannt command-log-mode, dass dies so angepasst werden kann, dass es mit Zeitstempeln protokolliert, aber es ist nur für interaktive Befehle nützlich, nicht für alle Nachrichten, einschließlich der "System" -Nachrichten von Emacs.

Stattdessen sollte jede im Nachrichtenpuffer protokollierte Nachricht mit einem Zeitstempel versehen werden.

Wie kann man jedem Eintrag im Nachrichtenpuffer von Emacs einen Zeitstempel hinzufügen , unabhängig von seiner Quelle?

gsl
quelle
2
Dies klingt nach einer Funktionsanforderung für Emacs. Der messageBefehl ist in C implementiert und hat wahrscheinlich direkte Anrufer, sodass Sie nicht sicherstellen können, dass jede protokollierte Nachricht einen Zeitstempel erhält, ohne Emacs selbst zu erstellen. Sie können dem messageBefehl jedoch möglicherweise raten , einen Zeitstempel einzuführen, wenn er von Elisp aufgerufen wird. Einige Vorsicht ist geboten: messageKann ohne Argumente, eine leere Formatzeichenfolge usw. aufgerufen werden. Sie möchten auch eine rekursive Schleife vermeiden, falls Ihr Zeitstempel-Hinweis selbst messageeinen Codepfad aufruft.
Glucas
1
Ich habe versucht , es nicht , aber es scheint , wie Sie auf Mitteilung an Rat der Lage sein sollten emacswiki.org/emacs/AdvisingFunctions stackoverflow.com/questions/21524488/... superuser.com/questions/669701/...
eflanigan00
1
Ich würde gerne after-change-functions(im Nachrichtenpuffer) verwenden, um dies zu implementieren. Wenn am Ende des Puffers etwas eingefügt wird, stellen Sie ihm einen Zeitstempel voran.
Phils
1
@phils Siehe gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html Die Ausgabe von Nachrichten in den Nachrichtenpuffer ruft diese Funktionen nicht auf, und bestimmte interne Pufferänderungen, wie z. B. Änderungen an erstellten Puffern, werden auch nicht aufgerufen von Emacs intern für bestimmte Jobs, die für Lisp-Programme nicht sichtbar sein sollten.
Xinfa Tang

Antworten:

7

Ich habe das folgende Snippet in meiner init.el, das von einem Original übernommen wurde, das ich im folgenden Reddit-Thread gefunden habe: http://www.reddit.com/r/emacs/comments/16tzu9/anyone_know_of_a_reasonable_way_to_timestamp/

(BEARBEITEN: Modernisiert, um ungeschickte schreibgeschützte Pufferhandhabung auf Empfehlung von @blujay hinzuzufügen und zu entfernen)

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

Dies führt zu einer Dekoration des * Nachrichten * -Puffers wie folgt:

[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
quelle
3
Ich frage mich, warum dies nicht standardmäßig als Option bereitgestellt wird.
Bertfred
1
Genial, genau das habe ich gesucht. Vielen Dank.
gsl
2
@bertfred Weil niemand es möglich gemacht hat. Vielleicht bist du das?
Phil Lord
2
Könnten Sie den Rat mit umschreiben advice-add? Es ist jetzt die bevorzugte Methode, da es weiß, wie man mit Situationen umgeht, defadvicedie nicht möglich sind. Auch sollten Sie wahrscheinlich nicht tun (read-only-mode 0), weil das wahrscheinlich dauerhaft ist. Sie können an den Code binden inhibit-read-only, tder den Puffer ändert.
Blujay
2
Ich benutze Ihren Code, aber viele Nachrichten nur einen Zeitstempel
anzeigen
5

Die Übersetzung von @ xinfatangs einfacher Lösung in die neue advice-addSyntax als Wrapper um die messageFunktion lautet:

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

Ausgaben *Messages*wie:

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

Hinzufügen:

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

Zu entfernen:

 (advice-remove 'message #'my-message-with-timestamp)
Mithos
quelle
3
Sie könnten auch nur die Argumente filtern, anstatt Ratschläge zu verwenden: (advice-add 'message :filter-args 'with-timestamp)würde mit einer Funktion wie dieser funktionieren:(defun with-timestamp (args) (push (concat (format-time-string "[%F %T.%3N] ") (car args)) (cdr args)))
Glucas
1
@ Glucas Schön! Ich erhalte jedoch Zeitstempel ohne Nachricht, wenn ich die Maus über den Minibuffer bewege. Gibt es eine Möglichkeit, dies zu vermeiden?
AstroFloyd
3

Siehe unter 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)) ))

Schließlich mag ich immer noch die Antwort von Stuart Hickinbottom , weil sie das Anzeigen des Zeitstempels im Minibuffer vermeidet. Die folgende Version wurde modifiziert. Ich ignoriere Nachrichten, die nur im Echobereich angezeigt werden ( let message-log-maxbis nilvor dem Aufruf der Nachrichtenfunktion):

 (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
quelle
2
Ändern Sie das Zeitstempelformat auf %F %T.%3Nfür Mikrosekunden
anzeigen