Function: define-globalized-minor-mode
define-globalized-minor-mode is an autoloaded macro defined in
easy-mmode.el.gz.
Signature
(define-globalized-minor-mode GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)
Documentation
Make a global mode GLOBAL-MODE corresponding to buffer-local minor MODE.
TURN-ON is a function that will be called with no args in every buffer and that should try to turn MODE on if applicable for that buffer.
Each of KEY VALUE is a pair of CL-style keyword arguments. :predicate
specifies which major modes the globalized minor mode should be switched on
in. As the minor mode defined by this function is always global, any
:global keyword is ignored. Other keywords have the same meaning as in
define-minor-mode, which see. In particular, :group specifies the custom
group. The most useful keywords are those that are passed on to the
defcustom. It normally makes no sense to pass the :lighter or :keymap
keywords to define-globalized-minor-mode, since these are usually passed
to the buffer-local version of the minor mode.
BODY contains code to execute each time the mode is enabled or disabled. It is executed after toggling the mode, and before running GLOBAL-MODE-hook.
If MODE's set-up depends on the major mode in effect when it was enabled, then disabling and reenabling MODE should make MODE work correctly with the current major mode. This is important to prevent problems with derived modes, that is, major modes that call another major mode in their body.
When a major mode is initialized, MODE is actually turned on just after running the major mode's hook. However, MODE is not turned on if the hook has explicitly disabled it.
Probably introduced at or before Emacs version 22.1.
Aliases
easy-mmode-define-global-mode
define-global-minor-mode
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/easy-mmode.el.gz
;;;###autoload
(defmacro define-globalized-minor-mode (global-mode mode turn-on &rest body)
"Make a global mode GLOBAL-MODE corresponding to buffer-local minor MODE.
TURN-ON is a function that will be called with no args in every buffer
and that should try to turn MODE on if applicable for that buffer.
Each of KEY VALUE is a pair of CL-style keyword arguments. :predicate
specifies which major modes the globalized minor mode should be switched on
in. As the minor mode defined by this function is always global, any
:global keyword is ignored. Other keywords have the same meaning as in
`define-minor-mode', which see. In particular, :group specifies the custom
group. The most useful keywords are those that are passed on to the
`defcustom'. It normally makes no sense to pass the :lighter or :keymap
keywords to `define-globalized-minor-mode', since these are usually passed
to the buffer-local version of the minor mode.
BODY contains code to execute each time the mode is enabled or disabled.
It is executed after toggling the mode, and before running
GLOBAL-MODE-hook.
If MODE's set-up depends on the major mode in effect when it was
enabled, then disabling and reenabling MODE should make MODE work
correctly with the current major mode. This is important to
prevent problems with derived modes, that is, major modes that
call another major mode in their body.
When a major mode is initialized, MODE is actually turned on just
after running the major mode's hook. However, MODE is not turned
on if the hook has explicitly disabled it.
\(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)"
(declare (doc-string 2))
(let* ((global-mode-name (symbol-name global-mode))
(mode-name (symbol-name mode))
(pretty-name (easy-mmode-pretty-mode-name mode))
(pretty-global-name (easy-mmode-pretty-mode-name global-mode))
(group nil)
(extra-keywords nil)
(MODE-variable mode)
(MODE-buffers (intern (concat global-mode-name "-buffers")))
(MODE-enable-in-buffers
(intern (concat global-mode-name "-enable-in-buffers")))
(MODE-check-buffers
(intern (concat global-mode-name "-check-buffers")))
(MODE-cmhh (intern (concat global-mode-name "-cmhh")))
(minor-MODE-hook (intern (concat mode-name "-hook")))
(MODE-set-explicitly (intern (concat mode-name "-set-explicitly")))
(MODE-major-mode (intern (concat (symbol-name mode) "-major-mode")))
(MODE-predicate (intern (concat (replace-regexp-in-string
"-mode\\'" "" global-mode-name)
"-modes")))
(turn-on-function `#',turn-on)
keyw predicate)
;; Check keys.
(while (keywordp (setq keyw (car body)))
(pop body)
(pcase keyw
(:group (setq group (nconc group (list :group (pop body)))))
(:global (pop body))
(:variable (setq MODE-variable (pop body)))
(:predicate
(setq predicate (list (pop body)))
(setq turn-on-function
`(lambda ()
(require 'easy-mmode)
(when (easy-mmode--globalized-predicate-p ,(car predicate))
(funcall ,turn-on-function)))))
(_ (push keyw extra-keywords) (push (pop body) extra-keywords))))
`(progn
(progn
(put ',global-mode 'globalized-minor-mode t)
:autoload-end
(defvar-local ,MODE-major-mode nil))
;; The actual global minor-mode
(define-minor-mode ,global-mode
,(concat (format "Toggle %s in all buffers.\n" pretty-name)
(internal--format-docstring-line
(concat "With prefix ARG, enable %s if ARG is positive; "
"otherwise, disable it.")
pretty-global-name)
"\n\n"
"If called from Lisp, toggle the mode if ARG is `toggle'.
Enable the mode if ARG is nil, omitted, or is a positive number.
Disable the mode if ARG is a negative number.\n\n"
(internal--format-docstring-line
"%s is enabled in all buffers where `%s' would do it."
pretty-name turn-on)
"\n\n"
(internal--format-docstring-line
"See `%s' for more information on %s."
mode pretty-name)
(if predicate
(concat
"\n\n"
(internal--format-docstring-line
"`%s' is used to control which modes this minor mode is used in."
MODE-predicate))
""))
:global t ,@group ,@(nreverse extra-keywords)
;; Setup hook to handle future mode changes and new buffers.
(if ,global-mode
(progn
(add-hook 'after-change-major-mode-hook
#',MODE-enable-in-buffers)
(add-hook 'find-file-hook #',MODE-check-buffers)
(add-hook 'change-major-mode-hook #',MODE-cmhh))
(remove-hook 'after-change-major-mode-hook #',MODE-enable-in-buffers)
(remove-hook 'find-file-hook #',MODE-check-buffers)
(remove-hook 'change-major-mode-hook #',MODE-cmhh))
;; Go through existing buffers.
(dolist (buf (buffer-list))
(with-current-buffer buf
(if ,global-mode (funcall ,turn-on-function)
(when ,mode (,mode -1)))))
,@body)
,(when predicate
`(defcustom ,MODE-predicate ,(car predicate)
,(format "Which major modes `%s' is switched on in.
This variable can be either t (all major modes), nil (no major modes),
or a list of modes and (not modes) to switch use this minor mode or
not. For instance
(c-mode (not message-mode mail-mode) text-mode)
means \"use this mode in all modes derived from `c-mode', don't use in
modes derived from `message-mode' or `mail-mode', but do use in other
modes derived from `text-mode'\". An element with value t means \"use\"
and nil means \"don't use\". There's an implicit nil at the end of the
list."
mode)
:type '(repeat sexp)
,@group))
;; Autoloading define-globalized-minor-mode autoloads everything
;; up-to-here.
:autoload-end
;; MODE-set-explicitly is set in MODE-set-explicitly and cleared by
;; kill-all-local-variables.
(defvar-local ,MODE-set-explicitly nil)
(defun ,MODE-set-explicitly ()
(setq ,MODE-set-explicitly t))
(put ',MODE-set-explicitly 'definition-name ',global-mode)
;; A function which checks whether MODE has been disabled in the major
;; mode hook which has just been run.
(add-hook ',minor-MODE-hook #',MODE-set-explicitly)
;; List of buffers left to process.
(defvar ,MODE-buffers nil)
;; The function that calls TURN-ON in each buffer.
(defun ,MODE-enable-in-buffers ()
(let ((buffers ,MODE-buffers))
;; Clear MODE-buffers to avoid scanning the same list of
;; buffers in recursive calls to MODE-enable-in-buffers.
;; Otherwise it could lead to infinite recursion.
(setq ,MODE-buffers nil)
(dolist (buf buffers)
(when (buffer-live-p buf)
(with-current-buffer buf
(unless ,MODE-set-explicitly
(unless (eq ,MODE-major-mode major-mode)
(if ,MODE-variable
(progn
(,mode -1)
(funcall ,turn-on-function))
(funcall ,turn-on-function))))
(setq ,MODE-major-mode major-mode))))))
(put ',MODE-enable-in-buffers 'definition-name ',global-mode)
(defun ,MODE-check-buffers ()
(,MODE-enable-in-buffers)
(remove-hook 'post-command-hook #',MODE-check-buffers))
(put ',MODE-check-buffers 'definition-name ',global-mode)
;; The function that catches kill-all-local-variables.
(defun ,MODE-cmhh ()
(add-to-list ',MODE-buffers (current-buffer))
(add-hook 'post-command-hook #',MODE-check-buffers))
(put ',MODE-cmhh 'definition-name ',global-mode))))