branch: elpa/logview
commit 1fdeaec361abe67cdb3a31285c2fe37ce4be99dc
Author: Paul Pogonyshev <pogonys...@gmail.com>
Commit: Paul Pogonyshev <pogonys...@gmail.com>

    Fix section commands and also a few commands added earlier to behave 
properly when narrowing is in effect.
---
 logview.el                | 110 +++++++++-------
 test/log4j/sections-1.log |  38 +++---
 test/logview.el           | 324 ++++++++++++++++++++++++----------------------
 3 files changed, 253 insertions(+), 219 deletions(-)

diff --git a/logview.el b/logview.el
index 0c5dd16aff..ccba975091 100644
--- a/logview.el
+++ b/logview.el
@@ -1806,7 +1806,8 @@ can use command 
`\\<logview-mode-map>\\[logview-set-section-view]' to change tha
   ;; Second "p" is only needed so that SET-VIEW-IF-NEEDED is non-nil when 
called
   ;; interactively.
   (interactive "p\np")
-  (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0)))
+  (logview--std-temporarily-widening
+    (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 
0))))
 
 (defun logview-go-to-section-end (&optional n set-view-if-needed)
   "Move point to the end of current section.
@@ -1824,7 +1825,8 @@ can use command 
`\\<logview-mode-map>\\[logview-set-section-view]' to change tha
   ;; Second "p" is only needed so that SET-VIEW-IF-NEEDED is non-nil when 
called
   ;; interactively.
   (interactive "p\np")
-  (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0) 
t))
+  (logview--std-temporarily-widening
+    (logview--do-forward-section-as-command set-view-if-needed (if n (1- n) 0) 
t)))
 
 (defun logview-next-section (&optional n set-view-if-needed)
   "Move point down N (1 by default) log sections.
@@ -1835,7 +1837,8 @@ visible entry (usually the header) of the resulting 
section"
   (interactive "p\np")
   (unless n
     (setf n 1))
-  (logview--maybe-complain-about-movement n 
(logview--do-forward-section-as-command set-view-if-needed n) 'section))
+  (logview--std-temporarily-widening
+    (logview--maybe-complain-about-movement n 
(logview--do-forward-section-as-command set-view-if-needed n) 'section)))
 
 (defun logview-previous-section (&optional n set-view-if-needed)
   "Move point up N (1 by default) log sections.
@@ -1877,7 +1880,8 @@ visible entry (usually the header) of the section."
   (interactive "p")
   (unless (region-active-p)
     (push-mark))
-  (logview--do-forward-section-as-command set-view-if-needed 
most-negative-fixnum))
+  (logview--std-temporarily-widening
+    (logview--do-forward-section-as-command set-view-if-needed 
most-negative-fixnum)))
 
 (defun logview-last-section (&optional set-view-if-needed)
   "Move point to the last (visible) section in this thread.
@@ -1888,8 +1892,9 @@ visible entry (usually the header) of the section."
   (interactive "p")
   (unless (region-active-p)
     (push-mark))
-  (when (> (logview--do-forward-section-as-command set-view-if-needed 
most-positive-fixnum) 0)
-    (logview--forward-section 0)))
+  (logview--std-temporarily-widening
+    (when (> (logview--do-forward-section-as-command set-view-if-needed 
most-positive-fixnum) 0)
+      (logview--forward-section 0))))
 
 (defun logview-first-section-any-thread (&optional set-view-if-needed)
   "Move point to the first (visible) section regardless of thread.
@@ -1947,40 +1952,46 @@ the argument is positive, non-bound otherwise."
     ;; The logic of this code is pretty much impossible to follow.  Just trust 
it as long
     ;; as it passes the tests.
     (let* ((forward         (or (> n 0) (and (= n 0) go-to-end)))
+           (limit           (if forward (logview--point-max) 
(logview--point-min)))
            (section-thread  (when (logview-sections-thread-bound-p)
                               (logview--entry-group last-valid-entry 
last-valid-start logview--thread-group)))
            (header-filter   (cdr logview--section-header-filter))
            ;; Current section is always visible.
            (visible-section t)
            (callback        (lambda (entry start)
-                              ;; Ignore entries belonging to a "wrong" thread 
and continue.
-                              (or (and section-thread (not (string= 
(logview--entry-group entry start logview--thread-group) section-thread)))
-                                  (let ((header (funcall header-filter entry 
start)))
-                                    (if (and (= n 0) forward go-to-end header)
-                                        nil
-                                      (let ((invisible (invisible-p start)))
-                                        (when header
-                                          (unless (or invisible forward)
-                                            (setf visible-section t))
-                                          (when visible-section
-                                            (setf n (if forward (1- n) (1+ 
n))))
-                                          (when forward
-                                            (setf visible-section nil)))
-                                        (or invisible
-                                            (progn
-                                              (setf last-valid-entry entry
-                                                    last-valid-start start)
-                                              (when (or forward (not header))
-                                                (setf visible-section t))
-                                              (or (if forward
-                                                      (or (> n 0) go-to-end)
-                                                    (when (if go-to-end
-                                                              (or (< n 0) 
header)
-                                                            (or (<= n 0) (not 
header)))
-                                                      (when header
-                                                        (setf visible-section 
nil))
-                                                      t))
-                                                  (progn (setf n 0) 
nil)))))))))))
+                              ;; See comment above iterating calls.
+                              (and (if forward (<= start limit) (> 
(logview--entry-end entry start) limit))
+                                   ;; Ignore entries belonging to a "wrong" 
thread and continue.
+                                   (or (and section-thread (not (string= 
(logview--entry-group entry start logview--thread-group) section-thread)))
+                                       (let ((header (funcall header-filter 
entry start)))
+                                         (if (and (= n 0) forward go-to-end 
header)
+                                             nil
+                                           (let ((invisible (invisible-p 
start)))
+                                             (when header
+                                               (unless (or invisible forward)
+                                                 (setf visible-section t))
+                                               (when visible-section
+                                                 (setf n (if forward (1- n) 
(1+ n))))
+                                               (when forward
+                                                 (setf visible-section nil)))
+                                             (or invisible
+                                                 (progn
+                                                   (setf last-valid-entry entry
+                                                         last-valid-start 
start)
+                                                   (when (or forward (not 
header))
+                                                     (setf visible-section t))
+                                                   (or (if forward
+                                                           (or (> n 0) 
go-to-end)
+                                                         (when (if go-to-end
+                                                                   (or (< n 0) 
header)
+                                                                 (or (<= n 0) 
(not header)))
+                                                           (when header
+                                                             (setf 
visible-section nil))
+                                                           t))
+                                                       (progn (setf n 0) 
nil))))))))))))
+      ;; We don't skip invisible entries, since we need to detect section 
bounds even if
+      ;; the headers are filtered out.  Therefore, the callback needs to take 
narrowing
+      ;; into account explicitly.
       (if forward
           (logview--iterate-entries-forward last-valid-start callback nil nil 
t)
         (logview--iterate-entries-backward  last-valid-start callback))
@@ -2303,14 +2314,14 @@ entry after the gap."
     (logview--assert 'thread))
   (unless n
     (setq n 1))
-  (logview--locate-current-entry started-at-entry started-at
-    (let ((thread (when same-thread-only
-                    (logview--entry-group started-at-entry started-at 
logview--thread-group))))
-      (when (< n 0)
-        (logview--forward-entry -1 (when thread
-                                     (lambda (entry start)
-                                       (string-equal (logview--entry-group 
entry start logview--thread-group) thread)))))
-      (logview--std-temporarily-widening
+  (logview--std-temporarily-widening
+    (logview--locate-current-entry started-at-entry started-at
+      (let ((thread (when same-thread-only
+                      (logview--entry-group started-at-entry started-at 
logview--thread-group))))
+        (when (< n 0)
+          (logview--forward-entry -1 (when thread
+                                       (lambda (entry start)
+                                         (string-equal (logview--entry-group 
entry start logview--thread-group) thread)))))
         (logview--locate-current-entry entry start
           (let ((remaining (logview--forward-entry n 
(logview--entry-timestamp-gap-validator entry start thread)))
                 (success   (when logview--last-found-large-gap
@@ -2976,7 +2987,11 @@ returns non-nil."
   "Return the entry around POSITION and its beginning.
 If POSITION is nil, take the current value of point as the
 position, and also signal a user-level error if no entries can be
-located."
+located.
+
+This function may misbehave if any narrowing is in effect.  Make
+sure to cancel it using `logview--std-temporarily-widening' or
+something similar first."
   (let* ((entry-at (or position (point)))
          (entry    (or (get-text-property entry-at 'logview-entry)
                        (progn (logview--find-region-entries entry-at (+ 
entry-at logview--lazy-region-size))
@@ -3013,7 +3028,7 @@ CALLBACK."
     (when entry+start
       (let ((entry    (car entry+start))
             (entry-at (cdr entry+start))
-            (limit    (1+ (buffer-size))))
+            (limit    (if only-visible (logview--point-max) (1+ 
(buffer-size)))))
         (unless (and skip-current (>= (setq entry-at (logview--entry-end entry 
entry-at)) limit))
           (while (progn (setq entry (or (get-text-property entry-at 
'logview-entry)
                                         (progn (logview--find-region-entries 
entry-at (+ entry-at logview--lazy-region-size))
@@ -3029,8 +3044,9 @@ See `logview--iterate-entries-forward' for details."
   (let ((entry+start (logview--do-locate-current-entry position)))
     (when entry+start
       (let ((entry    (car entry+start))
-            (entry-at (cdr entry+start)))
-        (unless (and skip-current (<= (setq entry-at (1- entry-at)) 0 ))
+            (entry-at (cdr entry+start))
+            (limit    (if only-visible (logview--point-min) 1)))
+        (unless (and skip-current (< (setq entry-at (1- entry-at)) limit))
           (while (and (setq entry (or (get-text-property entry-at 
'logview-entry)
                                       (progn (logview--find-region-entries 
(max 1 (- entry-at logview--lazy-region-size)) (1+ entry-at) t)
                                              (get-text-property entry-at 
'logview-entry))))
@@ -3039,7 +3055,7 @@ See `logview--iterate-entries-forward' for details."
                              (when (or (and only-visible (invisible-p 
entry-at))
                                        (and validator (not (funcall validator 
entry entry-at)))
                                        (funcall callback entry entry-at))
-                               (> (setq entry-at (1- entry-at)) 0))))))))))
+                               (>= (setq entry-at (1- entry-at)) 
limit))))))))))
 
 (defun logview--iterate-successive-entries (position n callback &optional 
only-visible validator)
   (when (/= n 0)
diff --git a/test/log4j/sections-1.log b/test/log4j/sections-1.log
index 4332cb0235..8afe2ddd0f 100644
--- a/test/log4j/sections-1.log
+++ b/test/log4j/sections-1.log
@@ -1,19 +1,19 @@
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Startup - starting up
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - before any sections
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - before any sections 
continued
-2010-03-10 20:03:44.332 [thread 1] INFO my.Server - serving request 1
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - inside section 1
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing stuff (section 1)
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing more stuff (section 
1)
-2010-03-10 20:03:44.332 [thread 1] INFO my.Server - serving request 2
-2010-03-10 20:03:44.332 [thread 2] INFO my.Server - serving request 3 (in a 
different thread)
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - inside section 3
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - inside section 2
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing stuff (section 3)
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing stuff (section 2)
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing more stuff (section 
3)
-2010-03-10 20:03:44.332 [thread 2] INFO my.Server - serving request 4 (in a 
different thread)
-2010-03-10 20:03:44.332 [thread 1] DEBUG my.Class - doing more stuff (section 
2)
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - inside section 4
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing stuff (section 4)
-2010-03-10 20:03:44.332 [thread 2] DEBUG my.Class - doing more stuff (section 
4)
+2010-03-10 20:03:44.000 [thread 1] DEBUG my.Startup - starting up
+2010-03-10 20:03:44.100 [thread 1] DEBUG my.Class - before any sections
+2010-03-10 20:03:44.200 [thread 1] DEBUG my.Class - before any sections 
continued
+2010-03-10 20:03:45.000 [thread 1] INFO my.Server - serving request 1
+2010-03-10 20:03:45.100 [thread 1] DEBUG my.Class - inside section 1
+2010-03-10 20:03:45.200 [thread 1] DEBUG my.Class - doing stuff (section 1)
+2010-03-10 20:03:45.300 [thread 1] DEBUG my.Class - doing more stuff (section 
1)
+2010-03-10 20:03:46.000 [thread 1] INFO my.Server - serving request 2
+2010-03-10 20:03:46.100 [thread 2] INFO my.Server - serving request 3 (in a 
different thread)
+2010-03-10 20:03:46.200 [thread 2] DEBUG my.Class - inside section 3
+2010-03-10 20:03:46.300 [thread 1] DEBUG my.Class - inside section 2
+2010-03-10 20:03:46.400 [thread 2] DEBUG my.Class - doing stuff (section 3)
+2010-03-10 20:03:46.500 [thread 1] DEBUG my.Class - doing stuff (section 2)
+2010-03-10 20:03:46.600 [thread 2] DEBUG my.Class - doing more stuff (section 
3)
+2010-03-10 20:03:47.000 [thread 2] INFO my.Server - serving request 4 (in a 
different thread)
+2010-03-10 20:03:47.100 [thread 1] DEBUG my.Class - doing more stuff (section 
2)
+2010-03-10 20:03:47.200 [thread 2] DEBUG my.Class - inside section 4
+2010-03-10 20:03:47.300 [thread 2] DEBUG my.Class - doing stuff (section 4)
+2010-03-10 20:03:47.400 [thread 2] DEBUG my.Class - doing more stuff (section 
4)
diff --git a/test/logview.el b/test/logview.el
index 80afae4011..aefb440e20 100644
--- a/test/logview.el
+++ b/test/logview.el
@@ -60,14 +60,24 @@
 
 
 (defun logview--test-current-message ()
-  (logview--locate-current-entry entry start
-    (string-trim (logview--entry-message entry start))))
+  (logview--std-temporarily-widening
+    (logview--locate-current-entry entry start
+      (string-trim (logview--entry-message entry start)))))
 
 (defun logview--test-position-at-entry-with (message)
   (goto-char (point-min))
   (re-search-forward (rx-to-string `(seq ,message eol))))
 
 
+(defmacro logview--subtest (save-excursion operation &rest etc)
+  (declare (debug (form form body))
+           (indent 2))
+  `(,(if (eval save-excursion t) 'save-excursion 'progn)
+    (ert-info ((format "operation: %S" ',operation))
+      ,operation
+      ,@etc)))
+
+
 (ert-deftest logview-test-log4j-standard-1 ()
   (logview--test-with-file "log4j/en-1.log"
     (should (equal logview--submode-name "SLF4J"))
@@ -299,15 +309,6 @@
     (should (equal (logview--locate-current-entry entry nil 
(logview--entry-level entry)) 7))))
 
 
-(defmacro logview--subtest (save-excursion operation &rest etc)
-  (declare (debug (form form body))
-           (indent 2))
-  `(,(if (eval save-excursion t) 'save-excursion 'progn)
-    (ert-info ((format "operation: %S" ',operation))
-      ,operation
-      ,@etc)))
-
-
 ;; This is a huge test, but I find it easier to test various combinations this 
way.
 ;;
 ;; Expected results of `logview-*-section-any-thread' may seem wrong, but 
remember that
@@ -322,148 +323,165 @@
                             (logview--views-initialized t)
                             (logview--views-need-saving nil))
     (logview-set-section-view "sections")
-    ;; "Section zero", i.e. before any section headers.
-    (dolist (message '("starting up" "before any sections" "before any 
sections continued"))
-      (logview--test-position-at-entry-with message)
-      (ert-info ((format "operating from line \"%s\"" message))
-        (logview--subtest t (logview-go-to-section-beginning)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-go-to-section-end)
-          (should (string= (logview--test-current-message) "before any 
sections continued")))
-        (logview--subtest t (logview-next-section)
-          (should (string= (logview--test-current-message) "serving request 
1")))
-        ;; There is no previous section, obviously.
-        (logview--subtest t (should-error (logview-previous-section) :type 
'user-error)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-next-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 
1")))
-        (logview--subtest t (should-error 
(logview-previous-section-any-thread) :type 'user-error)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-first-section)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-first-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-last-section)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-last-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))))
-    ;; First real section.
-    (dolist (message '("serving request 1" "inside section 1" "doing stuff 
(section 1)" "doing more stuff (section 1)"))
-      (logview--test-position-at-entry-with message)
-      (ert-info ((format "operating from line \"%s\"" message))
-        (logview--subtest t (logview-go-to-section-beginning)
-          (should (string= (logview--test-current-message) "serving request 
1")))
-        (logview--subtest t (logview-go-to-section-end)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 1)")))
-        (logview--subtest t (logview-next-section)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-previous-section)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-next-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-previous-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-first-section)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-first-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-last-section)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-last-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))))
-    ;; Second real section, intervined with sections 3 and 4 in a different 
thread.
-    (dolist (message '("serving request 2" "inside section 2" "doing stuff 
(section 2)" "doing more stuff (section 2)"))
-      (logview--test-position-at-entry-with message)
-      (ert-info ((format "operating from line \"%s\"" message))
-        (logview--subtest t (logview-go-to-section-beginning)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-go-to-section-end)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 2)")))
-         ;; There is no next section in this thread.
-        (logview--subtest t (should-error (logview-next-section) :type 
'user-error)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 2)")))
-        (logview--subtest t (logview-previous-section)
-          (should (string= (logview--test-current-message) "serving request 
1")))
-        ;; Results of `logview-*-section-any-thread' depend on the starting 
line.
-        (pcase message
-          ("serving request 2"
-           (logview--subtest t (logview-next-section-any-thread)
-             (should (string= (logview--test-current-message) "serving request 
3 (in a different thread)"))))
-          ("doing more stuff (section 2)"
-           (logview--subtest t (should-error (logview-next-section-any-thread) 
:type 'user-error)
-             (should (string= (logview--test-current-message) "doing more 
stuff (section 4)"))))
-          (_
-           (logview--subtest t (logview-next-section-any-thread)
-             (should (string= (logview--test-current-message) "serving request 
4 (in a different thread)")))))
-        (pcase message
-          ("serving request 2"
-           (logview--subtest t (logview-previous-section-any-thread)
-             (should (string= (logview--test-current-message) "serving request 
1"))))
-          ("doing more stuff (section 2)"
-           (logview--subtest t (logview-previous-section-any-thread)
-             (should (string= (logview--test-current-message) "serving request 
3 (in a different thread)"))))
-          (_
-           (logview--subtest t (logview-previous-section-any-thread)
-             (should (string= (logview--test-current-message) "serving request 
2")))))
-        (logview--subtest t (logview-first-section)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-first-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-last-section)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-last-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))))
-    ;; Third real section, intervined with section 2 in a different thread.
-    (dolist (message '("serving request 3 (in a different thread)" "inside 
section 3" "doing stuff (section 3)" "doing more stuff (section 3)"))
-      (logview--test-position-at-entry-with message)
-      (ert-info ((format "operating from line \"%s\"" message))
-        (logview--subtest t (logview-go-to-section-beginning)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        (logview--subtest t (logview-go-to-section-end)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 3)")))
-        (logview--subtest t (logview-next-section)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))
-        ;; No previous section in _this thread_.
-        (logview--subtest t (should-error (logview-previous-section) :type 
'user-error)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        (logview--subtest t (logview-next-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))
-        (logview--subtest t (logview-previous-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 
2")))
-        (logview--subtest t (logview-first-section)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        (logview--subtest t (logview-first-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-last-section)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))
-        (logview--subtest t (logview-last-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))))
-    ;; Fourth section, the very last in the file.
-    (dolist (message '("serving request 4 (in a different thread)" "inside 
section 4" "doing stuff (section 4)" "doing more stuff (section 4)"))
-      (logview--test-position-at-entry-with message)
-      (ert-info ((format "operating from line \"%s\"" message))
-        (logview--subtest t (logview-go-to-section-beginning)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))
-        (logview--subtest t (logview-go-to-section-end)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 4)")))
-        ;; There is no next section in this thread.
-        (logview--subtest t (should-error (logview-next-section) :type 
'user-error)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 4)")))
-        (logview--subtest t (logview-previous-section)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        ;; No next section at all.
-        (logview--subtest t (should-error (logview-next-section-any-thread) 
:type 'user-error)
-          (should (string= (logview--test-current-message) "doing more stuff 
(section 4)")))
-        (logview--subtest t (logview-previous-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        (logview--subtest t (logview-first-section)
-          (should (string= (logview--test-current-message) "serving request 3 
(in a different thread)")))
-        (logview--subtest t (logview-first-section-any-thread)
-          (should (string= (logview--test-current-message) "starting up")))
-        (logview--subtest t (logview-last-section)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))
-        (logview--subtest t (logview-last-section-any-thread)
-          (should (string= (logview--test-current-message) "serving request 4 
(in a different thread)")))))))
+    (dolist (narrowing '((1 . 1) (2 . 1)))
+      (save-restriction
+        (when (> (car narrowing) 1)
+          (goto-char (point-min))
+          (logview-next-entry (1- (car narrowing)))
+          (logview-narrow-from-this-entry))
+        (when (> (cdr narrowing) 1)
+          (goto-char (point-max))
+          (logview-previous-entry (1- (cdr narrowing)))
+          (logview-narrow-up-to-this-entry))
+        (ert-info ((format "narrowing in effect: %s"
+                           (if (equal narrowing '(1 . 1))
+                               "none"
+                             (format "%s-%s" (if (= (car narrowing) 1) "" (car 
narrowing)) (if (= (cdr narrowing) 1) "" (cdr narrowing))))))
+          (let* ((have-first-line       (= (car narrowing) 1))
+                 (first-visible-message (if have-first-line "starting up" 
"before any sections")))
+            ;; "Section zero", i.e. before any section headers.
+            (dolist (message '("starting up" "before any sections" "before any 
sections continued"))
+              (when (or have-first-line (not (string= message "starting up")))
+                (logview--test-position-at-entry-with message)
+                (ert-info ((format "operating from line \"%s\"" message))
+                  (logview--subtest t (logview-go-to-section-beginning)
+                    (should (string= (logview--test-current-message) 
first-visible-message)))
+                  (logview--subtest t (logview-go-to-section-end)
+                    (should (string= (logview--test-current-message) "before 
any sections continued")))
+                  (logview--subtest t (logview-next-section)
+                    (should (string= (logview--test-current-message) "serving 
request 1")))
+                  ;; There is no previous section, obviously.
+                  (logview--subtest t (should-error (logview-previous-section) 
:type 'user-error)
+                    (should (string= (logview--test-current-message) 
first-visible-message)))
+                  (logview--subtest t (logview-next-section-any-thread)
+                    (should (string= (logview--test-current-message) "serving 
request 1")))
+                  (logview--subtest t (should-error 
(logview-previous-section-any-thread) :type 'user-error)
+                    (should (string= (logview--test-current-message) 
first-visible-message)))
+                  (logview--subtest t (logview-first-section)
+                    (should (string= (logview--test-current-message) 
first-visible-message)))
+                  (logview--subtest t (logview-first-section-any-thread)
+                    (should (string= (logview--test-current-message) 
first-visible-message)))
+                  (logview--subtest t (logview-last-section)
+                    (should (string= (logview--test-current-message) "serving 
request 2")))
+                  (logview--subtest t (logview-last-section-any-thread)
+                    (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)"))))))
+            ;; First real section.
+            (dolist (message '("serving request 1" "inside section 1" "doing 
stuff (section 1)" "doing more stuff (section 1)"))
+              (logview--test-position-at-entry-with message)
+              (ert-info ((format "operating from line \"%s\"" message))
+                (logview--subtest t (logview-go-to-section-beginning)
+                  (should (string= (logview--test-current-message) "serving 
request 1")))
+                (logview--subtest t (logview-go-to-section-end)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 1)")))
+                (logview--subtest t (logview-next-section)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-previous-section)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-next-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-previous-section-any-thread)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-first-section)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-first-section-any-thread)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-last-section)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-last-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))))
+            ;; Second real section, intervined with sections 3 and 4 in a 
different thread.
+            (dolist (message '("serving request 2" "inside section 2" "doing 
stuff (section 2)" "doing more stuff (section 2)"))
+              (logview--test-position-at-entry-with message)
+              (ert-info ((format "operating from line \"%s\"" message))
+                (logview--subtest t (logview-go-to-section-beginning)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-go-to-section-end)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 2)")))
+                ;; There is no next section in this thread.
+                (logview--subtest t (should-error (logview-next-section) :type 
'user-error)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 2)")))
+                (logview--subtest t (logview-previous-section)
+                  (should (string= (logview--test-current-message) "serving 
request 1")))
+                ;; Results of `logview-*-section-any-thread' depend on the 
starting line.
+                (pcase message
+                  ("serving request 2"
+                   (logview--subtest t (logview-next-section-any-thread)
+                     (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)"))))
+                  ("doing more stuff (section 2)"
+                   (logview--subtest t (should-error 
(logview-next-section-any-thread) :type 'user-error)
+                     (should (string= (logview--test-current-message) "doing 
more stuff (section 4)"))))
+                  (_
+                   (logview--subtest t (logview-next-section-any-thread)
+                     (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))))
+                (pcase message
+                  ("serving request 2"
+                   (logview--subtest t (logview-previous-section-any-thread)
+                     (should (string= (logview--test-current-message) "serving 
request 1"))))
+                  ("doing more stuff (section 2)"
+                   (logview--subtest t (logview-previous-section-any-thread)
+                     (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)"))))
+                  (_
+                   (logview--subtest t (logview-previous-section-any-thread)
+                     (should (string= (logview--test-current-message) "serving 
request 2")))))
+                (logview--subtest t (logview-first-section)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-first-section-any-thread)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-last-section)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-last-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))))
+            ;; Third real section, intervined with section 2 in a different 
thread.
+            (dolist (message '("serving request 3 (in a different thread)" 
"inside section 3" "doing stuff (section 3)" "doing more stuff (section 3)"))
+              (logview--test-position-at-entry-with message)
+              (ert-info ((format "operating from line \"%s\"" message))
+                (logview--subtest t (logview-go-to-section-beginning)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                (logview--subtest t (logview-go-to-section-end)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 3)")))
+                (logview--subtest t (logview-next-section)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))
+                ;; No previous section in _this thread_.
+                (logview--subtest t (should-error (logview-previous-section) 
:type 'user-error)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                (logview--subtest t (logview-next-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))
+                (logview--subtest t (logview-previous-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 2")))
+                (logview--subtest t (logview-first-section)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                (logview--subtest t (logview-first-section-any-thread)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-last-section)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))
+                (logview--subtest t (logview-last-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))))
+            ;; Fourth section, the very last in the file.
+            (dolist (message '("serving request 4 (in a different thread)" 
"inside section 4" "doing stuff (section 4)" "doing more stuff (section 4)"))
+              (logview--test-position-at-entry-with message)
+              (ert-info ((format "operating from line \"%s\"" message))
+                (logview--subtest t (logview-go-to-section-beginning)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))
+                (logview--subtest t (logview-go-to-section-end)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 4)")))
+                ;; There is no next section in this thread.
+                (logview--subtest t (should-error (logview-next-section) :type 
'user-error)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 4)")))
+                (logview--subtest t (logview-previous-section)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                ;; No next section at all.
+                (logview--subtest t (should-error 
(logview-next-section-any-thread) :type 'user-error)
+                  (should (string= (logview--test-current-message) "doing more 
stuff (section 4)")))
+                (logview--subtest t (logview-previous-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                (logview--subtest t (logview-first-section)
+                  (should (string= (logview--test-current-message) "serving 
request 3 (in a different thread)")))
+                (logview--subtest t (logview-first-section-any-thread)
+                  (should (string= (logview--test-current-message) 
first-visible-message)))
+                (logview--subtest t (logview-last-section)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))
+                (logview--subtest t (logview-last-section-any-thread)
+                  (should (string= (logview--test-current-message) "serving 
request 4 (in a different thread)")))))))))))
 
 
 (define-derived-mode logview--test-derived-mode logview-mode


Reply via email to