Before and after columns aligned

I've been writing a lot of GraphQL resolvers in ruby at work recently, and frequently run into a situation where I have to align many columns of text by hand. I figured this isn't a very unique problem, and that there was probably already some code within Emacs to handle it.

As it turns out I was correct in my assumption. There's an excellent built-in package called align that takes care of just that.

Many of the features of the align package are mode-specific, but I just wanted a function that can align columns regardless of which mode they're used in. There's a function that's part of the package that can be used for just that fortunately, align-regexp, which takes a regular expression as input and uses it to guide the alignment.

I was able to use it to make a generic function.

(defun align-non-space (BEG END)
  "Align non-space columns in region BEG END."
  (interactive "r")
  (align-regexp BEG END "\\(\\s-*\\)\\S-+" 1 1 t))

Let's walk through what's going on here.

  • BEG and END are the beginning and end positions of the area to be aligned
  • (interactive "r") tells Emacs that the function is interactive, meaning that it can be called from the M-x menu

    • "r" tells Emacs that when the function is called interactively, it expects a region (beginning and end points) as arguments
  • align-regexp where the work is happening. This function has the following signature.

    (align-regexp BEG END REGEXP &optional GROUP SPACING REPEAT)
    • BEG and END is the region that it expects as the first arguments
    • "\\(\\s-*\\)\\S-+" is an Emacs regular expression. Backslashes are doubled because they need to be escaped in a string literal

      • \( \) is a capture group

      • \S- is similar to the previous construct, but instead means to match anything other than whitespace
      • + means one or more
    • 1 here refers to the group within the regex that will be modified to align the fields
    • 1 is the number of spaces between fields once aligned
    • t indicates to repeat the rule multiple times on the same line

To use this function, simply highlight a region you want to align and run M-x align-non-space.