¿Cómo agregar una marca de tiempo a cada entrada en el búfer * Mensajes * de Emacs?

11

Depende *Messages*mucho del búfer, pero las entradas no tienen fecha y hora.

¿Cómo se puede agregar una marca de tiempo a cada entrada en el búfer de mensajes de Emacs ?

Entonces algo como esto:

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]

se convertirá en algo como esto:

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]

Busqué en EmacsWiki, Reddit y emacs.sx, por supuesto, en vano.

Soy consciente de command-log-modeque se puede ajustar para iniciar sesión con marcas de tiempo, pero es útil solo para comandos interactivos, no para todos los mensajes, incluidos los del "sistema" de Emacs.

En cambio, cada mensaje registrado en el búfer de Mensajes debe tener una marca de tiempo.

¿Cómo se puede agregar una marca de tiempo a cada entrada en el búfer de mensajes de Emacs , sin importar su origen?

gsl
fuente
2
Esto suena como una solicitud de función para Emacs. El messagecomando se implementa en C y es probable que tenga llamadas directas, por lo que no podrá asegurarse de que cada mensaje registrado reciba una marca de tiempo sin construir Emacs usted mismo. Dicho esto, es posible que pueda aconsejar al messagecomando que introduzca una marca de tiempo cuando se lo llame desde Elisp. Se requiere cierta precaución: messagese puede llamar sin argumentos, una cadena de formato vacía, etc. También debe evitar un bucle recursivo si su propio aviso de marca de tiempo invoca messagealguna ruta de código.
glucas
1
Yo no lo he probado, pero parece que usted debería ser capaz de asesoramiento a los mensajes emacswiki.org/emacs/AdvisingFunctions stackoverflow.com/questions/21524488/... superuser.com/questions/669701/...
eflanigan00
1
Me inclinaría a usar after-change-functions(en el búfer de mensajes) para implementar eso. Siempre que se inserte algo al final del búfer, coloque un prefijo en él.
phils
1
@phils Consulte gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html La salida de mensajes en el búfer de Mensajes no llama a estas funciones, y tampoco lo hacen ciertos cambios internos del búfer, como los cambios en los búferes creados por Emacs internamente para ciertos trabajos, que no deberían ser visibles para los programas Lisp.
xinfa tang

Respuestas:

7

Tengo el siguiente fragmento en mi init.el, que fue adaptado de un original que encontré en el siguiente hilo de Reddit: http://www.reddit.com/r/emacs/comments/16tzu9/anyone_know_of_a_reasonable_way_to_timestamp/

(EDITAR: modernizado para agregar consejos y eliminar el torpe manejo de búfer de solo lectura siguiendo los consejos de @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)

Esto da como resultado la decoración del búfer * Messages * de la siguiente manera:

[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
fuente
3
Me pregunto por qué esto no se proporciona como una opción por defecto.
atrapado el
1
Brillante, esto es exactamente lo que estaba buscando. Gracias.
gsl
2
@bertfred Porque nadie lo ha hecho posible. ¿Quizás eres tú?
Phil Lord
2
¿Podrías reescribir el consejo usando advice-add? Es el método preferido ahora, ya que sabe cómo manejar situaciones que defadviceno pueden. Además, probablemente no debería hacerlo (read-only-mode 0), porque probablemente sea permanente. Puede enlazar inhibit-read-onlya ttodo el código que modifica el búfer.
blujay
2
Uso su código, pero visualizo muchos mensajes solo con una marca de tiempo
xinfa tang
5

La traducción de la solución simple de @xinfatang a la nueva advice-addsintaxis como envoltorio alrededor de la messagefunción es:

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

Salidas *Messages*como:

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

Para agregar:

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

Para eliminar:

 (advice-remove 'message #'my-message-with-timestamp)
mithos
fuente
3
También puede simplemente filtrar los argumentos, en lugar de usar consejos: (advice-add 'message :filter-args 'with-timestamp)funcionaría con una función como esta:(defun with-timestamp (args) (push (concat (format-time-string "[%F %T.%3N] ") (car args)) (cdr args)))
glucas
1
@glucas Nice! Sin embargo, recibo marcas de tiempo sin mensaje cuando paso el mouse sobre el minibúfer. ¿Hay alguna manera de evitar eso?
AstroFloyd
3

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

Por último todavía tengo gusto Stuart Hickinbottom respuesta 's, ya que evitar espectáculo marca de tiempo en el minibúfer, la siguiente es una versión modificada que yo uso, se ignoran los mensajes sólo se muestran en el área de eco (por let message-log-maxque nilantes de la llamada función de mensaje):

 (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
fuente
2
Cambie el formato de marca de tiempo %F %T.%3Npara mostrar microsegundos
xinfa tang