The customization system is a built-in feature of Emacs designed to solve precisely the problem you describe—programming may not be the ideal way for the average user to configure their editor.
The primary entry point to the customization functionality is M-x customize RET (or Options > Customize Emacs > Top-level Customization Group from the menu). ...
Is the use of defcustom another way of doing (customizable) global variables?
Yes. Especially if you want users of your code to be able to change variables easily through the M-x customize interface.
defcustom provides two important benefits to your users: documentation and type safety. Documentation is nice to have right there. Type safety allows one to ...
Standard Info workflow
Here's how to get the info that you need:
<f1> i to start Info.
g (elisp) RET to select the Elisp node.
i defcustom RET to search the index for defcustom.
Immediately you'll see:
Use TYPE as the data type for this option. It specifies which
values are legitimate, and how to display the value (*...
Your understanding of Emacs Lisp notion of hook is absolutely correct. Indeed,
“normal” hooks are just lists of functions (every function doesn't take
arguments, otherwise it's not usually called “hook” or “normal hook” in
Most of these variables have names ending with -hook. They are normal
hooks, run by means of run-hooks. The value of ...
Use customize-set-variable or custom-set-variables, depending on just what you want/need.
Both of those make use of any initialization or setter functions (and so on) with which the user option might have been defined. See (elisp) Variable Definitions for information about these things.
If a given user option is defined without specifying any particular ...
This has been discussed more than once on email@example.com.
Here is one such thread, from 2016.
And here is something from Stefan, who dislikes such autoloading, from 2014.
Likewise, Glenn, in this 2010 thread.
And Stefan again, in 2009.
And here is an earlier 2009 thread about it.
There are many more such discussions, going back further.
One reason ...
Don't use type variable. Use type restricted-sexp.
The predicate checks for a symbolp that is boundp (i.e., a variable) and whose symbol-name is matched by your chosen prefix.
See the Elisp manual, node Composite Types.
Use :type restricted-sexp. It accepts a Lisp value that must fit the :match-alternatives restriction that you specify -- in this case that the value must satisfy vectorp and each of the vector's elements must satisfy stringp.
(defcustom foo ["a" "bb" "ccc"]
:type '(restricted-sexp :tag "Vector"
There is no more or less emacsy way, here, in my opinion. Rather, what you do with respect to (at least) the two approaches you outline depends on what your intention is - what behavior you want to provide users now and in the future.
This part of your question is unclear, to me: You say that existing uses of a single string should continue to work. But you ...
If you want Customize (or custom-set-variables or customize-set-variable) to not only change the value of the option but also define that new key value in the keymap then you need to use a :set function in your defcustom:
(defcustom myfeature-kb-configure "C-c C-p"
:set (lambda (sym defs)
(custom-set-default sym defs)
defcustom (and defvar) are only for the library that defines the variable. You don't want to copy those.
As a user, you can either use the customize interface:
M-x customize-option RET xyz RET
or else you can use setq to set the value in your init file:
(setq xyz "path2")
As you'll have guessed from the names, the customize interface only works on ...
"customize feature" there should probably be written as "Customize feature" or "the Customize user interface" or some such.
Try M-x customize-option or M-x customize-face or M-x customize.
See the Emacs manual, node Easy Customization.
And remember that the Emacs manual is your friend:
C-h r i customize RET takes you to the above part of the manual.
Yes, if the :set function is not appropriate also for initialization, explicitly provide a different :initialize function. Using custom-initialize-default is a common use case for this.
If you really do not want to do that, but you want to use just :set, then your :set function will need to do the necessary initialization, either conditionally or ...
Yes. See the doc for defcustom. What you want, in particular, is :set, which you specify as a function that does two things:
Sets the value. Just use the standard function for this.
Does whatever else you want to do -- in this case, mirror the new setting, transforming it first, in your external file.
You can do those two things in either order, i.e., ...
In a comment to @Drew's answer you've said:
Doesn't this require the user to use customize-set-variable instead of setq or setq-default ?
Indicating that you want your function to be called even when a variable is set by the likes of setq, which means you're looking for the variable-watcher functionality.
Refer to C-hig (elisp)Watching Variables for ...
It looks to me like you misunderstand the logic of the backquote. Even though it allows evaluation of code (instead of simply using the quoted value), it is still evaluated at runtime. That is, defcustom does receive a value in the same sense that a quoted list produces a value. Which is why if you look at the stored customizations in your custom.el file, ...
It's not clear (to me) what you want. The closest you seem to come to it is this, which is also not very clear:
"I just want it to keep using the backquote instead. Or somehow dynamically embed the variable reference there. But I don't see a way to do this."
Can you specify what you want as the value of the option, and how you want to be able to ...
Well, murphy's law strikes again...
I just realized that the Customize buffer was showing mismatch beside the data structure...
The problem I had tied to the fact that the last element of my inner list is itself a list, and the default declaration identified just 1 string.
So instead of writing
'((global "<>" "<>\...
It's not true that :set is used only for interactive use of Customize.
Functions customize-set-variable and customize-save-variable respect the :set function of the defcustom.
customize-set-variable is an interactive autoloaded compiled Lisp
function in cus-edit.el.
(customize-set-variable VARIABLE VALUE &optional COMMENT)
Set the default ...
Is it possible to use require (or similar) to organize my config into a modular structure of directories, without running into this issue?
Yes. Don't add custom-set-variables to multiple places in your init. There should be exactly one instance of custom-set-variables. By default, Emacs creates this in your init.el file. If it's already there, you cannot use ...
It sounds like you have done both of the following for some options, i.e., you've done them both for at least one option:
Used Customize to set and save the option.
Tried to call customize functions to set the option in your init file.
If so, it's you who introduced the redundancy. For a given option, choose one or the other. For example, if you want to ...
There are many options, but here's one approach:
(defmacro csetq (&rest pairs)
"For each SYMBOL VALUE pair, calls either `custom-set' or `set-default'."
(let ((variable (pop pairs))
(value (pop pairs)))
(push `(funcall (or (get ',variable 'custom-set) 'set-default)