Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 9946D431FD4 for ; Fri, 24 Oct 2014 09:38:59 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[RCVD_IN_DNSWL_NONE=-0.0001] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BROqyCc1DxPj for ; Fri, 24 Oct 2014 09:38:54 -0700 (PDT) Received: from cmta3.telus.net (cmta3.telus.net [209.171.16.76]) by olra.theworths.org (Postfix) with ESMTP id E956E431FBD for ; Fri, 24 Oct 2014 09:38:53 -0700 (PDT) Received: from ovo.mains.priv ([207.102.88.62]) by cmta3.telus.net with TELUS id 74es1p00k1LiWEf014etix; Fri, 24 Oct 2014 10:38:53 -0600 X-Authority-Analysis: v=2.0 cv=GePJa3rL c=1 sm=2 a=EcQDfIwDZEqJA1f7rVUV8Q==:17 a=tsa3CZZnAAAA:8 a=_rKzicO8r5wJqIb2hKcA:9 a=FXHsT42GvahHVR3Y:21 a=jLL51SobAh7xBaDs:21 a=EcQDfIwDZEqJA1f7rVUV8Q==:117 X-Telus-Outbound-IP: 207.102.88.62 From: Ian Main To: notmuch@notmuchmail.org Subject: [PATCH v4 1/2] VIM: Add better attachment support Date: Fri, 24 Oct 2014 09:38:39 -0700 Message-Id: <1414168720-1574-1-git-send-email-imain@stemwinder.org> X-Mailer: git-send-email 1.9.3 X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Oct 2014 16:38:59 -0000 Change how the notmuch vim client supports attachments: - For each message part a 'Part : ' is added to the header. - You can then use 'e' to extract the attachment under the cursor or use it elsewhere to extract all attachments (the prior behavior) - You can use 'v' to 'view' the attachment/part using xdg-open by default. - If the message is 'text/html' we include a 'Part:' for the body of the message so you can easily view it in a web browser if you so choose. Ian --- - Fixed commit message - Fixed documentation vim/notmuch.txt | 8 +++++- vim/notmuch.vim | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/vim/notmuch.txt b/vim/notmuch.txt index 4374102..d5e1ad2 100644 --- a/vim/notmuch.txt +++ b/vim/notmuch.txt @@ -72,6 +72,9 @@ q Quit view A Archive (-inbox -unread) I Mark as read (-unread) t Tag (prompted) +e Extract attachment on the current 'Part' line or all + attachments if the cursor is elsewhere. + View attachment on the current 'Part' line. s Search p Save patches r Reply @@ -148,6 +151,9 @@ You can also configure your externail mail reader and sendemail program: > let g:notmuch_reader = 'mutt -f %s' let g:notmuch_sendmail = 'sendmail' -< + +You can also configure what probram is used to view attachments: + + let g:notmuch_view_attachment = 'xdg-open' vim:tw=78:ts=8:noet:ft=help: diff --git a/vim/notmuch.vim b/vim/notmuch.vim index cad9517..1466e50 100644 --- a/vim/notmuch.vim +++ b/vim/notmuch.vim @@ -35,6 +35,7 @@ let g:notmuch_show_maps = { \ 't': 'show_tag("")', \ 'o': 'show_open_msg()', \ 'e': 'show_extract_msg()', + \ '': 'show_view_attachment()', \ 's': 'show_save_msg()', \ 'p': 'show_save_patches()', \ 'r': 'show_reply()', @@ -58,6 +59,8 @@ let s:notmuch_date_format_default = '%d.%m.%y' let s:notmuch_datetime_format_default = '%d.%m.%y %H:%M:%S' let s:notmuch_reader_default = 'mutt -f %s' let s:notmuch_sendmail_default = 'sendmail' +let s:notmuch_view_attachment_default = 'xdg-open' +let s:notmuch_attachment_tmpdir_default = '~/.notmuch/tmp' let s:notmuch_folders_count_threads_default = 0 let s:notmuch_compose_start_insert_default = 1 @@ -152,13 +155,72 @@ function! s:show_info() ruby vim_puts get_message.inspect endfunction +function! s:show_view_attachment() + let line = getline(".") +ruby << EOF + m = get_message + line = VIM::evaluate('line') + + match = line.match(/^Part (\d*):/) + if match and match.length == 2 + # Set up the tmpdir + tmpdir = VIM::evaluate('g:notmuch_attachment_tmpdir') + tmpdir = File.expand_path(tmpdir) + Dir.mkdir(tmpdir) unless Dir.exists?(tmpdir) + + p = m.mail.parts[match[1].to_i - 1] + if p == nil + # Not a multipart message, use the message itself. + p = m.mail + end + if p.filename and p.filename.length > 0 + filename = p.filename + else + suffix = '' + if p.mime_type == 'text/html' + suffix = '.html' + end + filename = "part-#{match[1]}#{suffix}" + end + + # Sanitize just in case.. + filename.gsub!(/[^0-9A-Za-z.\-]/, '_') + + fullpath = File.expand_path("#{tmpdir}/#{filename}") + vim_puts "Viewing attachment #{fullpath}" + File.open(fullpath, 'w') do |f| + f.write p.body.decoded + cmd = VIM::evaluate('g:notmuch_view_attachment') + system(cmd, fullpath) + end + else + vim_puts "No attachment on this line." + end +EOF +endfunction + function! s:show_extract_msg() + let line = getline(".") ruby << EOF m = get_message - m.mail.attachments.each do |a| + line = VIM::evaluate('line') + + # If the user is on a line that has an 'Part' + # line, we just extract the one attachment. + match = line.match(/^Part (\d*):/) + if match and match.length == 2 + a = m.mail.parts[match[1].to_i - 1] File.open(a.filename, 'w') do |f| f.write a.body.decoded - print "Extracted '#{a.filename}'" + vim_puts "Extracted #{a.filename}" + end + else + # Extract them all.. + m.mail.attachments.each do |a| + File.open(a.filename, 'w') do |f| + f.write a.body.decoded + vim_puts "Extracted #{a.filename}" + end end end EOF @@ -331,6 +393,16 @@ ruby << EOF b << "To: %s" % msg['to'] b << "Cc: %s" % msg['cc'] b << "Date: %s" % msg['date'] + cnt = 0 + m.parts.each do |p| + cnt += 1 + b << "Part %d: %s (%s)" % [cnt, p.mime_type, p.filename] + end + # Add a special case for text/html messages. Here we show the + # only 'part' so that we can view it in a web browser if we want. + if m.parts.length == 0 and part.mime_type == 'text/html' + b << "Part 1: text/html" + end nm_m.body_start = b.count b << "--- %s ---" % part.mime_type part.convert.each_line do |l| @@ -425,6 +497,14 @@ function! s:set_defaults() endif endif + if !exists('g:notmuch_attachment_tmpdir') + let g:notmuch_attachment_tmpdir = s:notmuch_attachment_tmpdir_default + endif + + if !exists('g:notmuch_view_attachment') + let g:notmuch_view_attachment = s:notmuch_view_attachment_default + endif + if !exists('g:notmuch_folders_count_threads') if exists('g:notmuch_rb_count_threads') let g:notmuch_count_threads = g:notmuch_rb_count_threads -- 1.9.3