I was talking to a friend I met on the internet about using neomutt for writing emails. It was a nice conversation with at least one gem that I was able to take away. They said two related things:

  1. They don’t write their To: fields in the mutt prompt
  2. They use an autocomplete thing to fill in their email addresses

Auto Edit

There are two config settings we are looking at here. edit_headers which allows you to … edit your headers but inside of your editor when composing the email. The other is autoedit which “skip[s] the initial send-menu (prompting for subject and recipients) and allow you to immediately begin editing the body of your message.”

set edit_headers=yes # https://neomutt.org/guide/reference#edit-headers
set autoedit=yes # https://neomutt.org/guide/reference#auto-edit

This was good news for me as the send-menu wasn’t a whole lot of fun to use, primarily because you can’t use vim keybindings there, it is arrow keys all the way. Skipping this allows you to edit all the headers at the top of the text editor screen, including all your keyboard shortcuts you want to use everywhere.

Autocomplete

The autocomplete solution that was shared with me was one based on Deoplete, which isn’t something that I use. Under the hood it is using notmuch to pull out all the email addresses from your email archive. TIL you can use notmuch for things like this.

I have been using Telescope as a lua fuzzy finder in my new all lua neovim config (it hasn’t been all that much fun porting to a lua based config but it is a good spring cleaning exercise nonetheless). One of the things that you can do with Telescope is write your own extension that implements your own picker. Given the basic idea from the Deoplete plugin with the documentation for writing your own picker, I was able to have the output of notmuch in the Telescope UI.

Making an extension for Telescope

telescope-notmuch.nvim is the result of all this and is very close to the example picker given in the Telescope documentation. There were a few parts which tripped me up, one of which was how to package it up and call it as an extension. After looking through the other extensions I was able to get a working picker.

-- telescope-notmuch.nvim/lua/notmuch/init.lua

local notmuch = function(opts)

    [...]

  }):find()
end

return notmuch -- This here I couldn't see in the docs


-- telescope-notmuch.nvim/lua/telescope/_extensions/notmuch.lua

return require("telescope").register_extension {
  setup = function(ext_config, config)
    -- access extension config and user config
  end,
  exports = {
      notmuch = require("notmuch") -- I was missing this as well
  },
}

Where I went wrong, reading the documentation, was not returning my picker function and then requiring it in the _extensions configuration object. Once I had done this, Telescope was able to see it and I could call that picker like any other.

It can be installed with Packer :

use {
    "https://codeberg.org/JoshuaCrewe/telescope-notmuch.nvim.git",
    config = function()
        require"telescope".load_extension("notmuch")
    end,
    ft = {'mail'}
}

(which I am pretty pleased with)

JQ or no?

This extension currently has a dependency on jq, which was fine when I was trying to get up and running quickly. I would rather it didn’t have this dependency and actually I did go on to make a version of it that used an internal lua function. You can see that both versions are in the code but the performance completely tanked so I went back to using jq.

I don’t really know why the startup time suffered so much but with the jq version and lazyloading for only when emails are written it is unnoticeable (largely becuase 90% of the time it isn’t being loaded at all!).

That is the story of how I make an extension to take email addresses from my archive into a fuzzy autocompleter.