There are a few major kinds of customization you can perform:
- Change the variables for already existing code.
- Create new keybindings (or erase ones that were there already).
- Create new functions to add new interactive capabilities.
- Load new packages that alter the behavior of emacs, and call
functions that setup the initial state of those packages.
I'm going to focus on changing the variables in this post.
There are two main ways to change variables: by using setq directly,
or by using customize. Looking at my
init file, my first line setting
a variable directly is this:
;; This only gets set for real when cc mode is enabled
(setq c-buffer-is-cc-mode nil)
This is an example of using
setq
. If you are new to elisp, you may
wonder why it is called
setq
instead of
set
. The answer is pretty
simple:
setq
stands for "set quoted", and there already is a
set
. Here's the same thing with
set
:
(set 'c-buffer-is-cc-mode nil)
The difference here is we have to quote the variable we are setting,
c-buffer-if-cc-mode
, whereas in
setq
it is done for you. At any
rate,
setq
is more idiomatic in elisp, so let's use that.
The other main way to set variables in using customize. To set the
same variable with customize, we can type
M-x customize-variable
and
then enter
c-buffer-is-cc-mode
. However, if you try this, you'll
see that
c-buffer-is-cc-mode
doesn't work; it has no customization
option. That's probably because it isn't intended to be customized,
and indeed if you look at it, you'll see that it is buffer-local,
which means that it isn't a global variable, it is one that has a
potentially different meaning in every buffer. To such variables,
there isn't much need for global customization.
As you can see, you can't customize everything. For many things,
though, customization is pretty nice. You can also do
M-x customize-group
and then put the name of some package, such as
ido
.
You'll see a list of variables printed as phrases: the first letter
capitalized and the dashes replaced with spaces. For example, the
variable
ido-before-fallback-functions
is referred to as "Ido Before
Fallback Functions". For variables with a freeform value, you can edit the
value in a small textbox. For lists, you can insert an element at a
time. For things that can be one of a few values, you get a selection widget. It's all very nice and easy to use. The documentation is also right there. After making a
modification, you can save for the current emacs session, or
permanently. Permanently saving puts the customization in your
initialization file in a stanza that looks like:
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(ido-auto-merge-delay-time 1.5))
There is a choice to make for customizing options, then. Use
plain-old
setq
, or use the snazzy built-in customization? I think each has it's uses, but my current configuration isn't a good
example of this. Let's fix it.
Generally, I think it's best to use customization for machine-specific
things, and
setq
for everything else.
setq
has some nice
advantages to it, but also a few drawbacks. The advantages are that
you can group the
setq
statements with similar customization (for
example, keybindings). Also, you can comment on the variable
settings. This is very important. Looking at my setting of
c-buffer-is-cc-mode
, my only comment is "This only gets set for real
when cc mode is enabled". This comment sucks. Looking at this, I
don't recall why I felt the need to set it, and this comment does not
help at all. Ideally, I'd like to know what horrible fate will befall
me if I fail to set this variable. I'm going to remove this from my
config. When I figure out why I needed it, I should remember to leave
a better comment. Maybe I'll never figure it out, which is fine,
since my config will be just that much cleaner.
The drawbacks to
setq
are that the UI for changing the settings is
not nearly so nice as the built-in customize. That's about it.
A variable can be set with
setq
before the variable is even defined,
and the value set with
setq
will still take effect. For example:
(setq foo 10)
(defvar foo 3 "An example variable")
(princ foo)
--
10
It's also worth noting that you can have one
setq
to set many
variables, like so:
(setq foo 1
bar 2)
As I mentioned above, customization may be useful for per-machine
settings, such as the location of binaries. This is because we can
separate out the customization to another file. The docs to
custom-file
explain this nicely, but the basic idea is that you
setup another file to hold your customization. With things split into
another file, you can add this file to your
.gitignore
, and then just not
check it in. There should be no need to.
To do this, first, copy any customizations we have into your new file.
If you have an
~/.emacs.d/
directory like I suggest, then
~/.emacs.d/custom.el
is a reasonable choice.
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file t t)
Loading in this way will let the file not be there without throwing an error. That's fine, usually it shouldn't be there when running this config on a new machine.
Just in case you were wondering, customization does
not act like
setq
; it
matters where you do it:
(custom-set-variables
'(bar 10))
(defvar bar 3 "An example variable")
(princ bar)
--
3
This is why customization always happens last.
You can actually change this behavior. And you can add comments.
(custom-set-variables
'(baz 10 t nil "With the t argument, this will be evaluated explicitly"))
(defvar baz 3 "An example variable")
(princ baz)
--
10
There is one other interesting thing you can do with
custom-set-variables
, which is to have the customization
per-feature.
(custom-set-variables
'(jabber-keepalive-interval 10 nil (jabber) "Only pertains to feature 'jabber"))
This will load up the feature in question, in this case
jabber
when
customizing. I'm not really sure why this is useful. If anyone knows,
please tell me in the comments.
Customization has even more complexity. You can have customization
themes that you can change between, or layer on top of each other.
It's all very interesting, but to me it's best to just have the
separate file, and store machine-specific settings there.
In summary, my suggestions for variable settings are:
- Use
setq
for each variable you want to set.
- Unless it is dead obvious, comment on why you are changing the variable.
- Keep all similar variables together.
- If the variable is something inherintly machine-specific, such
as the location of a binary, then customize it, and put your
customization in a different file that will not be shared
between computers.
- Load customization last.
I plan on going through my configuration file and making these changes, and I encourage you to do the same.