branch: elpa/logview commit 9140067afdc2f0d1eb493dc4dfdb53645289dd2b Author: Paul Pogonyshev <pogonys...@gmail.com> Commit: Paul Pogonyshev <pogonys...@gmail.com>
Fix a couple of problems with displaying timestamp differences; add tests. --- logview.el | 46 ++++++++++++++++++++++------------- test/logview.el | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/logview.el b/logview.el index 0df4a24cce..8e199d5617 100644 --- a/logview.el +++ b/logview.el @@ -701,9 +701,11 @@ settings) with this face.") (defvar-local logview--hide-all-details nil) (defvar-local logview--timestamp-difference-base nil - "Either nil or (POSITION . TIMESTAMP-AS-FLOAT).") + "Either nil or (ENTRY . START). +ENTRY will have its timestamp parsed.") (defvar-local logview--timestamp-difference-per-thread-bases nil - "Either nil or a hash-table of strings to cons cells.") + "Either nil or a hash-table of strings to cons cells. +See `logview--timestamp-difference-base' for details.") (defvar-local logview--buffer-target-gap-length nil) (defvar-local logview--last-found-large-gap nil) @@ -2395,10 +2397,13 @@ difference bases (appointed with `\\<logview-mode-map>\\[logview-thread-differen (logview--assert 'timestamp) (logview--std-temporarily-widening (logview--locate-current-entry entry start - (unless (and (equal (cdr logview--timestamp-difference-base) start) (null logview--timestamp-difference-per-thread-bases)) - (setq logview--timestamp-difference-base (cons entry start) - logview--timestamp-difference-per-thread-bases nil) - (logview--refontify-buffer))))) + ;; Make sure that it is parsed. + (logview--entry-timestamp entry start) + (let ((base (cons entry start))) + (unless (and (equal logview--timestamp-difference-base base) (null logview--timestamp-difference-per-thread-bases)) + (setq logview--timestamp-difference-base base + logview--timestamp-difference-per-thread-bases nil) + (logview--refontify-buffer)))))) (defun logview-thread-difference-to-current-entry () "Display difference to current entry's timestamp in its thread. @@ -2408,11 +2413,14 @@ it stays in effect for other threads." (logview--assert 'timestamp 'thread) (logview--std-temporarily-widening (logview--locate-current-entry entry start - (let ((thread (logview--entry-group entry start logview--thread-group))) - (unless (and logview--timestamp-difference-per-thread-bases (equal (cdr (gethash thread logview--timestamp-difference-per-thread-bases)) start)) + ;; Make sure that it is parsed. + (logview--entry-timestamp entry start) + (let ((base (cons entry start)) + (thread (logview--entry-group entry start logview--thread-group))) + (unless (and logview--timestamp-difference-per-thread-bases (equal (gethash thread logview--timestamp-difference-per-thread-bases) base)) (unless logview--timestamp-difference-per-thread-bases (setq logview--timestamp-difference-per-thread-bases (make-hash-table :test #'equal))) - (puthash thread (cons entry start) logview--timestamp-difference-per-thread-bases) + (puthash thread base logview--timestamp-difference-per-thread-bases) (logview--refontify-buffer)))))) (defun logview-go-to-difference-base-entry () @@ -2427,10 +2435,10 @@ it stays in effect for other threads." logview--timestamp-difference-base))) (unless difference-base (user-error "There is no timestamp difference base for the current entry")) - (when (invisible-p difference-base) - (user-error "Timestamp difference base for the current entry is currently hidden")) - (let* ((entry (car difference-base)) - (start (cdr difference-base))) + (when (invisible-p (cdr difference-base)) + (user-error "Timestamp difference base is either hidden or not in the current file contents anymore (e.g. due to log rolling)")) + (let ((entry (car difference-base)) + (start (cdr difference-base))) (unless (and (< start (logview--point-max)) (> (logview--entry-end entry start) (logview--point-min))) (user-error "Difference base entry is outside the narrowing region")) (goto-char (logview--entry-message-start entry start)) @@ -3870,9 +3878,9 @@ This list is preserved across Emacs session in (have-name (memq 'name logview--submode-features)) (have-thread (memq 'thread logview--submode-features)) (validator (cdr logview--effective-filter)) - (difference-base logview--timestamp-difference-base) + (common-difference-base logview--timestamp-difference-base) (difference-bases-per-thread logview--timestamp-difference-per-thread-bases) - (displaying-differences (or difference-base difference-bases-per-thread)) + (displaying-differences (or common-difference-base difference-bases-per-thread)) (difference-format-string logview--timestamp-difference-format-string) (header-filter (cdr logview--section-header-filter)) (highlighter (cdr logview--highlighted-filter)) @@ -3898,8 +3906,12 @@ This list is preserved across Emacs session in (when displaying-differences (let ((difference-base (or (when difference-bases-per-thread (gethash (logview--entry-group entry start logview--thread-group) difference-bases-per-thread)) - difference-base))) - (when (and difference-base (not (= (cdr difference-base) start))) + common-difference-base))) + ;; Hide timestamp with time difference if there is a difference + ;; base entry and we are not positioned over it right now. + (when (and difference-base (not (and (= (cdr difference-base) start) + (progn (logview--entry-timestamp entry start) ; Make sure that it is parsed. + (equal (car difference-base) entry))))) ;; FIXME: It is possible that fractionals are not the last ;; thing in the timestamp, in which case it would be ;; nicer to add some spaces on the right. However, diff --git a/test/logview.el b/test/logview.el index 90910e263c..14d0ebecd4 100644 --- a/test/logview.el +++ b/test/logview.el @@ -31,6 +31,11 @@ (error "Warning elevated to an error: %S" arguments)) (defmacro logview--test-with-file (filename &rest body) + "Activate Logview in a temporary buffer with contents of the file. +Instead of visiting the file, this macro creates a new buffer for +it. This avoids annoying clashes if the file is already open +(when in interactive mode) and also allows to further modify +buffer if the test needs that." (declare (debug (form body)) (indent 1)) ;; We do the following to avoid customizations influence testing @@ -61,6 +66,23 @@ (advice-remove 'display-warning #'logview--test-display-warning-advice))))) +(defun logview--test-user-visible-buffer-string () + (font-lock-ensure) + (let ((from (point-min)) + chunks) + (while from + (let ((to (next-property-change from))) + (unless (invisible-p from) + (let ((display-as (get-text-property from 'display))) + (unless (and display-as to (eq display-as (get-text-property to 'display))) + (push (cond ((stringp display-as) display-as) + (display-as (prin1-to-string display-as)) + (t (buffer-substring-no-properties from (or to (point-max))))) + chunks)))) + (setf from to))) + (mapconcat #'identity (nreverse chunks) nil))) + + (defun logview--test-current-message () (logview--std-temporarily-widening (logview--locate-current-entry entry start @@ -158,6 +180,59 @@ (logview-difference-to-current-entry) (logview-go-to-difference-base-entry))) +(ert-deftest logview-hidden-difference-base () + (logview--test-with-file "log4j/sections-1.log" + ;; Testing only one line, but it should hopefully be the same for other lines. + (should (string-match-p (rx bol "2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections" eol) + (logview--test-user-visible-buffer-string))) + (logview-next-entry) + (logview-difference-to-current-entry) + (should (string-match-p (rx bol " -0.100 [thread 1] DEBUG my.Startup - starting up" eol) + (logview--test-user-visible-buffer-string))) + (should (string-match-p (rx bol "2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections" eol) + (logview--test-user-visible-buffer-string))) + (goto-char 1) + (logview-go-to-difference-base-entry) + (should (looking-at (rx "before any sections" eol))) + (logview-show-errors-warnings-and-information) + ;; Must be filtered out and invisible now. + (should-not (string-match-p (rx bol "2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections" eol) + (logview--test-user-visible-buffer-string))) + (should-error (logview-go-to-difference-base-entry) :type 'user-error))) + +(ert-deftest logview-time-differences-after-full-buffer-reload () + ;; Using a test file with different timestamps for different entries. + (logview--test-with-file "log4j/sections-1.log" + ;; Testing only one line, but it should hopefully be the same for other lines. + (should (string-match-p (rx bol "2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections" eol) + (logview--test-user-visible-buffer-string))) + (logview-difference-to-current-entry) + ;; This first entry should stay the same (not because it's the first, but because it's + ;; the difference base). + (should (string-match-p (rx bol "2010-03-10 20:03:44.000 [thread 1] DEBUG my.Startup - starting up" eol) + (logview--test-user-visible-buffer-string))) + (should (string-match-p (rx bol " +0.100 [thread 1] DEBUG my.Class - before any sections" eol) + (logview--test-user-visible-buffer-string))) + (goto-char (point-max)) + (logview-go-to-difference-base-entry) + (should (looking-at (rx "starting up" eol))) + ;; Emulate the log being fully changed, e.g. due to file rotation. + (logview--std-altering + (save-excursion + (goto-char (point-min)) + (while (re-search-forward (rx "20:03:") nil t) + (replace-match "20:05:") + (end-of-line) + (insert " (changed)")))) + (logview--invalidate-region-entries (point-min) (point-max)) + ;; Same buffer position, but the entry is now different, so must display time + ;; difference. + (should (string-match-p (rx bol " +120.000 [thread 1] DEBUG my.Startup - starting up (changed)" eol) + (logview--test-user-visible-buffer-string))) + (should (string-match-p (rx bol " +120.100 [thread 1] DEBUG my.Class - before any sections (changed)" eol) + (logview--test-user-visible-buffer-string))))) + + ;; See https://github.com/doublep/logview/issues/48 for rationale to have this at all. (ert-deftest logview-custom-submode-with-special-regexp () (logview--test-with-file "custom/2.log"