Mutt, the Address Book and Completion
I was astounded to see how easy it was to add some clever completion for my address book contacts to my mail composer. And guess what: all thanks to Vim.
1 Vim as Editor
In fact, mutt doesn't have much to do with this, except that it's got the very good taste of letting you choose which editor to compose mail with. And also that it lets you edit headers such as the subject and, crucially here, the recipient list in that same editor, too.
I should take the opportunity to encourage everyone to set up their mutt to edit their mail right in Vim – or any editor they're completely fluent with. This enables sender to comfortably juggle with short or long lists of recipients, search them, sort them, make searches, even use a spelling checker. All the tools are here to make life easier and also avoid making those blunders which are too easily made with those more graphical and limited modern mailers.
2 Parsing the Address Book
Using a custom, powerful editor for composing lists of recipients unleashes a flexibility which is hard to appreciate at first. But the simple fact that you can, in the case of Vim, write functions to perform any operation gives you an inkling. Here, I wrote a simple function which fuzzily parses my ~/.muttrc
file in search for aliases making up my address book:
set completefunc=CompleteAddress
fun! CompleteAddress(findstart, base)
if a:findstart
return searchpos('\s', 'b', line('.'))[1]
else
let results = []
for line in readfile($HOME . '/.muttrc')
if line =~ '^alias' && line =~ a:base
let line = substitute(line, '^alias\s\+\S\+\s\+', '', '')
call add(results, line)
endif
endfor
return results
endif
endfun
Such a function is then summoned by hitting Ctrl x u . The completion system hence triggered displays 2 behaviours depending on the value of that argument called a:findstart
:
- When it passes
a:findstart
astrue
, it searches and returns the position of the previous space (as the'b'
argument makes it search backward) to identify the word typed so far (which will becomea:base
). - When it passes
a:findstart
asfalse
, it parses each line in~/.muttrc
in search for matches starting with thealias
mutt command and which contain the word typed so far (a:base
). It returns such matching lines with thealias
command and its key stripped off, leaving only the address. An address can comprise a display name and the actual address in angle brackets:John Doe <john.doe@example.com>