[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
scratch/so-long 98cb78f 7/7: Support 'preserved' variables and minor mod
From: |
Phil |
Subject: |
scratch/so-long 98cb78f 7/7: Support 'preserved' variables and minor modes in `so-long-mode' |
Date: |
Sun, 10 Jan 2021 08:07:00 -0500 (EST) |
branch: scratch/so-long
commit 98cb78fed1f22ec6177e2dee687f84e1d74f8d6d
Author: Phil Sainty <psainty@orcon.net.nz>
Commit: Phil Sainty <psainty@orcon.net.nz>
Support 'preserved' variables and minor modes in `so-long-mode'
The default values support preserving the state of `view-mode' when
switching to (and reverting from) `so-long-mode' (bug#45084).
* lisp/so-long.el (so-long-mode-preserved-variables)
(so-long-mode-preserved-minor-modes): New user options.
(so-long-mode-maintain-preserved-variables)
(so-long-mode-maintain-preserved-minor-modes): New functions.
(so-long-remember-all, so-long-after-change-major-mode)
(so-long-mode-revert): Use them.
* etc/NEWS: Describe changes.
* test/lisp/so-long-tests/so-long-tests-helpers.el:
* test/lisp/so-long-tests/so-long-tests.el: Update tests.
---
etc/NEWS | 6 ++
lisp/so-long.el | 77 +++++++++++++++++++++++-
test/lisp/so-long-tests/so-long-tests-helpers.el | 20 +++++-
test/lisp/so-long-tests/so-long-tests.el | 52 ++++++++++++++++
4 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index 9d90792..6d0997d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1891,6 +1891,12 @@ not recognised. (This only has an effect if
'set-auto-mode' chooses
'fundamental-mode'; buffers which are simply in 'fundamental-mode' by
default are unaffected.)
+---
+*** New user options 'so-long-mode-preserved-minor-modes' and
+'so-long-mode-preserved-variables' allow specified mode and variable
+states to be maintained if 'so-long-mode' replaces the original major
+mode. By default, these new options support 'view-mode'.
+
* New Modes and Packages in Emacs 28.1
diff --git a/lisp/so-long.el b/lisp/so-long.el
index e1085ab..e95d292 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -394,6 +394,8 @@
;; 1.1 - 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'.
@@ -854,6 +856,40 @@ 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."
+ :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."
+ :type '(repeat variable)
+ :package-version '(so-long . "1.1"))
+
(defcustom so-long-hook nil
"List of functions to call after `so-long' is called.
@@ -940,10 +976,17 @@ If RESET is non-nil, remove any existing values before
storing the new ones."
(setq so-long-original-values nil))
(so-long-remember 'so-long-variable-overrides)
(so-long-remember 'so-long-minor-modes)
+ (so-long-remember 'so-long-mode-preserved-variables)
+ (so-long-remember 'so-long-mode-preserved-minor-modes)
(dolist (ovar so-long-variable-overrides)
(so-long-remember (car ovar)))
(dolist (mode so-long-minor-modes)
(when (and (boundp mode) mode)
+ (so-long-remember mode)))
+ (dolist (var so-long-mode-preserved-variables)
+ (so-long-remember var))
+ (dolist (mode so-long-mode-preserved-minor-modes)
+ (when (and (boundp mode) mode)
(so-long-remember mode))))
(defun so-long-menu ()
@@ -1328,6 +1371,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
@@ -1372,7 +1425,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
@@ -1388,6 +1441,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.
@@ -1415,6 +1486,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)))))
diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el
b/test/lisp/so-long-tests/so-long-tests-helpers.el
index ab4d9c6..c7c4ef7 100644
--- a/test/lisp/so-long-tests/so-long-tests-helpers.el
+++ b/test/lisp/so-long-tests/so-long-tests-helpers.el
@@ -43,7 +43,8 @@
(cl-case action
('so-long-mode
(should (eq major-mode 'so-long-mode))
- (so-long-tests-assert-overrides))
+ (so-long-tests-assert-overrides)
+ (so-long-tests-assert-preserved-modes-enabled))
('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-modes-enabled))
('so-long-minor-mode
(should-not (eq so-long-minor-mode t))
(so-long-tests-assert-overrides-reverted))
@@ -90,6 +92,12 @@
(when (boundp (car ovar))
(should (equal (symbol-value (car ovar)) (cdr ovar))))))
+(defun so-long-tests-assert-preserved-modes-enabled ()
+ "Assert that 'preserved' minor modes are still enabled."
+ (dolist (mode (so-long-original 'so-long-mode-preserved-minor-modes))
+ (when (and (boundp mode))
+ (should-not (eq mode nil)))))
+
(defun so-long-tests-remember ()
"Remember the original states of modes and variables.
@@ -107,6 +115,14 @@ state against this remembered state."
(dolist (mode so-long-minor-modes)
(when (boundp mode)
(push (cons mode (symbol-value mode))
+ so-long-tests-memory)))
+ (dolist (var so-long-mode-preserved-variables)
+ (when (boundp var)
+ (push (cons var (symbol-value var))
+ so-long-tests-memory)))
+ (dolist (mode so-long-mode-preserved-minor-modes)
+ (when (boundp mode)
+ (push (cons mode (symbol-value mode))
so-long-tests-memory))))
(provide 'so-long-tests-helpers)
diff --git a/test/lisp/so-long-tests/so-long-tests.el
b/test/lisp/so-long-tests/so-long-tests.el
index a6d8721..e06d60e 100644
--- a/test/lisp/so-long-tests/so-long-tests.el
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -323,6 +323,58 @@
(normal-mode)
(should (eq major-mode 'so-long-mode)))))
+(ert-deftest so-long-tests-preserved-variables-and-modes ()
+ "Preserved variables and minor modes when using `so-long-mode'."
+ ;; Test the user options `so-long-mode-preserved-variables' and
+ ;; `so-long-mode-preserved-minor-modes'. The minor mode `view-mode'
+ ;; is 'preserved' by default (using both options).
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ ;; We enable `view-mode' before triggering `so-long'.
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (view-mode 1)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ (so-long-tests-remember)
+ (let ((so-long-action 'so-long-mode)
+ (menu (so-long-menu)))
+ (so-long)
+ (so-long-tests-assert-active 'so-long-mode)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ ;; Revert.
+ (funcall (lookup-key menu [so-long-revert]))
+ (so-long-tests-assert-reverted 'so-long-mode)
+ (should (eq view-mode t))
+ (should (eq buffer-read-only t))
+ ;; Disable `view-mode'. Note that without the preserved
+ ;; variables, the conflict between how `view-mode' and `so-long'
+ ;; each deal with the buffer's original `buffer-read-only' value
+ ;; would lead to a situation whereby the buffer would still be
+ ;; read-only after `view-mode' had been disabled.
+ (view-mode 0)
+ (should (eq view-mode nil))
+ (should (eq buffer-read-only nil))))
+ ;; Without `view-mode'.
+ (with-temp-buffer
+ (display-buffer (current-buffer))
+ (insert "#!emacs\n")
+ (normal-mode)
+ (insert (make-string (1+ so-long-threshold) ?x))
+ (should (eq view-mode nil))
+ (so-long-tests-remember)
+ (let ((so-long-action 'so-long-mode)
+ (menu (so-long-menu)))
+ (so-long)
+ (so-long-tests-assert-active 'so-long-mode)
+ (should (eq view-mode nil))
+ ;; Revert.
+ (funcall (lookup-key menu [so-long-revert]))
+ (so-long-tests-assert-reverted 'so-long-mode)
+ (should (eq view-mode nil)))))
+
(ert-deftest so-long-tests-predicate ()
"Custom predicate function."
;; Test the `so-long-predicate' user option.
- branch scratch/so-long created (now 98cb78f), Phil, 2021/01/10
- scratch/so-long a799d9b 2/7: ; * lisp/so-long.el: Bump to version 1.1, Phil, 2021/01/10
- scratch/so-long 6ed757f 1/7: ; * lisp/so-long.el: Documentation, Phil, 2021/01/10
- scratch/so-long bb5fa1b 4/7: Make `global-so-long-mode' handle unrecognised file types, Phil, 2021/01/10
- scratch/so-long 4ff1dbc 6/7: ; * lisp/so-long.el: Minor bug fixes, Phil, 2021/01/10
- scratch/so-long 98cb78f 7/7: Support 'preserved' variables and minor modes in `so-long-mode',
Phil <=
- scratch/so-long 4c9fc80 3/7: Increase `so-long-threshold' and `so-long-max-lines' defaults, Phil, 2021/01/10
- scratch/so-long b5dd69a 5/7: * lisp/so-long.el (so-long-minor-modes): Add smartparens modes, Phil, 2021/01/10