branch: externals/compat commit 2f3813bf78ec129119b86076e7d43f0a30e4eb39 Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
compat-27: Add major-mode-suspend and major-mode-restore --- NEWS.org | 1 + compat-27.el | 31 +++++++++++++++++++++++++++++++ compat-macs.el | 7 +++++-- compat-tests.el | 13 +++++++++++++ compat.texi | 25 ++++++++++++++++++++----- 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/NEWS.org b/NEWS.org index 0feece8f92..f1d75124ec 100644 --- a/NEWS.org +++ b/NEWS.org @@ -8,6 +8,7 @@ - compat-25: Add ~save-mark-and-excursion~. - compat-26: Add ~region-bounds~. - compat-27: Add ~date-ordinal-to-time~. +- compat-27: Add ~major-mode-suspend~ and ~major-mode-restore~. - compat-27: Add ~make-decoded-time~. - compat-27: Add ~minibuffer-history-value~. - compat-27: Add ~ring-resize~. diff --git a/compat-27.el b/compat-27.el index 01af37dee5..6f940ce9ac 100644 --- a/compat-27.el +++ b/compat-27.el @@ -280,6 +280,37 @@ return nil." (setq tail tail-cdr)))) alist) +(compat-defvar major-mode--suspended nil ;; <compat-tests:major-mode-suspend> + "Suspended major mode." + :local permanent) + +(compat-defun major-mode-suspend () ;; <compat-tests:major-mode-suspend> + "Exit current major mode, remembering it." + (let* ((prev-major-mode (or major-mode--suspended + (unless (eq major-mode 'fundamental-mode) + major-mode)))) + (kill-all-local-variables) + (setq-local major-mode--suspended prev-major-mode))) + +(compat-defun major-mode-restore (&optional avoided-modes) ;; <compat-tests:major-mode-suspend> + "Restore major mode earlier suspended with `major-mode-suspend'. +If there was no earlier suspended major mode, then fallback to `normal-mode', +though trying to avoid AVOIDED-MODES." + (if major-mode--suspended + (funcall (prog1 major-mode--suspended + (kill-local-variable 'major-mode--suspended))) + (let ((auto-mode-alist + (let ((alist (copy-sequence auto-mode-alist))) + (dolist (mode avoided-modes) + (setq alist (rassq-delete-all mode alist))) + alist)) + (magic-fallback-mode-alist + (let ((alist (copy-sequence magic-fallback-mode-alist))) + (dolist (mode avoided-modes) + (setq alist (rassq-delete-all mode alist))) + alist))) + (normal-mode)))) + ;;;; Defined in simple.el (compat-guard (not (fboundp 'decoded-time-second)) diff --git a/compat-macs.el b/compat-macs.el index b3edaf6a57..addef5ecd1 100644 --- a/compat-macs.el +++ b/compat-macs.el @@ -234,8 +234,11 @@ definition is generated. ,@(cond ((eq local 'permanent) `((put ',name 'permanent-local t))) - (local - `((make-variable-buffer-local ',name))))))))) + ((eq local t) + `((make-variable-buffer-local ',name))) + ((not local) + nil) + (t (error "Invalid value for :local")))))))) (provide 'compat-macs) ;;; compat-macs.el ends here diff --git a/compat-tests.el b/compat-tests.el index e221f8534f..e98d1fc94a 100644 --- a/compat-tests.el +++ b/compat-tests.el @@ -2809,5 +2809,18 @@ (should-equal 4 (count-sentences (point-min) (point-max))) (should-equal 2 (count-sentences 16 50)))) +(ert-deftest major-mode-suspend () + (with-temp-buffer + (text-mode) + (should sentence-end-double-space) + (setq-local sentence-end-double-space nil) + (major-mode-suspend) + (should-not line-spacing) + (prog-mode) + (should-equal major-mode 'prog-mode) + (major-mode-restore) + (should sentence-end-double-space) + (should-equal major-mode 'text-mode))) + (provide 'compat-tests) ;;; compat-tests.el ends here diff --git a/compat.texi b/compat.texi index efc88ac306..95b92a1042 100644 --- a/compat.texi +++ b/compat.texi @@ -952,6 +952,25 @@ The following functions and macros are implemented in Emacs 27.1. These functions are made available by Compat on Emacs versions older than 27.1. +@c copied from lispref/modes.texi +@defun major-mode-suspend +This function works like @code{fundamental-mode}, in that it kills all +buffer-local variables, but it also records the major mode in effect, +so that it could subsequently be restored. This function and +@code{major-mode-restore} (described next) are useful when you need to +put a buffer under some specialized mode other than the one Emacs +chooses for it automatically, but would also like to be able to switch +back to the original mode later. +@end defun + +@c copied from lispref/modes.texi +@defun major-mode-restore &optional avoided-modes +This function restores the major mode recorded by +@code{major-mode-suspend}. If no major mode was recorded, this +function calls @code{normal-mode}, but tries to force it not to choose +any modes in @var{avoided-modes}, if that argument is non-@code{nil}. +@end defun + @c copied from lispref/sequences.texi @defun ring-resize ring size Set the size of @var{ring} to @var{size}. If the new size is smaller, @@ -1479,8 +1498,6 @@ The macro @code{with-suppressed-warnings}. @item Support for @code{condition-case} to handle t. @item -The functions @code{major-mode-suspend} and @code{major-mode-restore}. -@item The function @code{file-system-info}. @item The function @code{group-name}. @@ -2034,7 +2051,7 @@ Support for @code{:interactive} argument to @code{define-minor-mode} and Support for @code{:predicate} argument to @code{define-globalized-minor-mode}. @item -"Success handler" for @code{condition-case}. +Support for the @code{:success} handler of @code{condition-case}. @item The function @code{benchmark-call}. @item @@ -2086,8 +2103,6 @@ The function @code{max-mini-window-lines}. @item The function @code{lock-file} and @code{unlock-file}. @item -The macro @code{with-window-non-dedicated}. -@item Any @code{multisession} functionality. @end itemize