Wednesday, December 26, 2012

An emacs configuration smell

Have you ever seen code that just looked slightly wrong?  Like a function that takes in an argument that doesn't seem relevant to the task at hand, or a class with an overly generic name like "Utilities"?  That's what some people call "code smell".  Something doesn't seem right, and you don't know exactly what it is.  All you know is that something is rotten.

There's a "code smell" I've found in my own emacs customization code.  It's anywhere where there are several functions all related to the same thing.  Whenever this happens, I realize that an emacs package is trying to be born.  Whatever I'm doing is more than trivial, and usually it is of some use to someone else. It's worthwhile to see if someone has already tried to solve this problem, or if no one has, to try and solve it in a proper way yourself.  The proper way would be to make an actual project of it, put it on github, and get it included in MELPA or some other ELPA.

For example, a few years ago, I noticed a cool vi command as I watched a colleague work.  It cleared out everything between quotes, or parenthesis, or any kind of delimiter.  I did some looking around at the time, but didn't see anything out that was relevant.  So I implemented it myself in my initialization file.  It was about 30 or so lines of code, nothing too gigantic.  But since then the great package expand-region (available in MELPA) came out, and it basically can easily do everything I was doing.  So I got to delete all that code, and replace it with:

(defun ash-clear ()
  (require 'expand-region)
  (er/expand-region 1)
  (kill-region (region-beginning) (region-end))
  (er/expand-region 0))

This is much simpler, clearer, and frankly it works much better than the half-assed thing I put together.  But if this package hadn't existed, it probably would be worth my while to create it. In the process of doing so, I'd inevitably make it much better, as well as making it public so that other people can take it and possibly even contribute.

So I advise everyone to look through their personal initialization files.  Are there packages in there that need to come out?  Are they code that can be simplified by using someone else's package? If something in your emacs initialization is worth spending more than a few lines of code doing, it's worth doing right, and for everyone.

Saturday, December 22, 2012

Encrypted emacs customizations

Sometimes you want to store passwords in your configuration. Several things need it, such as gnus and emacs-jabber. You don't want to have to lock down your whole initialization file, you just want to protect the settings you care about.

There is a way to do this, and it isn't too hard, at least on GNU/Linux.

What you need to do is to put your settings in a file in the ~/.emacs.d/ directory (assuming that you have this in your load path), with a .el.gpg suffix. The gpg suffix will tell emacs that this is something that needs to be encrypted with the gpg program (the program referenced in variable epg-gpg-program, defaulting to "gpg"). Whenever you save such a buffer, you need to supply a password with which to encode the file. It's kind of a pain in the ass, actually, but hopefully your settings are a write-once sort of thing.

Assuming that you can create such a file because you have gpg installed, you then need to make sure that those elisp files with gpg suffixes are loadable via require and load statements:

(add-to-list 'load-suffixes ".el.gpg")

Then it's a simple matter of requiring your file. If your file was named secure-config.el.gpg, then (require 'secure-config) will load it. Be warned: when it loads, you have to enter the password it was saved it so it can be decrypted. That means that you shouldn't just have the require statement in your initialization, otherwise you'd have to enter the password on loading emacs. Better to do something like:

(defun ash-jabber ()
  (require 'secure-config)

This makes sure that I'll be prompted for the password only when I want to use the program that requires the password. You could also instead "advise" the loading function (in this case, jabber-connect-all) if you want to avoid having an extra function.

I'd highly encourage you to use this system when dealing with passwords in your initialization files.

Monday, December 17, 2012

Sane font setup with dynamic-fonts

If you share your emacs initialization amongst several computers, and each has their own fonts, then things aren't so straightforward. You have two basic choices. The simplest is to not configure fonts at all, and just set up some appropriate fonts in your custom.el file that is local to your computer. The other is to engage in a complicated guessing game, matching the system type with likely fonts, or perhaps by checking for fonts and then setting.

Fortunately for us, there's a better way! (Cue emacs informercial intro music). dynamic-fonts is a package from the Roland Walker available on an ELPA that fixes this for you.
Using it, you don't have to do much of anything except:

(require 'dynamic-fonts)


Update: This is what is in the documentation, but the documentation is not always correct.  This will not work with emacs started in daemon mode.  A better way is:

(require 'dynamic-fonts)
;; If we started with a frame, just setup the fonts, otherwise wait until
;; we make a frame.
(if initial-window-system
  (add-to-list 'after-make-frame-functions
               (lambda (frame) (dynamic-fonts-setup))))

But even this doesn't seem to work on the Mac.  I don't know why yet.

This sets up both a preferred proportional and monospace font. You should probably set it to the fonts you like in order of preference, although there are reasonable lists already pre-populated.  I'd recommend setting these font preferences in your machine-agnostic customization file ( ~/.emacs.d/init.el for me).

(setq dynamic-fonts-preferred-proportional-fonts
      '("Source Sans Pro" "DejaVu Sans" "Helvetica"))

(setq dynamic-fonts-preferred-monospace-fonts
      '("Source Code Pro" "Inconsolata" "Monaco" "Consolas" "Menlo"
        "DejaVu Sans Mono" "Droid Sans Mono Pro" "Droid Sans Mono"))

This should come before the dynamic-fonts-setup call. These fonts are listed in order of preference. They should contain enough fonts that all systems will have at least one of them.  I don't know whether my list has that property, but I suppose if I ever end up with bad fonts, I can fix the issue in either my computer or my font list.

This package is such a good idea. One of the things I'd like to do with my emacs customization is to similarly extract any good ideas into packages which I put on github. This would force me to write much better solutions than I would have written otherwise, or else remove those solutions entirely in favor of another package.

Wednesday, December 12, 2012

Customization with keybindings

Much has already been written about keybindings. I'd like to demonstrate creating two new function to do something, and binding one to a global key, and one to a mode-specific key.

I've been wanting to create a function for a while that easily lets me store and paste links to an org-mode file. Org already supports this, so this should be quite easy.

I'd like to bind a key to store a link to the present point. The function org-store-link does this, so all we need is a keybinding for this, since one doesn't exist by default. We do this with the function global-set-key. But we have to choose a key sequence first. If you want a great guide on keybinding, the awesome blog Mastering Emacs has a wonderful writeup. So, as the Mastering Emacs blog notes, all keys starting with C-c and function keys to F5 onward are available for user binding. For some reason I don't understand, org-mode takes many of these bindings for itself. So, we should check what's already bround, so I need to take a look at all currently keybindings C-h b. Looking at my keybindings, I see I don't have any bindings for C-c g, so let's use that. I'll add the following in my init.el:

(define-key global-map (kbd "C-c g") 'org-store-link)

The next part is to write a small function to add the link in an org file. There's a function already org-insert-link that has our basic functionality, but by default it prompts the user twice, which I think is unnecessary. Fortunately, the method takes a LINK-LOCATION and DEFAULT-DESCRIPTION as optional arguments, so we shouldn't have to do much work. Here's what the method looks like:

(defun ash/org-link-description (link)
  "Makes a useful description from a link."
  (cond ((string-match "^file:" link)
         (file-name-nondirectory link))
        (t nil)))

(defun ash/org-paste-link ()
  "Paste all stored links without prompting."
      (flet ((read-string (prompt &optional initial-input history default-value
          (dolist (link (delete-duplicates org-stored-links :test 'equal))
            (org-insert-link nil (car link) (ash/org-link-description (car link)))))
    (setq org-stored-links nil)))

(define-key org-mode-map (kbd "C-c p") 'ash/org-paste-link)

The definition of ash/org-paste-link has a few interesting features, but what I really want to talk about is keybindings, so I won't explain why I had to do things the way I did. I may get into writing new commands in a later post.

The interesting part for keybindings here is that I bound it to org-mode-map. That means this binding will only be in effect in org-mode buffers. I found that org-mode-map is the one to use by just running M-x apropos on the regex org.*map. In general, any mode will have a map, and the pattern is usually -mode-map, where can be whatever mode you interested in adding to.

I'll add this code to my large eval-after-load form for org-mode, so that it will only evaluated once I start using org-mode. This might be a bad idea if I want to grab a link before I visit an org-mode file for the first time, since my keybinding will not be loaded at that point. I'll have to see if that is something I'm liable to do, and if so, I'll move that keybinding out.

The lessons here are:
  1. Use keybindings for common tasks.
  2. Use global keybindings for things you might want to do in any buffer.
  3. For things you only want to do depending on the mode, use the mode specific keybinding, which can be found at the package map with suffix -mode-map.
  4. Use the user-space keybindings, those starting with C-c, and the function keys F5 on up.

Monday, December 10, 2012

Hooks, local variables, and namespaces

Sometimes you want to customize variables depending on what mode you are in. The usual way to do this is through hooks. These are variables that hold a list of functions to call when they are triggered. Most modes have a hook for when they are enabled, which lets you then use the hook to customize based on modes. For example, here's how I currently customize c++ and Java modes:

(add-hook 'c++-mode-hook (lambda ()
                           (setq fill-column 80)
                           (fci-mode 1)
                           ;; compatible with fci-mode
                           (setq whitespace-style '(face trailing))))
(add-hook 'java-mode-hook (lambda ()
                            (setq fill-column 80)
                            (fci-mode 1)

This means that when I load or create a c++ file, we'll set the fill-column to 80, enable fci-mode (which has a marker which indicates when you are over the fill-column), enables electric-pair-mode (which inserts closing parens or similar item when you type the open parens), and sets the whitespace-style so that trailing whitespace is visible.

To use hooks properly, you have to understand and global and local variables.  In elisp, all variables are global. But there are different kinds of global variables. One is the truly global variable. If you set it in one buffer, it is set for all buffers. Some variables are local, so they are the same in all buffers except the one in which make-variable-local was called. Finally, there's a variable that is always local to a buffer whenever it is a setup with make-variable-buffer-local. There's also a similar make-variable-frame-local. To set a variable in a hook, you are setting it in the context of a buffer. You want to ensure when you set it, it is set just in that buffer. So it needs to be either buffer-local, or you need to make it local. The easiest way to check to see if a variable is local or buffer-local is to look at it's help page C-h f. If the variable is local, it will be noted there. You can programmatically do this with local-variable-if-set-p, which will return a true value if the variable will be local when set. The similarly local-variable-p returns true if the variable has been set and is now local.

fill-column is a variable that will become local whenever it is set, as the documentation mentions. So this is safe to set. However whitespace-style does not have documentation that mentions this. And if we check manually in ielm, we can confirm this:

ELISP> (local-variable-if-set-p 'fill-column)
ELISP> (local-variable-if-set-p 'whitespace-style)

This looks like a bug in my customization code, then. Whenever I'm loading a c++ file, I'm changing the global value of whitespace-style! We can fix this by making the variable buffer local before we set it.

(add-hook 'c++-mode-hook (lambda ()
                           (setq fill-column 80)
                           (fci-mode 1)
                           ;; compatible with fci-mode
                           (set (make-local-variable 'whitespace-style)
                                '(face trailing))))  

This uses the fact that the function make-local-variable returns the unquoted function, and therefore it can be used with set.

We can improve this further. If you look at the C++ and Java versions, you can see that there is considerable overlap. It's useful to make everything a function, so that if there's any issue, we can simply redefine it to change the behavior. Otherwise, if you just used a lambda, and there's an issue with it, you'd have to remove the hook manually and re-add it after fixing.

Here's our factored code:

(defun ash/c-like-initialization ()
  (setq fill-column 80)

(defun ash/show-trailing-whitespace ()
  (set (make-local-variable 'whitespace-style)
                                '(face trailing)))

(add-hook 'c++-mode-hook 'ash/c-like-initialization)
(add-hook 'c++-mode-hook 'ash/show-trailing-whitespace)
(add-hook 'java-mode-hook 'ash/c-like-initialization)

This is much cleaner, and now it's much easier to add new behaviors to either C++ or Java mode.

You may notice the code above has functions that start with ash/, such as ash/show-trailing-whitespace. Elisp allows all sorts of characters in identifiers, including slashes. It's wise to use a personal prefix in your elisp, so that nothing you do conflicts with built-in functions or packages you may have loaded. I used to use the prefix with a dash, but I've recently seen many uses of the slash, and agree it's better. The slash makes the namespacing clear.

With the refactorings in mind, here are the key ideas to remember when working with your own configuration file:
  1. When setting variables in a hook, make sure each variable is a local variable. If not, make it a local variable in the code you are adding to the hook.
  2. Prefer functions to lambdas in hooks.
  3. Use a namespace, separated with a slash, for your named functions and variables.

Sunday, December 09, 2012

Customizing exec-path and load-path

Emacs has two main list of paths it uses to find files, the load-path and the exec-path. The load-path is a list of directories that should be used to look for load files. The exec-path is a list of directories that should be used to look for binary executables, the equivalent of the shell variable $PATH (and is initialized from it).

The exec-path is the one that usually doesn't require any modification. If it is modified, it makes sense to do so by customizing the variable, which puts it in custom.el, which I've already recommended be local-only, and not checked into git.

The load-path controls what directories are searched for load, load-library, and require. The directories in load-path are used in order of their appearance in that variable. So if there's two entries in load-path, ("~/foo" "~/bar"), and they both have a file baz.el, a (require 'baz) will load the one in ~/foo. Most people add to the load-path with the elisp add-to-list command, which will put the new entry in the front of the list, which will mean anything in that directory will override everything else. This is useful for using a more recent version of a library that comes bundled with emacs.

By default, the load-path contains with the list of emacs directories that is part of the emacs standard set of elisp, such as (on my mac) "/Applications/", and many other similar directories. This variable used to frequently need customization, and I've long had something in my initialization that adds everything under ~/.emacs.d to my load-path:

;; We don't really want to specify every single directory...
(let ((default-directory "~/.emacs.d"))
  (add-to-list 'load-path default-directory)

This is the only way I've found to recursive add things to the load-path. When I added this, I felt it was necessary to avoid having to specify directories for every package I downloaded. Some packages, like org, needed two directories to be put in the load-path. It was annoying. But this is a heavy-handed solution to the problem. It adds a whopping 110 entries to my load-path. That can't be good.

Furthermore, ELPA already handles adding things to the load-path. I'm going to get rid of it under the theory that ELPA is handling everything I currently care about, and anything else can be dealt with as a special case. However, there is one directory I'd like to be on my load-path that isn't right now, and that's the ~/.emacs.d/ directory itself. I'd like to be able to add other .elisp files in this directory as well. The following elisp accomplishes that:

(add-to-list 'load-path "~/.emacs.d/")  

Today's lesson is a simple one: Using ELPA largely obviates the need for adding directories to load-path. But if you do have special directories you'd like to add, then use add-to-list to add them.

Saturday, December 08, 2012

ELPA and el-get

In my last post, I discussed how to tie ELPA into your customization. There's another alternative, el-get, which is a wrapper around ELPA and many other things, and lets you install and keep up to date with just about any piece of elisp out there.

The advantage here is that not everything is on ELPA. Many bits are in github, or Emacswiki, or some other more random system. Using el-get lets you easily deal with all of those things in a similar manner. The configuration options seem well-done too, though. It's a really nice system.

I played around with el-get, and I didn't have any issues. However, I wouldn't recommend it. I think more things are moving to ELPA, and anything that isn't there is best ignored for now. When Emacs 24 is the baseline emacs people use, which should be a few years from now, I'd expect every notable package to be on ELPA. So I'd keep it simple, and ignore el-get for now.

Friday, December 07, 2012

ELPA and initialization

ELPA is one of the biggest improvements to Emacs 24. It stands for the Emacs Lisp Package Archive, and it give Emacs users a way to install and maintain packages from centralized repositories. ELPA takes care of browsing the list of packages, finding out more about each one, downloading each package, downloading dependent packages, byte-compiling each package, and installing them in a standard place.

Using ELPA already will simplify your config file. You no longer have to change the load-path for each package. All ELPA packages will be on the load-path automatically.

Furthermore, some packages are specifically designed to give you a sane startup environment, notably the starter-kit package. Just downloading the package from ELPA will get you its extra initialization.

However, it'd be best to not have to do any manual downloading for core packages that make up the customization we want. It'd be nice if we can set up our ~/.emacs.d/ directory on a new machine from git, and just start emacs and have everything set up for us.

Right now, in my initialization file, I have the following code that will set up packages on a new machine:

(require 'package)
(setq package-archives '(("ELPA" . "")
                         ("gnu" . "")
                         ("melpa" . "")
                         ("marmalade" . "")
                         ("technomancy" . "")))

;; Package setup, taken from
(setq ash-packages

;;; install missing packages
(let ((not-installed (remove-if 'package-installed-p ash-packages)))
  (if not-installed
      (if (y-or-n-p (format "there are %d packages to be installed. install them? "
                            (length not-installed)))
          (progn (package-refresh-contents)
                 (dolist (package not-installed)
                   (package-install package))))))

First, this code loads the package code with a require statement, then sets the list of ELPA archives I use. Then, it sets up a list of packages I'd like to install in the variable ash-packages. After a necessary initialization, it looks at each of the packages, and for each one that isn't already installed, it installs it from ELPA. As the comment mentions, I took this whole thing from zane's dotemacs repository. As I mentioned in an earlier post, stealing other people's customizations is a time-honored emacs tradition.

Further down in the file, you will see that for some of these packages, some basic configuration happens. I try to group all configuration for a package together. It would be nice if we could specify the package for download and the configuration together, since then we could remove an unwanted package and all configuration at once. I don't think this is worth it, though, at least right now. Maybe I'll pursue this in a further blog post.

Finally, it's worth noting that I do all my customization in eval-after-load functions. The purpose of those functions is that the contents of them are loaded only when the package is required or autoloaded, which avoids issues with missing functions or variables. If the package is already loaded, then everything is evaluated immediately. It's also important note that these are written with the function to execute quoted (since we don't want to execute it right away).

For example, here's something that I use to setup the key-chord package:

(eval-after-load 'key-chord
     (key-chord-mode 1)
     (key-chord-define-global "jk" 'dabbrev-expand)
     (key-chord-define-global "l;" 'magit-status)
     (key-chord-define-global "`1" 'yas/expand)
     (key-chord-define-global "-=" (lambda () (interactive) (switch-to-buffer "*compilation*")))

     (key-chord-define-global "xb" 'recentf-ido-find-file)
     (key-chord-define-global "xg" 'smex)
     (key-chord-define-global "XG" 'smex-major-mode-commands)
     (key-chord-define-global "fj" 'ash-clear)))

When a file that provides key-chord is loaded, this will execute. If key-chord is already loaded when this eval-after-load is evaluated, it will execute immediately.

Sometimes you want to have only load things when two packages are simultaneously loaded. Then you can nest one eval-after-load in another. I do that in that following elisp:

(eval-after-load 'multiple-cursors
     (global-set-key (kbd "C-c m m") 'mc/edit-lines)
     (global-set-key (kbd "C-c m a") 'mc/edit-beginnings-of-lines)
     (global-set-key (kbd "C-c m e") 'mc/edit-ends-of-lines)
     (global-set-key (kbd "C-c m r") 'mc/set-rectangular-region-anchor)
     (global-set-key (kbd "C-c m =") 'mc/mark-all-like-this)
     (global-set-key (kbd "C-c m n") 'mc/mark-next-like-this)
     (global-set-key (kbd "C-c m p") 'mc/mark-previous-like-this)
     (global-set-key (kbd "C-c m x") 'mc/mark-more-like-this-extended)
     (global-set-key (kbd "C-c m u") 'mc/mark-all-in-region)
     (eval-after-load 'key-chord
          (key-chord-define-global "zm" 'mc/edit-lines)
          (key-chord-define-global "za" 'mc/edit-lines)
          (key-chord-define-global "ze" 'mc/edit-lines)
          (key-chord-define-global "zr" 'set-rectangular-region-anchor)
          (key-chord-define-global "z=" 'mc/mark-all-like-this)
          (key-chord-define-global "i\\" 'mc/mark-all-like-this)
          (key-chord-define-global "zn" 'mc/mark-next-like-this)
          (key-chord-define-global "zp" 'mc/mark-previous-like-this)
          (key-chord-define-global "zx" 'mc/mark-more-like-this-extended)
          (key-chord-define-global "zu" 'mc/mark-all-in-region)))))

This is important! If we were to to put all the key-chord-define-global in the top-level eval-after-load, then if key-chord were not downloaded from ELPA, or not loaded for some reason, this would break, throwing an error that key-chord-define-global is undefined. Doing things this way is much safer.

However, you can't do this all the time. If we were to take this statement:

(eval-after-load 'key-chord
     (key-chord-mode 1)
     (key-chord-define-global "l;" 'magit-status)))
and turn it into this:
(eval-after-load 'key-chord
     (key-chord-mode 1)
     (eval-after-load 'magit
       '(key-chord-define-global "l;" 'magit-status))))

That would pose an issue. It would protect us against the case where the magit package isn't installed, and therefore we shouldn't have a keychord defined. However, if it was installed, we wouldn't have a keybinding, and unless we run (require 'magit), this keybinding wouldn't appear. We don't really want to run that, though, because an autoload is more efficient, and magit-status is an autoload. That means that the magit package may be unloaded, but we still have the entry functions from the package. When the user invokes any of those commands, then magit is loaded at that point.

Autoloads make our initialization files load much quicker. I think it's better to use them then to require everything, so I don't have nesting eval-after-load statements for anything autoloaded.

Here's the lessons we can take from this:
  1. Set up your ELPA such that you have a good set of package-archives.
  2. Set things up so that you have a list of must-have ELPA packages, which are downloaded when they don't exist.
  3. Customize through eval-after-load, and keep all your customization for a package in one place.
  4. When you are customizing things that only exist when two packages are loaded at the same time, use nested eval-after-loads.
  5. The exception to the above rule is autoloads. There is no need to nest an eval-after-load for an autoloaded function. You can usually just assume that any major function in a package is autoloaded, but if you want to check, jump to the source and look for a comment above that says ;;;###autoload.

Wednesday, December 05, 2012

Fixing some incorrect initialization

Remember when I removed the setting for c-buffer-is-cc-mode? I couldn't remember why it could possibly be important to set it in init, especially since it was buffer local.  Well, after restarting, I find I cannot paste anymore, and I'm getting an error involving c-buffer-is-cc-mode. In these situations, it's best to do M-x toggle-debug-on-error.

Reproducing the problem, I see from the backtrace that my error comes from my advice I define for pasting:

(defadvice yank (after c-indent-after-yank activate)
  "Do an indent after a yank"
  (if c-buffer-is-cc-mode
      (let ((transient-mark-mode nil))
        (indent-region (region-beginning) (region-end) nil))))

The error is now easy to spot. Not every buffer has c-buffer-is-cc-mode defined, so when elisp tries to evaluate the undefined variable, it throws a void-variable error. The fix is pretty simple, which is to use boundp, which checks to see if a symbol is void or not.

(defadvice yank (after c-indent-after-yank activate)
  "Do an indent after a yank"
  (if (and (boundp 'c-buffer-is-cc-mode) c-buffer-is-cc-mode)
      (let ((transient-mark-mode nil))
        (indent-region (region-beginning) (region-end) nil))))

After evaluating this, everything works well once again. The hacky setq of c-buffer-is-cc-mode is removed, and the yank advice now stands on its own.

Let's fix one more problem before calling it a day. I use an awesome package called key-chord. This enables me to set the press of two keys simultaneously (such as "j" and "k") to a command. I noticed that when I start up, though, it doesn't work until I toggle the to disabled, and then back to enabled.

First, I noticed that (key-chord-mode 1) is called before any of the key-chord-define-global is called. Maybe it should be last? I try it out, but it doesn't help the problem. Maybe the problem is that the feature isn't actually loaded yet. I looked at my config, and saw that I only do operations on key-chord in eval-after-load calls (which I'll be writing about later). But nothing ever loads it!

When I invoke M-x key-chord-mode, what must be happening is that the autoload for key-chord kicks in, loads it, then evaluates everything in all the eval-after-load calls, one of which calls (key-chord-mode 1). Then the M-x invocation executes, which turns the mode off. To fix this, we just need to add a (require 'key-chord nil t) statement. And that does fix the problem.
I'll go into the require statement in another post, and why I use the additional arguments to the function.

I looked in my init file for other locations in which I'm making the same mistake. I see that I have setup for bc (a breadcrumb system), but no actual library backing that up right now. I checked, and it isn't available on any of my ELPA servers I use. To me, this is a bad sign. ELPA makes things so much easier that I think it's better if I use some other bookmarking solution and retrain myself. So I'm deleting my config for this, and I'll investigate other bookmarking systems later.

The lessons I've gotten from today's debugging session are this:
  1. Strange things in init files are a sign that there may be a bug. Don't patch around it. Find the problem and fix it!
  2. After modifying your init file, load it up and try a few things. Fixing things while working on your init file is much better than discovering some problem at a more inconvenient time. That's when bad fixes and hacks start to creep in.
  3. If you want a global mode to be on as soon as you start up emacs, don't forget to require the package. Most other things don't need the require, since they have elisp autoloads that will load up the code when you execute one of the package's commands.

Tuesday, December 04, 2012

setq / custom.el changes up

I made the changes corresponding to yesterday's post on setting variables to my emacs configuration.  If you are interested, you can look at the diff to see what kind of cleanup is the result of taking the advice I gave in the last post.

In the progress, I realized that the code I gave yesterday for loading custom files could be improved, and I've edited the post to reflect that.

Also, I've actually seen a live example of using the package-loading capabilities of custom-set-variables. Evidently, this is used to set global modes to true. For modes, using setq doesn't work, you either have to use a function or change it through the customization interface. When you set this variable, you really want to load the package you are setting the variable on. The resulting bit of code looks something like:

  '(foo-global-mode t nil (foo))

This will load the package foo and set its global mode to true.

For these kinds of things, I prefer to use the method instead in setup, so that enabling the global mode can be grouped with any other customization for the feature.  So instead of using customize to set the variable, instead we'd just call:

;; Turn on foo everywhere.
(foo-global-mode 1)

Monday, December 03, 2012

Variable customization

There are a few major kinds of customization you can perform:
  1. Change the variables for already existing code.
  2. Create new keybindings (or erase ones that were there already).
  3. Create new functions to add new interactive capabilities.
  4. 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 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)  


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:

 '(bar 10))
(defvar bar 3 "An example variable")
(princ bar)


This is why customization always happens last.

You can actually change this behavior. And you can add comments.

 '(baz 10 t nil "With the t argument, this will be evaluated explicitly"))
(defvar baz 3 "An example variable")
(princ baz)


There is one other interesting thing you can do with custom-set-variables, which is to have the customization per-feature.

 '(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:
  1. Use setq for each variable you want to set.
  2. Unless it is dead obvious, comment on why you are changing the variable.
  3. Keep all similar variables together.
  4. 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.
  5. Load customization last.
I plan on going through my configuration file and making these changes, and I encourage you to do the same.

Sunday, December 02, 2012

Some people don't customize emacs. If you are one of them, there's no need to read further. However, the more packages you use, and the more you want to optimize, the more customization you require. Furthermore, the more customization you need, the more valuable that customization is, and the more you want to keep it around. With Emacs 24 and ELPA, getting and using packages is incredibly easy, so I anticipate that customization is going to be more important than ever.

I'm planning to write a series of posts on customizing Emacs, sharing tips and developing elisp to make the job easier. This is an introductory post to this series.

My first tip is to store your setup on github. I've done this with my emacs-setup project. I'll be updating this repository as I develop new elisp. Having your setup on github means you can put it on any computer you use, and other people can see and refer to your config. Stealing bits of elisp from other people's setup is a long-held emacs tradition, and github makes this easy.

My second tip is to store your configuration in ~/.emacs.d/init.el, not ~/.emacs. The .emacs.d directory is where all the action happens these days. Configuration files are stored there, as well as ELPA packages (in the elpa subdirectory). So if you are just starting your configuration, put it in ~/.emacs.d/init.el, or else move your existing configuration there.

Finally, all the tips I'll be giving assume Emacs 24. If you haven't upgrade, please consider doing so.

Stay tuned for more tips!

ELPA for App Engine

I've just released on open-source project: ELPA on AppEngine.  This is an implementation of ELPA written in the Go programming language, that runs on AppEngine.  Right now it isn't ready to be a real running system, but it probably won't take too much work to get it the rest of the way there.

It might have the possibility into being a really cool ELPA that is open to all, as opposed to the other ELPAs which are hand-curated.  I'm still thinking about where I want to take this.