[PATCH v2 5/5] News for Emacs part handling changes

2013-05-29 Thread Austin Clements
---
 NEWS |   16 
 1 file changed, 16 insertions(+)

diff --git a/NEWS b/NEWS
index a7f2ec6..23f4c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision.
 Emacs Interface
 ---

+New keymap to view/save parts
+
+  To view or save a single MIME part of a message, use the new "."
+  submap (e.g., ". s" to save, ". v" to view).  Previously, these keys
+  were only available when point was on a part button and they did not
+  have the "." prefix, so they were difficult to invoke (impossible if
+  a part did not have a button) and clashed with other bindings.
+  These new bindings also appear in show's help, so you don't have to
+  memorize them.
+
+Default part save directory is now `mm-default-directory`
+
+  Previously, notmuch offered to save parts and attachments to a mix
+  of `mm-default-directory`, `mailcap-download-directory`, and `~/`.
+  This has been standardized on `mm-default-directory`.
+
 No Emacs 22 support

   The Emacs 22 support added late 2010 was sufficient only for a short
-- 
1.7.10.4



[PATCH v2 4/5] emacs: Bind MIME part commands to "." submap

2013-05-29 Thread Austin Clements
Since the part commands are no longer tied to a button, but can be
applied with point anywhere within a part, bind the part commands
keymap to "." everywhere in the show buffer.  This lets you save or
view parts without having to navigate to the part button, and is
particularly useful for parts that have no button.

This removes the un-prefixed MIME part commands from the part button
keymap, but that's okay because those clashed in annoying ways with
show buffer bindings like "s" for search.  RET on part buttons is
unaffected, which is the most important part button binding.
---
 emacs/notmuch-show.el |   23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 0d9a34c..613e666 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -466,22 +466,10 @@ message at DEPTH in the current thread."

 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
-  'keymap 'notmuch-show-part-button-map
   'follow-link t
   'face 'message-mml
   :supertype 'notmuch-button-type)

-(defvar notmuch-show-part-button-map
-  (let ((map (make-sparse-keymap)))
-(set-keymap-parent map button-map)
-(define-key map "s" 'notmuch-show-save-part)
-(define-key map "v" 'notmuch-show-view-part)
-(define-key map "o" 'notmuch-show-interactively-view-part)
-(define-key map "|" 'notmuch-show-pipe-part)
-map)
-  "Submap for button commands")
-(fset 'notmuch-show-part-button-map notmuch-show-part-button-map)
-
 (defun notmuch-show-insert-part-header (nth content-type declared-type 
 name comment)
   (let ((button)
(base-label (concat (when name (concat name ": "))
@@ -1202,6 +1190,16 @@ reset based on the original query."
   "Submap for stash commands")
 (fset 'notmuch-show-stash-map notmuch-show-stash-map)

+(defvar notmuch-show-part-map
+  (let ((map (make-sparse-keymap)))
+(define-key map "s" 'notmuch-show-save-part)
+(define-key map "v" 'notmuch-show-view-part)
+(define-key map "o" 'notmuch-show-interactively-view-part)
+(define-key map "|" 'notmuch-show-pipe-part)
+map)
+  "Submap for part commands")
+(fset 'notmuch-show-part-map notmuch-show-part-map)
+
 (defvar notmuch-show-mode-map
   (let ((map (make-sparse-keymap)))
(define-key map "?" 'notmuch-help)
@@ -1244,6 +1242,7 @@ reset based on the original query."
(define-key map "$" 'notmuch-show-toggle-process-crypto)
(define-key map "<" 'notmuch-show-toggle-thread-indentation)
(define-key map "t" 'toggle-truncate-lines)
+   (define-key map "." 'notmuch-show-part-map)
map)
   "Keymap for \"notmuch show\" buffers.")
 (fset 'notmuch-show-mode-map notmuch-show-mode-map)
-- 
1.7.10.4



[PATCH v2 3/5] emacs: Simplify MIME part command implementation

2013-05-29 Thread Austin Clements
This unifies the part button actions and the underlying part action
functions into single interactive command that simply applies to the
part containing point using the just-added part p-list text property
instead of button properties.  Since all part actions can be performed
by applying the appropriate mm function to an mm-handle, this patch
abstracts out the creation of mm handles, making the implementations
of the part commands trivial.  This also eliminates our special
handling for part save in favor of using the appropriate mm function.

This necessarily modifies the way we handle the default part button
action, but in a way that does not change the meaning of the
notmuch-show-part-button-default-action defcustom.

Since these commands are no longer specific to buttons, this patch
eliminates the extra metadata stored with each button.  This also
eliminates one rather special-purpose macro for a collection of
general purpose part handling utilities.
---
 emacs/notmuch-show.el |  133 +
 test/emacs|4 +-
 2 files changed, 61 insertions(+), 76 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index e84e1ba..0d9a34c 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -474,10 +474,10 @@ message at DEPTH in the current thread."
 (defvar notmuch-show-part-button-map
   (let ((map (make-sparse-keymap)))
 (set-keymap-parent map button-map)
-(define-key map "s" 'notmuch-show-part-button-save)
-(define-key map "v" 'notmuch-show-part-button-view)
-(define-key map "o" 'notmuch-show-part-button-interactively-view)
-(define-key map "|" 'notmuch-show-part-button-pipe)
+(define-key map "s" 'notmuch-show-save-part)
+(define-key map "v" 'notmuch-show-view-part)
+(define-key map "o" 'notmuch-show-interactively-view-part)
+(define-key map "|" 'notmuch-show-pipe-part)
 map)
   "Submap for button commands")
 (fset 'notmuch-show-part-button-map notmuch-show-part-button-map)
@@ -494,61 +494,11 @@ message at DEPTH in the current thread."
  (insert-button
   (concat "[ " base-label " ]")
   :base-label base-label
-  :type 'notmuch-show-part-button-type
-  :notmuch-part nth
-  :notmuch-filename name
-  :notmuch-content-type content-type))
+  :type 'notmuch-show-part-button-type))
 (insert "\n")
 ;; return button
 button))

-;; Functions handling particular MIME parts.
-
-(defmacro notmuch-with-temp-part-buffer (message-id nth  body)
-  (declare (indent 2))
-  (let ((process-crypto (make-symbol "process-crypto")))
-`(let ((,process-crypto notmuch-show-process-crypto))
-   (with-temp-buffer
-(setq notmuch-show-process-crypto ,process-crypto)
-;; Always acquires the part via `notmuch part', even if it is
-;; available in the JSON output.
-(insert (notmuch-get-bodypart-internal ,message-id ,nth 
notmuch-show-process-crypto))
-, at body
-
-(defun notmuch-show-save-part (message-id nth  filename content-type)
-  (notmuch-with-temp-part-buffer message-id nth
-(let ((file (read-file-name
-"Filename to save as: "
-(or mailcap-download-directory "~/")
-nil nil
-filename)))
-  ;; Don't re-compress .gz & al.  Arguably we should make
-  ;; `file-name-handler-alist' nil, but that would chop
-  ;; ange-ftp, which is reasonable to use here.
-  (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion 
t
-
-(defun notmuch-show-view-part (message-id nth  filename content-type )
-  (notmuch-with-temp-part-buffer message-id nth
-(let* ((disposition (if filename `(attachment (filename . ,filename
-  (handle (mm-make-handle (current-buffer) (list content-type)
-  nil nil disposition))
-  ;; Set the default save directory to be consistent with
-  ;; `notmuch-show-save-part'.
-  (mm-default-directory (or mailcap-download-directory "~/"))
-  ;; set mm-inlined-types to nil to force an external viewer
-  (mm-inlined-types nil))
-  (mm-display-part handle
-
-(defun notmuch-show-interactively-view-part (message-id nth  filename 
content-type)
-  (notmuch-with-temp-part-buffer message-id nth
-(let ((handle (mm-make-handle (current-buffer) (list content-type
-  (mm-interactively-view-part handle
-
-(defun notmuch-show-pipe-part (message-id nth  filename content-type)
-  (notmuch-with-temp-part-buffer message-id nth
-(let ((handle (mm-make-handle (current-buffer) (list content-type
-  (mm-pipe-part handle
-
 ;; This is taken from notmuch-wash: maybe it should be unified?
 (defun notmuch-show-toggle-part-invisibility ( button)
   (interactive)
@@ -570,6 +520,8 @@ message at DEPTH in the current thread."
  (delete-region (point) old-end))
(goto-char (min 

[PATCH v2 2/5] emacs: Record part p-list in a text property

2013-05-29 Thread Austin Clements
This is similar to what we already do with the message p-list, though
we apply the part's text property to the whole part's text, in
contrast with the message p-list, which is (rather obscurely) only
applied to the first character.
---
 emacs/notmuch-lib.el  |   12 
 emacs/notmuch-show.el |   20 +++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 790136e..2186783 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -360,6 +360,18 @@ OBJECT."
below
string))

+(defun notmuch-map-text-property (start end prop func  object)
+  "Transform text property PROP using FUNC.
+
+Applies FUNC to each distinct value of the text property PROP
+between START and END of OBJECT, setting PROP to the value
+returned by FUNC."
+  (while (< start end)
+(let ((value (get-text-property start prop object))
+ (next (next-single-property-change start prop object end)))
+  (put-text-property start next prop (funcall func value) object)
+  (setq start next
+
 (defun notmuch-logged-error (msg  extra)
   "Log MSG and EXTRA to *Notmuch errors* and signal MSG.

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index a080134..e84e1ba 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -900,7 +900,17 @@ If HIDE is non-nil then initially hide this part."
 ;; Ensure that the part ends with a carriage return.
 (unless (bolp)
   (insert "\n"))
-(notmuch-show-create-part-overlays msg beg (point) hide)))
+(notmuch-show-create-part-overlays msg beg (point) hide)
+;; Record part information.  Since we already inserted subparts,
+;; don't override existing :notmuch-part properties.
+(notmuch-map-text-property beg (point) :notmuch-part
+  (lambda (v) (or v part)))
+;; Make :notmuch-part front sticky and rear non-sticky so it stays
+;; applied to the beginning of each line when we indent the message.
+(notmuch-map-text-property beg (point) 'front-sticky
+  (lambda (v) (pushnew :notmuch-part v)))
+(notmuch-map-text-property beg (point) 'rear-nonsticky
+  (lambda (v) (pushnew :notmuch-part v)

 (defun notmuch-show-insert-body (msg body depth)
   "Insert the body BODY at depth DEPTH in the current thread."
@@ -1404,6 +1414,14 @@ Some useful entries are:
 (notmuch-show-move-to-message-top)
 (get-text-property (point) :notmuch-message-properties)))

+(defun notmuch-show-get-part-properties ()
+  "Return the properties of the innermost part containing point.
+
+This is the part property list retrieved from the CLI.  Signals
+an error if there is no part containing point."
+  (or (get-text-property (point) :notmuch-part)
+  (error "No message part here")))
+
 (defun notmuch-show-set-prop (prop val  props)
   (let ((inhibit-read-only t)
(props (or props
-- 
1.7.10.4



[PATCH v2 1/5] emacs: Retain text properties when toggling buttons

2013-05-29 Thread Austin Clements
Previously, we lost any text properties applied to part buttons or
wash buttons when they were toggled because `insert' directly copies
the text properties of the string being inserted.  Fix this by
capturing the properties applied to the button beforehand and
re-applying them after inserting the new text.
---
 emacs/notmuch-show.el |2 ++
 emacs/notmuch-wash.el |2 ++
 2 files changed, 4 insertions(+)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index b0a8d8a..a080134 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -559,10 +559,12 @@ message at DEPTH in the current thread."
 (new-start (button-start button))
 (button-label (button-get button :base-label))
 (old-point (point))
+(properties (text-properties-at (point)))
 (inhibit-read-only t))
(overlay-put overlay 'invisible (not show))
(goto-char new-start)
(insert "[ " button-label (if show " ]" " (hidden) ]"))
+   (set-text-properties new-start (point) properties)
(let ((old-end (button-end button)))
  (move-overlay button new-start (point))
  (delete-region (point) old-end))
diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 8a68819..8fe91e1 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -104,9 +104,11 @@ lower).")
 (overlay (button-get cite-button 'overlay))
 (button-label (notmuch-wash-button-label overlay))
 (old-point (point))
+(properties (text-properties-at (point)))
 (inhibit-read-only t))
 (goto-char new-start)
 (insert button-label)
+(set-text-properties new-start (point) properties)
 (let ((old-end (button-end cite-button)))
   (move-overlay cite-button new-start (point))
   (delete-region (point) old-end))
-- 
1.7.10.4



[PATCH v2 0/5] emacs: Part command improvements

2013-05-29 Thread Austin Clements
This is v2 of id:87zjvghx82.fsf at qmul.ac.uk.  In addition to some
general improvements, this fixes the handling of part overlays in
indented messages, removes the special part button map entirely in
favor of the "." submap, and adds a NEWS patch.

The diff from v1 follows

diff --git a/NEWS b/NEWS
index a7f2ec6..23f4c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision.
 Emacs Interface
 ---

+New keymap to view/save parts
+
+  To view or save a single MIME part of a message, use the new "."
+  submap (e.g., ". s" to save, ". v" to view).  Previously, these keys
+  were only available when point was on a part button and they did not
+  have the "." prefix, so they were difficult to invoke (impossible if
+  a part did not have a button) and clashed with other bindings.
+  These new bindings also appear in show's help, so you don't have to
+  memorize them.
+
+Default part save directory is now `mm-default-directory`
+
+  Previously, notmuch offered to save parts and attachments to a mix
+  of `mm-default-directory`, `mailcap-download-directory`, and `~/`.
+  This has been standardized on `mm-default-directory`.
+
 No Emacs 22 support

   The Emacs 22 support added late 2010 was sufficient only for a short
diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 09ce25e..2186783 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -360,21 +360,17 @@ OBJECT."
below
string))

-(defun notmuch-put-text-property-if-nil (start end property value
-   object)
-  "Like `put-text-property', but only set the property where it is nil."
+(defun notmuch-map-text-property (start end prop func  object)
+  "Transform text property PROP using FUNC.
+
+Applies FUNC to each distinct value of the text property PROP
+between START and END of OBJECT, setting PROP to the value
+returned by FUNC."
   (while (< start end)
-(let ((start-nil (text-property-any start end property nil object)))
-  (if (null start-nil)
- ;; There are no more nil regions; exit the loop
- (setq start end)
-   ;; Find the end of the nil region
-   (let ((end-nil
-  (or (text-property-not-all start-nil end property nil object)
-  end)))
- ;; Set the property
- (put-text-property start-nil end-nil property value object)
- (setq start end-nil))
+(let ((value (get-text-property start prop object))
+ (next (next-single-property-change start prop object end)))
+  (put-text-property start next prop (funcall func value) object)
+  (setq start next

 (defun notmuch-logged-error (msg  extra)
   "Log MSG and EXTRA to *Notmuch errors* and signal MSG.
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 380b144..613e666 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -466,7 +466,6 @@ message at DEPTH in the current thread."

 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
-  'keymap 'notmuch-show-part-button-map
   'follow-link t
   'face 'message-mml
   :supertype 'notmuch-button-type)
@@ -843,8 +842,15 @@ If HIDE is non-nil then initially hide this part."
   (insert "\n"))
 (notmuch-show-create-part-overlays msg beg (point) hide)
 ;; Record part information.  Since we already inserted subparts,
-;; don't override exiting :notmuch-part properties.
-(notmuch-put-text-property-if-nil beg (point) :notmuch-part part)))
+;; don't override existing :notmuch-part properties.
+(notmuch-map-text-property beg (point) :notmuch-part
+  (lambda (v) (or v part)))
+;; Make :notmuch-part front sticky and rear non-sticky so it stays
+;; applied to the beginning of each line when we indent the message.
+(notmuch-map-text-property beg (point) 'front-sticky
+  (lambda (v) (pushnew :notmuch-part v)))
+(notmuch-map-text-property beg (point) 'rear-nonsticky
+  (lambda (v) (pushnew :notmuch-part v)

 (defun notmuch-show-insert-body (msg body depth)
   "Insert the body BODY at depth DEPTH in the current thread."
@@ -1194,11 +1200,6 @@ reset based on the original query."
   "Submap for part commands")
 (fset 'notmuch-show-part-map notmuch-show-part-map)

-(defvar notmuch-show-part-button-map
-  (make-composed-keymap notmuch-show-part-map button-map)
-  "Keymap for part button commands")
-(fset 'notmuch-show-part-button-map notmuch-show-part-button-map)
-
 (defvar notmuch-show-mode-map
   (let ((map (make-sparse-keymap)))
(define-key map "?" 'notmuch-help)
@@ -1365,7 +1366,7 @@ Some useful entries are:
 (get-text-property (point) :notmuch-message-properties)))

 (defun notmuch-show-get-part-properties ()
-  "Return the properties of the part containing point.
+  "Return the properties of the innermost part containing point.

 This is 

[PATCH 0/4] emacs: Part command improvements

2013-05-29 Thread Austin Clements
Quoth Mark Walters on May 27 at 11:30 pm:
> Austin Clements  writes:
> 
> > This is a follow-up of sorts to id:"8761ycc19t.fsf at qmul.ac.uk", where
> > Mark suggested that the part handling commands could all use the
> > correponding mm-* functions.  I ran with the idea and wound up with
> > this series, which, in addition to standardizing on the mm-* functions
> > for everything and simplifying the implementation overall, decouples
> > the part commands from part buttons, which removes an entire layer
> > from the implementation and adds the ability to invoke part commands
> > with point anywhere in a part (something I often find myself wanting).
> 
> Overall I really like this series. In addition to the clean up etc it
> makes it easy to export the text/plain part (which doesn't have a part
> button). I have recollection of this being difficult if it is base64
> encoded.

Right.  That's one of the reasons I wanted a global part keymap (and
this series happened to be a convenient place to introduce that).
Also helpful is that the part bindings now appear in the show help,
which is good because I can never remember which key used the default
viewer and which prompted for a viewer.

> I have a few small comments
> 
> As mentioned on irc (just included here in case other people are
> testing) make-composed-keymap is emacs 24 only.

I've removed the button map entirely, so this is no longer a problem.

> This does change the default directory for saving: not serious but it's
> probably worth deciding do we want to use mailcap-download-directory or
> home or where emacs was started or?

I don't really care what the default directory is, as long as we're
consistent, which we currently aren't.  mm-default-directory seems
like a fine thing to be consistent with, since we use mm for
everything else.

> I don't know if we want to keep a special keymap for the button or just
> always use the . prefix; the advantage is that you don't have 's' on a
> button acting differently from 's' in the text (which has annoyed me
> several times) otoh it is the extra keystroke which may annoy people
> too. Let the bikeshedding begin! (obviously return for the default
> action would remain.

I'm all for removing the special button keymap.  The less hidden
functionality the better.

> Would it be worth having . return in the part body  as the default
> action ?

I played with this for a while and eventually decided it wasn't worth
the effort.  Maybe in a followup.

> Finally, with message indenting it's the start/end of the part are a
> little unclear. I think it's the [ of the part button at the start of
> the part to the character before the [ of the next part button. In
> particular on the line of a new part but before the button is still the
> old part. Since parts are whole lines it would be nice if the region
> were line based but I don't know if that is easy.

Fixed in v2.

> Best wishes
> 
> Mark


v3 of --stderr=FILE patches

2013-05-29 Thread David Bremner
Tomi Ollila  writes:

> This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi
>

pushed, with one spelling correction in a commit message.

d


v3 of --stderr=FILE patches

2013-05-29 Thread Mark Walters

Just confirming LGTM +1 for this version too.

Best wishes

Mark

Tomi Ollila  writes:

> This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi
>
> In id:m2a9nfr4tb.fsf at guru.guru-group.fi I suggested to use 0600 as
> permission bits so that files written to /tmp would not have write
> bits set in any case. That would have been inconsistent what is
> normally expected in redirection cases. The problem I described
> is easily avoided in emacs as (make-temp-file "nmerr") will create
> file "/tmp/nmerrXX" with permissions 0600 -- and writing to
> that already-created file will not change its permissions. Writing
> elsewhere is usually covered with directory permissions.
>
>
> Diffdiff from v2 is shown below.
>
> diff --git a/NEWS b/NEWS
> index 990b038..80abd97 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -38,8 +38,7 @@ Top level option to specify configuration file
>  Top level option to redirect writes to stderr
>  
>With `notmuch --stderr=FILE` all writes to stderr are redirected to
> -  the specified file. If the file name is a plain '-', stderr is
> -  written to stdout.
> +  the specified file. If FILE is '-', stderr is redirected to stdout.
>  
>  Deprecated commands "part" and "search-tags" are removed.
>  
> diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
> index fbd575a..f5ca0ad 100644
> --- a/man/man1/notmuch.1
> +++ b/man/man1/notmuch.1
> @@ -83,7 +83,7 @@ configuration file specified by ${NOTMUCH_CONFIG}.
>  .B \-\-stderr=FILE
>  
>  Redirect all writes to stderr to the specified file.
> -If the file name is a plain '-', stderr is written to stdout.
> +If FILE is '-', stderr is redirected to stdout.
>  .RE
>  
>  .SH COMMANDS
> diff --git a/notmuch.c b/notmuch.c
> index 654a568..15e90c8 100644
> --- a/notmuch.c
> +++ b/notmuch.c
> @@ -260,7 +260,7 @@ redirect_stderr (const char * stderr_file)
>   return 1;
>   }
>  } else {
> - int fd = open (stderr_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
> + int fd = open (stderr_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
>   if (fd < 0) {
>   fprintf (stderr, "Error: Cannot redirect stderr to '%s': %s\n",
>stderr_file, strerror (errno));
>
>
> From Tomi Ollila  # This line is ignored.
>
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


v3 of --stderr=FILE patches

2013-05-29 Thread Austin Clements
LGTM.

Quoth Tomi Ollila on May 28 at  9:38 pm:
> This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi
> 
> In id:m2a9nfr4tb.fsf at guru.guru-group.fi I suggested to use 0600 as
> permission bits so that files written to /tmp would not have write
> bits set in any case. That would have been inconsistent what is
> normally expected in redirection cases. The problem I described
> is easily avoided in emacs as (make-temp-file "nmerr") will create
> file "/tmp/nmerrXX" with permissions 0600 -- and writing to
> that already-created file will not change its permissions. Writing
> elsewhere is usually covered with directory permissions.


[PATCH v5 03/12] cli: add insert command

2013-05-29 Thread Peter Wang
On Sun, 28 Apr 2013 00:24:28 +0300, Jani Nikula  wrote:
> On Wed, 03 Apr 2013, Peter Wang  wrote:
> > The notmuch insert command reads a message from standard input,
> > writes it to a Maildir folder, and then incorporates the message into
> > the notmuch database.  Essentially it moves the functionality of
> > notmuch-deliver into notmuch.
> >
> > Though it could be used as an alternative to notmuch new, the reason
> > I want this is to allow my notmuch frontend to add postponed or sent
> > messages to the mail store and notmuch database, without resorting to
> > another tool (e.g. notmuch-deliver) nor directly modifying the maildir.
> > ---
> >  Makefile.local   |   1 +
> >  notmuch-client.h |   3 +
> >  notmuch-insert.c | 336 
> > +++
> >  notmuch.c|   3 +
> >  4 files changed, 343 insertions(+)
> >  create mode 100644 notmuch-insert.c
> >
...
> > +/* Add the specified message file to the notmuch database, applying tags.
> > + * The file is renamed to encode notmuch tags as maildir flags. */
> > +static notmuch_bool_t
> > +add_file_to_database (notmuch_database_t *notmuch, const char *path,
> > + tag_op_list_t *tag_ops)
> > +{
> > +notmuch_message_t *message;
> > +notmuch_status_t status;
> > +
> > +status = notmuch_database_add_message (notmuch, path, );
> > +switch (status) {
> > +case NOTMUCH_STATUS_SUCCESS:
> > +case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
> > +   break;
> > +default:
> > +case NOTMUCH_STATUS_FILE_NOT_EMAIL:
> 
> If such a message really arrives, the mail system will keep trying if
> failure is returned. Maybe deliver the file without indexing, and return
> success?
> 

Rethinking it, if notmuch insert is going to used as a general mail
delivery tool (not my own use case) then its primary job should be to
get the file to disk.  As long as that is done, we should return success.

Indexing the message would be considered a bonus, and failure there
or in syncing tags to flags should not cause the file to be deleted and
an error code returned.  (A warning can be written to standard error.)

> > +case NOTMUCH_STATUS_READ_ONLY_DATABASE:
> > +case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
> > +case NOTMUCH_STATUS_OUT_OF_MEMORY:
> > +case NOTMUCH_STATUS_FILE_ERROR:
> > +case NOTMUCH_STATUS_NULL_POINTER:
> > +case NOTMUCH_STATUS_TAG_TOO_LONG:
> > +case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
> > +case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
> > +case NOTMUCH_STATUS_LAST_STATUS:
> > +   fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n",
> > +path, notmuch_status_to_string (status));
> > +   return FALSE;
> > +}
> > +
> > +if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {
> > +   /* Don't change tags of an existing message. */
> > +   status = notmuch_message_tags_to_maildir_flags (message);
> > +   if (status != NOTMUCH_STATUS_SUCCESS)
> > +   fprintf (stderr, "Error: failed to sync tags to maildir flags\n");
> > +} else {
> > +   status = tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC);
> 
> Syncing tags to maildir flags is more interesting here than above. And
> it should be done because notmuch insert allows arbitrary tags on the
> command line. Having, for example, -unread or +flagged on the command
> line makes the flags go out of sync. (notmuch new should do the syncing
> too, but it's less important because it only adds new.tags.)
> 
> However, calling notmuch_message_tags_to_maildir_flags() may rename the
> file from new to cur, which blows up the directory syncing and file
> unlinking on the error path in insert_message() below.

We would sidestep these problems.

> > +static notmuch_bool_t
> > +insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
> > +   const char *dir, tag_op_list_t *tag_ops)
> > +{
> > +char *tmppath;
> > +char *newpath;
> > +char *newdir;
> > +int fdout;
> > +char *cleanup_path;
> > +
> > +fdout = maildir_open_tmp_file (ctx, dir, , , );
> > +if (fdout < 0)
> > +   return FALSE;
> > +
> > +cleanup_path = tmppath;
> > +
> > +if (! copy_stdin (fdin, fdout))
> > +   goto FAIL;
> > +
> > +if (fsync (fdout) != 0) {
> > +   fprintf (stderr, "Error: fsync failed: %s\n", strerror (errno));
> > +   goto FAIL;
> > +}
> > +
> > +close (fdout);
> > +fdout = -1;
> > +
> > +/* Atomically move the new message file from the Maildir 'tmp' 
> > directory
> > + * to the 'new' directory.  We follow the Dovecot recommendation to
> > + * simply use rename() instead of link() and unlink().
> > + * See also: 
> > http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery
> > + */
> > +if (rename (tmppath, newpath) != 0) {
> > +   fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno));
> > +   goto FAIL;
> > +}
> > +
> > +cleanup_path = newpath;
> > +
> > +if (! 

Re: v3 of --stderr=FILE patches

2013-05-29 Thread Mark Walters

Just confirming LGTM +1 for this version too.

Best wishes

Mark

Tomi Ollila tomi.oll...@iki.fi writes:

 This is v3 of id:1369557954-13439-1-git-send-email-tomi.oll...@iki.fi

 In id:m2a9nfr4tb@guru.guru-group.fi I suggested to use 0600 as
 permission bits so that files written to /tmp would not have write
 bits set in any case. That would have been inconsistent what is
 normally expected in redirection cases. The problem I described
 is easily avoided in emacs as (make-temp-file nmerr) will create
 file /tmp/nmerrXX with permissions 0600 -- and writing to
 that already-created file will not change its permissions. Writing
 elsewhere is usually covered with directory permissions.


 Diffdiff from v2 is shown below.

 diff --git a/NEWS b/NEWS
 index 990b038..80abd97 100644
 --- a/NEWS
 +++ b/NEWS
 @@ -38,8 +38,7 @@ Top level option to specify configuration file
  Top level option to redirect writes to stderr
  
With `notmuch --stderr=FILE` all writes to stderr are redirected to
 -  the specified file. If the file name is a plain '-', stderr is
 -  written to stdout.
 +  the specified file. If FILE is '-', stderr is redirected to stdout.
  
  Deprecated commands part and search-tags are removed.
  
 diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
 index fbd575a..f5ca0ad 100644
 --- a/man/man1/notmuch.1
 +++ b/man/man1/notmuch.1
 @@ -83,7 +83,7 @@ configuration file specified by ${NOTMUCH_CONFIG}.
  .B \-\-stderr=FILE
  
  Redirect all writes to stderr to the specified file.
 -If the file name is a plain '-', stderr is written to stdout.
 +If FILE is '-', stderr is redirected to stdout.
  .RE
  
  .SH COMMANDS
 diff --git a/notmuch.c b/notmuch.c
 index 654a568..15e90c8 100644
 --- a/notmuch.c
 +++ b/notmuch.c
 @@ -260,7 +260,7 @@ redirect_stderr (const char * stderr_file)
   return 1;
   }
  } else {
 - int fd = open (stderr_file, O_WRONLY|O_CREAT|O_APPEND, 0644);
 + int fd = open (stderr_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
   if (fd  0) {
   fprintf (stderr, Error: Cannot redirect stderr to '%s': %s\n,
stderr_file, strerror (errno));


 From Tomi Ollila tomi.oll...@iki.fi # This line is ignored.

 ___
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: v3 of --stderr=FILE patches

2013-05-29 Thread Austin Clements
LGTM.

Quoth Tomi Ollila on May 28 at  9:38 pm:
 This is v3 of id:1369557954-13439-1-git-send-email-tomi.oll...@iki.fi
 
 In id:m2a9nfr4tb@guru.guru-group.fi I suggested to use 0600 as
 permission bits so that files written to /tmp would not have write
 bits set in any case. That would have been inconsistent what is
 normally expected in redirection cases. The problem I described
 is easily avoided in emacs as (make-temp-file nmerr) will create
 file /tmp/nmerrXX with permissions 0600 -- and writing to
 that already-created file will not change its permissions. Writing
 elsewhere is usually covered with directory permissions.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/4] emacs: Part command improvements

2013-05-29 Thread Austin Clements
Quoth Mark Walters on May 27 at 11:30 pm:
 Austin Clements amdra...@mit.edu writes:
 
  This is a follow-up of sorts to id:8761ycc19t@qmul.ac.uk, where
  Mark suggested that the part handling commands could all use the
  correponding mm-* functions.  I ran with the idea and wound up with
  this series, which, in addition to standardizing on the mm-* functions
  for everything and simplifying the implementation overall, decouples
  the part commands from part buttons, which removes an entire layer
  from the implementation and adds the ability to invoke part commands
  with point anywhere in a part (something I often find myself wanting).
 
 Overall I really like this series. In addition to the clean up etc it
 makes it easy to export the text/plain part (which doesn't have a part
 button). I have recollection of this being difficult if it is base64
 encoded.

Right.  That's one of the reasons I wanted a global part keymap (and
this series happened to be a convenient place to introduce that).
Also helpful is that the part bindings now appear in the show help,
which is good because I can never remember which key used the default
viewer and which prompted for a viewer.

 I have a few small comments
 
 As mentioned on irc (just included here in case other people are
 testing) make-composed-keymap is emacs 24 only.

I've removed the button map entirely, so this is no longer a problem.

 This does change the default directory for saving: not serious but it's
 probably worth deciding do we want to use mailcap-download-directory or
 home or where emacs was started or?

I don't really care what the default directory is, as long as we're
consistent, which we currently aren't.  mm-default-directory seems
like a fine thing to be consistent with, since we use mm for
everything else.

 I don't know if we want to keep a special keymap for the button or just
 always use the . prefix; the advantage is that you don't have 's' on a
 button acting differently from 's' in the text (which has annoyed me
 several times) otoh it is the extra keystroke which may annoy people
 too. Let the bikeshedding begin! (obviously return for the default
 action would remain.

I'm all for removing the special button keymap.  The less hidden
functionality the better.

 Would it be worth having . return in the part body  as the default
 action ?

I played with this for a while and eventually decided it wasn't worth
the effort.  Maybe in a followup.

 Finally, with message indenting it's the start/end of the part are a
 little unclear. I think it's the [ of the part button at the start of
 the part to the character before the [ of the next part button. In
 particular on the line of a new part but before the button is still the
 old part. Since parts are whole lines it would be nice if the region
 were line based but I don't know if that is easy.

Fixed in v2.

 Best wishes
 
 Mark
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 5/5] News for Emacs part handling changes

2013-05-29 Thread Austin Clements
---
 NEWS |   16 
 1 file changed, 16 insertions(+)

diff --git a/NEWS b/NEWS
index a7f2ec6..23f4c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision.
 Emacs Interface
 ---
 
+New keymap to view/save parts
+
+  To view or save a single MIME part of a message, use the new .
+  submap (e.g., . s to save, . v to view).  Previously, these keys
+  were only available when point was on a part button and they did not
+  have the . prefix, so they were difficult to invoke (impossible if
+  a part did not have a button) and clashed with other bindings.
+  These new bindings also appear in show's help, so you don't have to
+  memorize them.
+
+Default part save directory is now `mm-default-directory`
+
+  Previously, notmuch offered to save parts and attachments to a mix
+  of `mm-default-directory`, `mailcap-download-directory`, and `~/`.
+  This has been standardized on `mm-default-directory`.
+
 No Emacs 22 support
 
   The Emacs 22 support added late 2010 was sufficient only for a short
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 0/5] emacs: Part command improvements

2013-05-29 Thread Austin Clements
This is v2 of id:87zjvghx82@qmul.ac.uk.  In addition to some
general improvements, this fixes the handling of part overlays in
indented messages, removes the special part button map entirely in
favor of the . submap, and adds a NEWS patch.

The diff from v1 follows

diff --git a/NEWS b/NEWS
index a7f2ec6..23f4c6a 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision.
 Emacs Interface
 ---
 
+New keymap to view/save parts
+
+  To view or save a single MIME part of a message, use the new .
+  submap (e.g., . s to save, . v to view).  Previously, these keys
+  were only available when point was on a part button and they did not
+  have the . prefix, so they were difficult to invoke (impossible if
+  a part did not have a button) and clashed with other bindings.
+  These new bindings also appear in show's help, so you don't have to
+  memorize them.
+
+Default part save directory is now `mm-default-directory`
+
+  Previously, notmuch offered to save parts and attachments to a mix
+  of `mm-default-directory`, `mailcap-download-directory`, and `~/`.
+  This has been standardized on `mm-default-directory`.
+
 No Emacs 22 support
 
   The Emacs 22 support added late 2010 was sufficient only for a short
diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 09ce25e..2186783 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -360,21 +360,17 @@ OBJECT.
below
string))
 
-(defun notmuch-put-text-property-if-nil (start end property value
-  optional object)
-  Like `put-text-property', but only set the property where it is nil.
+(defun notmuch-map-text-property (start end prop func optional object)
+  Transform text property PROP using FUNC.
+
+Applies FUNC to each distinct value of the text property PROP
+between START and END of OBJECT, setting PROP to the value
+returned by FUNC.
   (while ( start end)
-(let ((start-nil (text-property-any start end property nil object)))
-  (if (null start-nil)
- ;; There are no more nil regions; exit the loop
- (setq start end)
-   ;; Find the end of the nil region
-   (let ((end-nil
-  (or (text-property-not-all start-nil end property nil object)
-  end)))
- ;; Set the property
- (put-text-property start-nil end-nil property value object)
- (setq start end-nil))
+(let ((value (get-text-property start prop object))
+ (next (next-single-property-change start prop object end)))
+  (put-text-property start next prop (funcall func value) object)
+  (setq start next
 
 (defun notmuch-logged-error (msg optional extra)
   Log MSG and EXTRA to *Notmuch errors* and signal MSG.
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 380b144..613e666 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -466,7 +466,6 @@ message at DEPTH in the current thread.
 
 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
-  'keymap 'notmuch-show-part-button-map
   'follow-link t
   'face 'message-mml
   :supertype 'notmuch-button-type)
@@ -843,8 +842,15 @@ If HIDE is non-nil then initially hide this part.
   (insert \n))
 (notmuch-show-create-part-overlays msg beg (point) hide)
 ;; Record part information.  Since we already inserted subparts,
-;; don't override exiting :notmuch-part properties.
-(notmuch-put-text-property-if-nil beg (point) :notmuch-part part)))
+;; don't override existing :notmuch-part properties.
+(notmuch-map-text-property beg (point) :notmuch-part
+  (lambda (v) (or v part)))
+;; Make :notmuch-part front sticky and rear non-sticky so it stays
+;; applied to the beginning of each line when we indent the message.
+(notmuch-map-text-property beg (point) 'front-sticky
+  (lambda (v) (pushnew :notmuch-part v)))
+(notmuch-map-text-property beg (point) 'rear-nonsticky
+  (lambda (v) (pushnew :notmuch-part v)
 
 (defun notmuch-show-insert-body (msg body depth)
   Insert the body BODY at depth DEPTH in the current thread.
@@ -1194,11 +1200,6 @@ reset based on the original query.
   Submap for part commands)
 (fset 'notmuch-show-part-map notmuch-show-part-map)
 
-(defvar notmuch-show-part-button-map
-  (make-composed-keymap notmuch-show-part-map button-map)
-  Keymap for part button commands)
-(fset 'notmuch-show-part-button-map notmuch-show-part-button-map)
-
 (defvar notmuch-show-mode-map
   (let ((map (make-sparse-keymap)))
(define-key map ? 'notmuch-help)
@@ -1365,7 +1366,7 @@ Some useful entries are:
 (get-text-property (point) :notmuch-message-properties)))
 
 (defun notmuch-show-get-part-properties ()
-  Return the properties of the part containing point.
+  Return the properties of the innermost part containing point.
 
 This is 

[PATCH v2 1/5] emacs: Retain text properties when toggling buttons

2013-05-29 Thread Austin Clements
Previously, we lost any text properties applied to part buttons or
wash buttons when they were toggled because `insert' directly copies
the text properties of the string being inserted.  Fix this by
capturing the properties applied to the button beforehand and
re-applying them after inserting the new text.
---
 emacs/notmuch-show.el |2 ++
 emacs/notmuch-wash.el |2 ++
 2 files changed, 4 insertions(+)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index b0a8d8a..a080134 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -559,10 +559,12 @@ message at DEPTH in the current thread.
 (new-start (button-start button))
 (button-label (button-get button :base-label))
 (old-point (point))
+(properties (text-properties-at (point)))
 (inhibit-read-only t))
(overlay-put overlay 'invisible (not show))
(goto-char new-start)
(insert [  button-label (if show  ]  (hidden) ]))
+   (set-text-properties new-start (point) properties)
(let ((old-end (button-end button)))
  (move-overlay button new-start (point))
  (delete-region (point) old-end))
diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el
index 8a68819..8fe91e1 100644
--- a/emacs/notmuch-wash.el
+++ b/emacs/notmuch-wash.el
@@ -104,9 +104,11 @@ lower).)
 (overlay (button-get cite-button 'overlay))
 (button-label (notmuch-wash-button-label overlay))
 (old-point (point))
+(properties (text-properties-at (point)))
 (inhibit-read-only t))
 (goto-char new-start)
 (insert button-label)
+(set-text-properties new-start (point) properties)
 (let ((old-end (button-end cite-button)))
   (move-overlay cite-button new-start (point))
   (delete-region (point) old-end))
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 2/5] emacs: Record part p-list in a text property

2013-05-29 Thread Austin Clements
This is similar to what we already do with the message p-list, though
we apply the part's text property to the whole part's text, in
contrast with the message p-list, which is (rather obscurely) only
applied to the first character.
---
 emacs/notmuch-lib.el  |   12 
 emacs/notmuch-show.el |   20 +++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 790136e..2186783 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -360,6 +360,18 @@ OBJECT.
below
string))
 
+(defun notmuch-map-text-property (start end prop func optional object)
+  Transform text property PROP using FUNC.
+
+Applies FUNC to each distinct value of the text property PROP
+between START and END of OBJECT, setting PROP to the value
+returned by FUNC.
+  (while ( start end)
+(let ((value (get-text-property start prop object))
+ (next (next-single-property-change start prop object end)))
+  (put-text-property start next prop (funcall func value) object)
+  (setq start next
+
 (defun notmuch-logged-error (msg optional extra)
   Log MSG and EXTRA to *Notmuch errors* and signal MSG.
 
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index a080134..e84e1ba 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -900,7 +900,17 @@ If HIDE is non-nil then initially hide this part.
 ;; Ensure that the part ends with a carriage return.
 (unless (bolp)
   (insert \n))
-(notmuch-show-create-part-overlays msg beg (point) hide)))
+(notmuch-show-create-part-overlays msg beg (point) hide)
+;; Record part information.  Since we already inserted subparts,
+;; don't override existing :notmuch-part properties.
+(notmuch-map-text-property beg (point) :notmuch-part
+  (lambda (v) (or v part)))
+;; Make :notmuch-part front sticky and rear non-sticky so it stays
+;; applied to the beginning of each line when we indent the message.
+(notmuch-map-text-property beg (point) 'front-sticky
+  (lambda (v) (pushnew :notmuch-part v)))
+(notmuch-map-text-property beg (point) 'rear-nonsticky
+  (lambda (v) (pushnew :notmuch-part v)
 
 (defun notmuch-show-insert-body (msg body depth)
   Insert the body BODY at depth DEPTH in the current thread.
@@ -1404,6 +1414,14 @@ Some useful entries are:
 (notmuch-show-move-to-message-top)
 (get-text-property (point) :notmuch-message-properties)))
 
+(defun notmuch-show-get-part-properties ()
+  Return the properties of the innermost part containing point.
+
+This is the part property list retrieved from the CLI.  Signals
+an error if there is no part containing point.
+  (or (get-text-property (point) :notmuch-part)
+  (error No message part here)))
+
 (defun notmuch-show-set-prop (prop val optional props)
   (let ((inhibit-read-only t)
(props (or props
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 4/5] emacs: Bind MIME part commands to . submap

2013-05-29 Thread Austin Clements
Since the part commands are no longer tied to a button, but can be
applied with point anywhere within a part, bind the part commands
keymap to . everywhere in the show buffer.  This lets you save or
view parts without having to navigate to the part button, and is
particularly useful for parts that have no button.

This removes the un-prefixed MIME part commands from the part button
keymap, but that's okay because those clashed in annoying ways with
show buffer bindings like s for search.  RET on part buttons is
unaffected, which is the most important part button binding.
---
 emacs/notmuch-show.el |   23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 0d9a34c..613e666 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -466,22 +466,10 @@ message at DEPTH in the current thread.
 
 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-default
-  'keymap 'notmuch-show-part-button-map
   'follow-link t
   'face 'message-mml
   :supertype 'notmuch-button-type)
 
-(defvar notmuch-show-part-button-map
-  (let ((map (make-sparse-keymap)))
-(set-keymap-parent map button-map)
-(define-key map s 'notmuch-show-save-part)
-(define-key map v 'notmuch-show-view-part)
-(define-key map o 'notmuch-show-interactively-view-part)
-(define-key map | 'notmuch-show-pipe-part)
-map)
-  Submap for button commands)
-(fset 'notmuch-show-part-button-map notmuch-show-part-button-map)
-
 (defun notmuch-show-insert-part-header (nth content-type declared-type 
optional name comment)
   (let ((button)
(base-label (concat (when name (concat name : ))
@@ -1202,6 +1190,16 @@ reset based on the original query.
   Submap for stash commands)
 (fset 'notmuch-show-stash-map notmuch-show-stash-map)
 
+(defvar notmuch-show-part-map
+  (let ((map (make-sparse-keymap)))
+(define-key map s 'notmuch-show-save-part)
+(define-key map v 'notmuch-show-view-part)
+(define-key map o 'notmuch-show-interactively-view-part)
+(define-key map | 'notmuch-show-pipe-part)
+map)
+  Submap for part commands)
+(fset 'notmuch-show-part-map notmuch-show-part-map)
+
 (defvar notmuch-show-mode-map
   (let ((map (make-sparse-keymap)))
(define-key map ? 'notmuch-help)
@@ -1244,6 +1242,7 @@ reset based on the original query.
(define-key map $ 'notmuch-show-toggle-process-crypto)
(define-key map  'notmuch-show-toggle-thread-indentation)
(define-key map t 'toggle-truncate-lines)
+   (define-key map . 'notmuch-show-part-map)
map)
   Keymap for \notmuch show\ buffers.)
 (fset 'notmuch-show-mode-map notmuch-show-mode-map)
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch