Выделяйте только недавно добавленные строки, когда буфер Emacs автоматически возвращается


У меня есть команда Emacs, которая добавляет разделительную строку в лог-файлах, когда между метками времени, найденными на 2 последовательных строках, находится более 3 секунд:

(defun log-mode-display-separator-line ()
  "Separate blocks of log lines with an horizontal line."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let (last ov)
      (while (re-search-forward "[0-9]\{4\}-[01][1-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]" nil t)
        (when last
          (when (> (- (float-time (date-to-time (match-string 0)))
                      (float-time (date-to-time last)))
                   3)
            (setq ov (make-overlay (line-beginning-position) (line-end-position)))
            (overlay-put ov 'face 'log-mode-separator-face)))
        (setq last (match-string 0))))))

log-mode-separator-face использует атрибут overline, чтобы визуально поместить горизонтальную линию между "семантическими" блоками строк.

Я хотел бы, чтобы эта горизонтальная линия автоматически вставлялась при возврате буфера (каждые 5 секунд), но обработка может стать слишком большой для огромных файлов журнала, которые постоянно обновляются. Теперь каждый раз, когда мы вызываем эту команду, весь файл сканируется с самого начала...

Как же мне тогда это осознать? (С Emacs, без сомнения, так и есть...)

1 2

1 ответ:

Во-первых, нет никакой гарантии, что буфер возвращается каждые 5 секунд. Начиная с Emacs 24.4, autorevert использует уведомления о файлах, что означает, что буфер возвращается всякий раз, когда файл изменяется на диске. Если вы хотите подавить это, установите auto-revert-use-notify равным нулю.

Далее, это зависит от того, как вы хотите вернуть свой файл журнала. Я полагаю, вы используете auto-revert-tail-mode. Этот режим вызывает функции крючка, содержащиеся в before-revert-hook и after-revert-hook. В качестве стратегии я бы написал функцию для after-revert-hook, которая подчеркивает последнее строка в буфере, подлежащая возврату. Что-то вроде этого:

(defun my-auto-revert-tail-mode-display-separator-line ()
  "Separate blocks of log lines with an horizontal line."
  (save-excursion
    (goto-char (point-max))
    (while (and (= (line-beginning-position) (line-end-position))
        (> (point) (point-min)))
      (forward-line -1))
    (let ((ov (make-overlay (line-beginning-position) (line-end-position))))
      (overlay-put ov 'face 'underline))))

(add-hook 'after-revert-hook 'my-auto-revert-tail-mode-display-separator-line)