Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs
This commit is contained in:
commit
3b3e7da601
9 changed files with 2445 additions and 0 deletions
|
@ -1176,6 +1176,7 @@ Dealing with Emacs Trouble
|
|||
* Crashing:: What Emacs does when it crashes.
|
||||
* After a Crash:: Recovering editing in an Emacs session that crashed.
|
||||
* Emergency Escape:: What to do if Emacs stops responding.
|
||||
* Long Lines:: Mitigating slowness due to extremely long lines.
|
||||
|
||||
Reporting Bugs
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ Emacs.
|
|||
* Crashing:: What Emacs does when it crashes.
|
||||
* After a Crash:: Recovering editing in an Emacs session that crashed.
|
||||
* Emergency Escape:: What to do if Emacs stops responding.
|
||||
* Long Lines:: Mitigating slowness due to extremely long lines.
|
||||
@end menu
|
||||
|
||||
@node DEL Does Not Delete
|
||||
|
@ -457,6 +458,30 @@ program.
|
|||
emergency escape---but there are cases where it won't work, when a
|
||||
system call hangs or when Emacs is stuck in a tight loop in C code.
|
||||
|
||||
@node Long Lines
|
||||
@subsection Long Lines
|
||||
@cindex long lines
|
||||
|
||||
For a variety of reasons (some of which are fundamental to the Emacs
|
||||
redisplay code and the complex range of possibilities it handles;
|
||||
others of which are due to modes and features which do not scale well
|
||||
in unusual circumstances), Emacs can perform poorly when extremely
|
||||
long lines are present (where ``extremely long'' usually means at
|
||||
least many thousands of characters).
|
||||
|
||||
A particular problem is that Emacs may ``hang'' for a long time at
|
||||
the point of visiting a file with extremely long lines, and this case
|
||||
can be mitigated by enabling the @file{so-long} library, which detects
|
||||
when a visited file contains abnormally long lines, and takes steps to
|
||||
disable features which are liable to cause slowness in that situation.
|
||||
|
||||
This library can also significantly improve performance when moving
|
||||
and editing in such a buffer -- performance is still likely to degrade
|
||||
as you get deeper into the long lines, but the improvements can
|
||||
nevertheless be substantial.
|
||||
|
||||
Use @kbd{M-x so-long-commentary} to view the documentation for this
|
||||
library and learn how to enable and configure it.
|
||||
@node Bugs
|
||||
@section Reporting Bugs
|
||||
|
||||
|
|
8
etc/NEWS
8
etc/NEWS
|
@ -1711,6 +1711,14 @@ expansion to backtrace buffers produced by the Lisp debugger, Edebug
|
|||
and ERT. See the node "(elisp) Backtraces" in the Elisp manual for
|
||||
documentation of the new mode and its commands.
|
||||
|
||||
+++
|
||||
** so-long.el helps to mitigate performance problems with long lines.
|
||||
When 'global-so-long-mode' has been enabled, visiting a file with very
|
||||
long lines will (subject to configuration) cause the user's preferred
|
||||
'so-long-action' to be automatically invoked (by default, the buffer's
|
||||
major mode is replaced by 'so-long-mode'). In extreme cases this can
|
||||
prevent delays of several minutes, and make Emacs responsive almost
|
||||
immediately. Type 'M-x so-long-commentary' for full documentation.
|
||||
|
||||
* Incompatible Lisp Changes in Emacs 27.1
|
||||
|
||||
|
|
1703
lisp/so-long.el
Normal file
1703
lisp/so-long.el
Normal file
File diff suppressed because it is too large
Load diff
51
test/lisp/so-long-tests/autoload-longlines-mode-tests.el
Normal file
51
test/lisp/so-long-tests/autoload-longlines-mode-tests.el
Normal file
|
@ -0,0 +1,51 @@
|
|||
;;; autoload-longlines-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phil Sainty <psainty@orcon.net.nz>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(load (expand-file-name "so-long-tests-helpers"
|
||||
(file-name-directory (or load-file-name
|
||||
default-directory))))
|
||||
|
||||
(declare-function so-long-tests-remember "so-long-tests-helpers")
|
||||
(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
|
||||
(defvar so-long-action)
|
||||
|
||||
;; We're testing the initial state. We could alternatively use
|
||||
;; `unload-feature' to revert to that, but this option is simple.
|
||||
|
||||
(autoload 'so-long "so-long")
|
||||
(autoload 'longlines-mode "longlines")
|
||||
|
||||
(ert-deftest so-long-tests-autoload-longlines-mode ()
|
||||
"File-local -*- so-long-action: longlines-mode; eval: (so-long) -*-"
|
||||
(with-temp-buffer
|
||||
(so-long-tests-remember)
|
||||
(insert "-*- so-long-action: longlines-mode; eval: (so-long) -*-\n")
|
||||
(put 'so-long-action 'safe-local-variable #'symbolp)
|
||||
(push '(eval . (so-long)) safe-local-variable-values)
|
||||
(hack-local-variables)
|
||||
(should (eq so-long-action 'longlines-mode))
|
||||
(so-long-tests-assert-and-revert 'longlines-mode)))
|
||||
|
||||
;;; autoload-longlines-mode-tests.el ends here
|
46
test/lisp/so-long-tests/autoload-major-mode-tests.el
Normal file
46
test/lisp/so-long-tests/autoload-major-mode-tests.el
Normal file
|
@ -0,0 +1,46 @@
|
|||
;;; autoload-major-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phil Sainty <psainty@orcon.net.nz>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(load (expand-file-name "so-long-tests-helpers"
|
||||
(file-name-directory (or load-file-name
|
||||
default-directory))))
|
||||
|
||||
(declare-function so-long-tests-remember "so-long-tests-helpers")
|
||||
(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
|
||||
|
||||
;; We're testing the initial state. We could alternatively use
|
||||
;; `unload-feature' to revert to that, but this option is simple.
|
||||
|
||||
(autoload 'so-long-mode "so-long")
|
||||
|
||||
(ert-deftest so-long-tests-autoload-major-mode ()
|
||||
"File-local -*- so-long -*-"
|
||||
(with-temp-buffer
|
||||
(so-long-tests-remember)
|
||||
(insert "-*- so-long -*-\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode)))
|
||||
|
||||
;;; autoload-major-mode-tests.el ends here
|
50
test/lisp/so-long-tests/autoload-minor-mode-tests.el
Normal file
50
test/lisp/so-long-tests/autoload-minor-mode-tests.el
Normal file
|
@ -0,0 +1,50 @@
|
|||
;;; autoload-minor-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phil Sainty <psainty@orcon.net.nz>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(load (expand-file-name "so-long-tests-helpers"
|
||||
(file-name-directory (or load-file-name
|
||||
default-directory))))
|
||||
|
||||
(declare-function so-long-tests-remember "so-long-tests-helpers")
|
||||
(declare-function so-long-tests-assert-and-revert "so-long-tests-helpers")
|
||||
(defvar so-long-action)
|
||||
|
||||
;; We're testing the initial state. We could alternatively use
|
||||
;; `unload-feature' to revert to that, but this option is simple.
|
||||
|
||||
(autoload 'so-long "so-long")
|
||||
|
||||
(ert-deftest so-long-tests-autoload-minor-mode ()
|
||||
"File-local -*- so-long-action: so-long-minor-mode; eval: (so-long) -*-"
|
||||
(with-temp-buffer
|
||||
(so-long-tests-remember)
|
||||
(insert "-*- so-long-action: so-long-minor-mode; eval: (so-long) -*-\n")
|
||||
(put 'so-long-action 'safe-local-variable #'symbolp)
|
||||
(push '(eval . (so-long)) safe-local-variable-values)
|
||||
(hack-local-variables)
|
||||
(should (eq so-long-action 'so-long-minor-mode))
|
||||
(so-long-tests-assert-and-revert 'so-long-minor-mode)))
|
||||
|
||||
;;; autoload-minor-mode-tests.el ends here
|
113
test/lisp/so-long-tests/so-long-tests-helpers.el
Normal file
113
test/lisp/so-long-tests/so-long-tests-helpers.el
Normal file
|
@ -0,0 +1,113 @@
|
|||
;;; so-long-tests-helpers.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phil Sainty <psainty@orcon.net.nz>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(require 'so-long)
|
||||
|
||||
(defvar longlines-mode)
|
||||
(declare-function longlines-mode "longlines")
|
||||
|
||||
(defvar so-long-tests-memory nil
|
||||
"Original values of minor modes and variables.")
|
||||
|
||||
(defun so-long-tests-assert-active (action)
|
||||
"Assert that ACTION is active."
|
||||
(cl-destructuring-bind (_key _label actionfunc revertfunc)
|
||||
(assq action so-long-action-alist)
|
||||
(should (eq so-long-function actionfunc))
|
||||
(should (eq so-long-revert-function revertfunc))
|
||||
(should (eq so-long-enabled t))
|
||||
(should (eq so-long--active t))
|
||||
;; pcase fails here in Emacs 24.
|
||||
(cl-case action
|
||||
('so-long-mode
|
||||
(should (eq major-mode 'so-long-mode))
|
||||
(so-long-tests-assert-overrides))
|
||||
('so-long-minor-mode
|
||||
(should (eq so-long-minor-mode t))
|
||||
(so-long-tests-assert-overrides))
|
||||
('longlines-mode
|
||||
(should (eq longlines-mode t))))))
|
||||
|
||||
(defun so-long-tests-assert-reverted (action)
|
||||
"Assert that ACTION has been reverted."
|
||||
(cl-destructuring-bind (_key _label actionfunc revertfunc)
|
||||
(assq action so-long-action-alist)
|
||||
(should (eq so-long-function actionfunc))
|
||||
(should (eq so-long-revert-function revertfunc))
|
||||
(should (eq so-long-enabled t))
|
||||
(should (eq so-long--active nil))
|
||||
;; pcase fails here in Emacs 24.
|
||||
(cl-case action
|
||||
('so-long-mode
|
||||
(should-not (eq major-mode 'so-long-mode))
|
||||
(so-long-tests-assert-overrides-reverted))
|
||||
('so-long-minor-mode
|
||||
(should-not (eq so-long-minor-mode t))
|
||||
(so-long-tests-assert-overrides-reverted))
|
||||
('longlines-mode
|
||||
(should-not (eq longlines-mode t))))))
|
||||
|
||||
(defun so-long-tests-assert-and-revert (action)
|
||||
"Assert ACTION, revert it, and then assert the revert."
|
||||
(so-long-tests-assert-active action)
|
||||
(so-long-revert)
|
||||
(so-long-tests-assert-reverted action))
|
||||
|
||||
(defun so-long-tests-assert-overrides ()
|
||||
"Assert that overridden modes and variables have their expected values."
|
||||
(dolist (ovar so-long-variable-overrides)
|
||||
(when (boundp (car ovar))
|
||||
(should (equal (symbol-value (car ovar)) (cdr ovar)))))
|
||||
(dolist (mode so-long-minor-modes)
|
||||
(when (boundp mode)
|
||||
(should (eq (symbol-value mode) nil)))))
|
||||
|
||||
(defun so-long-tests-assert-overrides-reverted ()
|
||||
"Assert that each remembered variable has its original value."
|
||||
(dolist (ovar so-long-tests-memory)
|
||||
(when (boundp (car ovar))
|
||||
(should (equal (symbol-value (car ovar)) (cdr ovar))))))
|
||||
|
||||
(defun so-long-tests-remember ()
|
||||
"Remember the original states of modes and variables.
|
||||
|
||||
Call this after setting up a buffer in the normal (not so-long)
|
||||
state for its major mode, so that after triggering a so-long
|
||||
action we can call `so-long-revert' and compare the reverted
|
||||
state against this remembered state."
|
||||
(setq so-long-tests-memory nil)
|
||||
(push (cons 'major-mode major-mode)
|
||||
so-long-tests-memory)
|
||||
(dolist (ovar so-long-variable-overrides)
|
||||
(when (boundp (car ovar))
|
||||
(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))))
|
||||
|
||||
(provide 'so-long-tests-helpers)
|
||||
;;; so-long-tests-helpers.el ends here
|
448
test/lisp/so-long-tests/so-long-tests.el
Normal file
448
test/lisp/so-long-tests/so-long-tests.el
Normal file
|
@ -0,0 +1,448 @@
|
|||
;;; so-long-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Phil Sainty <psainty@orcon.net.nz>
|
||||
;; Keywords: convenience
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Most of these tests use the shebang #!emacs to get `normal-mode' to
|
||||
;; select `emacs-lisp-mode', as using a file-local mode variable would
|
||||
;; usually trigger `so-long-file-local-mode-function'. In cases where
|
||||
;; we need to `hack-local-variables', we instead set `buffer-file-name'.
|
||||
;; (We could consistently use the latter, but the mixture of approaches
|
||||
;; means that we're testing more things.)
|
||||
|
||||
;; Running the tests with "make lisp/so-long-tests" is like:
|
||||
;;
|
||||
;; HOME=/nonexistent EMACSLOADPATH= LC_ALL=C \
|
||||
;; EMACS_TEST_DIRECTORY=/home/phil/emacs/trunk/repository/test \
|
||||
;; "../src/emacs" --no-init-file --no-site-file --no-site-lisp \
|
||||
;; -L ":." -l ert -l lisp/so-long-tests.el --batch --eval \
|
||||
;; '(ert-run-tests-batch-and-exit (quote (not (tag :unstable))))'
|
||||
;;
|
||||
;; See also `ert-run-tests-batch-and-exit'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ert)
|
||||
(require 'so-long)
|
||||
(load (expand-file-name "so-long-tests-helpers"
|
||||
(file-name-directory (or load-file-name
|
||||
default-directory))))
|
||||
|
||||
(declare-function so-long-tests-remember "so-long-tests-helpers")
|
||||
(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")
|
||||
|
||||
;; 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
|
||||
(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
|
||||
(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
|
||||
(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
|
||||
(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
|
||||
(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
|
||||
(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
|
||||
(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
|
||||
(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)))
|
||||
(normal-mode)
|
||||
(should (eq major-mode 'emacs-lisp-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-actions ()
|
||||
"Test each of the standard actions."
|
||||
(dolist (action (mapcar #'car so-long-action-alist))
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(let ((so-long-action action))
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert action)))))
|
||||
|
||||
(ert-deftest so-long-tests-command-so-long ()
|
||||
"Test the `so-long' command."
|
||||
;; Includes argument of nil, meaning the default `so-long-mode' action.
|
||||
(dolist (action (cons nil (mapcar #'car so-long-action-alist)))
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(so-long action)
|
||||
(so-long-tests-assert-and-revert (or action 'so-long-mode)))))
|
||||
|
||||
(ert-deftest so-long-tests-so-long-menu-item-replace-action ()
|
||||
"Test using the `so-long-menu-item-replace-action' menu item."
|
||||
(with-temp-buffer
|
||||
;; Due to (with-selected-window (so-long-menu-click-window) ...)
|
||||
;; (used by `so-long-menu-item-replace-action'), our temp buffer
|
||||
;; must be in the selected window.
|
||||
(set-window-buffer nil (current-buffer))
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(let (action)
|
||||
(dolist (item so-long-action-alist)
|
||||
;; n.b. Any existing action is first reverted.
|
||||
(so-long-menu-item-replace-action item)
|
||||
(setq action (car item))
|
||||
(so-long-tests-assert-active action))
|
||||
;; After all actions have been used, revert to normal and assert
|
||||
;; that the most recent action to have been applied is the one
|
||||
;; we have just reverted.
|
||||
(so-long-menu-item-revert)
|
||||
(so-long-tests-assert-reverted action))))
|
||||
|
||||
(ert-deftest so-long-tests-major-mode ()
|
||||
"Test calling `so-long-mode' directly."
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember)
|
||||
(so-long-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode)))
|
||||
|
||||
(ert-deftest so-long-tests-minor-mode ()
|
||||
"Test calling `so-long-minor-mode' directly."
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember)
|
||||
(so-long-minor-mode 1)
|
||||
(so-long-tests-assert-active 'so-long-minor-mode)
|
||||
(so-long-minor-mode 0)
|
||||
(so-long-tests-assert-reverted 'so-long-minor-mode)))
|
||||
|
||||
(ert-deftest so-long-tests-target-modes ()
|
||||
"Targeted major modes."
|
||||
;; Test the `so-long-target-modes' user option.
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
;; Nil target modes.
|
||||
(let ((so-long-target-modes nil))
|
||||
(normal-mode)
|
||||
(should (eq major-mode 'emacs-lisp-mode)))
|
||||
;; Non-matching target modes.
|
||||
(let ((so-long-target-modes '(text-mode)))
|
||||
(normal-mode)
|
||||
(should (eq major-mode 'emacs-lisp-mode)))
|
||||
;; Matching mode (direct).
|
||||
(let ((so-long-target-modes '(emacs-lisp-mode)))
|
||||
(normal-mode)
|
||||
(should (eq major-mode 'so-long-mode)))
|
||||
;; Matching mode (indirect).
|
||||
(let ((so-long-target-modes '(prog-mode)))
|
||||
(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.
|
||||
(with-temp-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)))))
|
||||
|
||||
(ert-deftest so-long-tests-file-local-action ()
|
||||
"File-local action."
|
||||
;; Test `so-long-action' as a file-local variable.
|
||||
;; Only valid in Emacs26+. Refer to "Caveats" in the so-long.el Commentary.
|
||||
(unless (version< emacs-version "26")
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember))
|
||||
;; n.b. `run-mode-hooks' *only* runs `hack-local-variables' when there's a
|
||||
;; (buffer-file-name), so the #!emacs approach is insufficient here. It's
|
||||
;; valid for the file-locals to be on the second line after the shebang,
|
||||
;; but with the *.el filename we no longer need the shebang.
|
||||
(with-temp-buffer
|
||||
(setq buffer-file-name (expand-file-name "so-long-tests-data.el"))
|
||||
(insert ";; -*- so-long-action:so-long-minor-mode; -*-\n")
|
||||
(put 'so-long-action 'safe-local-variable #'symbolp)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-minor-mode))))
|
||||
|
||||
(ert-deftest so-long-tests-file-local-action-eval-so-long ()
|
||||
"File-local action and eval:(so-long)."
|
||||
;; As per previous test, but using file-local `eval' to call `so-long'.
|
||||
;; Only valid in Emacs26+. Refer to "Caveats" in the so-long.el Commentary.
|
||||
;; See also `so-long-tests-file-local-action' above.
|
||||
(unless (version< emacs-version "26")
|
||||
(with-temp-buffer
|
||||
(insert "#!emacs\n")
|
||||
(normal-mode)
|
||||
(so-long-tests-remember))
|
||||
(with-temp-buffer
|
||||
(setq buffer-file-name (concat (make-temp-name "so-long-tests-") ".el"))
|
||||
(insert ";; -*- so-long-action:so-long-minor-mode; eval:(so-long) -*-\n")
|
||||
(put 'so-long-action 'safe-local-variable #'symbolp)
|
||||
(push '(eval . (so-long)) safe-local-variable-values)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-minor-mode))))
|
||||
|
||||
(defvar so-long-tests-local-mode 'unset
|
||||
"Set by `so-long-tests-file-local-mode-function'.")
|
||||
|
||||
(defun so-long-tests-file-local-mode-function (mode)
|
||||
"A custom value for `so-long-file-local-mode-function'."
|
||||
(setq so-long-tests-local-mode mode))
|
||||
|
||||
;; Test `so-long-file-local-mode-function' when the file-local major
|
||||
;; mode is `emacs-lisp-mode'.
|
||||
|
||||
(defmacro so-long-tests-deftest-file-local-emacs-lisp-mode
|
||||
(sym docstring prop-line &optional local-vars)
|
||||
"Generate tests for using `emacs-lisp-mode' as a file-local mode."
|
||||
(setq prop-line (or prop-line "")
|
||||
local-vars (or local-vars ""))
|
||||
`(ert-deftest ,sym ()
|
||||
,docstring
|
||||
(let ((orig so-long-file-local-mode-function))
|
||||
;; Do nothing at all when a file-local mode is used.
|
||||
(setq-default so-long-file-local-mode-function 'so-long-inhibit)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
;; Remember the `emacs-lisp-mode' state. The other cases
|
||||
;; will validate the 'reverted' state against this.
|
||||
(so-long-tests-remember)
|
||||
(should (eq major-mode 'emacs-lisp-mode)))
|
||||
;; Downgrade the action from major mode to minor mode.
|
||||
(setq-default so-long-file-local-mode-function 'so-long-mode-downgrade)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-minor-mode))
|
||||
;; Do not treat the file-local mode specially.
|
||||
(setq-default so-long-file-local-mode-function nil)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode))
|
||||
;; Custom function
|
||||
(setq-default so-long-file-local-mode-function
|
||||
#'so-long-tests-file-local-mode-function)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(let (so-long-tests-local-mode)
|
||||
(normal-mode)
|
||||
(should (eq so-long-tests-local-mode 'emacs-lisp-mode))
|
||||
(so-long-tests-assert-active 'so-long-mode)))
|
||||
;; end
|
||||
(setq-default so-long-file-local-mode-function orig))))
|
||||
|
||||
(so-long-tests-deftest-file-local-emacs-lisp-mode
|
||||
so-long-tests-file-local-emacs-lisp-mode-short-form
|
||||
"File-local mode (short form). -*- emacs-lisp -*-"
|
||||
";; -*- emacs-lisp -*-\n")
|
||||
|
||||
(so-long-tests-deftest-file-local-emacs-lisp-mode
|
||||
so-long-tests-file-local-emacs-lisp-mode-long-form
|
||||
"File-local mode (long form). -*- emacs-lisp -*-"
|
||||
";; -*- mode: emacs-lisp -*-\n")
|
||||
|
||||
(so-long-tests-deftest-file-local-emacs-lisp-mode
|
||||
so-long-tests-file-local-emacs-lisp-mode-long-form2
|
||||
"File-local mode (long form). -*- emacs-lisp -*-"
|
||||
nil "\n;; Local Variables:\n;; mode: emacs-lisp\n;; End:\n")
|
||||
|
||||
;; Test `so-long-file-local-mode-function' when the file-local major
|
||||
;; mode is `so-long-mode'. In this case we should always end up with
|
||||
;; the major mode being `so-long-mode'.
|
||||
|
||||
(defmacro so-long-tests-deftest-file-local-so-long-mode
|
||||
(sym docstring prop-line &optional local-vars)
|
||||
"Generate tests for using `so-long-mode' as a file-local mode."
|
||||
(setq prop-line (or prop-line "")
|
||||
local-vars (or local-vars ""))
|
||||
`(ert-deftest ,sym ()
|
||||
,docstring
|
||||
(let ((orig so-long-file-local-mode-function))
|
||||
;; Do nothing at all when a file-local mode is used.
|
||||
(setq-default so-long-file-local-mode-function 'so-long-inhibit)
|
||||
(with-temp-buffer
|
||||
;; Remember the new-buffer state. The other cases will
|
||||
;; validate the 'reverted' state against this.
|
||||
(so-long-tests-remember)
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode))
|
||||
;; Downgrade from major mode to minor mode.
|
||||
(setq-default so-long-file-local-mode-function 'so-long-mode-downgrade)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode))
|
||||
;; Do not treat the file-local mode specially.
|
||||
(setq-default so-long-file-local-mode-function nil)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(normal-mode)
|
||||
(so-long-tests-assert-and-revert 'so-long-mode))
|
||||
;; Custom function.
|
||||
(setq-default so-long-file-local-mode-function
|
||||
#'so-long-tests-file-local-mode-function)
|
||||
(with-temp-buffer
|
||||
(insert ,prop-line)
|
||||
(insert (make-string (1+ so-long-threshold) ?x))
|
||||
(insert ,local-vars)
|
||||
(let (so-long-tests-local-mode)
|
||||
(normal-mode)
|
||||
(should (eq so-long--inhibited t))
|
||||
(should (eq so-long-tests-local-mode 'so-long-mode))
|
||||
(so-long-tests-assert-active 'so-long-mode)))
|
||||
;; end
|
||||
(setq-default so-long-file-local-mode-function orig))))
|
||||
|
||||
(so-long-tests-deftest-file-local-so-long-mode
|
||||
so-long-tests-file-local-so-long-mode-short-form
|
||||
"File-local mode (short form). -*- so-long -*-"
|
||||
";; -*- so-long -*-\n")
|
||||
|
||||
(so-long-tests-deftest-file-local-so-long-mode
|
||||
so-long-tests-file-local-so-long-mode-long-form
|
||||
"File-local mode (long form). -*- mode: so-long -*-"
|
||||
";; -*- mode: so-long -*-\n")
|
||||
|
||||
(so-long-tests-deftest-file-local-so-long-mode
|
||||
so-long-tests-file-local-so-long-mode-long-form2
|
||||
"File-local mode (long form). -*- mode: so-long -*-"
|
||||
nil "\n;; Local Variables:\n;; mode: so-long\n;; End:\n")
|
||||
|
||||
(ert-deftest so-long-tests-commentary ()
|
||||
"Test the `so-long-commentary' command."
|
||||
(so-long-commentary)
|
||||
(should (string= (buffer-name) "*So Long: Commentary*"))
|
||||
(should (eq major-mode 'outline-mode))
|
||||
(should (eq view-mode t))
|
||||
(should (looking-at "^\\* Introduction$"))
|
||||
(goto-char (point-min))
|
||||
(should (looking-at "^so-long\\.el$"))
|
||||
(should (re-search-forward "^\\* Change Log:$")))
|
||||
|
||||
(ert-deftest so-long-tests-customize ()
|
||||
"Test the `so-long-customize' command."
|
||||
(so-long-customize)
|
||||
(should (string= (buffer-name) "*Customize Group: So Long*"))
|
||||
(should (eq major-mode 'Custom-mode)))
|
||||
|
||||
;; Page break to prevent the local vars strings above from
|
||||
;; being misinterpreted as actual local vars declarations.
|
||||
|
||||
;;; so-long-tests.el ends here
|
Loading…
Add table
Reference in a new issue