diff options
| author | Stephen Gildea | 2021-11-13 07:00:30 -0800 |
|---|---|---|
| committer | Stephen Gildea | 2021-11-13 07:04:13 -0800 |
| commit | 4df334a0f74700e72bfea7817e660605c3f2a2ee (patch) | |
| tree | 04701661f2e58c65b2071aaf6558afdcd56a16a7 | |
| parent | d3666ccdba7c3837ffffe3c50a179c110ed55569 (diff) | |
| download | emacs-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.el | 2 | ||||
| -rw-r--r-- | lisp/mh-e/mh-thread.el | 10 | ||||
| -rw-r--r-- | test/lisp/mh-e/mh-thread-tests.el | 131 |
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'." | |||
| 509 | Note that columns in Emacs start with 0. | 509 | Note that columns in Emacs start with 0. |
| 510 | 510 | ||
| 511 | If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this | 511 | If `mh-scan-format-file' is set to \"Use MH-E scan Format\" this |
| 512 | means that either `mh-scan-format-mh' or `mh-scan-format-nmh' are | 512 | means that either `mh-scan-format-mh' or `mh-scan-format-nmh' is |
| 513 | in use. This function therefore assumes that the first column is | 513 | in use. This function therefore assumes that the first column is |
| 514 | empty (to provide room for the cursor), the following WIDTH | 514 | empty (to provide room for the cursor), the following WIDTH |
| 515 | columns contain the message number, and the column for notations | 515 | columns 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. | ||
| 28 | The 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 | ||