- 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.
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.
2 comments:
One thing I'm not totally sure how to do is customizations that happen when you enter a mode. For instance, by default I want whitespace-mode to highlight tabs, but not when I'm writing go. whitespace-mode has a variable called "whitespace-style" which is a list of things for it to highlight. How would I tell emacs to remove "tabs" from that list when I enter go-mode? Currently this is what I have:
(add-hook 'go-mode-hook
(lambda ()
(set (make-local-variable 'whitespace-style)
'(face trailing space-before-tab space-after-tab empty))
(whitespace-mode)))
But constructing this was entirely guess-and-check until it worked, and it's not ideal because I explicitly set whitespace-mode, rather than just removing "tabs" from my default config.
Customizing on entering a mode like you have done is correct. I should go into this in another post.
As far as removing tabs from 'whitespace-style, you could have done
(set (make-local-variable 'whitespace-style) (remove 'tabs whitespace-style))
Post a Comment