[vox-tech] tags with mutt

Mike Simons msimons at simons-clan.com
Mon Apr 20 23:31:32 PDT 2009


Disclaimer: I don't use any of the methods discussed here.
I did some basic proof of concept tests ... you'll want to test and
debug.  

I've whipped them together tonight while avoiding doing work 
(and waiting for a batch of cocoa-strawberry ice cream to freeze).


On Sat, Apr 18, 2009 at 05:46:25PM -0400, Peter Jay Salzman wrote:
> FireFox and GMail have sort-of recently (past year) converted me from the
> directory paradigm to the tag paradigm.
> 
> Is there a way to use tags with email and mutt?

First search, using mutt's limit "l" command you can filter a 
folder based on most anything ... header searches are fairly fast.

X-Label header appears to have built in support 
  l~y thing 
would select messages that have a match for "thing" in any X-Label headers

If you don't like X-Label: then a search like
  l~h X-tags:.*linux
should match your X-tags: header.


> I might be able to roll my own system if there's a convenient way to add a
> header line to the email (I'd rather not do control-E and hand write the
> header line -- after all, tagging is to increase efficiency/convenience).

Searching on headers was the easy but adding/deleting tags from
messages seems to requires a little elbow grease.

Hunting through the manual, I didn't see an obvious way to update
any specific mail headers.  However there are ways to edit the whole 
message ... and ways to switch the editor ... so we'll combine those.

One of the more seemless ways of doing this seems to use a mutt macro
to replace the editor with a command which prompts you just for the tag
you want applied.

The attached script prompts for "what tag? ".  Tell it + to add 
or - to remove.  Then give a space separated list of tag names to 
add/remove, it updates the X-Label header or creates one ... based on 
what's appropriate.

Add to your muttrc
===
set my_vi=$editor
macro index "z" ":set editor=tag\ne:set editor=$my_vi\n"
===

Save the attached perl script "tag" into someplace in your PATH
You can call it whatever you want, update the first editor=tag to 
match the name you used if not "tag", full path if it's not in PATH.  


You may want to enhance tag so that it prints a list of tags found
in the message before prompting for "what tags? "


While testing I see one problem, the ';' command to bulk process
't' tagged messages, doesn't handle 'e' correctly.  So doing something
like 'T' to tag a bunch of messages then ';z' to tag them doesn't work
as expected.

I'm expecting most people want to bulk tag messages so this issue
will need to be addressed.  Ideas for how to get around this are use
some more macros to "set" the string you want add/delete from x-label
then have the 'z' command to apply... this without prompting.

something like (completely untested)
===
macro index "\" ":set my_tag="
macro index "," ":set editor=\"tag -t '$my_tag'\"\ne:set editor=$my_vi\nj"
===
so to set the tag being applied you'd use 
  \+stuff
to mark things with that tag you'd hit
  ,
which would tag it and move to the next message


> Then when I delete, I can probably use some kind of hook to save the
> email-to-be-deleted to a backup file.

You probably want to start using "s" to save messages instead of delete.
That saves them to another folder and marks them to be deleted at the same
time.  You can define a macro like 'Z' that automatically saves
messages to the "read" folder.
  macro index "Z" "s+read\n"


> Maybe an email tagged as "spam" could be auto-fed into bogofilter and
> deleted without backing it up...

You can define a macro like
  macro index "S" "|spam\nd"
to pipe the message into a spam processor and mark it for deletion.


On Sat, Apr 18, 2009 at 06:47:53PM -0700, Bill Kendrick wrote:
> [*] I believe ice cream is his main power source.

ice cream or the glow of monitors.


On Sat, Apr 18, 2009 at 09:29:14PM -0500, Chanoch (Ken) Bloom wrote:
> http://madduck.net/blog/2006.09.08:mutt-tagging/ discusses this problem.
> He hasn't found a perfect solution yet, but he says that
> http://www.steve.org.uk/Software/mutt-tagging/ comes close.

It's true that folders and tags are very different ways of organizing
things... mixing both modes in mutt probably won't work well as it is
now.

I'll punt on the searching many folders for tags ... heavy tags users
probably don't use folders.  I'd expect that the best "tag" experience in
mutt would be from merging all of the mail folders into a single folder
for everything (sent and inbox).


> I think an even better solution might be to create a LUFS filesystem to
> expose a single mail directory as a collection of directories
> representing tags, and to propagate updates automatically, but I don't
> care enough to build such a thing. The plus side of this solution would
> be that it would work with any mail client, and you could even expose
> the results via an IMAP server.

if I understand correctly, you would add a tag by copying the message
to a given folder, delete a tag by deleting the message from folder.
you'd probably see which tags exist on a message by looking at the header.
that seems like it could work well.

mutt's IMAP server handling must have gotten better since the last time
I tried it.
-------------- next part --------------
#! /usr/bin/perl -w

print "what tag? ";
$_ = <STDIN>;
s/([+-])(.*)//;
my $mod = $1;
die "$0 error: tag must begin with +|-\n" if (!defined $mod);

my @tags = split /[\s,]+/, $2;
die "$0 error: tag must contain some non-space characters\n" if (@tags < 1);

open OUT, ">", $ARGV[0] . ".new" or
  die "$0 error: failed to open output file \"$ARGV[0].new\" $!\n";
open FILE, "<", $ARGV[0] or 
  die "$0 error: failed to open input file \"$ARGV[0].new\" $!\n";

my %h;
my $once = 1;
while (<FILE>) {
  if (m/^X-Label: (.*)/) {
    map { $h{$_} = 1; } split /[\s,]+/, $1;
  } elsif ($once && m/^$/) {
    $once = 0;
    if ($mod eq "-") {
      map { delete $h{$_} } @tags;
    } else {
      map { $h{$_} = 1; } @tags;
    }
    print OUT "X-Label: ", join(", ", sort keys %h), "\n\n";
  } else {
    print OUT "$_";
  }
}

rename "$ARGV[0].new", $ARGV[0];


More information about the vox-tech mailing list