Is :custom capable of setting minor-mode variables, or is it more limited than customization menu?
I noted that which-key doesn't seem to activate at all if I include the minor mode variable (which-key-mode) in :custom. If I call which-key-mode twice in succession, only now does which-key's popup activate. This issue arises with :custom (which-key-mode t); however, it doesn't arise if I use :config (which-key-mode t).
I'm guessing that minor-mode variables can be set via customization menu but not :custom? I had assumed the keyword was able to set the values of everything the customization menu could. Is it limited to variables and options?
What Emacs version are you using? It worked well on 26.3 for me
I'm using Version 27.0.91. I was able to get around the issue by simply calling the mode function from :config, but I wasn't sure if either way should work.
it looks like it was broken in #850
Yep. Here is an example of use-package expansion. As you can see, custom-set property is accessed before the variable is defined and use-package always fallbacks to set-default.
;; (use-package delsel
;; :custom (delete-selection-mode t))
(progn
(defvar use-package--warning69
#'(lambda
(keyword err)
(let
((msg
(format "%s/%s: %s" 'delsel keyword
(error-message-string err))))
(display-warning 'use-package msg :error))))
(condition-case-unless-debug err
(progn
(funcall
(or
(get 'delete-selection-mode 'custom-set)
#'set-default)
'delete-selection-mode t)
(if
(not
(require 'delsel nil t))
(display-warning 'use-package
(format "Cannot load %s" 'delsel)
:error)))
(error
(funcall use-package--warning69 :catch err))))
I'm not sure of the best way here. I've always used something like this to activate a minor mode but understand the problem is that it's not the only way:
:config
(ivy-mode 1))
- We could add a global and a local override to call
customize-set-variabledirectly when the user knows it's needed (moves the work to them) - We could call
customize-set-variablefor any variable name ending with-mode(reverting to the old behavior) - We could call
custom-load-symbolfor any variable name ending with-mode(using the nativecustom.elcode to load dependencies) - We could warn the user they should use
:configfor variables ending with-mode(ugly)
@jwiegley any opinions?
I used to have minor mode turned on in :custom, but it wasn't enabled in some packages for some reason.
An easy solution to this problem is to call minor mode directly as an argument of 1, as @tzz says.
This is already solved in leaf, where the user uses the :global-minor-mode keyword instead of the :custom keyword.
I think use-package should also have leaf's :global-minor-mode like keyword.
(It should be noted that I kept thinking of a better name for this keyword, but in the end I couldn't come up with a better name...)
- We could call
customize-set-variablefor any variable name ending with-mode(reverting to the old behavior)- We could call
custom-load-symbolfor any variable name ending with-mode(using the nativecustom.elcode to load dependencies)
TMO both are ugly too, in theory an (abnormal?) minor mode which doesn't end with the suffix can exist as well
@conao3 The thing is minor modes are defcustoms, so :custom should work for them
@tzz How about adding a function which mimics customize-set-variable, but doesn't save customizations into custom-file?
@conao3 The thing is minor modes are defcustoms, so :custom should work for them
I know what define-minor-mode does. And I know what define-minor-mode actually does. But, in principle, there can be minor modes that are not defined in define-minor-mode, can't there? And since it's true that there was a minor mode that couldn't be enabled in :custom, I added a dedicated keyword in leaf.
@tzz How about adding a function which mimics customize-set-variable, but doesn't save customizations into custom-file?
This is not for me, but I want to comment. This is a good idea that essentially solves this problem. I'll send this function to ML.
But, in principle, there can be minor modes that are not defined in define-minor-mode, can't there?
They can exist but I don't think it's a good idea
As far as I understand this, reason minor mode is not enabled by using :custom now is the change to set-default from customize-set-variable.
define-minor-mode expansion includes defcustom macro for mode's varaible with :initialize function set to custom-initialize-default. This is the case, I checked, for which-key-mode.
custom-initialize-default is one of default custom.el initializers specifically intended for minor modes. It's designed so that :set function (which enables/disables mode) is not called for pre-set values (like those set with set-default). But whenever the varaible is set via Customize (e.g. via direct call to customize-set-variable), the setter is called and the mode is enabled.
See elisp#Variable Definitions for a section about this initializer.
Enabling minor modes also works if set in a Custom theme (like in the user theme stored in custom-file). Though I haven't been able yet to trace the exact code that calls setter for minor modes in custom.el, it does work.
I have written and use my tiny evelineraine/init-custom.el package that aggregates all settings to customizable variables in init.el and then runs them through custom-theme-set-variables code as setitngs of a single Custom theme.
The way I use it is:
(use-package PACKAGE
:defer t
:init
; VAR can be a -mode variable
(init-custom-set 'VAR VALUE))
;; at the bottom of init.el
(load-theme 'init-custom :no-confirm)
By doing customizations this way, any and all obscure Custom features work (setters, ordering, dependencies, /and/ enabling minor modes), but values can be set from anywhere in init file and nothing seems to be saved to custom-file.
Have a look at my code if this approach looks interesting.
I am thinking about adding an :init-custom keyword to use-package so it can be uses just like :custom keyword.
I am thinking about adding an :init-custom keyword to use-package so it can be uses just like :custom keyword.
why are you trying to invent new keywords instead of reverting to the old working behavior?
why are you trying to invent new keywords instead of reverting to the old working behavior?
- the old
customize-set-variablewasn't working well enough, hence the move toset-defaultinstead. - use-package is extensible via adding support for new keywords. So far I haven't considered suggesting my approach as the replacement of
:customimplementation to the upstream.
In my opinion customize-set-variable isn't the right approach because:
- It marks the symbol as customize-but-unsaved (by storing the value in
customized-value). Any timecustom-save-variablesis called (and Emacs carelessly calls it in a lot of places, e. g. frompackage.elwhen installing / removing packages), all these settings are written to thecustom-file. This creates clutter and redundancy, but also leads to unexpected behavior: remove customization frominit.el, but it would still be installed viacustom-file. - Due to how underdeveloped
custom.elis (IMO), there is only one fully supported way to install customizations - via themes (custom-theme-set-variablesorcustom-set-variablesforusertheme). Exceptcustom-set-variablesdoesn't do type-checking, but that was intentional.customize-set-variablesseems only intened for interactive use, as a setter-aware version ofset-variableminus type-checking (no good reason for that). It doesn't support theme precedence, undoing customizations, ordering via:set-after, deferred evaluation, and something else maybe.
To me: custom-theme-set-variables > set-default > customize-set-variable, so reverting back would be worse.
the old customize-set-variable wasn't working well enough
It had worked for me for years, any example of invalid behavior?
all these settings are written to the custom-file.
any reason to use both :custom and custom-file?
custom-theme-set-variables > set-default > customize-set-variable
(defun custom-set-variables (&rest args)
;; ...
(apply 'custom-theme-set-variables 'user args))
A significant chunk of my emacs config stopped working now that I've got a version of use-package with #850 present. Are there plans to get the old behavior back (or something close to it), or should I rework my config to avoid depending on defcustom behaviors? Or is there another reasonable workaround?
Please see #881 for an attempt to resolve this issue. Thanks to everyone who chimed in, and apologies for the late followup.
@jkroes if you want provide a test to ensure minor mode vars behave properly, that would be really terrific.
@benley I think you may be commenting on something other than this particular bug report?
A significant chunk of my emacs config stopped working now that I've got a version of use-package with #850 present. Are there plans to get the old behavior back (or something close to it), or should I rework my config to avoid depending on defcustom behaviors? Or is there another reasonable workaround?
I'll do my best to address your issues, but would appreciate more detail than "stopped working." If you're just confirming someone else's report, you can say that or react to their report.
Ah, sorry - I commented on this issue before I really understood what was happening, and I've since found workarounds for my own needs. My problem was indeed about setting minor-mode variables with :custom, and I've switched to using :config (customize-set-variable ....) to handle those for now.
#881 switches to the custom-theme-set-variables approach which should address this issue as well. Please test and update. Thank you.
Also @a13 and everyone else commenting here, I think a test that verifies correct behavior would be quite welcome and provide some assurance that the code won't break user expectations in the future.
#881 has been merged, I'd like to close this issue if anyone can independently confirm and ideally provide a test for it.
#881 has been merged, I'd like to close this issue if anyone can independently confirm and ideally provide a test for it.
Thanks, closing.