Como adicionar um registro de data e hora a cada entrada no buffer * Messages * do Emacs?

11

Eu dependo muito do *Messages*buffer, mas as entradas não têm registro de data e hora.

Como adicionar um carimbo de data / hora a cada entrada no buffer de mensagens do Emacs ?

Então, algo assim:

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]

vai se tornar algo como isto:

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]

Pesquisei no EmacsWiki, Reddit e emacs.sx, é claro, sem sucesso.

Estou ciente de command-log-modeque pode ser ajustado para registrar com registros de data e hora, mas é útil apenas para comandos interativos, nem todas as mensagens, incluindo as do "sistema" do Emacs.

Em vez disso, todas as mensagens registradas no buffer de Mensagens devem ter registro de data e hora.

Como se pode adicionar um carimbo de data / hora a cada entrada no buffer de mensagens do Emacs , independentemente da sua origem?

gsl
fonte
2
Isso soa como uma solicitação de recurso para o Emacs. O messagecomando é implementado em C e provavelmente possui chamadores diretos, portanto você não poderá garantir que todas as mensagens registradas recebam um carimbo de data / hora sem criar o Emacs. Dito isto, você pode aconselhar o messagecomando a introduzir um carimbo de data / hora quando for chamado pelo Elisp. É necessário algum cuidado: messagepode ser chamado sem argumentos, uma string de formato vazia etc. Você também deseja evitar um loop recursivo, caso o próprio conselho de registro de data e hora chame messagealgum caminho de código.
glucas
11
Eu não tentei, mas parece que você deve ser capaz de aconselhamento sobre mensagens emacswiki.org/emacs/AdvisingFunctions stackoverflow.com/questions/21524488/... superuser.com/questions/669701/...
eflanigan00
11
Eu estaria inclinado a usar after-change-functions(no buffer de mensagens) para implementar isso. Sempre que algo for inserido no final do buffer, coloque um carimbo de data e hora nele.
phils
11
@phils Consulte gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html A saída de mensagens no buffer de Mensagens não chama essas funções, nem certas alterações internas do buffer, como alterações nos buffers criados pelo Emacs internamente para determinados trabalhos, que não devem ser visíveis para os programas Lisp.
Xinfa tang

Respostas:

7

Eu tenho o seguinte trecho no meu init.el, que foi adaptado de um original encontrado no seguinte tópico do Reddit: http://www.reddit.com/r/emacs/comments/16tzu9/anyone_know_of_a_reasonable_way_to_timestamp/

(EDIT: modernizado para adicionar conselhos e remover o desajeitado tratamento de buffer somente leitura, sob orientação 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)

Isso resulta na decoração do buffer * Messages * da seguinte maneira:

[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
fonte
3
Gostaria de saber por que isso não é fornecido como uma opção por padrão.
bertfred
11
Brilhante, é exatamente isso que eu estava procurando. Obrigado.
GSL
2
@bertfred Porque ninguém fez isso acontecer. Talvez seja você?
Phil Lord
2
Você poderia reescrever o conselho usando advice-add? É o método preferido agora, pois sabe como lidar com situações que defadvicenão podem. Além disso, você provavelmente não deve fazer isso (read-only-mode 0), porque isso provavelmente é permanente. Você pode vincular inhibit-read-onlyao tredor do código que modifica o buffer.
blujay
2
Eu uso o seu código, mas exibir muitas mensagens apenas um timestamp
Xinfa tang
5

A tradução da solução simples do @ xinfatang para a nova advice-addsintaxe como um invólucro em torno da messagefunção é:

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

Saídas *Messages*como:

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

Adicionar:

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

Remover:

 (advice-remove 'message #'my-message-with-timestamp)
mithos
fonte
3
Você também pode filtrar os argumentos, em vez de usar o conselho: (advice-add 'message :filter-args 'with-timestamp)funcionaria com uma função como esta:(defun with-timestamp (args) (push (concat (format-time-string "[%F %T.%3N] ") (car args)) (cdr args)))
glucas
11
@glucas Nice! Eu recebo carimbos de data / hora sem mensagem quando passo o mouse sobre o minibuffer. Existe uma maneira de evitar isso?
AstroFloyd 23/12/19
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)) ))

Finalmente eu ainda gosto Stuart Hickinbottom resposta 's, porque evitar show de timestamp em minibuffer, o seguinte é uma versão modificada que eu uso, é ignorar as mensagens mostram apenas no eco área (por let message-log-maxque nil, antes chamada de função mensagem):

 (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
fonte
2
Formato timestamp mudança para %F %T.%3Na mostra microssegundos
Xinfa tang