unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Austin Clements <amdragon@mit.edu>
To: Mark Walters <markwalters1009@gmail.com>
Cc: notmuch@notmuchmail.org
Subject: Re: [PATCH 08/11] emacs: Support caching in notmuch-get-bodypart-{binary, text}
Date: Sat, 24 Jan 2015 13:06:59 -0500	[thread overview]
Message-ID: <87vbjwt5mk.fsf@csail.mit.edu> (raw)
In-Reply-To: <87d2g5uczr.fsf@qmul.ac.uk>

On Fri, 25 Apr 2014, Mark Walters <markwalters1009@gmail.com> wrote:
> On Thu, 24 Apr 2014, Austin Clements <amdragon@MIT.EDU> wrote:
>> Quoth Mark Walters on Apr 24 at 11:46 am:
>>> 
>>> On Mon, 21 Apr 2014, Austin Clements <amdragon@MIT.EDU> wrote:
>>> > (The actual code change here is small, but requires re-indenting
>>> > existing code.)
>>> > ---
>>> >  emacs/notmuch-lib.el | 52 ++++++++++++++++++++++++++++++----------------------
>>> >  1 file changed, 30 insertions(+), 22 deletions(-)
>>> >
>>> > diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
>>> > index fc67b14..fee8512 100644
>>> > --- a/emacs/notmuch-lib.el
>>> > +++ b/emacs/notmuch-lib.el
>>> > @@ -503,33 +503,39 @@ (defun notmuch-parts-filter-by-type (parts type)
>>> >     (lambda (part) (notmuch-match-content-type (plist-get part :content-type) type))
>>> >     parts))
>>> >  
>>> > -(defun notmuch-get-bodypart-binary (msg part process-crypto)
>>> > +(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 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
>>> > -      ;; 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)
>>> > -	(buffer-string)))))
>>> > -
>>> > -(defun notmuch-get-bodypart-text (msg part process-crypto)
>>> > +  (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
>>> > +	(plist-put part :binary-content data)))
>>> > +    data))
>>> 
>>> I am a little puzzled by this but that could be lack of familiarity with
>>> elisp. As far as I can see plist-put will sometimes modify the original
>>> plist and sometimes return a new plist. If the latter happens then I
>>> think it works out as if we hadn't cached anything as the part passed to
>>> the function is unmodified. That might not matter in this case (though I
>>> find the lack of determinism disturbing).
>>> 
>>> Or is something else going on?
>>
>> No, your familiarity with Elisp serves you well.  I'm completely
>> cheating here.  According to the specification of plist-put, it's
>> allowed to return a new list but in reality this only happens when the
>> original plist is nil.  We lean on this already all over the
>> notmuch-emacs code, but maybe that doesn't excuse me adding one more
>> cheat.
>>
>> I could add a comment here explaining what's going on, I could
>> manually do the list insertion in a way that's guaranteed to mutate it
>> in place, or I could add a nil :binary-content property when parts are
>> created (since plist-put is guaranteed to mutate existing keys in
>> place).
>
> I think a comment is fine. 

Done.

> (Incidentally what is the best way of telling if emacs has changed an
> object or returned a new one for other commands? Something like (setq
> oldobject object) (setq object (operation-on object)) (if (eq object
> oldobject) ... ))

If `eq' returns t, it definitely returned the original object, though it
may or may not have modified it.  If `eq' returns nil, there's no
guarantee that it *didn't* modify the object you passed in (maybe it
modified it and tacked a new cons on the beginning).  In short, there's
really no way of knowing.

> Also, I think the function should have a comment about the lifetime of
> the caching. I think in some cases the addition of :binary-content could
> occur on load and thus the plist with binary content added would get
> saved in the buffer when the msg plist was saved as a
> text-property. However, maybe in other cases this gets called after the
> initial insertion and thus the cached value is just used during this
> operation on msg? Sorry that is a little incoherent as I haven't checked
> all callers.

I believe the caching will always last as long as the buffer.  We only
have one instance of each message plist.  This plist goes in to the text
properties and caching works by mutating this same plist.

However, I updated the docstring to clarify that the cache is stored in
MSG.  These functions don't ultimately control the lifetime of MSG, but
this gives the caller enough information to know the lifetime of the
cache if it knows the lifetime of MSG.

> Best wishes
>
> Mark
>
>
>
>>> Best wishes
>>> 
>>> Mark
>>> 
>>> 
>>> 
>>> > +
>>> > +(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
>>> > @@ -546,7 +552,9 @@ (defun notmuch-get-bodypart-text (msg part process-crypto)
>>> >  	     (npart (apply #'notmuch-call-notmuch-sexp args)))
>>> >  	(setq content (plist-get npart :content))
>>> >  	(when (not content)
>>> > -	  (error "Internal error: No :content from %S" args))))
>>> > +	  (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

  reply	other threads:[~2015-01-24 18:07 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-21 18:37 [PATCH 00/11] Improve charset and cid: handling Austin Clements
2014-04-21 18:37 ` [PATCH 01/11] emacs: Remove redundant NTH argument from `notmuch-get-bodypart-content' Austin Clements
2014-07-10  9:46   ` David Bremner
2014-04-21 18:37 ` [PATCH 02/11] test: New tests for Emacs charset handling Austin Clements
2014-04-24 14:38   ` Mark Walters
2014-04-24 18:29     ` Austin Clements
2014-04-25  6:18       ` Mark Walters
2014-04-25 13:57       ` Tomi Ollila
2014-04-21 18:37 ` [PATCH 03/11] emacs: Fix coding system in `notmuch-show-view-raw-message' Austin Clements
2014-07-10  9:48   ` David Bremner
2014-09-23 17:59   ` David Bremner
2014-04-21 18:37 ` [PATCH 04/11] emacs: Track full message and part descriptor in w3m CID store Austin Clements
2014-07-10  9:52   ` David Bremner
2015-01-24 16:45     ` Austin Clements
2014-04-21 18:37 ` [PATCH 05/11] emacs: Create an API for fetching parts as undecoded binary Austin Clements
2014-04-21 18:37 ` [PATCH 06/11] emacs: Remove broken `notmuch-get-bodypart-content' API Austin Clements
2014-07-11 11:48   ` David Bremner
2015-01-24 17:10     ` Austin Clements
2014-04-21 18:37 ` [PATCH 07/11] emacs: Return unibyte strings for binary part data Austin Clements
2014-04-21 18:37 ` [PATCH 08/11] emacs: Support caching in notmuch-get-bodypart-{binary, text} Austin Clements
2014-04-24 10:46   ` Mark Walters
2014-04-24 18:12     ` Austin Clements
2014-04-25  6:42       ` Mark Walters
2015-01-24 18:06         ` Austin Clements [this message]
2014-04-21 18:37 ` [PATCH 09/11] emacs: Use generalized content caching in w3m CID code Austin Clements
2014-04-21 18:37 ` [PATCH 10/11] emacs: Rewrite content ID handling Austin Clements
2014-04-21 18:37 ` [PATCH 11/11] emacs: Support cid: references with shr renderer Austin Clements
2014-05-01  9:20   ` David Edmondson
2015-01-24 17:12     ` Austin Clements
2014-04-21 20:26 ` [PATCH 00/11] Improve charset and cid: handling Tomi Ollila
2014-04-26 10:50 ` Mark Walters
2015-01-24 17:29   ` Austin Clements

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87vbjwt5mk.fsf@csail.mit.edu \
    --to=amdragon@mit.edu \
    --cc=markwalters1009@gmail.com \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).