1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 12:21:25 -08:00

(custom-initialize-after-file): New function

Some global minor modes require initialization.  Those that are preloaded
currently abuse `custom-initialize-delay` for that, but it's suboptimal
and doesn't help those that aren't preloaded.
So introduce a new function to fill that need.
While at it, make `define-globalized-minor-mode` use it
automatically when useful.

* lisp/custom.el (custom-initialize-after-file-load): New function.
* lisp/tooltip.el (tooltip-mode):
* lisp/paren.el (show-paren-mode):
* lisp/rfn-eshadow.el (file-name-shadow-mode):
* lisp/epa-hook.el (auto-encryption-mode):
* lisp/minibuffer.el (minibuffer-regexp-mode, minibuffer-nonselected-mode):
* lisp/electric.el (electric-indent-mode): Use it instead of
`custom-initialize-delay` since the value does not depend on the
runtime context.
(electric-quote-mode): Don't use `custom-initialize-delay` since
the default value is nil anyway.

* lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode):
Automatically add `:initialize` if needed.
* lisp/emacs-lisp/eldoc.el (global-eldoc-mode): Remove `:initialize`,
now provided automatically.

* doc/lispref/customize.texi (Variable Definitions):
* doc/lispref/modes.texi (Defining Minor Modes): Document and Suggest
`custom-initialize-after-file-load` instead of `custom-initialize-delay`.
This commit is contained in:
Stefan Monnier 2025-10-22 17:12:10 -04:00
parent 100963b492
commit 287fb2fbad
13 changed files with 69 additions and 40 deletions

View file

@ -434,14 +434,12 @@ Use the @code{:set} function to initialize the variable, if it is
already set or has been customized; otherwise, just use
@code{set-default-toplevel-value}.
@item custom-initialize-delay
@item custom-initialize-after-file-load
This function behaves like @code{custom-initialize-set}, but it
delays the actual initialization to the next Emacs start. This should
be used in files that are preloaded (or for autoloaded variables), so
that the initialization is done in the run-time context rather than
the build-time context. This also has the side-effect that the
(delayed) initialization is performed with the @code{:set} function.
@xref{Building Emacs}.
delays the actual initialization until after the containing file is loaded.
This can be useful to break the common dependency where the setter
is (or uses) a function which needs to be defined after the variable,
such as when a global minor mode has a non-@code{nil} @code{:init-value}.
@end table
@item :local @var{value}

View file

@ -1868,18 +1868,19 @@ marking the @code{define-minor-mode} form as autoloaded.
@item :init-value @var{init-value}
This is the value to which the @var{mode} variable is initialized.
Except in unusual circumstances (see below), this value must be
@code{nil}. If the mode is global (see below) and preloaded, and the
initial value is @code{t}, i.e., the mode is turned on by default, you
should consider forcing Emacs to run the mode function at startup, like
this:
@code{nil}. Note that @code{define-minor-mode} does not automatically
run the body of the minor mode to ensure the mode is really enabled
according to this value, so if the mode is global (see above) and the
initial value is non-@code{nil}, you should consider forcing Emacs to
run the mode function when loading the mode, like this:
@lisp
:initialize #'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
@end lisp
@noindent
otherwise, the minor mode might not appear in the @file{*Help*} buffer
generated by @kbd{C-h m} (@pxref{Mode Help}).
otherwise, the minor mode might say it's enabled even though it has not
been properly set up.
@item :lighter @var{lighter}
The string @var{lighter} says what to display in the mode line

View file

@ -2674,6 +2674,13 @@ New faces have been added to 'icomplete-vertical-mode':
** Customize
+++
*** New function 'custom-initialize-after-file-load'.
Useful to delay initialization to the end of the file, so it can use
functions defined later than the variable, as is common for minor modes.
'define-globalized-minor-mode' now automatically uses it if the
init-value is non-nil.
---
*** New major mode 'Customize-dirlocals-mode'.
This is intended for customizing directory-local variables in the

View file

@ -140,6 +140,7 @@ For the standard setting, use `set-default-toplevel-value'."
Once this list has been processed, this var is set to a non-list value.")
(defun custom-initialize-delay (symbol value)
;; FIXME: Rename to `custom-initialize-after-dump'?
"Delay initialization of SYMBOL to the next Emacs start.
This is used in files that are preloaded (or for autoloaded
variables), so that the initialization is done in the run-time
@ -159,6 +160,27 @@ the :set function."
;; delay it, so initialize it "normally" (bug#47072).
(custom-initialize-reset symbol value)))
(defun custom-initialize-after-file-load (symbol value)
"Delay initialization to after the current file is loaded.
This is handy when the initialization needs functions defined after the variable,
such as for global minor modes."
;; Defvar it so as to mark it special, etc (bug#25770).
(internal--define-uninitialized-variable symbol)
;; Until the var is actually initialized, it is kept unbound.
;; This seemed to be at least as good as setting it to an arbitrary
;; value like nil (evaluating `value' is not an option because it
;; may have undesirable side-effects).
(if (not load-file-name)
;; There's no "after file" to speak of.
(custom-initialize-set symbol value)
(let ((thisfile load-file-name))
(letrec ((f (lambda (file)
(when (equal file thisfile)
(remove-hook 'after-load-functions f)
(custom-initialize-set symbol value)))))
(add-hook 'after-load-functions f)))))
(defun custom-declare-variable (symbol default doc &rest args)
"Like `defcustom', but SYMBOL and DEFAULT are evaluated as normal arguments.
DEFAULT should be an expression to evaluate to compute the default value,

View file

@ -383,7 +383,7 @@ indent the line according to context and rules of the major mode.
This is a global minor mode. To toggle the mode in a single buffer,
use `electric-indent-local-mode'."
:global t :group 'electricity
:initialize 'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:init-value t
(if (not electric-indent-mode)
(unless (catch 'found
@ -767,7 +767,7 @@ ones listed here. Also see `electric-quote-replace-consecutive'.
This is a global minor mode. To toggle the mode in a single buffer,
use `electric-quote-local-mode'."
:global t :group 'electricity
:initialize 'custom-initialize-delay
;; :initialize #'custom-initialize-after-file-load
:init-value nil
(if (not electric-quote-mode)
(unless (catch 'found

View file

@ -522,6 +522,12 @@ on if the hook has explicitly disabled it.
(when (easy-mmode--globalized-predicate-p ,MODE-predicate)
(funcall ,turn-on-function)))))
(_ (push keyw extra-keywords) (push (pop body) extra-keywords))))
(setq extra-keywords (nreverse extra-keywords))
(when (and (plist-get extra-keywords :init-value)
(null (plist-get extra-keywords :initialize)))
(setq extra-keywords `(:initialize #'custom-initialize-after-file-load
. ,extra-keywords)))
`(progn
(progn
@ -553,7 +559,7 @@ Disable the mode if ARG is a negative number.\n\n"
"`%s' is used to control which modes this minor mode is used in."
MODE-predicate))
""))
:global t ,@group ,@(nreverse extra-keywords)
:global t ,@group ,@extra-keywords
;; Setup hook to handle future mode changes and new buffers.
(if ,global-mode

View file

@ -238,7 +238,6 @@ expression point is on." :lighter eldoc-minor-mode-string
;;;###autoload
(define-globalized-minor-mode global-eldoc-mode eldoc-mode turn-on-eldoc-mode
:initialize 'custom-initialize-delay
:init-value t
;; For `read--expression', the usual global mode mechanism of
;; `change-major-mode-hook' runs in the minibuffer before

View file

@ -99,11 +99,10 @@ interface, update `file-name-handler-alist'."
(define-minor-mode auto-encryption-mode
"Toggle automatic file encryption/decryption (Auto Encryption mode)."
:global t :init-value t :group 'epa-file :version "23.1"
;; We'd like to use custom-initialize-set here so the setup is done
;; before dumping, but at the point where the defcustom is evaluated,
;; At the point where the defcustom is evaluated,
;; the corresponding function isn't defined yet, so
;; custom-initialize-set signals an error.
:initialize 'custom-initialize-delay
;; custom-initialize-set would signal an error.
:initialize #'custom-initialize-after-file-load
(setq file-name-handler-alist
(delq epa-file-handler file-name-handler-alist))
(remove-hook 'find-file-hook 'epa-file-find-file-hook)

View file

@ -270,9 +270,7 @@ means that Font Lock mode is turned on for buffers in C and C++ modes only."
(define-globalized-minor-mode global-font-lock-mode
font-lock-mode turn-on-font-lock-if-desired
;; What was this :extra-args thingy for? --Stef
;; :extra-args (dummy)
:initialize 'custom-initialize-delay
:initialize #'custom-initialize-delay
:init-value (not (or noninteractive emacs-basic-display))
:group 'font-lock
:version "22.1")

View file

@ -2349,7 +2349,7 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(goto-char (point-max))
(recenter -1)))))
(remove-hook 'window-scroll-functions
'completion--lazy-insert-strings-on-scroll t))
#'completion--lazy-insert-strings-on-scroll t))
(defun completion--lazy-insert-strings (&optional button)
(setq button (or button completions--lazy-insert-button))
@ -5617,7 +5617,7 @@ and make sexp navigation more intuitive.
The list of prompts activating this mode in specific minibuffer
interactions is customizable via `minibuffer-regexp-prompts'."
:global t
:initialize #'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:init-value t
(if minibuffer-regexp-mode
(progn
@ -5711,7 +5711,7 @@ Use the face `minibuffer-nonselected' to highlight the contents of the
minibuffer window when the minibuffer remains active but its window is
no longer selected."
:global t
:initialize #'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:init-value t
:version "31.1"
(if minibuffer-nonselected-mode

View file

@ -155,7 +155,7 @@ this mode is enabled in.
This is a global minor mode. To toggle the mode in a single buffer,
use `show-paren-local-mode'."
:global t :group 'paren-showing
:initialize 'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:init-value t
;; Enable or disable the mechanism.
;; First get rid of the old idle timer.

View file

@ -214,11 +214,10 @@ ignored (because the result is passed through
`file-name-shadow-properties', which can be used to make that
portion dim, invisible, or otherwise less visually noticeable."
:global t
;; We'd like to use custom-initialize-set here so the setup is done
;; before dumping, but at the point where the defcustom is evaluated,
;; At the point where the defcustom is evaluated,
;; the corresponding function isn't defined yet, so
;; custom-initialize-set signals an error.
:initialize 'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:init-value t
:group 'minibuffer
:version "22.1"

View file

@ -53,19 +53,19 @@ echo area, instead of making a pop-up window."
;; Even if we start on a text-only terminal, make this non-nil by
;; default because we can open a graphical frame later (multi-tty).
:init-value t
:initialize 'custom-initialize-delay
:initialize #'custom-initialize-after-file-load
:group 'tooltip
(if (and tooltip-mode (fboundp 'x-show-tip))
(progn
(add-hook 'pre-command-hook 'tooltip-hide)
(add-hook 'tooltip-functions 'tooltip-help-tips)
(add-hook 'x-pre-popup-menu-hook 'tooltip-hide))
(add-hook 'pre-command-hook #'tooltip-hide)
(add-hook 'tooltip-functions #'tooltip-help-tips)
(add-hook 'x-pre-popup-menu-hook #'tooltip-hide))
(unless (and (boundp 'gud-tooltip-mode) gud-tooltip-mode)
(remove-hook 'pre-command-hook 'tooltip-hide)
(remove-hook 'x-pre-popup-menu-hook 'tooltip-hide))
(remove-hook 'tooltip-functions 'tooltip-help-tips))
(remove-hook 'pre-command-hook #'tooltip-hide)
(remove-hook 'x-pre-popup-menu-hook #'tooltip-hide))
(remove-hook 'tooltip-functions #'tooltip-help-tips))
(setq show-help-function
(if tooltip-mode 'tooltip-show-help 'tooltip-show-help-non-mode)))
(if tooltip-mode #'tooltip-show-help #'tooltip-show-help-non-mode)))
;;; Customizable settings