]> git.eshelyaron.com Git - emacs.git/commitdiff
MH-E threads code: use mh-scan variables correctly
authorStephen Gildea <stepheng+emacs@gildea.com>
Sat, 13 Nov 2021 15:00:30 +0000 (07:00 -0800)
committerStephen Gildea <stepheng+emacs@gildea.com>
Sat, 13 Nov 2021 15:04:13 +0000 (07:04 -0800)
* lisp/mh-e/mh-thread.el (mh-thread-current-indentation-level)
(mh-thread-find-children): Fix off-by-one error by using
'mh-scan-field-from-start-offset' directly, as
'mh-thread-parse-scan-line' does.  Previously, these functions would
incorrectly consider the "date note" column as part of the thread
indenting.  Since that column is almost always a Space character, that
almost always worked.
(mh-thread-ancestor): Update caller.
* test/lisp/mh-e/mh-thread-tests.el: New unit tests for affected code.
* lisp/mh-e/mh-scan.el (mh-msg-num-width-to-column): Fix doc string typo.

lisp/mh-e/mh-scan.el
lisp/mh-e/mh-thread.el
test/lisp/mh-e/mh-thread-tests.el [new file with mode: 0644]

index 5a1a671aee2c3b4d3fe7431d56bdb7bf2aab2bc2..bf3cfeff5cbc4bf4e752745383657d4ac5e71a3e 100644 (file)
@@ -509,7 +509,7 @@ with `mh-scan-msg-format-string'."
 Note that columns in Emacs start with 0.
 
 If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this
-means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are
+means that either `mh-scan-format-mh' or `mh-scan-format-nmh' is
 in use.  This function therefore assumes that the first column is
 empty (to provide room for the cursor), the following WIDTH
 columns contain the message number, and the column for notations
index 21954da6acd111327263cb30aee100ad236a695a..1be2185ecdf118f5539bf3d613542f50114e2440 100644 (file)
@@ -139,7 +139,7 @@ to the message that started everything."
     (cond (thread-root-flag
            (while (mh-thread-immediate-ancestor))
            (mh-maybe-show))
-          ((equal current-level 1)
+          ((equal current-level 0)
            (message "Message has no ancestor"))
           (t (mh-thread-immediate-ancestor)
              (mh-maybe-show)))))
@@ -242,8 +242,8 @@ sibling."
 (defun mh-thread-current-indentation-level ()
   "Find the number of spaces by which current message is indented."
   (save-excursion
-    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
-                                   mh-scan-date-width 1))
+    (let ((address-start-offset (+ mh-cmd-note
+                                   mh-scan-field-from-start-offset))
           (level 0))
       (beginning-of-line)
       (forward-char address-start-offset)
@@ -275,8 +275,8 @@ at the end."
   (beginning-of-line)
   (if (eobp)
       nil
-    (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width
-                                   mh-scan-date-width 1))
+    (let ((address-start-offset (+ mh-cmd-note
+                                   mh-scan-field-from-start-offset))
           (level (mh-thread-current-indentation-level))
           spaces begin)
       (setq begin (point))
diff --git a/test/lisp/mh-e/mh-thread-tests.el b/test/lisp/mh-e/mh-thread-tests.el
new file mode 100644 (file)
index 0000000..4f09677
--- /dev/null
@@ -0,0 +1,131 @@
+;;; mh-thread-tests.el --- tests for mh-thread.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'mh-thread)
+(eval-when-compile (require 'cl-lib))
+
+(defun mh-thread-tests-before-from ()
+  "Generate the fields of a scan line up to where the 'From' field would start.
+The exact contents are not important, but the number of characters is."
+    (concat (make-string mh-cmd-note ?9)
+            (make-string mh-scan-cmd-note-width ?A)
+            (make-string mh-scan-destination-width ?t)
+            (make-string mh-scan-date-width ?/)
+            (make-string mh-scan-date-flag-width ?*)))
+
+;;; Tests of support routines
+
+(ert-deftest mh-thread-current-indentation-level ()
+  "Test that `mh-thread-current-indentation-level' identifies the level."
+  (with-temp-buffer
+    (insert (mh-thread-tests-before-from) "[Sender One]  Subject of msg 1\n")
+    (insert (mh-thread-tests-before-from) "  [Sender Two]  Subject of msg 2\n")
+    (goto-char (point-min))
+    (should (equal 0 (mh-thread-current-indentation-level)))
+    (forward-line)
+    (should (equal 2 (mh-thread-current-indentation-level)))))
+
+(ert-deftest mh-thread-find-children ()
+  "Test `mh-thread-find-children'."
+  (let (expected-start expected-end)
+    (with-temp-buffer
+      (insert (mh-thread-tests-before-from) "[Sender One]  line 1\n")
+      (setq expected-start (point))
+      (insert (mh-thread-tests-before-from) "  [Sender Two]  line 2\n")
+      (insert (mh-thread-tests-before-from) "    [Sender Three]  line 3\n")
+      (insert (mh-thread-tests-before-from) "      [Sender Four]  line 4\n")
+      (setq expected-end (1- (point)))
+      (insert (mh-thread-tests-before-from) "  [Sender Five]  line 5\n")
+      (goto-char (1+ expected-start))
+      (should (equal (list expected-start expected-end)
+                     (mh-thread-find-children))))))
+
+(ert-deftest mh-thread-immediate-ancestor ()
+  "Test that `mh-thread-immediate-ancestor' moves to the correct message."
+  (with-temp-buffer
+    (insert (mh-thread-tests-before-from) "[Sender Other]  line 1\n")
+    (insert (mh-thread-tests-before-from) "[Sender One]  line 2\n")
+    (insert (mh-thread-tests-before-from) "  [Sender Two]  line 3\n")
+    (insert (mh-thread-tests-before-from) "    [Sender Three]  line 4\n")
+    (insert (mh-thread-tests-before-from) "      [Sender Four]  line 5\n")
+    (insert (mh-thread-tests-before-from) "      [Sender Five]  line 6\n")
+    (forward-line -1)
+    (should (equal (line-number-at-pos) 6))
+    (mh-thread-immediate-ancestor)
+    (should (equal (line-number-at-pos) 4)) ;skips over sibling
+    (mh-thread-immediate-ancestor)
+    (should (equal (line-number-at-pos) 3)) ;goes up only one level at a time
+    (mh-thread-immediate-ancestor)
+    (should (equal (line-number-at-pos) 2))
+    (mh-thread-immediate-ancestor)
+    (should (equal (line-number-at-pos) 2)))) ;no further motion at thread root
+
+;;; Tests of MH-Folder Commands
+
+(ert-deftest mh-thread-sibling-and-ancestor ()
+  "Test motion by `mh-thread-ancestor' and `mh-thread-next-sibling'."
+  (with-temp-buffer
+    (insert (mh-thread-tests-before-from) "[Sender Other]  line 1\n")
+    (insert (mh-thread-tests-before-from) "[Sender One]  line 2\n")
+    (insert (mh-thread-tests-before-from) "  [Sender Two]  line 3\n")
+    (insert (mh-thread-tests-before-from) "    [Sender Three]  line 4\n")
+    (insert (mh-thread-tests-before-from) "      [Sender Four]  line 5\n")
+    (insert (mh-thread-tests-before-from) "      [Sender Five]  line 6\n")
+    (forward-line -1)
+    (let ((mh-view-ops '(unthread))
+          (show-count 0))
+      (cl-letf (((symbol-function 'mh-maybe-show)
+                 (lambda ()
+                  (setq show-count (1+ show-count)))))
+        (should (equal (line-number-at-pos) 6))
+        ;; test mh-thread-ancestor
+        (mh-thread-ancestor)
+        (should (equal (line-number-at-pos) 4)) ;skips over sibling
+        (should (equal show-count 1))
+        (mh-thread-ancestor t)
+        (should (equal (line-number-at-pos) 2)) ;root flag skips to root
+        (should (equal show-count 2))
+        (mh-thread-ancestor)
+        (should (equal (line-number-at-pos) 2)) ;do not move from root
+        (should (equal show-count 2))   ;do not re-show at root
+        ;; test mh-thread-sibling
+        (mh-thread-next-sibling)
+        (should (equal (line-number-at-pos) 2)) ;no next sibling, no motion
+        (should (equal show-count 2))   ;no sibling, no show
+        (mh-thread-next-sibling t)
+        (should (equal (line-number-at-pos) 1))
+        (should (equal show-count 3))
+        (mh-thread-next-sibling t)
+        (should (equal (line-number-at-pos) 1)) ;no previous sibling
+        (should (equal show-count 3))
+        (goto-char (point-max))
+        (forward-line -1)
+        (should (equal (line-number-at-pos) 6))
+        (mh-thread-next-sibling t)
+        (should (equal (line-number-at-pos) 5))
+        (should (equal show-count 4))
+        (mh-thread-next-sibling t)
+        (should (equal (line-number-at-pos) 5)) ;no previous sibling
+        (should (equal show-count 4))
+        ))))
+
+;;; mh-thread-tests.el ends here