mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-19 19:37:58 +00:00
Merge branch 'scratch/so-long'
This commit is contained in:
commit
3a56d4eea9
5 changed files with 428 additions and 137 deletions
28
etc/NEWS
28
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
|
||||
|
||||
|
|
|
|||
232
lisp/so-long.el
232
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."
|
||||
:type 'integer
|
||||
:package-version '(so-long . "1.0"))
|
||||
Line length is counted in either bytes or characters, depending on
|
||||
`so-long-predicate'.
|
||||
|
||||
(defcustom so-long-max-lines 5
|
||||
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.1"))
|
||||
|
||||
(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,9 +1026,16 @@ 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))))
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
@ -105,9 +118,24 @@ state against this remembered state."
|
|||
(push (cons (car ovar) (symbol-value (car ovar)))
|
||||
so-long-tests-memory)))
|
||||
(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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
;; 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 '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 '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-predicate ()
|
||||
"Custom predicate function."
|
||||
;; Test the `so-long-predicate' user option.
|
||||
(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.
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in a new issue