dgc / Mutt
dgc / Mutt

I use mutt, a mail user agent (MUA) for UNIX TM and other sufficiently Linux-like operating systems.

I've done some minor development for Mutt. Here are my add-ons and patches. If you want to try a patch, but there's not one for your version of Mutt, try one for the nearest lesser version number. This software is not warranted for any purpose, etc.

NEW 2002/06/13 To simplify and to reduce confusion, I've removed all patches prior to 1.4. If you're really aching to see old patches, though, you can perhaps find them on my archival copy.

Directory Lookups in Qi

Mutt has a simple interface for directory lookup plugins. I wrote one to look up names in one or more CCSO nameservers (a.k.a. Qi, a.k.a. Ph). To use this, install the agent in your path as "mutt-phquery", and add:

    set query_command = "mutt-phquery '%s'"
to your .muttrc file.

(There are other Ph query agents for Mutt; see the links at the Mutt web site. I prefer mine because it allows one to query any number of directories (with different parameters for each), and because it doesn't depend on the ph program or the qiapi libraries. Since we have three Qi directories on our campus and most of our neighboring institutions use Qi/Ph, too, this works well for me.

Kerberos patches

Most historical Kerberos problems are now fixed. There's a new one as of late 1.3.x releases, though: Mutt's configure script won't detect MIT Kerberos 1.2.4, and it can cause failures to link network libraries, too.

Custom message-tagging X-Label:

I like my mailing list mail to have a tag identifying messages as mailing-list messages. Some MLMs do this automatically by putting the list name in brackets on the subject header, but others don't. Anyway, I'd rather that the message have this property independently of the subject. It gives the mailer a lot more control.

These patches implement message labelling to meet that wish. The labels also can be used to mark messages according to interest or disposition.

My original mailing-list article describes the patch's use more fully.

  • patch-1.4.dgc.xlabel_ext.5 [PGP]
    patch-1.5.1.dgc.xlabel_ext.5 [PGP]

    As of mutt 1.4, basic X-Label: support is built in. This patch adds to the basic support an onboard label editor for the index and pager menus. The editor can be used to change, create, or delete message labels. Its function name is label, and its default binding is to the y key.

    If you've been using older versions of this patch, and you're upgrading, take note: this function binding has been renamed from <label> to <edit-label>.

Undo stroke and macro bindings

At a time there seemed to be interest in undoing keystroke bindings and macros more simply than rebinding strokes to noop or macros to nothing. In particular, I believe that people wanted to unbind everything on a menu's binding list. I wrote this as an exercise and in response.

  • patch-1.4.dgc.unbind.1 [PGP]
    patch-1.5.1.dgc.unbind.1 [PGP]
    This patch defines the unbind and unmacro directives. Syntax is as:
    unbind menu-name keysym
    unmacro menu-name sequence
    The menu-name and keysym terms are as in the bind directive. The * symbol can be used in place of either.
    unbind * *
    is enough rope to hang yourself, so it leaves : (bound to enter-command) and some minimal editor bindings active.

Attachment-counting patch
MIME attachments are useful, but I often lose track of where attachments are. I might be looking for a specific file that someone sent me, but if I get much mail from that person, the search can be somewhat difficult: Mutt's index doesn't tell me which messages have attachments, and there's no way to search for attachments across a whole mailbox.
  • patch-1.4.dgc.attach.5 [PGP]
    patch-1.4.dgc.attach_nntp.5.1 [PGP] for vvv.nntp users
    patch-1.5.1.dgc.attach.5 [PGP]
    This patch creates the %X expando for $index_format, and the ~X search operator. %X expands to the number of attachments Mutt can find in a message. In a wacky deviation from Mutt's norm, %-X expands to the number of attachments in the outermost part of a multipart message. (In a boolean context, as in the example above, %X is true if there is one or more attachment.)

    The ~X operator is a numeric operator. It takes the form:

    ~X [MIN]-[MAX]
    See the Mutt manual (section 4.2, Patterns) if you don't understand what that means.

    NOTE WELL that this patch has changed somewhat since earlier incarnations. First, it's now %X/~X instead of the earlier %V/~V. This change had to be made because the core Mutt code chose to use %V for key verification with the adoption of S/MIME support.

    More importantly, perhaps, I've completely changed the way the code counts attachments. Be sure to include the new attachment-related configuration in your Muttrc or .muttrc files! Default settings can be found in Muttrc.head.in or (once you've compiled Mutt) Muttrc.

    • dgc.attach.2's $attach_count_inline_ok is supplanted by the inline-allow and inline-exclude parameters.
    • The old dgc.attach.2 $attach_count_recurse is now named $attach_recurse. It has the same function as before: it makes the counter recurse into message/rfc822 containers.
    • $attach_count_containers_ok no longer exists. Instead, you should allow/exclude message/.* and/or multipart/.* types. See the example in the Muttrc file generated when you compile mutt.
    • dgc.attach.2 always discounted the first MIME part of any message. Since we're more flexible now about MIME types, that's not necessarily the right behavior. Setting $attach_ignore_fundamental provides loose compatibility to the old behavior; it's on by default.
    In short, you get a lot more control over what MIME parts get counted as attachments.

Nested if-else sequences in strings
If-else sequences in strings give menu displays a way of varying the conditionally. For example:
This index_format checks whether a thread is collapsed. If it is, and at least one message is hidden from view, it will expand to <%2M> — the number of hidden messages. Otherwise, it expands to %4c, the message size.

What if you want a three-way condition, though — "if A, then X; else, if B, then Y; else, if C, then Z"? Mutt doesn't allow that until you apply this patch.

  • patch-1.4.dgc.deepif.1 [PGP]
    patch-1.5.1.dgc.deepif.1 [PGP]
    This permits nested if-else sequences like this:
    This means: "If the thread is collapsed and there are hidden messages, show the number of hidden messages in angle brackets. Otherwise, if there are attachments on this message, show the number of attachments in curly braces. If neither is true, then just show the message's size."

Alias-matching pattern-matching symbol
People have, on occasion, written to the mutt-users mailing list wishing for a way to use Mutt's pattern matcher to find messages from, to, etc. addresses which are aliases known to Mutt. I once had a need for this, myself.
  • patch-1.4.dgc.isalias.1 [PGP]
    patch-1.5.1.dgc.isalias.1 [PGP]
    This patch extends the pattern syntax, adding the @ pattern modifier (see section 4.2.1 Pattern Modifier in the mutt manual). This modifier alters any address-matching pattern expression to force the specified address to be a known alias. A documentation patch is included.
    ~f elkins Anyone with "elkins" in the name or address.
    @~f elkins Any alias named "elkins", or with "elkins" in the name or address.

Marking messages to return to later
There's a feature in vi that I}}m so accustomed to, I kept trying to use it in mutt, too. In vi, you can mark a point in the current file with the m key, strike another key to act as the identifier for that mark, and then return to that mark later on by pressing the apostrophe (}}) and the identifier key.
  • patch-1.4.dgc.markmsg.2 [PGP]
    patch-1.5.1.dgc.markmsg.2 [PGP]
    This creates the mark-message binding, bound to the tilde (~) by default. Entering this binding prompts for a key sequence to identify the current message. This creates a macro sequence that will return to the message-id of the currently-selected message. The macro sequence is the apostrophe (}}), followed by the identifier you were prompted for. You can change the apostrophe to some other character or sequence by redefining the mark_macro_prefix variable to that character or sequence.

    I}}m not sure how useful this really is in practice, but that's for you to decide.

Piped strings
Now and again people want to do funky things with strings. Mutt allows this via the backtick, but some commands can get quite messy this way once you begin to escape and double- and triple-escape things for multiple levels of parsing.

Mutt's filename variables have a nice alternative: if you terminate a "file name" with a pipe character ("|"), it's judged to be a command whose standard output contains the actual file content to be read.

  • patch-1.4.dgc.fmtpipe.1 [PGP]
    patch-1.5.1.dgc.fmtpipe.1 [PGP]
    This patch allows you to use the same structure in any variable setting that's a string — anything that will take %-expandos and substitute values for them. It's a handy way to pass internal values (the % tokens) to an external process and have something different handed back. What's more, if the string that your program returns ends in a % token, it will be re-evaluated by the string formatting routine, so you can achieve some pretty astounding effects, and effectively have complex conditional processing and state-machine processing in your variables.

    Some interesting examples can be found in my announcement message to the mutt-users mailing list.

$Id: index.html4,v 1.3 2003/10/16 19:34:47 dgc Exp $
Mail: dgc@uchicago.edu