aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gildea2021-11-13 07:00:30 -0800
committerStephen Gildea2021-11-13 07:04:13 -0800
commit4df334a0f74700e72bfea7817e660605c3f2a2ee (patch)
tree04701661f2e58c65b2071aaf6558afdcd56a16a7
parentd3666ccdba7c3837ffffe3c50a179c110ed55569 (diff)
downloademacs-4df334a0f74700e72bfea7817e660605c3f2a2ee.tar.gz
emacs-4df334a0f74700e72bfea7817e660605c3f2a2ee.zip
MH-E threads code: use mh-scan variables correctly
* 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.
-rw-r--r--lisp/mh-e/mh-scan.el2
-rw-r--r--lisp/mh-e/mh-thread.el10
-rw-r--r--test/lisp/mh-e/mh-thread-tests.el131
3 files changed, 137 insertions, 6 deletions
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
index 5a1a671aee2..bf3cfeff5cb 100644
--- a/lisp/mh-e/mh-scan.el
+++ b/lisp/mh-e/mh-scan.el
@@ -509,7 +509,7 @@ with `mh-scan-msg-format-string'."
509Note that columns in Emacs start with 0. 509Note that columns in Emacs start with 0.
510 510
511If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this 511If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this
512means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are 512means that either `mh-scan-format-mh' or `mh-scan-format-nmh' is
513in use. This function therefore assumes that the first column is 513in use. This function therefore assumes that the first column is
514empty (to provide room for the cursor), the following WIDTH 514empty (to provide room for the cursor), the following WIDTH
515columns contain the message number, and the column for notations 515columns contain the message number, and the column for notations
diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el
index 21954da6acd..1be2185ecdf 100644
--- a/lisp/mh-e/mh-thread.el
+++ b/lisp/mh-e/mh-thread.el
@@ -139,7 +139,7 @@ to the message that started everything."
139 (cond (thread-root-flag 139 (cond (thread-root-flag
140 (while (mh-thread-immediate-ancestor)) 140 (while (mh-thread-immediate-ancestor))
141 (mh-maybe-show)) 141 (mh-maybe-show))
142 ((equal current-level 1) 142 ((equal current-level 0)
143 (message "Message has no ancestor")) 143 (message "Message has no ancestor"))
144 (t (mh-thread-immediate-ancestor) 144 (t (mh-thread-immediate-ancestor)
145 (mh-maybe-show))))) 145 (mh-maybe-show)))))
@@ -242,8 +242,8 @@ sibling."
242(defun mh-thread-current-indentation-level () 242(defun mh-thread-current-indentation-level ()
243 "Find the number of spaces by which current message is indented." 243 "Find the number of spaces by which current message is indented."
244 (save-excursion 244 (save-excursion
245 (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width 245 (let ((address-start-offset (+ mh-cmd-note
246 mh-scan-date-width 1)) 246 mh-scan-field-from-start-offset))
247 (level 0)) 247 (level 0))
248 (beginning-of-line) 248 (beginning-of-line)
249 (forward-char address-start-offset) 249 (forward-char address-start-offset)
@@ -275,8 +275,8 @@ at the end."
275 (beginning-of-line) 275 (beginning-of-line)
276 (if (eobp) 276 (if (eobp)
277 nil 277 nil
278 (let ((address-start-offset (+ mh-cmd-note mh-scan-date-flag-width 278 (let ((address-start-offset (+ mh-cmd-note
279 mh-scan-date-width 1)) 279 mh-scan-field-from-start-offset))
280 (level (mh-thread-current-indentation-level)) 280 (level (mh-thread-current-indentation-level))
281 spaces begin) 281 spaces begin)
282 (setq begin (point)) 282 (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
index 00000000000..4f09677e53f
--- /dev/null
+++ b/test/lisp/mh-e/mh-thread-tests.el
@@ -0,0 +1,131 @@
1;;; mh-thread-tests.el --- tests for mh-thread.el -*- lexical-binding: t -*-
2
3;; Copyright (C) 2021 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23(require 'mh-thread)
24(eval-when-compile (require 'cl-lib))
25
26(defun mh-thread-tests-before-from ()
27 "Generate the fields of a scan line up to where the 'From' field would start.
28The exact contents are not important, but the number of characters is."
29 (concat (make-string mh-cmd-note ?9)
30 (make-string mh-scan-cmd-note-width ?A)
31 (make-string mh-scan-destination-width ?t)
32 (make-string mh-scan-date-width ?/)
33 (make-string mh-scan-date-flag-width ?*)))
34
35;;; Tests of support routines
36
37(ert-deftest mh-thread-current-indentation-level ()
38 "Test that `mh-thread-current-indentation-level' identifies the level."
39 (with-temp-buffer
40 (insert (mh-thread-tests-before-from) "[Sender One] Subject of msg 1\n")
41 (insert (mh-thread-tests-before-from) " [Sender Two] Subject of msg 2\n")
42 (goto-char (point-min))
43 (should (equal 0 (mh-thread-current-indentation-level)))
44 (forward-line)
45 (should (equal 2 (mh-thread-current-indentation-level)))))
46
47(ert-deftest mh-thread-find-children ()
48 "Test `mh-thread-find-children'."
49 (let (expected-start expected-end)
50 (with-temp-buffer
51 (insert (mh-thread-tests-before-from) "[Sender One] line 1\n")
52 (setq expected-start (point))
53 (insert (mh-thread-tests-before-from) " [Sender Two] line 2\n")
54 (insert (mh-thread-tests-before-from) " [Sender Three] line 3\n")
55 (insert (mh-thread-tests-before-from) " [Sender Four] line 4\n")
56 (setq expected-end (1- (point)))
57 (insert (mh-thread-tests-before-from) " [Sender Five] line 5\n")
58 (goto-char (1+ expected-start))
59 (should (equal (list expected-start expected-end)
60 (mh-thread-find-children))))))
61
62(ert-deftest mh-thread-immediate-ancestor ()
63 "Test that `mh-thread-immediate-ancestor' moves to the correct message."
64 (with-temp-buffer
65 (insert (mh-thread-tests-before-from) "[Sender Other] line 1\n")
66 (insert (mh-thread-tests-before-from) "[Sender One] line 2\n")
67 (insert (mh-thread-tests-before-from) " [Sender Two] line 3\n")
68 (insert (mh-thread-tests-before-from) " [Sender Three] line 4\n")
69 (insert (mh-thread-tests-before-from) " [Sender Four] line 5\n")
70 (insert (mh-thread-tests-before-from) " [Sender Five] line 6\n")
71 (forward-line -1)
72 (should (equal (line-number-at-pos) 6))
73 (mh-thread-immediate-ancestor)
74 (should (equal (line-number-at-pos) 4)) ;skips over sibling
75 (mh-thread-immediate-ancestor)
76 (should (equal (line-number-at-pos) 3)) ;goes up only one level at a time
77 (mh-thread-immediate-ancestor)
78 (should (equal (line-number-at-pos) 2))
79 (mh-thread-immediate-ancestor)
80 (should (equal (line-number-at-pos) 2)))) ;no further motion at thread root
81
82;;; Tests of MH-Folder Commands
83
84(ert-deftest mh-thread-sibling-and-ancestor ()
85 "Test motion by `mh-thread-ancestor' and `mh-thread-next-sibling'."
86 (with-temp-buffer
87 (insert (mh-thread-tests-before-from) "[Sender Other] line 1\n")
88 (insert (mh-thread-tests-before-from) "[Sender One] line 2\n")
89 (insert (mh-thread-tests-before-from) " [Sender Two] line 3\n")
90 (insert (mh-thread-tests-before-from) " [Sender Three] line 4\n")
91 (insert (mh-thread-tests-before-from) " [Sender Four] line 5\n")
92 (insert (mh-thread-tests-before-from) " [Sender Five] line 6\n")
93 (forward-line -1)
94 (let ((mh-view-ops '(unthread))
95 (show-count 0))
96 (cl-letf (((symbol-function 'mh-maybe-show)
97 (lambda ()
98 (setq show-count (1+ show-count)))))
99 (should (equal (line-number-at-pos) 6))
100 ;; test mh-thread-ancestor
101 (mh-thread-ancestor)
102 (should (equal (line-number-at-pos) 4)) ;skips over sibling
103 (should (equal show-count 1))
104 (mh-thread-ancestor t)
105 (should (equal (line-number-at-pos) 2)) ;root flag skips to root
106 (should (equal show-count 2))
107 (mh-thread-ancestor)
108 (should (equal (line-number-at-pos) 2)) ;do not move from root
109 (should (equal show-count 2)) ;do not re-show at root
110 ;; test mh-thread-sibling
111 (mh-thread-next-sibling)
112 (should (equal (line-number-at-pos) 2)) ;no next sibling, no motion
113 (should (equal show-count 2)) ;no sibling, no show
114 (mh-thread-next-sibling t)
115 (should (equal (line-number-at-pos) 1))
116 (should (equal show-count 3))
117 (mh-thread-next-sibling t)
118 (should (equal (line-number-at-pos) 1)) ;no previous sibling
119 (should (equal show-count 3))
120 (goto-char (point-max))
121 (forward-line -1)
122 (should (equal (line-number-at-pos) 6))
123 (mh-thread-next-sibling t)
124 (should (equal (line-number-at-pos) 5))
125 (should (equal show-count 4))
126 (mh-thread-next-sibling t)
127 (should (equal (line-number-at-pos) 5)) ;no previous sibling
128 (should (equal show-count 4))
129 ))))
130
131;;; mh-thread-tests.el ends here