[notmuch] [PATCH] Rework saving of attachments.

2009-12-14 Thread cama...@picnicpark.org
From: Keith Amidon 

With this commit notmuch-show-mode supports saving a single attachment
from a message (bound to 'w') and saving all attachments to the
message (bound to 'W').  The new variable notmuch-default-save-dir
allows the user to specify a directory within which attachments should
be saved by default.  The user can modify this default path, even
specifying a non-existent directory path, in which case he or she will
be prompted to create the path.  Reporting of the actions taken is
also improved.
---
 notmuch.el |   93 ++-
 1 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 97914f2..b72548d 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -64,7 +64,8 @@
 (define-key map "f" 'notmuch-show-forward-current)
 (define-key map "r" 'notmuch-show-reply)
 (define-key map "|" 'notmuch-show-pipe-message)
-(define-key map "w" 'notmuch-show-save-attachments)
+(define-key map "w" 'notmuch-show-save-attachment)
+(define-key map "W" 'notmuch-show-save-all-attachments)
 (define-key map "V" 'notmuch-show-view-raw-message)
 (define-key map "v" 'notmuch-show-view-all-mime-parts)
 (define-key map "-" 'notmuch-show-remove-tag)
@@ -98,6 +99,9 @@ pattern can still test against the entire line).")
 (defvar notmuch-command "notmuch"
   "Command to run the notmuch binary.")

+(defvar notmuch-default-save-dir (file-name-as-directory (getenv "HOME" ))
+  "Default directory in which attachments are saved.")
+
 (defvar notmuch-show-message-begin-regexp"\fmessage{")
 (defvar notmuch-show-message-end-regexp  "\fmessage}")
 (defvar notmuch-show-header-begin-regexp "\fheader{")
@@ -329,28 +333,75 @@ buffer."
  mm-handle)
 count))

-(defun notmuch-save-attachments (mm-handle  queryp)
-  (notmuch-foreach-mime-part
-   (lambda (p)
- (let ((disposition (mm-handle-disposition p)))
-   (and (listp disposition)
-(or (equal (car disposition) "attachment")
-(and (equal (car disposition) "inline")
- (assq 'filename disposition)))
-(or (not queryp)
-(y-or-n-p
- (concat "Save '" (cdr (assq 'filename disposition)) "' ")))
-(mm-save-part p
-   mm-handle))
-
-(defun notmuch-show-save-attachments ()
-  "Save all attachments from the current message."
-  (interactive)
+(defun notmuch-attachment-q (mm-handle)
+  (let ((disposition (mm-handle-disposition p)))
+(and (listp disposition)
+ (assq 'filename disposition
+
+(defun notmuch-get-save-path (filename default-dir)
+  (let ((savepath nil))
+(while (not savepath)
+  (let* ((ddir (file-name-as-directory default-dir))
+ (fn (read-file-name "Save to: " ddir nil nil filename))
+ (efn (expand-file-name fn))
+ (dir (file-name-directory efn)))
+(when (not (file-accessible-directory-p dir))
+  (when (y-or-n-p (concat "Create directory " dir " "))
+(make-directory dir t)))
+(if (file-accessible-directory-p dir)
+(setq savepath fn)
+  (setq default-dir (file-name-directory fn)
+savepath))
+
+(defun notmuch-save-attachment (mm-handle default-dir)
+  "Save the current attachment part to a file."
+  (cond ((not (notmuch-attachment-q mm-handle))
+ (message "Current part is not an attachment.")
+ nil)
+(t
+ (let* ((fn (cdr (assq 'filename (mm-handle-disposition mm-handle
+(savepath (notmuch-get-save-path fn default-dir)))
+   (mm-save-part-to-file mm-handle savepath)
+   savepath
+
+(defun notmuch-save-attachment-num (mm-handle part-num)
+  "Save the nth part number"
+  (let ((nfound 0)
+(nsaved 0))
+(notmuch-foreach-mime-part
+ (lambda (p)
+   (when (notmuch-attachment-q p)
+ (cond ((equal (+ 1 nfound) part-num)
+(when (notmuch-save-attachment p notmuch-default-save-dir)
+  (incf nsaved
+ (incf nfound))) mm-handle)
+(equal nsaved 1)))
+
+(defun notmuch-show-save-attachment (num)
+  "Save a single attachment."
+  (interactive "p")
   (with-current-notmuch-show-message
(let ((mm-handle (mm-dissect-buffer)))
- (notmuch-save-attachments
-  mm-handle (> (notmuch-count-attachments mm-handle) 1
-  (message "Done"))
+ (if (notmuch-save-attachment-num mm-handle num)
+ (message "Attachment %d saved." num)
+   (message "Failed to save attachment.")
+
+(defun notmuch-show-save-all-attachments ()
+  "Save all attachments of a message to a directory."
+  (interactive)
+  (with-current-notmuch-show-message
+   (let ((nfound 0)
+ (nsaved 0)
+ (default-dir notmuch-default-save-dir)
+ (mm-handle (mm-dissect-buffer)))
+ (notmuch-foreach-mime-part
+  (lambda (p)
+(when (notmuch-attachment-q p)
+  

[notmuch] Rework of attachment saving

2009-12-14 Thread cama...@picnicpark.org
I think I've reworked the attachment savings to behave as we've been
discussing.  I don't know anything about the button handling so I
haven't attempted to implement the direct manipulation approach of of
saving using the buttons.  That would certainly be nice to have
however and I belive this change should make it easy for someone who
knows how buttons work to implement it.

 --- Keith



[notmuch] [PATCH 9/9] Key binding rearrangement for save attachments in show mode

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

The most obvious bindings for save attachments are already taken.  The
existing 'w' binding was bound to view the raw message.  This commit
moves it to 'V' which still seems somewhat mnemonic and uses 'w' for
save (write) attachments.
---
 notmuch.el |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 0c6b527..f0e8d65 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -76,7 +76,8 @@
 (define-key map "r" 'notmuch-show-reply)
 (define-key map "s" 'notmuch-search)
 (define-key map "v" 'notmuch-show-view-all-mime-parts)
-(define-key map "w" 'notmuch-show-view-raw-message)
+(define-key map "V" 'notmuch-show-view-raw-message)
+(define-key map "w" 'notmuch-show-save-attachments)
 (define-key map "x" 'kill-this-buffer)
 (define-key map "+" 'notmuch-show-add-tag)
 (define-key map "-" 'notmuch-show-remove-tag)
-- 
1.6.5.3



[notmuch] [PATCH 8/9] Provide ability to save attachments

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

Previously the only way to save an attachment was to attempt to view
it and then save it from within the viewer program.
---
 notmuch.el |   41 +
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index eaa5798..0c6b527 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -303,6 +303,47 @@ buffer."
   (with-current-notmuch-show-message
(mm-display-parts (mm-dissect-buffer

+(defun notmuch-foreach-mime-part (function mm-handle)
+  (cond ((stringp (car mm-handle))
+ (dolist (part (cdr mm-handle))
+   (notmuch-foreach-mime-part function part)))
+((bufferp (car mm-handle))
+ (funcall function mm-handle))
+(t (dolist (part mm-handle)
+ (notmuch-foreach-mime-part function part)
+
+(defun notmuch-count-attachments (mm-handle)
+  (let ((count 0))
+(notmuch-foreach-mime-part
+ (lambda (p)
+   (let ((disposition (mm-handle-disposition p)))
+ (and (listp disposition)
+  (equal (car disposition) "attachment")
+  (incf count
+ mm-handle)
+count))
+
+(defun notmuch-save-attachments (mm-handle  queryp)
+  (notmuch-foreach-mime-part
+   (lambda (p)
+ (let ((disposition (mm-handle-disposition p)))
+   (and (listp disposition)
+(equal (car disposition) "attachment")
+(or (not queryp)
+(y-or-n-p
+ (concat "Save '" (cdr (assq 'filename disposition)) "' ")))
+(mm-save-part p
+   mm-handle))
+
+(defun notmuch-show-save-attachments ()
+  "Save the attachments to a message"
+  (interactive)
+  (with-current-notmuch-show-message
+   (let ((mm-handle (mm-dissect-buffer)))
+ (notmuch-save-attachments
+  mm-handle (> (notmuch-count-attachments mm-handle) 1
+  (message "Done"))
+
 (defun notmuch-reply (query-string)
   (switch-to-buffer (generate-new-buffer "notmuch-draft"))
   (call-process notmuch-command nil t nil "reply" query-string)
-- 
1.6.5.3



[notmuch] [PATCH 7/9] Key bindings for message library based replies

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

---
 notmuch.el |3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index fe20b54..eaa5798 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -64,6 +64,9 @@
 (define-key map "A" 'notmuch-show-mark-read-then-archive-thread)
 (define-key map "f" 'notmuch-show-forward-current)
 (define-key map "m" 'message-mail)
+(define-key map "MA" 'notmuch-show-wide-reply-current)
+(define-key map "MR" 'notmuch-show-reply-current)
+(define-key map "MF" 'notmuch-show-followup-current)
 (define-key map "n" 'notmuch-show-next-message)
 (define-key map "N" 'notmuch-show-mark-read-then-next-open-message)
 (define-key map "p" 'notmuch-show-previous-message)
-- 
1.6.5.3



[notmuch] [PATCH 6/9] Reply to individual messages using message library

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

As an alternative to creating a reply from the current thread, this
commit provides functions to create replies directly in emacs using
the message library.

A future commit will provide keybindings so that they are easy to
change if a different set is preferred.
---
 notmuch.el |   15 +++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index d3d75f9..fe20b54 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -323,6 +323,21 @@ buffer."
   (with-current-notmuch-show-message
(message-forward)))

+(defun notmuch-show-reply-current ()
+  (interactive)
+  (with-current-notmuch-show-message
+   (message-reply)))
+
+(defun notmuch-show-wide-reply-current ()
+  (interactive)
+  (with-current-notmuch-show-message
+   (message-wide-reply)))
+
+(defun notmuch-show-followup-current ()
+  (interactive)
+  (with-current-notmuch-show-message
+   (message-followup)))
+
 (defun notmuch-show-pipe-message (command)
   "Pipe the contents of the current message to the given command.

-- 
1.6.5.3



[notmuch] [PATCH 4/9] Factor out message buffer mgmt from notmuch-show-view-all-mime-parts

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

The ability to temporarily create a buffer containing only the
contents of the currently selected message in notmuch show mode is
generally useful.  This commit factors the majority of the code
required to do so out of notmuch-show-view-all-mime-parts into a macro
called with-current-notmuch-show-message and rewrites the original
function in terms of the macro.

A future set of commits will provide additional functionality using
the macro as well.
---
 notmuch.el |   20 
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index cd6609d..a71a9f7 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -283,17 +283,21 @@ buffer."
   (interactive)
   (view-file (notmuch-show-get-filename)))

+(defmacro with-current-notmuch-show-message ( body)
+  "Evaluate body with current buffer set to the text of current message"
+  `(save-excursion
+ (let ((filename (notmuch-show-get-filename)))
+   (let ((buf (generate-new-buffer (concat "*notmuch-msg-" filename "*"
+ (with-current-buffer buf
+   (insert-file-contents filename nil nil nil t)
+   , at body)
+(kill-buffer buf)
+
 (defun notmuch-show-view-all-mime-parts ()
   "Use external viewers (according to mailcap) to view all MIME-encoded parts."
   (interactive)
-  (save-excursion
-(let ((filename (notmuch-show-get-filename)))
-  (switch-to-buffer (generate-new-buffer (concat "*notmuch-mime-"
-filename
-"*")))
-  (insert-file-contents filename nil nil nil t)
-  (mm-display-parts (mm-dissect-buffer))
-  (kill-this-buffer
+  (with-current-notmuch-show-message
+   (mm-display-parts (mm-dissect-buffer

 (defun notmuch-reply (query-string)
   (switch-to-buffer (generate-new-buffer "notmuch-draft"))
-- 
1.6.5.3



[notmuch] [PATCH 3/9] Add key binding for notmuch-search in show-mode

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

It's not uncommon to want to start a search as a result of something
read in a message so this is convenient.
---
 notmuch.el |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 6400199..cd6609d 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -70,6 +70,7 @@
 (define-key map (kbd "C-p") 'notmuch-show-previous-line)
 (define-key map "q" 'kill-this-buffer)
 (define-key map "r" 'notmuch-show-reply)
+(define-key map "s" 'notmuch-search)
 (define-key map "v" 'notmuch-show-view-all-mime-parts)
 (define-key map "w" 'notmuch-show-view-raw-message)
 (define-key map "x" 'kill-this-buffer)
-- 
1.6.5.3



[notmuch] [PATCH 2/9] Adjust autoload comments

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

The previous location of autoload comments didn't seem to correspond
with the functions most likely to be the entry points for using
notmuch.  This change adjusts them to match those likely entry points.
---
 notmuch.el |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index a1efa4f..6400199 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -707,8 +707,6 @@ view, (remove the \"inbox\" tag from each), with
mode-name "notmuch-show")
   (setq buffer-read-only t))

-;;;###autoload
-
 (defgroup notmuch nil
   "Notmuch mail reader for Emacs."
   :group 'mail)
@@ -1002,6 +1000,7 @@ This function advances point to the next line when 
finished."
  (set 'more nil))
   (delete-process proc

+;;;###autoload
 (defun notmuch-search (query  oldest-first)
   "Run \"notmuch search\" with the given query string and display results."
   (interactive "sNotmuch search: ")
@@ -1081,6 +1080,8 @@ current search results AND that are tagged with the given 
tag."
(list (notmuch-select-tag-with-completion "Filter by tag: ")))
   (notmuch-search (concat notmuch-search-query-string " and tag:" tag) 
notmuch-search-oldest-first))

+
+;;;###autoload
 (defun notmuch ()
   "Run notmuch to display all mail with tag of 'inbox'"
   (interactive)
@@ -1156,6 +1157,7 @@ results for the search terms in that line.
 (if search
(notmuch-search (cdr search) notmuch-search-oldest-first

+;;;###autoload
 (defun notmuch-folder ()
   "Show the notmuch folder view and update the displayed counts."
   (interactive)
-- 
1.6.5.3



[notmuch] [PATCH 1/9] Explicitly require the message library

2009-11-27 Thread cama...@picnicpark.org
From: Keith Amidon 

Functions provided by the message library were being used without
ensuring it was loaded.
---
 notmuch.el |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index d7c973c..a1efa4f 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -49,6 +49,7 @@

 (require 'cl)
 (require 'mm-view)
+(require 'message)

 (defvar notmuch-show-mode-map
   (let ((map (make-sparse-keymap)))
-- 
1.6.5.3



[notmuch] Show mode enhancements

2009-11-27 Thread cama...@picnicpark.org
I started using notmuch a few days ago and was astounded at how much
more efficiently I could process email with it. For my usage I needed
a bit more flexibility in replying/forwarding messages and the ability
to conveniently save attachments.  The set of patches that follow
contain these two enhancements, a few minor fixes, and the addition of
a binding of 's' in show mode to notmuch-search.

I'd be happy to address anything neded to get these changes into shape
to be included in the main distribution.  Thanks for all your work
putting together such a promising email client.

   --- Keith