The current code renders all html parts by default and then hides them. This is quite slow so this is an attempt to make it only render them when the user chooses to show them. In my testing this code seems to work but has some rough edges. However, it may be useful to people in its current form (and I am not sure when I will have enough time to do more). There are various problems with the current approach and implementation: It special cases text/html (rather than lazily rendering all initially hidden parts). If you toggle some multipart parts (the whole multipart part not the subpart) then you can end up with the html part claiming to be visible but not rendered. However toggling the html part twice fixes this. (If I didn't special case text/html this might just work.) It may get the depth wrong by 1 if the text/html is part of a multipart part. I think it adds an extra blank line at the end of the newly rendered html part. If I fix this then the following message can get messed up (this newly render part can end up inside the following header overlay). Maybe someone more familiar with overlays can see how to fix this easily. It just saves all the arguments which would have been passed to the html rendering function to the part-button and then calls the rendering function with them later. Given that we store the entire message json this may not be necessary. On the other hand this does make the code relatively simple. Any feedback on whether it works, much better ways of doing things etc gratefully received! Best wishes Mark --- emacs/notmuch-show.el | 27 ++++++++++++++++++++++++--- 1 files changed, 24 insertions(+), 3 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index face2a0..6749bc9 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -559,6 +559,7 @@ message at DEPTH in the current thread." (overlay (button-get button 'overlay))) (when overlay (let* ((show (overlay-get overlay 'invisible)) + (unparsed-html (button-get button :notmuch-html-properties)) (new-start (button-start button)) (button-label (button-get button :base-label)) (old-point (point)) @@ -569,7 +570,11 @@ message at DEPTH in the current thread." (let ((old-end (button-end button))) (move-overlay button new-start (point)) (delete-region (point) old-end)) - (goto-char (min old-point (1- (button-end button)))))))) + (goto-char (min old-point (1- (button-end button)))) + (when (and show unparsed-html) + (save-excursion + (button-put button :notmuch-html-properties nil) + (notmuch-show-lazy-html-part unparsed-html overlay))))))) (defun notmuch-show-multipart/*-to-list (part) (mapcar (lambda (inner-part) (plist-get inner-part :content-type)) @@ -823,8 +828,24 @@ message at DEPTH in the current thread." ;; in notmuch. We set mm-inline-text-html-with-w3m-keymap to nil to ;; tell w3m not to set a keymap (so the normal notmuch-show-mode-map ;; remains). - (let ((mm-inline-text-html-with-w3m-keymap nil)) - (notmuch-show-insert-part-*/* msg part content-type nth depth declared-type))) + (let ((button (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename)))) + (button-put button :notmuch-html-properties + (list msg part nth content-type notmuch-show-process-crypto))) + ;; We need to insert something or the part toggle gets suppressed. + (save-excursion + (insert "html")) + t) + +(defun notmuch-show-lazy-html-part (html overlay) + (interactive) + (let ((mm-inline-text-html-with-w3m-keymap nil) + (inhibit-read-only t)) + (delete-region (overlay-start overlay) (1- (overlay-end overlay))) + (apply #'notmuch-mm-display-part-inline html)) + (indent-rigidly (overlay-start overlay) + (1- (overlay-end overlay)) + (notmuch-show-get-depth))) + (defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type) ;; This handler _must_ succeed - it is the handler of last resort. -- 1.7.9.1