From a974db04c4b08166cd8c7ecb4656314f72b31790 Mon Sep 17 00:00:00 2001 From: TEC Date: Thu, 1 Oct 2020 01:52:58 +0800 Subject: [PATCH] Mu4e: further improve org-msg - stylistic tweaks - make accent colour easily user-settable - scale LaTeX fragments appropriately - make it easy to toggle org-msg-mode for one-off messages --- modules/email/mu4e/README.org | 10 +++ modules/email/mu4e/autoload/email.el | 108 ++++++++++++++++++++++++--- modules/email/mu4e/config.el | 56 +++++++++----- 3 files changed, 147 insertions(+), 27 deletions(-) diff --git a/modules/email/mu4e/README.org b/modules/email/mu4e/README.org index 4fa541360..a7b831243 100644 --- a/modules/email/mu4e/README.org +++ b/modules/email/mu4e/README.org @@ -18,6 +18,7 @@ - [[#offlineimap][offlineimap]] - [[#mbsync][mbsync]] - [[#mu-and-mu4e][mu and mu4e]] + - [[#orgmsg][OrgMsg]] - [[#troubleshooting][Troubleshooting]] - [[#no-such-file-or-directory-mu4e][=No such file or directory, mu4e=]] - [[#void-function-org-time-add-error-on-gentoo][~(void-function org-time-add)~ error on Gentoo]] @@ -168,6 +169,15 @@ Then configure Emacs to use your email address: (mu4e-compose-signature . "---\nHenrik Lissner")) t) #+END_SRC +** OrgMsg +By default, ~org-msg-mode~ is enabled before composing the first message. +To disable ~org-msg-mode~ by default, simply +#+BEGIN_SRC emacs-lisp :tangle no +(setq mu4e-compose--org-msg-toggle-next nil) +#+END_SRC + +To toggle org-msg for a single message, just apply the universal argument to the +compose or reply command (=SPC u= with ~evil~, =C-u= otherwise). * Troubleshooting ** =No such file or directory, mu4e= diff --git a/modules/email/mu4e/autoload/email.el b/modules/email/mu4e/autoload/email.el index c54bfcb8c..bb076d934 100644 --- a/modules/email/mu4e/autoload/email.el +++ b/modules/email/mu4e/autoload/email.el @@ -189,18 +189,18 @@ is tomorrow. With two prefixes, select the deadline." ;;;###autoload (defun my-mu4e-set-account () - "Set the account for composing a message. If a 'To' header is present, + "Set the account for composing a message. If a 'To' header is present, and correspands to an email account, this account will be selected. Otherwise, the user is prompted for the account they wish to use." - (unless (and mu4e-compose-parent-message - (let ((to (cdr (car (mu4e-message-field mu4e-compose-parent-message :to)))) - (from (cdr (car (mu4e-message-field mu4e-compose-parent-message :from))))) - (if (member to (plist-get mu4e~server-props :personal-addresses)) - (setq user-mail-address to) - (if (member from (plist-get mu4e~server-props :personal-addresses)) - (setq user-mail-address from) - nil)))) - (ivy-read "Account: " (plist-get mu4e~server-props :personal-addresses) :action (lambda (candidate) (setq user-mail-address candidate))))) + (unless (and mu4e-compose-parent-message + (let ((to (cdr (car (mu4e-message-field mu4e-compose-parent-message :to)))) + (from (cdr (car (mu4e-message-field mu4e-compose-parent-message :from))))) + (if (member to (plist-get mu4e~server-props :personal-addresses)) + (setq user-mail-address to) + (if (member from (plist-get mu4e~server-props :personal-addresses)) + (setq user-mail-address from) + nil)))) + (ivy-read "Account: " (plist-get mu4e~server-props :personal-addresses) :action (lambda (candidate) (setq user-mail-address candidate))))) ;;;###autoload (defun mu4e~main-action-prettier-str (str &optional func-or-shortcut) @@ -245,3 +245,91 @@ clicked." (+mu4e--old-wconf (set-window-configuration +mu4e--old-wconf) (setq +mu4e--old-wconf nil)))) + +;; org-msg hooks + +;;;###autoload +(defun +org-msg-img-scale-css (img-uri) + "For a given IMG-URI, use imagemagik to find its width." + (if org-msg-currently-exporting + (list :width + (format "%.1fpx" + (/ (string-to-number + (shell-command-to-string + (format "identify -format %%w %s" + (substring img-uri 7)))) ; 7=(length "file://") + (plist-get org-format-latex-options :scale)))) + (list :style (format "transform: scale(%.3f)" + (/ 1.0 (plist-get org-format-latex-options :scale)))))) + +(defun org-html-latex-fragment-scaled (latex-fragment _contents info) + "Transcode a LATEX-FRAGMENT object from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information. + +This differs from `org-html-latex-fragment' in that it uses the LaTeX fragment +as a meaningful alt value, applies a class to indicate what sort of fragment it is +(latex-fragment-inline or latex-fragment-block), and (on Linux) scales the image to +account for the value of :scale in `org-format-latex-options'." + (let ((latex-frag (org-element-property :value latex-fragment)) + (processing-type (plist-get info :with-latex))) + (cond + ((memq processing-type '(t mathjax)) + (org-html-format-latex latex-frag 'mathjax info)) + ((memq processing-type '(t html)) + (org-html-format-latex latex-frag 'html info)) + ((assq processing-type org-preview-latex-process-alist) + (let ((formula-link + (org-html-format-latex latex-frag processing-type info))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + (let ((source (org-export-file-uri (match-string 1 formula-link))) + (attributes (list :alt latex-frag + :class (concat "latex-fragment-" + (if (equal "\\(" (substring latex-frag 0 2)) + "inline" "block"))))) + (when (and (memq processing-type '(dvipng convert)) IS-LINUX) + (apply #'plist-put attributes (+org-msg-img-scale-css source))) + (org-html--format-image source attributes info))))) + (t latex-frag)))) + +(defun org-html-latex-environment-scaled (latex-environment _contents info) + "Transcode a LATEX-ENVIRONMENT element from Org to HTML. +CONTENTS is nil. INFO is a plist holding contextual information. + +This differs from `org-html-latex-environment' in that (on Linux) it +scales the image to account for the value of :scale in `org-format-latex-options'." + (let ((processing-type (plist-get info :with-latex)) + (latex-frag (org-remove-indentation + (org-element-property :value latex-environment))) + (attributes (org-export-read-attribute :attr_html latex-environment)) + (label (and (org-element-property :name latex-environment) + (org-export-get-reference latex-environment info))) + (caption (and (org-html--latex-environment-numbered-p latex-environment) + (number-to-string + (org-export-get-ordinal + latex-environment info nil + (lambda (l _) + (and (org-html--math-environment-p l) + (org-html--latex-environment-numbered-p l)))))))) + (plist-put attributes :class "latex-environment") + (cond + ((memq processing-type '(t mathjax)) + (org-html-format-latex + (if (org-string-nw-p label) + (replace-regexp-in-string "\\`.*" + (format "\\&\n\\\\label{%s}" label) + latex-frag) + latex-frag) + 'mathjax info)) + ((assq processing-type org-preview-latex-process-alist) + (let ((formula-link + (org-html-format-latex + (org-html--unlabel-latex-environment latex-frag) + processing-type info))) + (when (and formula-link (string-match "file:\\([^]]*\\)" formula-link)) + (let ((source (org-export-file-uri (match-string 1 formula-link)))) + (when (and (memq processing-type '(dvipng convert)) IS-LINUX) + (apply #'plist-put attributes (+org-msg-img-scale-css source))) + (org-html--wrap-latex-environment + (org-html--format-image source attributes info) + info caption label))))) + (t (org-html--wrap-latex-environment latex-frag info caption label))))) diff --git a/modules/email/mu4e/config.el b/modules/email/mu4e/config.el index a462a8e04..18fb94a6f 100644 --- a/modules/email/mu4e/config.el +++ b/modules/email/mu4e/config.el @@ -172,7 +172,7 @@ (when (featurep! :lang org) (use-package! org-msg - :hook (org-load . org-msg-mode) + :after (mu4e org) :config (setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t tex:dvipng" org-msg-startup "hidestars indent inlineimages" @@ -190,6 +190,27 @@ Usefull for affecting HTML export config.") :after #'org-msg-org-to-xml (setq org-msg-currently-exporting nil)) + (advice-add #'org-html-latex-fragment :override #'org-html-latex-fragment-scaled) + (advice-add #'org-html-latex-environment :override #'org-html-latex-environment-scaled) + + (defvar mu4e-compose--org-msg-toggle-next t ; t to initialise org-msg + "Whether to toggle ") + (defun mu4e-compose-org-msg-handle-toggle (toggle-p) + (when (xor toggle-p mu4e-compose--org-msg-toggle-next) + (org-msg-mode (if org-msg-mode -1 1)) + (setq mu4e-compose--org-msg-toggle-next + (not mu4e-compose--org-msg-toggle-next)))) + + (defadvice! mu4e-maybe-toggle-org-msg (orig-fn toggle-p) + :around #'mu4e-compose-new + :around #'mu4e-compose-reply + (interactive "p") + (mu4e-compose-org-msg-handle-toggle (/= 1 toggle-p)) + (funcall orig-fn)) + + (defvar +org-msg-accent-color "#c01c28" + "Accent color to use in org-msg's generated CSS. +Must be set before org-msg is loaded to take effect.") (setq org-msg-enforce-css (let* ((font-family '(font-family . "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell,\ \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";")) @@ -197,12 +218,13 @@ Usefull for affecting HTML export config.") (font-size '(font-size . "11pt")) (font `(,font-family ,font-size)) (line-height '(line-height . "1.2")) - (theme-color "#8a0400") + (theme-color +org-msg-accent-color) (bold '(font-weight . "bold")) (color `(color . ,theme-color)) (table `((margin-top . "6px") (margin-bottom . "6px") (border-left . "none") (border-right . "none") - (border-top . "2px solid #222222") (border-bottom . "2px solid #222222") + (border-top . "2px solid #222222") + (border-bottom . "2px solid #222222") )) (ftl-number `(,color ,bold (text-align . "left"))) (inline-modes '(asl c c++ conf cpp csv diff ditaa emacs-lisp @@ -234,10 +256,12 @@ Usefull for affecting HTML export config.") (margin-top . "0px") (margin-left . "30px") (padding-top . "0px") (padding-left . "5px"))) (nil signature (,@font (margin-bottom . "20px"))) - (blockquote nil ((padding . "0px 10px") (margin-left . "10px") - (margin-top . "20px") (margin-bottom . "0") - (border-left . "3px solid #ccc") (font-style . "italic") + (blockquote nil ((padding . "2px 12px") (margin-left . "10px") + (margin-top . "10px") (margin-bottom . "0") + (border-left . "3px solid #ccc") + (font-style . "italic") (background . "#f9f9f9"))) + (p blockquote ((margin . "0") (padding . "4px 0"))) (code nil (,font-size ,monospace-font (background . "#f9f9f9"))) ,@code-src (nil linenr ((padding-right . "1em") @@ -266,10 +290,7 @@ Usefull for affecting HTML export config.") (nil org-src-name ,ftl-number) (img nil ((vertical-align . "middle") (max-width . "100%"))) - (img latex-fragment-inline ((transform . ,(format "translateY(-1px) scale(%.3f)" - (/ 1.0 (if (boundp 'preview-scale) - preview-scale 1.4)))) - (margin . "0 -0.35em"))) + (img latex-fragment-inline ((margin . "0 0.1em"))) (table nil (,@table ,line-height (border-collapse . "collapse"))) (th nil ((border . "none") (border-bottom . "1px solid #222222") (background-color . "#EDEDED") (font-weight . "500") @@ -280,8 +301,9 @@ Usefull for affecting HTML export config.") (td org-right ((text-align . "right"))) (td org-center ((text-align . "center"))) (kbd nil ((border . "1px solid #d1d5da") (border-radius . "3px") - (box-shadow . "inset 0 -1px 0 #d1d5da") (background-color . "#fafbfc") - (color . "#444d56") (padding . "3px 5px") (display . "inline-block"))) + (box-shadow . "inset 0 -1px 0 #d1d5da") + (background-color . "#fafbfc") (color . "#444d56") + (padding . "3px 5px") (display . "inline-block"))) (div outline-text-4 ((margin-left . "15px"))) (div outline-4 ((margin-left . "10px"))) (h4 nil ((margin-bottom . "0px") (font-size . "11pt"))) @@ -289,11 +311,11 @@ Usefull for affecting HTML export config.") ,color (font-size . "14pt"))) (h2 nil ((margin-top . "20px") (margin-bottom . "20px") ,color (font-size . "18pt"))) - (h1 nil ((margin-top . "20px") - (margin-bottom . "0px") ,color (font-size . "24pt"))) - (p nil ((text-decoration . "none") (margin-bottom . "0px") - (margin-top . "10px") (line-height . "11pt") ,font-size - (max-width . "100ch"))) + (h1 nil ((margin-top . "20px") (margin-bottom . "0px") + ,color (font-size . "24pt"))) + (p nil ((text-decoration . "none") (line-height . "11pt") + (margin-top . "10px") (margin-bottom . "0px") + ,font-size (max-width . "100ch"))) (b nil ((font-weight . "500") (color . ,theme-color))) (div nil (,@font (line-height . "12pt"))))))))