Emacs自动恢复缓冲区:高效实现日志分隔线与新增行高亮的方法
Alright, let's work through your two Emacs requirements with efficient, practical fixes:
1. Highlight Only New Lines on Buffer Auto-Revert
To highlight just the lines added when your buffer auto-reverts, we'll track the buffer's end position after each revert and use an overlay to mark the new content. Here's the implementation:
(defvar-local my-last-revert-point nil "Stores the buffer position after the last revert.") (defun my-highlight-new-lines-after-revert () "Highlight lines added since the last buffer revert." (when (boundp 'my-last-revert-point) (let* ((old-point (or my-last-revert-point (point-min))) (new-point (point-max)) (ov (make-overlay old-point new-point))) (overlay-put ov 'face 'highlight) ;; Optional: Clear the highlight after 5 seconds (run-at-time 5 nil #'delete-overlay ov)) (setq my-last-revert-point (point-max)))) (add-hook 'after-revert-hook #'my-highlight-new-lines-after-revert)
How it works:
my-last-revert-pointis a buffer-local variable that remembers where the buffer ended after the last revert.- The hook function runs every time the buffer is reverted, creates an overlay for the content between the last end position and the current end, and uses the built-in
highlightface to make it stand out. - The optional timer clears the highlight after 5 seconds (adjust the number to change how long it stays visible).
2. Optimize Log Separator Command for Auto-Execution & Large Files
Your original command scans the entire file every run, which is slow for big, continuously updating logs. We'll fix this by only processing new content added since the last run, and hook it to auto-revert so it runs automatically every 5 seconds (matching your auto-revert interval).
Here's the optimized code, with a fix for a regex edge case in your original implementation:
(defvar-local my-last-separator-pos nil "Stores the last position where we added log separators.") (defface log-mode-separator-face '((t (:overline "white" :height 1.0))) "Face for log separator lines (adds overline between log blocks)." :group 'log-mode) (defun my-log-mode-display-separator-line () "Separate blocks of log lines with an horizontal line, only processing new content." (interactive) (save-excursion (let* ((start-pos (or my-last-separator-pos (point-min))) (last-timestamp nil) ov) (goto-char start-pos) ;; Fixed regex to match 10-12 months (original missed these) (while (re-search-forward "[0-9]\\{4\\}-[01][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]" nil t) (when last-timestamp (let* ((current-time (float-time (date-to-time (match-string 0)))) (last-time (float-time (date-to-time last-timestamp)))) (when (> (- current-time last-time) 3) ;; Add separator on the current line (matches your original logic) (setq ov (make-overlay (line-beginning-position) (line-end-position))) (overlay-put ov 'face 'log-mode-separator-face)))) (setq last-timestamp (match-string 0))) ;; Update last processed position to the end of the buffer (setq my-last-separator-pos (point-max))))) ;; Hook to run automatically on buffer revert (add-hook 'after-revert-hook #'my-log-mode-display-separator-line)
Key optimizations & fixes:
- Partial scanning only: Instead of starting from the beginning of the file every time, we use
my-last-separator-posto track where we left off. This means we only process new log lines added since the last run, eliminating full-file scans for large logs. - Auto-execution: By adding the function to
after-revert-hook, it runs automatically every time the buffer is reverted (default interval is 5 seconds; adjustauto-revert-intervalif you need a different timing). - Regex fix: The original regex missed months 10-12 (it used
[01][1-9]). The updated regex[01][0-9]correctly matches all valid months. - Face definition: Included a
deffaceblock to ensurelog-mode-separator-faceis properly configured with the overline attribute you need.
If you need to adjust the auto-revert interval, add this to your config:
(setq auto-revert-interval 5) ; Change 5 to your preferred number of seconds
内容的提问来源于stack exchange,提问作者user3341592

