]> git.notmuchmail.org Git - notmuch/blobdiff - emacs/notmuch-lib.el
emacs: renamed function notmuch-version to notmuch-cli-version
[notmuch] / emacs / notmuch-lib.el
index d4b668496e51cb48355473c6427facc6170d0cee..e16a1b971bd5e29bb3b78ba9f3a823c0b39acb85 100644 (file)
@@ -192,8 +192,8 @@ Otherwise the output will be returned"
 "Perhaps you haven't run \"notmuch setup\" yet? Try running this
 on the command line, and then retry your notmuch command")))
 
 "Perhaps you haven't run \"notmuch setup\" yet? Try running this
 on the command line, and then retry your notmuch command")))
 
-(defun notmuch-version ()
-  "Return a string with the notmuch version number."
+(defun notmuch-cli-version ()
+  "Return a string with the notmuch cli command version number."
   (let ((long-string
         ;; Trim off the trailing newline.
         (substring (notmuch-command-to-string "--version") 0 -1)))
   (let ((long-string
         ;; Trim off the trailing newline.
         (substring (notmuch-command-to-string "--version") 0 -1)))
@@ -529,25 +529,67 @@ the given type."
    (lambda (part) (notmuch-match-content-type (plist-get part :content-type) type))
    parts))
 
    (lambda (part) (notmuch-match-content-type (plist-get part :content-type) type))
    parts))
 
-(defun notmuch-get-bodypart-binary (msg part process-crypto)
-  "Return the unprocessed content of PART in MSG.
+(defun notmuch-get-bodypart-binary (msg part process-crypto &optional cache)
+  "Return the unprocessed content of PART in MSG as a unibyte string.
 
 This returns the \"raw\" content of the given part after content
 transfer decoding, but with no further processing (see the
 discussion of --format=raw in man notmuch-show).  In particular,
 
 This returns the \"raw\" content of the given part after content
 transfer decoding, but with no further processing (see the
 discussion of --format=raw in man notmuch-show).  In particular,
-this does no charset conversion."
-  (let ((args `("show" "--format=raw"
-               ,(format "--part=%d" (plist-get part :id))
-               ,@(when process-crypto '("--decrypt"))
-               ,(notmuch-id-to-query (plist-get msg :id)))))
-    (with-temp-buffer
-      (let ((coding-system-for-read 'no-conversion))
-       (apply #'call-process notmuch-command nil '(t nil) nil args)
-       (buffer-string)))))
-
-(defun notmuch-get-bodypart-content (msg part process-crypto)
-  (or (plist-get part :content)
-      (notmuch-get-bodypart-binary msg part process-crypto)))
+this does no charset conversion.
+
+If CACHE is non-nil, the content of this part will be saved in
+MSG (if it isn't already)."
+  (let ((data (plist-get part :binary-content)))
+    (when (not data)
+      (let ((args `("show" "--format=raw"
+                   ,(format "--part=%d" (plist-get part :id))
+                   ,@(when process-crypto '("--decrypt"))
+                   ,(notmuch-id-to-query (plist-get msg :id)))))
+       (with-temp-buffer
+         ;; Emacs internally uses a UTF-8-like multibyte string
+         ;; representation by default (regardless of the coding
+         ;; system, which only affects how it goes from outside data
+         ;; to this internal representation).  This *almost* never
+         ;; matters.  Annoyingly, it does matter if we use this data
+         ;; in an image descriptor, since Emacs will use its internal
+         ;; data buffer directly and this multibyte representation
+         ;; corrupts binary image formats.  Since the caller is
+         ;; asking for binary data, a unibyte string is a more
+         ;; appropriate representation anyway.
+         (set-buffer-multibyte nil)
+         (let ((coding-system-for-read 'no-conversion))
+           (apply #'call-process notmuch-command nil '(t nil) nil args)
+           (setq data (buffer-string)))))
+      (when cache
+       ;; Cheat.  part is non-nil, and `plist-put' always modifies
+       ;; the list in place if it's non-nil.
+       (plist-put part :binary-content data)))
+    data))
+
+(defun notmuch-get-bodypart-text (msg part process-crypto &optional cache)
+  "Return the text content of PART in MSG.
+
+This returns the content of the given part as a multibyte Lisp
+string after performing content transfer decoding and any
+necessary charset decoding.  It is an error to use this for
+non-text/* parts.
+
+If CACHE is non-nil, the content of this part will be saved in
+MSG (if it isn't already)."
+  (let ((content (plist-get part :content)))
+    (when (not content)
+      ;; Use show --format=sexp to fetch decoded content
+      (let* ((args `("show" "--format=sexp" "--include-html"
+                    ,(format "--part=%s" (plist-get part :id))
+                    ,@(when process-crypto '("--decrypt"))
+                    ,(notmuch-id-to-query (plist-get msg :id))))
+            (npart (apply #'notmuch-call-notmuch-sexp args)))
+       (setq content (plist-get npart :content))
+       (when (not content)
+         (error "Internal error: No :content from %S" args)))
+      (when cache
+       (plist-put part :content content)))
+    content))
 
 ;; Workaround: The call to `mm-display-part' below triggers a bug in
 ;; Emacs 24 if it attempts to use the shr renderer to display an HTML
 
 ;; Workaround: The call to `mm-display-part' below triggers a bug in
 ;; Emacs 24 if it attempts to use the shr renderer to display an HTML
@@ -568,18 +610,21 @@ this does no charset conversion."
 current buffer, if possible."
   (let ((display-buffer (current-buffer)))
     (with-temp-buffer
 current buffer, if possible."
   (let ((display-buffer (current-buffer)))
     (with-temp-buffer
-      ;; In case there is :content, the content string is already converted
-      ;; into emacs internal format. `gnus-decoded' is a fake charset,
-      ;; which means no further decoding (to be done by mm- functions).
-      (let* ((charset (if (plist-member part :content)
-                         'gnus-decoded
+      ;; In case we already have :content, use it and tell mm-* that
+      ;; it's already been charset-decoded by using the fake
+      ;; `gnus-decoded' charset.  Otherwise, we'll fetch the binary
+      ;; part content and let mm-* decode it.
+      (let* ((have-content (plist-member part :content))
+            (charset (if have-content 'gnus-decoded
                        (plist-get part :content-charset)))
             (handle (mm-make-handle (current-buffer) `(,content-type (charset . ,charset)))))
        ;; If the user wants the part inlined, insert the content and
        ;; test whether we are able to inline it (which includes both
        ;; capability and suitability tests).
        (when (mm-inlined-p handle)
                        (plist-get part :content-charset)))
             (handle (mm-make-handle (current-buffer) `(,content-type (charset . ,charset)))))
        ;; If the user wants the part inlined, insert the content and
        ;; test whether we are able to inline it (which includes both
        ;; capability and suitability tests).
        (when (mm-inlined-p handle)
-         (insert (notmuch-get-bodypart-content msg part process-crypto))
+         (if have-content
+             (insert (notmuch-get-bodypart-text msg part process-crypto))
+           (insert (notmuch-get-bodypart-binary msg part process-crypto)))
          (when (mm-inlinable-p handle)
            (set-buffer display-buffer)
            (mm-display-part handle)
          (when (mm-inlinable-p handle)
            (set-buffer display-buffer)
            (mm-display-part handle)