Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs

This commit is contained in:
Eli Zaretskii 2019-07-13 10:21:38 +03:00
commit 3b3e7da601
9 changed files with 2445 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

View 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

View 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

View 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

View 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

View 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