From 8160c2140c0019d1b11b83656b0f7f72b086b6f4 Mon Sep 17 00:00:00 2001 From: Ian Main Date: Fri, 24 Oct 2014 15:04:51 +1700 Subject: [PATCH] [PATCH] VIM: Add better attachment support --- 33/aeaed4d077b08ed3288eba06b10c649d874390 | 220 ++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 33/aeaed4d077b08ed3288eba06b10c649d874390 diff --git a/33/aeaed4d077b08ed3288eba06b10c649d874390 b/33/aeaed4d077b08ed3288eba06b10c649d874390 new file mode 100644 index 000000000..69e2ed4ae --- /dev/null +++ b/33/aeaed4d077b08ed3288eba06b10c649d874390 @@ -0,0 +1,220 @@ +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 17E6F431FD4 + for ; Thu, 23 Oct 2014 15:05:03 -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 SNFLBCwqqi1B for ; + Thu, 23 Oct 2014 15:04:59 -0700 (PDT) +Received: from cmta18.telus.net (cmta18.telus.net [209.171.16.91]) + by olra.theworths.org (Postfix) with ESMTP id 8E0D3431FBD + for ; Thu, 23 Oct 2014 15:04:59 -0700 (PDT) +Received: from ovo.mains.priv ([207.102.88.62]) by cmta18.telus.net with TELUS + id 6m4x1p00M1LiWEf01m4xok; Thu, 23 Oct 2014 16:04:58 -0600 +X-Authority-Analysis: v=2.0 cv=B+NnJpRM c=1 sm=2 + a=EcQDfIwDZEqJA1f7rVUV8Q==:17 a=tsa3CZZnAAAA:8 a=_rKzicO8r5wJqIb2hKcA:9 + a=yj7JwsOxHXLfrXF9:21 a=oO6dRLWuanIZ9Wjs:21 + a=EcQDfIwDZEqJA1f7rVUV8Q==:117 +X-Telus-Outbound-IP: 207.102.88.62 +From: Ian Main +To: notmuch@notmuchmail.org +Subject: [PATCH] VIM: Add better attachment support +Date: Thu, 23 Oct 2014 15:04:51 -0700 +Message-Id: <1414101891-10714-1-git-send-email-imain@stemwinder.org> +X-Mailer: git-send-email 1.9.3 +In-Reply-To: <1412236132-9624-1-git-send-email-imain@stemwinder.org> +References: <1412236132-9624-1-git-send-email-imain@stemwinder.org> +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: Thu, 23 Oct 2014 22:05:03 -0000 + +This patch changes 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 +--- + 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..838a904 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 'Attachment' line or all ++ attachments if the cursor is elsewhere. ++v View attachment on the current 'Attachment' 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 331e930..5f73dce 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 + + function! s:new_file_buffer(type, fname) +@@ -147,13 +150,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 +@@ -326,6 +388,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| +@@ -420,6 +492,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 + -- 2.26.2