[PATCH] VIM: Add better attachment support

Subject: [PATCH] VIM: Add better attachment support

Date: Thu, 2 Oct 2014 00:48:52 -0700

To: notmuch@notmuchmail.org

Cc:

From: Ian Main


This patch changes how the notmuch vim client supports attachments:

- For each attachment an 'Attachment <number>: <filename>' 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 using xdg-open by default.

    Ian
---
 vim/notmuch.txt |  8 +++++++-
 vim/notmuch.vim | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 65 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..a5830b5 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()',
+	\ 'v':		'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,53 @@ 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(/^Attachment (\d*):/)
+	if match and match.length == 2
+		a = m.mail.attachments[match[1].to_i - 1]
+		tmpdir = VIM::evaluate('g:notmuch_attachment_tmpdir')
+		tmpdir = File.expand_path(tmpdir)
+		Dir.mkdir(tmpdir) unless Dir.exists?(tmpdir)
+		filename = File.expand_path("#{tmpdir}/#{a.filename}")
+		vim_puts "Viewing attachment #{filename}"
+		File.open(filename, 'w') do |f|
+			f.write a.body.decoded
+			cmd = VIM::evaluate('g:notmuch_view_attachment')
+			system(cmd, filename)
+		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 'Attachment'
+	# line, we just extract the one attachment.
+	match = line.match(/^Attachment (\d*):/)
+	if match and match.length == 2
+		a = m.mail.attachments[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 +369,11 @@ ruby << EOF
 			b << "To: %s" % msg['to']
 			b << "Cc: %s" % msg['cc']
 			b << "Date: %s" % msg['date']
+			cnt = 0
+			nm_m.mail.attachments.each do |a|
+				cnt += 1
+				b << "Attachment %d: %s" % [cnt, a.filename]
+			end
 			nm_m.body_start = b.count
 			b << "--- %s ---" % part.mime_type
 			part.convert.each_line do |l|
@@ -420,6 +468,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


Thread: