samwood.org

(X)HTML Macros for Vim

Download here. I’ve also got a plain HTML4 version for those of you still using IE6 or something.

Every hacker and his dog probably has one of these kinds of set-ups, but there’s a neat little feature in mine that I think makes it worth posting. If, for some reason, you have ever cared to examine the HTML source of my pages, you’ve probably noticed that I have a very specific way that I like to format them. I always indent nested elements to make the tag hierarchy clearly visible, and I don’t like for lines of text like the ones in this paragraph to be longer than 80 characters. The trouble is, although Vim does have a setting to automatically break lines at a certain number of characters, it doesn’t work all that well with documents that have varying levels of indentation. If you’re always wrapping at 80 characters, and you have some paragraphs indented twice, others three times, maybe even some indented four times, the actual lines of text in each of those paragraphs will have different lengths, because Vim counts the indentation as part of the line length.

This made it a real pain in the neck to format my pages how I wanted, so I started looking for a way to have Vim do this automatically. Apparently, I am the first person who has ever wanted to do this, because hours of web searches yielded little. I thought I was onto something with the formatexpr and formatprg options, but it turns out that those are very finicky options, and a solution using those was probably going to be over my head. Eventually, it occurred to me that what I really wanted to do was not to change the way formatting worked, but just adjust the textwidth option whenever the indentation level of the line I was typing on changed. Wouldn’t you know it, Vim’s autocmd feature has events for when the cursor moves, so I could achieve exactly the effect I wanted with the following two lines:

let basetw = 80
autocmd cursormoved,cursormovedi *.xhtml let &textwidth = basetw + indent(line('.'))

The basetw value is your desired line length, not including the current indentation level. To calculate the appropriate textwidth for the current line, this value is added to the indentation level, retrieved with indent(), of the current line, retrieved with line('.'). Also note that we have to use let &textwidth instead of set textwidth, because set will only accept a literal value on the right-hand side of the assignment.

The rest of the macros are pretty standard. In general, you create a new tag by typing a ; followed by the first two letters of the tag you want to create. The macro will automatically place your cursor inside of the tag (or in the case of tags like <abbr>, which always have a title attribute, put your cursor inside of that attribute value). Some macros may generate one or more instances of the string <\>, which serve as markers for places to jump to. For example, if you create a <strong> tag, a <\> will be generated after it. This is so when you are finished typing inside of the <strong> tag, you can easily jump out of it again by typing the macro ;<TAB> and continue typing as normal.

Some macros also have versions for visual mode, which can be used to wrap already typed sections of text in a tag. For example, to add an <em> tag to a word, you can highlight it in visual mode, then type the ;em macro.

It still has a few rough edges, but it definitely helps me type my pages faster, and even if you don’t use the whole thing, maybe there’s some feature from it that you would like to add to your own macro set.


Valid XHTML Basic 1.1! Valid CSS level 2.1! This website is licensed under CC-BY-ND.