unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH v2 0/5] emacs: Part command improvements
@ 2013-05-30  1:13 Austin Clements
  2013-05-30  1:13 ` [PATCH v2 1/5] emacs: Retain text properties when toggling buttons Austin Clements
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

This is v2 of id:87zjvghx82.fsf@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 the part property list retrieved from the CLI.  Signals
 an error if there is no part containing point."

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 1/5] emacs: Retain text properties when toggling buttons
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
@ 2013-05-30  1:13 ` Austin Clements
  2013-05-30  1:13 ` [PATCH v2 2/5] emacs: Record part p-list in a text property Austin Clements
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/5] emacs: Record part p-list in a text property
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
  2013-05-30  1:13 ` [PATCH v2 1/5] emacs: Retain text properties when toggling buttons Austin Clements
@ 2013-05-30  1:13 ` Austin Clements
  2013-05-30  1:13 ` [PATCH v2 3/5] emacs: Simplify MIME part command implementation Austin Clements
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/5] emacs: Simplify MIME part command implementation
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
  2013-05-30  1:13 ` [PATCH v2 1/5] emacs: Retain text properties when toggling buttons Austin Clements
  2013-05-30  1:13 ` [PATCH v2 2/5] emacs: Record part p-list in a text property Austin Clements
@ 2013-05-30  1:13 ` Austin Clements
  2013-05-30  1:13 ` [PATCH v2 4/5] emacs: Bind MIME part commands to "." submap Austin Clements
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

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 &rest 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))
-	 ,@body))))
-
-(defun notmuch-show-save-part (message-id nth &optional 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 &optional 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 &optional 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 &optional 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 (&optional button)
   (interactive)
@@ -570,6 +520,8 @@ message at DEPTH in the current thread."
 	  (delete-region (point) old-end))
 	(goto-char (min old-point (1- (button-end button))))))))
 
+;; MIME part renderers
+
 (defun notmuch-show-multipart/*-to-list (part)
   (mapcar (lambda (inner-part) (plist-get inner-part :content-type))
 	  (plist-get part :content)))
@@ -2023,40 +1975,71 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')."
   (notmuch-show-stash-mlarchive-link mla)
   (browse-url (current-kill 0 t)))
 
-;; Commands typically bound to buttons.
+;; Interactive part functions and their helpers
+
+(defun notmuch-show-generate-part-buffer (message-id nth)
+  "Return a temporary buffer containing the specified part's content."
+  (let ((buf (generate-new-buffer " *notmuch-part*"))
+	(process-crypto notmuch-show-process-crypto))
+    (with-current-buffer buf
+      (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)))
+    buf))
+
+(defun notmuch-show-current-part-handle ()
+  "Return an mm-handle for the part containing point.
+
+This creates a temporary buffer for the part's content; the
+caller is responsible for killing this buffer as appropriate."
+  (let* ((part (notmuch-show-get-part-properties))
+	 (message-id (notmuch-show-get-message-id))
+	 (nth (plist-get part :id))
+	 (buf (notmuch-show-generate-part-buffer message-id nth))
+	 (content-type (plist-get part :content-type))
+	 (filename (plist-get part :filename))
+	 (disposition (if filename `(attachment (filename . ,filename)))))
+    (mm-make-handle buf (list content-type) nil nil disposition)))
+
+(defun notmuch-show-apply-to-current-part-handle (fn)
+  "Apply FN to an mm-handle for the part containing point.
+
+This ensures that the temporary buffer created for the mm-handle
+is destroyed when FN returns."
+  (let ((handle (notmuch-show-current-part-handle)))
+    (unwind-protect
+	(funcall fn handle)
+      (kill-buffer (mm-handle-buffer handle)))))
 
 (defun notmuch-show-part-button-default (&optional button)
   (interactive)
   (let ((button (or button (button-at (point)))))
     (if (button-get button 'overlay)
 	(notmuch-show-toggle-part-invisibility button)
-      (notmuch-show-part-button-internal button notmuch-show-part-button-default-action))))
+      (call-interactively notmuch-show-part-button-default-action))))
 
-(defun notmuch-show-part-button-save (&optional button)
+(defun notmuch-show-save-part ()
+  "Save the MIME part containing point to a file."
   (interactive)
-  (notmuch-show-part-button-internal button #'notmuch-show-save-part))
+  (notmuch-show-apply-to-current-part-handle #'mm-save-part))
 
-(defun notmuch-show-part-button-view (&optional button)
+(defun notmuch-show-view-part ()
+  "View the MIME part containing point in an external viewer."
   (interactive)
-  (notmuch-show-part-button-internal button #'notmuch-show-view-part))
+  ;; Set mm-inlined-types to nil to force an external viewer
+  (let ((mm-inlined-types nil))
+    (notmuch-show-apply-to-current-part-handle #'mm-display-part)))
 
-(defun notmuch-show-part-button-interactively-view (&optional button)
+(defun notmuch-show-interactively-view-part ()
+  "View the MIME part containing point, prompting for a viewer."
   (interactive)
-  (notmuch-show-part-button-internal button #'notmuch-show-interactively-view-part))
+  (notmuch-show-apply-to-current-part-handle #'mm-interactively-view-part))
 
-(defun notmuch-show-part-button-pipe (&optional button)
+(defun notmuch-show-pipe-part ()
+  "Pipe the MIME part containing point to an external command."
   (interactive)
-  (notmuch-show-part-button-internal button #'notmuch-show-pipe-part))
+  (notmuch-show-apply-to-current-part-handle #'mm-pipe-part))
 
-(defun notmuch-show-part-button-internal (button handler)
-  (let ((button (or button (button-at (point)))))
-    (if button
-	(let ((nth (button-get button :notmuch-part)))
-	  (if nth
-	      (funcall handler (notmuch-show-get-message-id) nth
-		       (button-get button :notmuch-filename)
-		       (button-get button :notmuch-content-type)))))))
-
-;;
 
 (provide 'notmuch-show)
diff --git a/test/emacs b/test/emacs
index f033bdf..3b26d32 100755
--- a/test/emacs
+++ b/test/emacs
@@ -525,7 +525,9 @@ test_expect_equal_file attachment1.gz "$EXPECTED/attachment"
 test_begin_subtest "Save attachment from within emacs using notmuch-show-save-part"
 # save as archive to test that Emacs does not re-compress .gz
 test_emacs '(let ((standard-input "\"attachment2.gz\""))
-	      (notmuch-show-save-part "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com" 5))'
+	      (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
+	      (search-forward "0001-Deal-with")
+	      (notmuch-show-save-part))'
 test_expect_equal_file attachment2.gz "$EXPECTED/attachment"
 
 test_begin_subtest "Save 8bit attachment from within emacs using notmuch-show-save-attachments"
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/5] emacs: Bind MIME part commands to "." submap
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
                   ` (2 preceding siblings ...)
  2013-05-30  1:13 ` [PATCH v2 3/5] emacs: Simplify MIME part command implementation Austin Clements
@ 2013-05-30  1:13 ` Austin Clements
  2013-05-30  1:13 ` [PATCH v2 5/5] News for Emacs part handling changes Austin Clements
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/5] News for Emacs part handling changes
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
                   ` (3 preceding siblings ...)
  2013-05-30  1:13 ` [PATCH v2 4/5] emacs: Bind MIME part commands to "." submap Austin Clements
@ 2013-05-30  1:13 ` Austin Clements
  2013-05-30 14:33 ` [PATCH v2 0/5] emacs: Part command improvements Mark Walters
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Austin Clements @ 2013-05-30  1:13 UTC (permalink / raw)
  To: notmuch

---
 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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/5] emacs: Part command improvements
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
                   ` (4 preceding siblings ...)
  2013-05-30  1:13 ` [PATCH v2 5/5] News for Emacs part handling changes Austin Clements
@ 2013-05-30 14:33 ` Mark Walters
  2013-05-31  0:26 ` Jameson Graef Rollins
  2013-06-01  1:05 ` David Bremner
  7 siblings, 0 replies; 9+ messages in thread
From: Mark Walters @ 2013-05-30 14:33 UTC (permalink / raw)
  To: Austin Clements, notmuch


This looks excellent. +1 from me.

Best wishes

Mark


Austin Clements <amdragon@MIT.EDU> writes:

> This is v2 of id:87zjvghx82.fsf@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 the part property list retrieved from the CLI.  Signals
>  an error if there is no part containing point."

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/5] emacs: Part command improvements
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
                   ` (5 preceding siblings ...)
  2013-05-30 14:33 ` [PATCH v2 0/5] emacs: Part command improvements Mark Walters
@ 2013-05-31  0:26 ` Jameson Graef Rollins
  2013-06-01  1:05 ` David Bremner
  7 siblings, 0 replies; 9+ messages in thread
From: Jameson Graef Rollins @ 2013-05-31  0:26 UTC (permalink / raw)
  To: Austin Clements, notmuch

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

On Wed, May 29 2013, Austin Clements <amdragon@MIT.EDU> wrote:
> This is v2 of id:87zjvghx82.fsf@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.

LGTM.  +1.

jamie.

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/5] emacs: Part command improvements
  2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
                   ` (6 preceding siblings ...)
  2013-05-31  0:26 ` Jameson Graef Rollins
@ 2013-06-01  1:05 ` David Bremner
  7 siblings, 0 replies; 9+ messages in thread
From: David Bremner @ 2013-06-01  1:05 UTC (permalink / raw)
  To: Austin Clements, notmuch

Austin Clements <amdragon@MIT.EDU> writes:

> This is v2 of id:87zjvghx82.fsf@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.
>

pushed,

d

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-06-01  1:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-30  1:13 [PATCH v2 0/5] emacs: Part command improvements Austin Clements
2013-05-30  1:13 ` [PATCH v2 1/5] emacs: Retain text properties when toggling buttons Austin Clements
2013-05-30  1:13 ` [PATCH v2 2/5] emacs: Record part p-list in a text property Austin Clements
2013-05-30  1:13 ` [PATCH v2 3/5] emacs: Simplify MIME part command implementation Austin Clements
2013-05-30  1:13 ` [PATCH v2 4/5] emacs: Bind MIME part commands to "." submap Austin Clements
2013-05-30  1:13 ` [PATCH v2 5/5] News for Emacs part handling changes Austin Clements
2013-05-30 14:33 ` [PATCH v2 0/5] emacs: Part command improvements Mark Walters
2013-05-31  0:26 ` Jameson Graef Rollins
2013-06-01  1:05 ` David Bremner

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).