diff --git a/emacs/mu4e-headers.el b/emacs/mu4e-headers.el index 8999690e..0837db25 100644 --- a/emacs/mu4e-headers.el +++ b/emacs/mu4e-headers.el @@ -333,7 +333,7 @@ after the end of the search results." (define-key map (kbd "") (lambda () (interactive) (mu4e-headers-split-view-resize -1))) - + ;; switching to view mode (if it's visible) (define-key map "y" 'mu4e-select-other-view) @@ -897,7 +897,7 @@ current window. " (erase-buffer) (insert (propertize "Waiting for message..." 'face 'mu4e-system-face 'intangible t)) - (mu4e~proc-view docid)))) + (mu4e~proc-view docid mu4e-view-show-images)))) (defun mu4e~headers-kill-buffer-and-window () "Quit the message view and return to the main view." diff --git a/emacs/mu4e-proc.el b/emacs/mu4e-proc.el index 85cb4962..a4fa5a2a 100644 --- a/emacs/mu4e-proc.el +++ b/emacs/mu4e-proc.el @@ -421,12 +421,15 @@ mean: response." (mu4e~proc-send-command "ping")) -(defun mu4e~proc-view (docid-or-msgid) +(defun mu4e~proc-view (docid-or-msgid &optional images) "Get one particular message based on its DOCID-OR-MSGID (keyword -argument). The result will be delivered to the function registered -as `mu4e-message-func'." - (mu4e~proc-send-command "view %s" - (mu4e--docid-msgid-param docid-or-msgid))) +argument). Optionally, if IMAGES is non-nil, backend will any +images attached to the message, and return them as temp files. The +result will be delivered to the function registered as +`mu4e-message-func'." + (mu4e~proc-send-command "view %s extract-images:%s" + (mu4e--docid-msgid-param docid-or-msgid) + (if images "true" "false"))) (provide 'mu4e-proc) diff --git a/emacs/mu4e-utils.el b/emacs/mu4e-utils.el index 2ba8dc0e..7372658c 100644 --- a/emacs/mu4e-utils.el +++ b/emacs/mu4e-utils.el @@ -720,6 +720,27 @@ mu4e logs some of its internal workings to a log-buffer. See (switch-to-buffer buf))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar mu4e-imagemagick-identify "identify" + "Name/path of the Imagemagick 'identify' program.") + +(defun mu4e-display-image (imgpath &optional maxwidth) + "Display image IMG at point; optionally specify +MAXWIDTH. Function tries to use imagemagick if available; otherwise +MAXWIDTH is ignored." + (when + (let* + ((identify (and maxwidth (executable-find mu4e-imagemagick-identify))) + (props (and identify (shell-command-to-string + (format "%s -format '%%w' %s" + identify (shell-quote-argument imgpath))))) + (width (and props (string-to-number props))) + (img + (if (> (or width 0) (or maxwidth 0)) + (create-image imgpath 'imagemagick nil :width maxwidth) + (create-image imgpath 'imagemagick)))) + (newline) + (insert-image img imgpath nil t)))) + (provide 'mu4e-utils) ;;; End of mu4e-utils.el diff --git a/emacs/mu4e-view.el b/emacs/mu4e-view.el index 720bc0fb..d773cc43 100644 --- a/emacs/mu4e-view.el +++ b/emacs/mu4e-view.el @@ -86,6 +86,15 @@ display with `mu4e-view-toggle-hide-cited (default keybinding: )." :group 'mu4e-view) +(defcustom mu4e-view-show-images nil + "Whether to automatically display attached images in the message +buffer." + :group 'mu4e-view) + +(defcustom mu4e-view-image-max-width 800 + "The maximum width for images to display; this is only effective + if you're using an emacs with Imagemagick support." + :group 'mu4e-view) (defvar mu4e-view-actions '( ("capture message" ?c mu4e-action-capture-message) @@ -134,11 +143,10 @@ where: - (defun mu4e-view-message-with-msgid (msgid) "View message with MSGID. This is meant for external programs wanting to show specific messages - for example, `mu4e-org'." - (mu4e~proc-view msgid)) + (mu4e~proc-view msgid mu4e-view-show-images)) (defun mu4e-view-message-text (msg) "Return the message to display (as a string), based on the MSG @@ -215,6 +223,8 @@ marking if it still had that." (mu4e~view-fontify-footer) (mu4e~view-make-urls-clickable) + (mu4e~view-show-images-maybe msg) + (unless refresh ;; if we're showing the message for the first time, use the values of ;; user-settable variables `mu4e~view-wrap-lines' and @@ -322,6 +332,15 @@ is nil, and otherwise open it." (unless (zerop id) (mu4e~view-construct-header (format "Attachments(%d)" id) attstr t)))) +(defun mu4e-view-for-each-part (msg func) + "Apply FUNC to each part in MSG. FUNC should be a function taking two arguments; + 1. the message MSG, and + 2. a plist describing the attachment. The plist looks like: + (:index 1 :name \"test123.doc\" + :mime-type \"application/msword\" :attachment t :size 1234)." + (dolist (part (mu4e-msg-field msg :parts)) + (funcall func msg part))) + (defvar mu4e-view-mode-map nil "Keymap for \"*mu4e-view*\" buffers.") @@ -369,7 +388,7 @@ is nil, and otherwise open it." (define-key map (kbd "") 'mu4e-headers-split-view-resize) (define-key map (kbd "") (lambda () (interactive) (mu4e-headers-split-view-resize -1))) - + ;; intra-message navigation (define-key map (kbd "SPC") 'scroll-up) (define-key map (kbd "") @@ -571,6 +590,18 @@ Seen; if the message is not New/Unread, do nothing." (browse-url url)))) +(defun mu4e~view-show-images-maybe (msg) + "Show attached images, if `mu4e-view-show-images' is non-nil." + (when (and (display-images-p) mu4e-view-show-images) + (mu4e-view-for-each-part msg + (lambda (msg part) + (when (string-match "^image/" (plist-get part :mime-type)) + (let ((imgfile (plist-get part :temp))) + (when (and imgfile (file-exists-p imgfile)) + (save-excursion + (goto-char (point-max)) + (mu4e-display-image imgfile mu4e-view-image-max-width))))))))) + ;; this is fairly simplistic... (defun mu4e~view-make-urls-clickable () "Turn things that look like URLs into clickable things, and @@ -595,7 +626,6 @@ number them so they can be opened using `mu4e-view-go-to-url'." 'face 'mu4e-view-url-number-face)))))))) - (defun mu4e~view-wrap-lines () "Wrap lines in the message body." (save-excursion diff --git a/emacs/mu4e.texi b/emacs/mu4e.texi index 1477e88a..f8f357b8 100644 --- a/emacs/mu4e.texi +++ b/emacs/mu4e.texi @@ -748,6 +748,26 @@ variable @code{mu4e-attachment-dir}, for example: (setq mu4e-attachment-dir (file-name-expand "~/Downloads")) @end lisp +@subsection Viewing images inline + +It is possible to show images inline in the message view buffer if you run +emacs in GUI-mode. You can enable this by setting the variable +@code{mu4e-view-show-images} to @t{t}. + +Since emacs does not always handle images correctly, this is not enabled by +default. Note, if you are using a (pre-) release of emacs 24 and build it +yourself, you probable want to build it with @emph{Imagemagick} support -- in +that case, also make sure you call @code{imagemagick-register-types} in your +configuration, so it is used for images. + +@lisp +;; enable inline images +(setq mu4e-view-show-images-t) +;; use imagemagick, if available +(when (fboundp 'imagemagick-register-types) + (imagemagick-register-types)) +@end lisp + @subsection Actions @code{mu4e-view-action} (@key{a}) lets you pick some custom action to perform