emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 3a56d4e 11/11: Merge branch 'scratch/so-long'


From: Phil Sainty
Subject: master 3a56d4e 11/11: Merge branch 'scratch/so-long'
Date: Tue, 3 Aug 2021 07:44:27 -0400 (EDT)

branch: master
commit 3a56d4eea93e2fe832021a0685e2d9fe5bbd034b
Merge: b44abac 59128bb
Author: Phil Sainty <psainty@orcon.net.nz>
Commit: Phil Sainty <psainty@orcon.net.nz>

    Merge branch 'scratch/so-long'
---
 etc/NEWS                                         |  28 +++
 lisp/so-long.el                                  | 230 ++++++++++++++++----
 test/lisp/so-long-tests/so-long-tests-helpers.el |  32 ++-
 test/lisp/so-long-tests/so-long-tests.el         | 265 +++++++++++++++--------
 test/lisp/so-long-tests/spelling-tests.el        |   2 +-
 5 files changed, 424 insertions(+), 133 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 95a2c87..48dec0a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2854,6 +2854,34 @@ GPG key servers can now be queried for keys with the
 'M-x epa-search-keys' command.  Keys can then be added to your
 personal key ring.
 
+** So Long
+
+---
+*** New 'so-long-predicate' function 'so-long-statistics-excessive-p'
+efficiently detects the presence of a long line anywhere in the buffer
+using 'buffer-line-statistics' (see above).  This is now the default
+predicate (replacing 'so-long-detected-long-line-p').
+
+---
+*** 'so-long-threshold' and 'so-long-max-lines' have been raised to
+10000 bytes and 500 lines respectively, to reduce the likelihood of
+false-positives when 'global-so-long-mode' is enabled.  The latter
+value is now only used by the old predicate, as the new predicate
+knows the longest line in the entire buffer.
+
+---
+*** 'so-long-target-modes' now includes 'fundamental-mode' by default,
+meaning that 'global-so-long-mode' will also process files which were
+not recognised.  (This only has an effect if 'set-auto-mode' chooses
+'fundamental-mode'; buffers which are simply in 'fundamental-mode' by
+default are unaffected.)
+
+---
+*** New user options 'so-long-mode-preserved-minor-modes' and
+'so-long-mode-preserved-variables' allow specified mode and variable
+states to be maintained if 'so-long-mode' replaces the original major
+mode.  By default, these new options support 'view-mode'.
+
 
 * New Modes and Packages in Emacs 28.1
 
diff --git a/lisp/so-long.el b/lisp/so-long.el
index d765d34..829afd6 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -8,7 +8,7 @@
 ;; Keywords: convenience
 ;; Created: 23 Dec 2015
 ;; Package-Requires: ((emacs "24.4"))
-;; Version: 1.0
+;; Version: 1.1
 
 ;; This file is part of GNU Emacs.
 
@@ -50,16 +50,17 @@
 ;; performance further, as well as making the so-long activity more obvious to
 ;; the user.  These kinds of minified files are typically not intended to be
 ;; edited, so not providing the usual editing mode in such cases will rarely be
-;; an issue.  However, you can reinstate the original state of the buffer by
-;; calling `so-long-revert' (the key binding of which is advertised when the 
major
-;; mode change occurs).  If you prefer that the major mode not be changed, you
-;; can customize the `so-long-minor-mode' action.
+;; an issue; however you can restore the buffer to its original state by 
calling
+;; `so-long-revert' (the key binding of which is advertised when the major mode
+;; change occurs).  If you prefer that the major mode not be changed in the
+;; first place, there is a `so-long-minor-mode' action available, which you can
+;; select by customizing the `so-long-action' user option.
 ;;
 ;; The user options `so-long-action' and `so-long-action-alist' determine what
-;; actions `so-long' and `so-long-revert' will take.  This allows you to 
configure
-;; alternative actions (including custom actions).  As well as
-;; the major and minor mode actions provided by this library, `longlines-mode'
-;; is also supported by default as an alternative action.
+;; `so-long' and `so-long-revert' will do, enabling you to configure 
alternative
+;; actions (including custom actions).  As well as the major and minor mode
+;; actions provided by this library, `longlines-mode' is also supported by
+;; default as an alternative action.
 ;;
 ;; Note that while the measures taken can improve performance dramatically when
 ;; dealing with such files, this library does not have any effect on the
@@ -127,9 +128,9 @@
 ;; Use M-x customize-group RET so-long RET
 ;; (or M-x so-long-customize RET)
 ;;
-;; The user options `so-long-target-modes', `so-long-threshold', and
-;; `so-long-max-lines' determine whether action will be taken automatically 
when
-;; visiting a file, and `so-long-action' determines what will be done.
+;; The user options `so-long-target-modes' and `so-long-threshold' determine
+;; whether action will be taken automatically when visiting a file, and
+;; `so-long-action' determines what will be done.
 
 ;; * Actions and menus
 ;; -------------------
@@ -152,7 +153,7 @@
 ;; * Files with a file-local 'mode'
 ;; --------------------------------
 ;; A file-local major mode is likely to be safe even if long lines are detected
-;; (as the author of the file would otherwise be unlikely to have set that 
mode),
+;; (the author of the file would otherwise be unlikely to have set that mode),
 ;; and so these files are treated as special cases.  When a file-local 'mode' 
is
 ;; present, the function defined by the `so-long-file-local-mode-function' user
 ;; option is called.  The default value will cause the `so-long-minor-mode'
@@ -213,6 +214,24 @@
 ;; performance or otherwise avoid undesirable behaviours.  If `so-long-revert'
 ;; is called, then the original values are restored.
 
+;; * Retaining minor modes and settings when switching to `so-long-mode'
+;; ---------------------------------------------------------------------
+;; A consequence of switching to a new major mode is that many buffer-local
+;; minor modes and variables from the original major mode will be disabled.
+;; For performance purposes this is a desirable trait of `so-long-mode', but
+;; specified modes and variables can also be preserved across the major mode
+;; transition by customizing the `so-long-mode-preserved-minor-modes' and
+;; `so-long-mode-preserved-variables' user options.
+;;
+;; When `so-long-mode' is called, the states of any modes and variables
+;; configured by these options are remembered in the original major mode, and
+;; reinstated after switching to `so-long-mode'.  Likewise, if `so-long-revert'
+;; is used to switch back to the original major mode, these modes and variables
+;; are again set to the same states.
+;;
+;; The default values for these options ensure that if `view-mode' was active
+;; in the original mode, then it will also be active in `so-long-mode'.
+
 ;; * Hooks
 ;; -------
 ;; `so-long-hook' runs at the end of the `so-long' command, after the 
configured
@@ -287,8 +306,9 @@
 ;; the criteria for calling `so-long' in any given mode (plus its derivatives)
 ;; by setting buffer-local values for the variables in question.  This includes
 ;; `so-long-predicate' itself, as well as any variables used by the predicate
-;; when determining the result.  By default this means `so-long-max-lines',
-;; `so-long-skip-leading-comments', and `so-long-threshold'.  E.g.:
+;; when determining the result.  By default this means `so-long-threshold' and
+;; possibly also `so-long-max-lines' and `so-long-skip-leading-comments' (these
+;; latter two are not used by default starting from Emacs 28.1).  E.g.:
 ;;
 ;;   (add-hook 'js-mode-hook 'my-js-mode-hook)
 ;;
@@ -390,6 +410,13 @@
 
 ;; * Change Log:
 ;;
+;; 1.1   - Utilise `buffer-line-statistics' in Emacs 28+, with the new
+;;         `so-long-predicate' function `so-long-statistics-excessive-p'.
+;;       - Increase `so-long-threshold' from 250 to 10,000.
+;;       - Increase `so-long-max-lines' from 5 to 500.
+;;       - Include `fundamental-mode' in `so-long-target-modes'.
+;;       - New user option `so-long-mode-preserved-minor-modes'.
+;;       - New user option `so-long-mode-preserved-variables'.
 ;; 1.0   - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs.
 ;;       - New global mode `global-so-long-mode' to enable/disable the library.
 ;;       - New user option `so-long-action'.
@@ -442,13 +469,19 @@
 
 (require 'cl-lib)
 
+;; Map each :package-version to the associated Emacs version.
+;; (This eliminates the need for explicit :version keywords on the
+;; custom definitions.)
 (add-to-list 'customize-package-emacs-version-alist
-             '(so-long ("1.0" . "27.1")))
+             '(so-long ("1.0" . "27.1")
+                       ("1.1" . "28.1")))
 
-(defconst so-long--latest-version "1.0")
+(defconst so-long--latest-version "1.1")
 
+(declare-function buffer-line-statistics "fns.c" t t) ;; Emacs 28+
 (declare-function longlines-mode "longlines")
 (defvar longlines-mode)
+
 (defvar so-long-enabled nil
   ;; This was initially a renaming of the old `so-long-mode-enabled' and
   ;; documented as "Set to nil to prevent `so-long' from being triggered
@@ -488,16 +521,24 @@
   :prefix "so-long"
   :group 'convenience)
 
-(defcustom so-long-threshold 250
+(defcustom so-long-threshold 10000
   "Maximum line length permitted before invoking `so-long-function'.
 
-See `so-long-detected-long-line-p' for details."
+Line length is counted in either bytes or characters, depending on
+`so-long-predicate'.
+
+This is the only variable used to determine the presence of long lines if
+the `so-long-predicate' function is `so-long-statistics-excessive-p'."
   :type 'integer
-  :package-version '(so-long . "1.0"))
+  :package-version '(so-long . "1.1"))
 
-(defcustom so-long-max-lines 5
+(defcustom so-long-max-lines 500
   "Number of non-blank, non-comment lines to test for excessive length.
 
+This option normally has no effect in Emacs versions >= 28.1, as the default
+`so-long-predicate' sees the entire buffer.  Older versions of Emacs still make
+use of this option.
+
 If nil then all lines will be tested, until either a long line is detected,
 or the end of the buffer is reached.
 
@@ -507,11 +548,15 @@ be counted.
 See `so-long-detected-long-line-p' for details."
   :type '(choice (integer :tag "Limit")
                  (const :tag "Unlimited" nil))
-  :package-version '(so-long . "1.0"))
+  :package-version '(so-long . "1.1"))
 
 (defcustom so-long-skip-leading-comments t
   "Non-nil to ignore all leading comments and whitespace.
 
+This option normally has no effect in Emacs versions >= 28.1, as the default
+`so-long-predicate' sees the entire buffer.  Older versions of Emacs still make
+use of this option.
+
 If the file begins with a shebang (#!), this option also causes that line to be
 ignored even if it doesn't match the buffer's comment syntax, to ensure that
 comments following the shebang will be ignored.
@@ -521,7 +566,7 @@ See `so-long-detected-long-line-p' for details."
   :package-version '(so-long . "1.0"))
 
 (defcustom so-long-target-modes
-  '(prog-mode css-mode sgml-mode nxml-mode)
+  '(prog-mode css-mode sgml-mode nxml-mode fundamental-mode)
   "`so-long' affects only these modes and their derivatives.
 
 Our primary use-case is minified programming code, so `prog-mode' covers
@@ -534,7 +579,7 @@ files would prevent Emacs from handling them correctly."
   ;; Use 'symbol', as 'function' may be unknown => mismatch.
   :type '(choice (repeat :tag "Specified modes" symbol)
                  (const :tag "All modes" t))
-  :package-version '(so-long . "1.0"))
+  :package-version '(so-long . "1.1"))
 
 (defcustom so-long-invisible-buffer-function #'so-long-deferred
   "Function called in place of `so-long' when the buffer is not displayed.
@@ -566,7 +611,9 @@ the mentioned options might interfere with some intended 
processing."
                 (function :tag "Custom function"))
   :package-version '(so-long . "1.0"))
 
-(defcustom so-long-predicate 'so-long-detected-long-line-p
+(defcustom so-long-predicate (if (fboundp 'buffer-line-statistics)
+                                 'so-long-statistics-excessive-p
+                               'so-long-detected-long-line-p)
   "Function, called after `set-auto-mode' to decide whether action is needed.
 
 Only called if the major mode is a member of `so-long-target-modes'.
@@ -574,10 +621,14 @@ Only called if the major mode is a member of 
`so-long-target-modes'.
 The specified function will be called with no arguments.  If it returns non-nil
 then `so-long' will be invoked.
 
-Defaults to `so-long-detected-long-line-p'."
-  :type '(radio (const so-long-detected-long-line-p)
+Defaults to `so-long-statistics-excessive-p' starting from Emacs 28.1, or
+`so-long-detected-long-line-p' in earlier versions.
+
+Note that `so-long-statistics-excessive-p' requires Emacs 28.1 or later."
+  :type '(radio (const so-long-statistics-excessive-p)
+                (const so-long-detected-long-line-p)
                 (function :tag "Custom function"))
-  :package-version '(so-long . "1.0"))
+  :package-version '(so-long . "1.1"))
 
 ;; Silence byte-compiler warning.  `so-long-action-alist' is defined below
 ;; as a user option; but the definition sequence required for its setter
@@ -757,6 +808,7 @@ was established."
     display-line-numbers-mode
     flymake-mode
     flyspell-mode
+    glasses-mode
     goto-address-mode
     goto-address-prog-mode
     hi-lock-mode
@@ -776,6 +828,8 @@ was established."
     hl-sexp-mode
     idle-highlight-mode
     rainbow-delimiters-mode
+    smartparens-mode
+    smartparens-strict-mode
     )
   ;; It's not clear to me whether all of these would be problematic, but they
   ;; seemed like reasonable targets.  Some are certainly excessive in smaller
@@ -800,7 +854,7 @@ disabled modes are re-enabled by calling them with the 
numeric argument 1.
 Please submit bug reports to recommend additional modes for this list, whether
 they are in Emacs core, GNU ELPA, or elsewhere."
   :type '(repeat symbol) ;; not function, as may be unknown => mismatch.
-  :package-version '(so-long . "1.0"))
+  :package-version '(so-long . "1.1"))
 
 (defcustom so-long-variable-overrides
   '((bidi-inhibit-bpa . t)
@@ -848,6 +902,44 @@ intended to be edited manually."
              (which-func-mode boolean))
   :package-version '(so-long . "1.0"))
 
+(defcustom so-long-mode-preserved-minor-modes
+  '(view-mode)
+  "List of buffer-local minor modes to preserve in `so-long-mode'.
+
+These will be enabled or disabled after switching to `so-long-mode' (by calling
+them with the numeric argument 1 or 0) in accordance with their state in the
+buffer's original major mode.  Unknown modes, and modes which are already in 
the
+desired state, are ignored.
+
+This happens before `so-long-variable-overrides' and `so-long-minor-modes'
+have been processed.
+
+By default this happens only if `so-long-action' is set to `so-long-mode'.
+If `so-long-revert' is subsequently invoked, then the modes are again set
+to their original state after the original major mode has been called.
+
+See also `so-long-mode-preserved-variables' (processed after this)."
+  :type '(repeat symbol) ;; not function, as may be unknown => mismatch.
+  :package-version '(so-long . "1.1"))
+
+(defcustom so-long-mode-preserved-variables
+  '(view-old-buffer-read-only)
+  "List of buffer-local variables to preserve in `so-long-mode'.
+
+The original value of each variable will be maintained after switching to
+`so-long-mode'.  Unknown variables are ignored.
+
+This happens before `so-long-variable-overrides' and `so-long-minor-modes'
+have been processed.
+
+By default this happens only if `so-long-action' is set to `so-long-mode'.
+If `so-long-revert' is subsequently invoked, then the variables are again
+set to their original values after the original major mode has been called.
+
+See also `so-long-mode-preserved-minor-modes' (processed before this)."
+  :type '(repeat variable)
+  :package-version '(so-long . "1.1"))
+
 (defcustom so-long-hook nil
   "List of functions to call after `so-long' is called.
 
@@ -934,10 +1026,17 @@ If RESET is non-nil, remove any existing values before 
storing the new ones."
     (setq so-long-original-values nil))
   (so-long-remember 'so-long-variable-overrides)
   (so-long-remember 'so-long-minor-modes)
+  (so-long-remember 'so-long-mode-preserved-variables)
+  (so-long-remember 'so-long-mode-preserved-minor-modes)
   (dolist (ovar so-long-variable-overrides)
     (so-long-remember (car ovar)))
   (dolist (mode so-long-minor-modes)
     (when (and (boundp mode) mode)
+      (so-long-remember mode)))
+  (dolist (var so-long-mode-preserved-variables)
+    (so-long-remember var))
+  (dolist (mode so-long-mode-preserved-minor-modes)
+    (when (and (boundp mode) mode)
       (so-long-remember mode))))
 
 (defun so-long-menu ()
@@ -1077,12 +1176,23 @@ serves the same purpose.")
 ;; We change automatically to faster code
 ;; And then I won't feel so mad
 
+(defun so-long-statistics-excessive-p ()
+  "Non-nil if the buffer contains a line longer than `so-long-threshold' bytes.
+
+This uses `buffer-line-statistics' (available from Emacs 28.1) to establish the
+longest line in the buffer (counted in bytes rather than characters).
+
+This is the default value of `so-long-predicate' in Emacs versions >= 28.1.
+\(In earlier versions `so-long-detected-long-line-p' is used by default.)"
+  (> (cadr (buffer-line-statistics))
+     so-long-threshold))
+
 (defun so-long-detected-long-line-p ()
   "Determine whether the current buffer contains long lines.
 
 Following any initial comments and blank lines, the next N lines of the buffer
-will be tested for excessive length (where \"excessive\" means above
-`so-long-threshold', and N is `so-long-max-lines').
+will be tested for excessive length (where \"excessive\" means greater than
+`so-long-threshold' characters, and N is `so-long-max-lines').
 
 Returns non-nil if any such excessive-length line is detected.
 
@@ -1090,7 +1200,9 @@ If `so-long-skip-leading-comments' is nil then the N 
lines will be counted
 starting from the first line of the buffer.  In this instance you will likely
 want to increase `so-long-max-lines' to allow for possible comments.
 
-This is the default value of `so-long-predicate'."
+This is the default `so-long-predicate' function in Emacs versions < 28.1.
+\(Starting from 28.1, the default and recommended predicate function is
+`so-long-statistics-excessive-p', which is faster and sees the entire buffer.)"
   (let ((count 0) start)
     (save-excursion
       (goto-char (point-min))
@@ -1191,7 +1303,8 @@ This minor mode is a standard `so-long-action' option."
         ;; Housekeeping.  `so-long-minor-mode' might be invoked directly rather
         ;; than via `so-long', so replicate the necessary behaviours.  The 
minor
         ;; mode also cares about whether `so-long' was already active, as we do
-        ;; not want to remember values which were potentially overridden 
already.
+        ;; not want to remember values which were (potentially) overridden
+        ;; already.
         (unless (or so-long--calling so-long--active)
           (so-long--ensure-enabled)
           (setq so-long--active t
@@ -1321,6 +1434,16 @@ This advice acts before `so-long-mode', with the 
previous mode still active."
   "Run by `so-long-mode' in `after-change-major-mode-hook'.
 
 Calls `so-long-disable-minor-modes' and `so-long-override-variables'."
+  ;; Check/set the state of 'preserved' variables and minor modes.
+  ;; (See also `so-long-mode-revert'.)
+  ;; The "modes before variables" sequence is important for the default
+  ;; preserved mode `view-mode' which remembers the `buffer-read-only' state
+  ;; (which is also permanent-local).  That causes problems unless we restore
+  ;; the original value of `view-old-buffer-read-only' after; otherwise the
+  ;; sequence `view-mode' -> `so-long' -> `so-long-revert' -> `view-mode'
+  ;; results in `view-mode' being disabled but the buffer still read-only.
+  (so-long-mode-maintain-preserved-minor-modes)
+  (so-long-mode-maintain-preserved-variables)
   ;; Disable minor modes.
   (so-long-disable-minor-modes)
   ;; Override variables (again).  We already did this in `so-long-mode' in
@@ -1334,14 +1457,15 @@ Calls `so-long-disable-minor-modes' and 
`so-long-override-variables'."
 (defun so-long-disable-minor-modes ()
   "Disable any active minor modes listed in `so-long-minor-modes'."
   (dolist (mode (so-long-original 'so-long-minor-modes))
-    (when (and (boundp mode) mode)
+    (when (and (boundp mode)
+               (symbol-value mode))
       (funcall mode 0))))
 
 (defun so-long-restore-minor-modes ()
   "Restore the minor modes which were disabled.
 
 The modes are enabled in accordance with what was remembered in `so-long'."
-  (dolist (mode so-long-minor-modes)
+  (dolist (mode (so-long-original 'so-long-minor-modes))
     (when (and (so-long-original mode)
                (boundp mode)
                (not (symbol-value mode)))
@@ -1356,7 +1480,7 @@ The modes are enabled in accordance with what was 
remembered in `so-long'."
   "Restore the remembered values for the overridden variables.
 
 The variables are set in accordance with what was remembered in `so-long'."
-  (dolist (ovar so-long-variable-overrides)
+  (dolist (ovar (so-long-original 'so-long-variable-overrides))
     (so-long-restore-variable (car ovar))))
 
 (defun so-long-restore-variable (variable)
@@ -1364,7 +1488,7 @@ The variables are set in accordance with what was 
remembered in `so-long'."
   ;; In the instance where `so-long-mode-revert' has just reverted the major
   ;; mode, note that `kill-all-local-variables' was already called by the
   ;; original mode function, and so these 'overridden' variables may now have
-  ;; global rather than buffer-local values.
+  ;; global rather than buffer-local values (if they are not permanent-local).
   (let* ((remembered (so-long-original variable :exists))
          (originally-local (nth 2 remembered)))
     (if originally-local
@@ -1380,6 +1504,24 @@ The variables are set in accordance with what was 
remembered in `so-long'."
       ;; the old value as a buffer-local value, so we keep it simple.
       (kill-local-variable variable))))
 
+(defun so-long-mode-maintain-preserved-variables ()
+  "Set any 'preserved' variables.
+
+The variables are set in accordance with what was remembered in `so-long'."
+  (dolist (var (so-long-original 'so-long-mode-preserved-variables))
+    (so-long-restore-variable var)))
+
+(defun so-long-mode-maintain-preserved-minor-modes ()
+  "Enable or disable 'preserved' minor modes.
+
+The modes are set in accordance with what was remembered in `so-long'."
+  (dolist (mode (so-long-original 'so-long-mode-preserved-minor-modes))
+    (when (boundp mode)
+      (let ((original (so-long-original mode))
+            (current (symbol-value mode)))
+        (unless (equal current original)
+          (funcall mode (if original 1 0)))))))
+
 (defun so-long-mode-revert ()
   "Call the `major-mode' which was selected before `so-long-mode' replaced it.
 
@@ -1407,6 +1549,10 @@ This is the `so-long-revert-function' for 
`so-long-mode'."
     ;; `kill-all-local-variables' was already called by the original mode
     ;; function, so we may be seeing global values.
     (so-long-restore-variables)
+    ;; Check/set the state of 'preserved' variables and minor modes.
+    ;; (Refer to `so-long-after-change-major-mode' regarding the sequence.)
+    (so-long-mode-maintain-preserved-minor-modes)
+    (so-long-mode-maintain-preserved-variables)
     ;; Restore the mode line construct.
     (unless (derived-mode-p 'so-long-mode)
       (setq so-long-mode-line-info (so-long-mode-line-info)))))
@@ -1648,8 +1794,7 @@ invoking the new action."
     (when so-long--active
       (so-long-revert))
     ;; Invoke the new action.
-    (let ((so-long--calling t)
-          (view-mode-active view-mode))
+    (let ((so-long--calling t))
       (so-long--ensure-enabled)
       ;; ACTION takes precedence if supplied.
       (when action
@@ -1678,10 +1823,7 @@ invoking the new action."
       ;; functions need to modify the buffer.  We use `inhibit-read-only' to
       ;; side-step the issue (and likewise in `so-long-revert').
       (let ((inhibit-read-only t))
-        (run-hooks 'so-long-hook))
-      ;; Restore `view-mode'.
-      (when view-mode-active
-        (view-mode)))))
+        (run-hooks 'so-long-hook)))))
 
 (defun so-long-revert ()
   "Revert the active `so-long-action' and run `so-long-revert-hook'.
@@ -1896,7 +2038,7 @@ If it appears in `%s', you should remove it."
       (unless global-so-long-mode
         (global-so-long-mode 1)))
     (makunbound 'so-long-mode-enabled))
-  ;; Update to version 1.N:
+  ;; Update to version 1.N from earlier versions:
   ;; (when (version< so-long-version "1.N") ...)
   ;;
   ;; All updates completed.
diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el 
b/test/lisp/so-long-tests/so-long-tests-helpers.el
index ab4d9c6..dd2331e 100644
--- a/test/lisp/so-long-tests/so-long-tests-helpers.el
+++ b/test/lisp/so-long-tests/so-long-tests-helpers.el
@@ -43,7 +43,8 @@
     (cl-case action
       ('so-long-mode
        (should (eq major-mode 'so-long-mode))
-       (so-long-tests-assert-overrides))
+       (so-long-tests-assert-overrides)
+       (so-long-tests-assert-preserved))
       ('so-long-minor-mode
        (should (eq so-long-minor-mode t))
        (so-long-tests-assert-overrides))
@@ -62,7 +63,8 @@
     (cl-case action
       ('so-long-mode
        (should-not (eq major-mode 'so-long-mode))
-       (so-long-tests-assert-overrides-reverted))
+       (so-long-tests-assert-overrides-reverted)
+       (so-long-tests-assert-preserved))
       ('so-long-minor-mode
        (should-not (eq so-long-minor-mode t))
        (so-long-tests-assert-overrides-reverted))
@@ -90,6 +92,17 @@
     (when (boundp (car ovar))
       (should (equal (symbol-value (car ovar)) (cdr ovar))))))
 
+(defun so-long-tests-assert-preserved ()
+  "Assert that preserved modes and variables have their expected values."
+  (dolist (var so-long-mode-preserved-variables)
+    (when (boundp var)
+      (should (equal (symbol-value var)
+                     (alist-get var so-long-tests-memory)))))
+  (dolist (mode so-long-mode-preserved-minor-modes)
+    (when (boundp mode)
+      (should (equal (symbol-value mode)
+                     (alist-get mode so-long-tests-memory))))))
+
 (defun so-long-tests-remember ()
   "Remember the original states of modes and variables.
 
@@ -107,7 +120,22 @@ state against this remembered state."
   (dolist (mode so-long-minor-modes)
     (when (boundp mode)
       (push (cons mode (symbol-value mode))
+            so-long-tests-memory)))
+  (dolist (var so-long-mode-preserved-variables)
+    (when (boundp var)
+      (push (cons var (symbol-value var))
+            so-long-tests-memory)))
+  (dolist (mode so-long-mode-preserved-minor-modes)
+    (when (boundp mode)
+      (push (cons mode (symbol-value mode))
             so-long-tests-memory))))
 
+(defun so-long-tests-predicates ()
+  "Return the list of testable predicate functions."
+  (if (fboundp 'buffer-line-statistics)
+      '(so-long-statistics-excessive-p
+        so-long-detected-long-line-p)
+    '(so-long-detected-long-line-p)))
+
 (provide 'so-long-tests-helpers)
 ;;; so-long-tests-helpers.el ends here
diff --git a/test/lisp/so-long-tests/so-long-tests.el 
b/test/lisp/so-long-tests/so-long-tests.el
index a6d8721..8e4597c 100644
--- a/test/lisp/so-long-tests/so-long-tests.el
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -57,101 +57,131 @@
 (declare-function so-long-tests-assert-active "so-long-tests-helpers")
 (declare-function so-long-tests-assert-reverted "so-long-tests-helpers")
 (declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
+(declare-function so-long-tests-predicates "so-long-tests-helpers")
 
-;; Enable the automated behavior for all tests.
+;; Enable the automated behaviour for all tests.
 (global-so-long-mode 1)
 
 (ert-deftest so-long-tests-threshold-under ()
   "Under line length threshold."
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1- so-long-threshold) ?x))
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode))))
+  (dolist (so-long-predicate (so-long-tests-predicates))
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1- so-long-threshold) ?x))
+      (normal-mode)
+      (should (eq major-mode 'emacs-lisp-mode)))))
 
 (ert-deftest so-long-tests-threshold-at ()
   "At line length threshold."
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1- so-long-threshold) ?x))
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode))))
+  (dolist (so-long-predicate (so-long-tests-predicates))
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1- so-long-threshold) ?x))
+      (normal-mode)
+      (should (eq major-mode 'emacs-lisp-mode)))))
 
 (ert-deftest so-long-tests-threshold-over ()
   "Over line length threshold."
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (normal-mode)
-    (so-long-tests-remember)
-    (insert (make-string (1+ so-long-threshold) ?x))
-    (normal-mode)
-    (so-long-tests-assert-and-revert 'so-long-mode)))
+  (dolist (so-long-predicate (so-long-tests-predicates))
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (normal-mode)
+      (so-long-tests-remember)
+      (insert (make-string (1+ so-long-threshold) ?x))
+      (normal-mode)
+      (so-long-tests-assert-and-revert 'so-long-mode))))
 
 (ert-deftest so-long-tests-skip-comments ()
   "Skip leading shebang, whitespace, and comments."
-  ;; Long comment, no newline.
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1+ so-long-threshold) ?\;))
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode)))
-  ;; Long comment, with newline.
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1+ so-long-threshold) ?\;))
-    (insert "\n")
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode)))
-  ;; Long comment, with short text following.
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1+ so-long-threshold) ?\;))
-    (insert "\n")
-    (insert (make-string so-long-threshold ?x))
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode)))
-  ;; Long comment, with long text following.
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    (insert (make-string (1+ so-long-threshold) ?\;))
-    (insert "\n")
-    (insert (make-string (1+ so-long-threshold) ?x))
-    (normal-mode)
-    (should (eq major-mode 'so-long-mode))))
+  ;; Only for `so-long-detected-long-line-p' -- comments are not
+  ;; treated differently when using `so-long-statistics-excessive-p'.
+  (dolist (so-long-predicate (so-long-tests-predicates))
+    ;; Long comment, no newline.
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1+ so-long-threshold) ?\;))
+      (normal-mode)
+      (should (eq major-mode
+                  (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+                         'emacs-lisp-mode)
+                        ((eq so-long-predicate 
#'so-long-statistics-excessive-p)
+                         'so-long-mode)))))
+    ;; Long comment, with newline.
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1+ so-long-threshold) ?\;))
+      (insert "\n")
+      (normal-mode)
+      (should (eq major-mode
+                  (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+                         'emacs-lisp-mode)
+                        ((eq so-long-predicate 
#'so-long-statistics-excessive-p)
+                         'so-long-mode)))))
+    ;; Long comment, with short text following.
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1+ so-long-threshold) ?\;))
+      (insert "\n")
+      (insert (make-string so-long-threshold ?x))
+      (normal-mode)
+      (should (eq major-mode
+                  (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+                         'emacs-lisp-mode)
+                        ((eq so-long-predicate 
#'so-long-statistics-excessive-p)
+                         'so-long-mode)))))
+    ;; Long comment, with long text following.
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      (insert (make-string (1+ so-long-threshold) ?\;))
+      (insert "\n")
+      (insert (make-string (1+ so-long-threshold) ?x))
+      (normal-mode)
+      (should (eq major-mode 'so-long-mode)))))
 
 (ert-deftest so-long-tests-max-lines ()
   "Give up after `so-long-max-lines'."
-  (with-temp-buffer
-    (display-buffer (current-buffer))
-    (insert "#!emacs\n")
-    ;; Insert exactly `so-long-max-lines' non-comment lines, followed
-    ;; by a long line.
-    (dotimes (_ so-long-max-lines)
-      (insert "x\n"))
-    (insert (make-string (1+ so-long-threshold) ?x))
-    (normal-mode)
-    (should (eq major-mode 'emacs-lisp-mode))
-    ;; If `so-long-max-lines' is nil, don't give up the search.
-    (let ((so-long-max-lines nil))
-      (normal-mode)
-      (should (eq major-mode 'so-long-mode)))
-    ;; If `so-long-skip-leading-comments' is nil, all lines are
-    ;; counted, and so the shebang line counts, which makes the
-    ;; long line one line further away.
-    (let ((so-long-skip-leading-comments nil)
-          (so-long-max-lines (1+ so-long-max-lines)))
+  ;; Only for `so-long-detected-long-line-p' -- the whole buffer is
+  ;; 'seen' when using `so-long-statistics-excessive-p'.
+  (dolist (so-long-predicate (so-long-tests-predicates))
+    (with-temp-buffer
+      (display-buffer (current-buffer))
+      (insert "#!emacs\n")
+      ;; Insert exactly `so-long-max-lines' non-comment lines, followed
+      ;; by a long line.
+      (dotimes (_ so-long-max-lines)
+        (insert "x\n"))
+      (insert (make-string (1+ so-long-threshold) ?x))
       (normal-mode)
-      (should (eq major-mode 'emacs-lisp-mode))
-      (let ((so-long-max-lines (1+ so-long-max-lines)))
+      (should (eq major-mode
+                  (cond ((eq so-long-predicate #'so-long-detected-long-line-p)
+                         'emacs-lisp-mode)
+                        ((eq so-long-predicate 
#'so-long-statistics-excessive-p)
+                         'so-long-mode))))
+      ;; If `so-long-max-lines' is nil, don't give up the search.
+      (let ((so-long-max-lines nil))
         (normal-mode)
-        (should (eq major-mode 'so-long-mode))))))
+        (should (eq major-mode 'so-long-mode)))
+      ;; If `so-long-skip-leading-comments' is nil, all lines are
+      ;; counted, and so the shebang line counts, which makes the
+      ;; long line one line further away.
+      (let ((so-long-skip-leading-comments nil)
+            (so-long-max-lines (1+ so-long-max-lines)))
+        (normal-mode)
+        (should (eq major-mode
+                    (cond ((eq so-long-predicate 
#'so-long-detected-long-line-p)
+                           'emacs-lisp-mode)
+                          ((eq so-long-predicate 
#'so-long-statistics-excessive-p)
+                           'so-long-mode))))
+        (let ((so-long-max-lines (1+ so-long-max-lines)))
+          (normal-mode)
+          (should (eq major-mode 'so-long-mode)))))))
 
 (ert-deftest so-long-tests-invisible-buffer-function ()
   "Call `so-long-invisible-buffer-function' in invisible buffers."
@@ -180,7 +210,7 @@
       ;; From Emacs 27 the `display-buffer' call is insufficient.
       ;; The various 'window change functions' are now invoked by the
       ;; redisplay, and redisplay does nothing at all in batch mode,
-      ;; so we cannot test under this revised behavior.  Refer to:
+      ;; so we cannot test under this revised behaviour.  Refer to:
       ;; https://lists.gnu.org/r/emacs-devel/2019-10/msg00971.html
       ;; For interactive (non-batch) test runs, calling `redisplay'
       ;; does do the trick; so do that first.
@@ -195,7 +225,9 @@
         ;; Emacs adds the framework necessary to make `redisplay' work
         ;; in batch mode.
         (unless (eq so-long--active t)
-          (run-window-configuration-change-hook))))
+          (with-suppressed-warnings
+              ((obsolete run-window-configuration-change-hook))
+            (run-window-configuration-change-hook)))))
     (so-long-tests-assert-and-revert 'so-long-mode))
   ;; `so-long-invisible-buffer-function' is `nil'.
   (with-temp-buffer
@@ -230,7 +262,9 @@
       (redisplay)
       (when noninteractive
         (unless (eq so-long--active t)
-          (run-window-configuration-change-hook))))
+          (with-suppressed-warnings
+              ((obsolete run-window-configuration-change-hook))
+            (run-window-configuration-change-hook)))))
     (should (eq major-mode 'emacs-lisp-mode))))
 
 (ert-deftest so-long-tests-actions ()
@@ -323,20 +357,76 @@
       (normal-mode)
       (should (eq major-mode 'so-long-mode)))))
 
+(ert-deftest so-long-tests-preserved-variables-and-modes ()
+  "Preserved variables and minor modes when using `so-long-mode'."
+  ;; Test the user options `so-long-mode-preserved-variables' and
+  ;; `so-long-mode-preserved-minor-modes'.  The minor mode `view-mode'
+  ;; is 'preserved' by default (using both options).
+  (with-temp-buffer
+    (display-buffer (current-buffer))
+    (insert "#!emacs\n")
+    (normal-mode)
+    ;; We enable `view-mode' before triggering `so-long'.
+    (insert (make-string (1+ so-long-threshold) ?x))
+    (view-mode 1)
+    (should (eq view-mode t))
+    (should (eq buffer-read-only t))
+    (so-long-tests-remember)
+    (let ((so-long-action 'so-long-mode)
+          (menu (so-long-menu)))
+      (so-long)
+      (so-long-tests-assert-active 'so-long-mode)
+      (should (eq view-mode t))
+      (should (eq buffer-read-only t))
+      ;; Revert.
+      (funcall (lookup-key menu [so-long-revert]))
+      (so-long-tests-assert-reverted 'so-long-mode)
+      (should (eq view-mode t))
+      (should (eq buffer-read-only t))
+      ;; Disable `view-mode'.  Note that without the preserved
+      ;; variables, the conflict between how `view-mode' and `so-long'
+      ;; each deal with the buffer's original `buffer-read-only' value
+      ;; would lead to a situation whereby the buffer would still be
+      ;; read-only after `view-mode' had been disabled.
+      (view-mode 0)
+      (should (eq view-mode nil))
+      (should (eq buffer-read-only nil))))
+  ;; Without `view-mode'.
+  (with-temp-buffer
+    (display-buffer (current-buffer))
+    (insert "#!emacs\n")
+    (normal-mode)
+    (insert (make-string (1+ so-long-threshold) ?x))
+    (should (eq view-mode nil))
+    (so-long-tests-remember)
+    (let ((so-long-action 'so-long-mode)
+          (menu (so-long-menu)))
+      (so-long)
+      (so-long-tests-assert-active 'so-long-mode)
+      (should (eq view-mode nil))
+      ;; Revert.
+      (funcall (lookup-key menu [so-long-revert]))
+      (so-long-tests-assert-reverted 'so-long-mode)
+      (should (eq view-mode nil)))))
+
 (ert-deftest so-long-tests-predicate ()
   "Custom predicate function."
   ;; Test the `so-long-predicate' user option.
+  ;; Always true.  Trigger when we normally wouldn't.
   (with-temp-buffer
     (display-buffer (current-buffer))
     (insert "#!emacs\n")
-    ;; Always false.
-    (let ((so-long-predicate #'ignore))
-      (normal-mode)
-      (should (eq major-mode 'emacs-lisp-mode)))
-    ;; Always true.
     (let ((so-long-predicate (lambda () t)))
       (normal-mode)
-      (should (eq major-mode 'so-long-mode)))))
+      (should (eq major-mode 'so-long-mode))))
+  ;; Always false.  Don't trigger when we normally would.
+  (with-temp-buffer
+    (display-buffer (current-buffer))
+    (insert "#!emacs\n")
+    (insert (make-string (1+ so-long-threshold) ?x))
+    (let ((so-long-predicate #'ignore))
+      (normal-mode)
+      (should (eq major-mode 'emacs-lisp-mode)))))
 
 (ert-deftest so-long-tests-file-local-action ()
   "File-local action."
@@ -405,7 +495,10 @@
          (insert ,local-vars)
          (normal-mode)
          ;; Remember the `emacs-lisp-mode' state.  The other cases
-         ;; will validate the 'reverted' state against this.
+         ;; will validate the 'reverted' state against this.  (Note
+         ;; that we haven't displayed the buffer, and therefore only
+         ;; `so-long-invisible-buffer-function' has acted, so we are
+         ;; still remembering the 'before' state.)
          (so-long-tests-remember)
          (should (eq major-mode 'emacs-lisp-mode)))
        ;; Downgrade the action from major mode to minor mode.
diff --git a/test/lisp/so-long-tests/spelling-tests.el 
b/test/lisp/so-long-tests/spelling-tests.el
index 0be8555..f778b64 100644
--- a/test/lisp/so-long-tests/spelling-tests.el
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -57,7 +57,7 @@
             (unwind-protect
                 (cl-letf (((symbol-function 'ispell-command-loop)
                            (lambda (_miss _guess word _start _end)
-                             (message "Unrecognized word: %s." word)
+                             (message "Unrecognised word: %s." word)
                              (throw 'mistake t))))
                   (catch 'mistake
                     (find-library "so-long")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]