#+TITLE: Aligning columns in Emacs #+DATE: 2021-03-26T11:27:34-04:00 #+DRAFT: true #+DESCRIPTION: #+TAGS[]: emacs elisp #+KEYWORDS[]: emacs elisp #+SLUG: #+SUMMARY: I've been writing a lot of ruby GraphQL queries and mutations 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 in the infinite wisdom of Emacs developers over the last couple decades, someone must have included a piece of code to take care of exactly this kind of situation. As it turns out I was correct in my assumption. There's an excellent built in package called =align.el= 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. #+begin_src elisp (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)) #+end_src 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. #+begin_src elisp (align-regexp BEG END REGEXP &optional GROUP SPACING REPEAT) #+end_src - =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 a [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Backslash.html][regular expression construct]] specific to Emacs which specifies a type of /syntax/ which is to be matched. - =-= refers to the [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Syntax-Class-Table.html][whitespace characters]] - =*= means match zero or more - =\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=.