From ffb440066d953391036b6d842e9612680d21bc9b Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Fri, 6 Feb 2015 12:00:30 +0800 Subject: Added 'X-Label' tools & settings to mutt. * mutt-xlabel.py: manipulate labels. --- .mutt/attachments | 2 +- .mutt/colors | 1 + .mutt/mailcap | 7 ++- .mutt/mutt-xlabel.py | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++ .mutt/mutt_bgrun.sh | 4 +- .mutt/muttrc | 19 +++--- 6 files changed, 186 insertions(+), 11 deletions(-) create mode 100755 .mutt/mutt-xlabel.py diff --git a/.mutt/attachments b/.mutt/attachments index 6535626..74575de 100644 --- a/.mutt/attachments +++ b/.mutt/attachments @@ -61,4 +61,4 @@ attachments -I message/external-body ## your current settings in Muttrc format, so that it can be pasted ## elsewhere. -# vim: filetype=muttrc +# vim: set ts=8 sw=4 tw=0 fenc=utf-8 ft=muttrc: # diff --git a/.mutt/colors b/.mutt/colors index c709d50..de2f902 100644 --- a/.mutt/colors +++ b/.mutt/colors @@ -36,6 +36,7 @@ color header brightmagenta default "^(From|Subject):" color header brightyellow default "^Date:" color header brightblue default "^To:" color header brightcyan default "^Cc:" +color header brightblue default "^X-Label:" mono header bold "^(From|Subject):" diff --git a/.mutt/mailcap b/.mutt/mailcap index fd1db6d..d531285 100644 --- a/.mutt/mailcap +++ b/.mutt/mailcap @@ -45,6 +45,9 @@ application/msword; word2text %s; copiousoutput application/vnd.msword; ~/.mutt/mutt_bgrun.sh libreoffice %s; \ test=sh -c 'test -n "${DISPLAY}"' application/vnd.msword; word2text %s; copiousoutput +application/vnd.openxmlformats-officedocument.wordprocessingml.document; \ + ~/.mutt/mutt_bgrun.sh libreoffice %s; \ + test=sh -c 'test -n "${DISPLAY}"' # application/excel; ~/.mutt/mutt_bgrun.sh libreoffice %s; \ test=sh -c 'test -n "${DISPLAY}"' @@ -103,8 +106,8 @@ video/*; ~/.mutt/mutt_bgrun.sh vlc %s; \ # Show archive conents. # application/x-compressed-tar; tar -tf %s; copiousoutput -application/x-gnuzip; gzcat; copiousoutput -application/x-bzip; bunzip2 -c %s | tar -tf -; copiousoutput +application/x-bzip-compressed-tar; \ + bunzip2 -c %s | tar -tf -; copiousoutput application/x-tar-gz; gunzip -c %s | tar -tf -; copiousoutput application/x-7z-compressed; 7z l %s; copiousoutput diff --git a/.mutt/mutt-xlabel.py b/.mutt/mutt-xlabel.py new file mode 100755 index 0000000..ea96e37 --- /dev/null +++ b/.mutt/mutt-xlabel.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +# +# Add/Modify 'X-Label' header for mutt. +# Label mails with mutt. +# +# Reference: +# [1] GTD (Getting Things Done) and Mutt +# https://docwhat.org/gtd-and-mutt/ +# +# muttrc settings: +# unignore X-Label: +# macro index,pager x 'set my_oldeditor=$editorset editor="~/.mutt/mutt-xlabel.py"Nset editor=$my_oldeditor' \ +# "edit X-Label" +# macro index \Cx "~y " \ +# "limit view to label" +# +# Weitian LI +# 2015/02/06 +# + +import sys +import os +import email +import readline + + +# Settings +HISTFILE = os.path.join(os.environ["HOME"], ".mutt/xlabel_history") +LABELFILE = os.path.join(os.environ["HOME"], ".mutt/xlabels") + + +class MyCompleter(object): + """ + Comstom completer for readline. + + Reference: + [1] autocomplete - How to code autocompletion in python? + http://stackoverflow.com/a/7821956 + """ + def __init__(self, options): + self.options = sorted(options) + + def complete(self, text, state): + if state == 0: # on first trigger, build possible matches + if text: # cache matches (entries that start with entered text) + self.matches = [s for s in self.options + if s and s.startswith(text)] + else: # no text entered, all matches possible + self.matches = self.options[:] + + # return match indexed by state + try: + return self.matches[state] + except IndexError: + return None + + +def my_input(prompt, default=None, completer=None): + if default is not None: + def pre_input_hook(): + readline.insert_text(default) + readline.redisplay() + readline.set_pre_input_hook(pre_input_hook) + # completer + if completer: + readline.set_completer(completer) + readline.parse_and_bind('tab: complete') + return input(prompt) + + +def load_labels(labelfile): + """ + Load saved labels from given labelfile, + return a list of labels. + """ + try: + with open(labelfile, 'r') as f: + label_list = f.read().split() + label_list = list(set(label_list)) + except FileNotFoundError: + label_list = [] + return label_list + + +def update_labels(labelfile, label_list, new_label_list): + """ + Save labels for later autocompletion. + """ + labels = sorted(list(set(label_list).union(set(new_label_list)))) + with open(labelfile, 'w') as f: + f.write(' '.join(labels)) + + +def get_xlabel(message): + """ + Get 'X-Label:' values from given Message object. + """ + labels = message.get_all('X-Label') + if labels: + label_str = ' '.join(labels) + else: + label_str = '' + # remove duplicates and sort + label_list = sorted(list(set(label_str.split()))) + return label_list + + +def write_xlabel(message, old_label_list, new_label_list, outfile): + """ + Update 'X-Label' value of given Message object; + then write Message object to outfile. + """ + # remove duplicates and sort + new_label_list = sorted(list(set(new_label_list))) + if set(old_label_list) != set(new_label_list): + # delete original 'X-Label' header (all occurences) + del message['X-Label'] + # add new 'X-Label' header + message['X-Label'] = ' '.join(new_label_list) + # write to outfile (Just OVERWRITE, OK??) + fp_out = open(outfile, 'w') + fp_out.write(message.as_string()) + fp_out.close() + + +def main(): + if len(sys.argv) != 2 and len(sys.argv) != 3: + print("Usage: %s [ outmail ]" % sys.argv[0]) + sys.exit(1) + + inmail = sys.argv[1] + if len(sys.argv) == 3: + outmail = sys.argv[2] + else: + outmail = inmail + + if hasattr(readline, 'read_history_file'): + try: + readline.read_history_file(HISTFILE) + except IOError: + pass + + # get all recorded labels for readline autocompletion + all_labels = load_labels(LABELFILE) + completer = MyCompleter(all_labels) + + # open mail and create email.message.Message object + msg = email.message_from_file(open(inmail, 'r')) + # get original labels + label_list = get_xlabel(msg) + # get user provided labels + new_label = my_input(prompt='X-Label: ', default=' '.join(label_list), + completer=completer.complete) + # write new labels to mail + write_xlabel(msg, label_list, new_label.split(), outmail) + # save readline history + readline.write_history_file(HISTFILE) + # save labels + update_labels(LABELFILE, all_labels, new_label.split()) + + +if "__main__" == __name__: + main() + diff --git a/.mutt/mutt_bgrun.sh b/.mutt/mutt_bgrun.sh index 08d5e6b..0b2c651 100755 --- a/.mutt/mutt_bgrun.sh +++ b/.mutt/mutt_bgrun.sh @@ -88,7 +88,7 @@ do shift done -file=$1 +file="$1" # Create a temporary directory for our copy of the temporary file. # @@ -99,6 +99,8 @@ tmpdir=/tmp/$LOGNAME$$ umask 077 mkdir "$tmpdir" || exit 1 tmpfile="$tmpdir/${file##*/}" +#echo "file: ${file}" > ~/debug.$$.log +#echo "tmpfile: ${tmpfile}" >> ~/debug.$$.log # Copy mutt's temporary file to our temporary directory so that we can # let mutt overwrite and delete it when we exit. diff --git a/.mutt/muttrc b/.mutt/muttrc index 6c640b7..cf30a88 100644 --- a/.mutt/muttrc +++ b/.mutt/muttrc @@ -88,9 +88,9 @@ unset mime_forward # forward attachments as part of body ### Headers ignore * -unignore from: to: cc: bcc: date: subject: +unignore from: to: cc: bcc: date: subject: X-Label: unhdr_order * -hdr_order from: to: cc: date: subject: +hdr_order from: to: cc: date: subject: X-Label: ### Encoding set send_charset = "us-ascii:utf-8" @@ -101,7 +101,7 @@ set rfc2047_parameters # to fix attachment filename encoding ### Index view # first bang ("!") to expand month week names in the C locale set date_format = "!%a %m/%d %I:%M" -set index_format = "[%Z] %d %3M %-15.15L (%4c) %s" +set index_format = "[%Z] %d %2M %-15.15L %4c%?X?[%X]& ? %s" set folder_format = "%2C %t %N %8s %f" set sort = threads set sort_aux = reverse-last-date-received @@ -166,7 +166,7 @@ macro index B "~b " \ macro index I "!" \ "go to Inbox" # Save a decoded copy in ~/ -macro index > "cat > ~/" \ +macro index,pager > "cat > ~/" \ "save message as" # Open in vim macro index,pager V "vim -c 'setlocal ft=mail buftype=nofile' -" \ @@ -188,6 +188,11 @@ macro pager ';' "" \ # notmuch macro index s "unset wait_key~/.mutt/mutt-notmuch.py -G $folder/search+search" \ "search mail (using notmuch)" +# labels +macro index,pager x 'set my_oldeditor=$editorset editor="~/.mutt/mutt-xlabel.py"Nset editor=$my_oldeditor' \ + "edit X-Label" +macro index \Cx "~y " \ + "limit view to label" ### aliases set sort_alias = alias # sort alias file by alias @@ -216,7 +221,7 @@ macro index,pager P "tmux new-window -a -t mutt 'mutt -F ~ "recall postponed message in new tmux window" # Set the editor for for editing messages in-place, # allows re-editing before sending, e.g. for use in forwarding messages. -macro compose E 'set my_oldeditor=$editorset editor="vim"set editor=$my_oldeditor' \ +macro compose E 'set my_oldeditor=$editorset editor="vim"set editor=$my_oldeditor' \ "edit message in-place" # open mailbox listing in a new window macro index,pager Y 'tmux new-window -a -t mutt "mutt -y"' \ @@ -232,8 +237,8 @@ source ~/.mutt/colors source ~/.mutt/gpg.rc ## auto view -auto_view text/html application/x-gunzip application/x-bzip \ - application/x-tar-gz application/x-compressed-tar +auto_view text/html application/x-tar-gz application/x-compressed-tar \ + application/x-bzip-compressed-tar ## MIME types that should *not* be treated according to their mailcap entry mime_lookup application/octet-stream application/X-Lotus-Manuscript -- cgit v1.2.2