From 84c5da844b23bfe26ac04672296cd35d4b7bb7bf Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 5 May 2019 14:11:59 -0400 Subject: [PATCH] Add email/{wanderlust,mu4e,notmuch} modules Removed app/{email,notmuch} --- core/core-modules.el | 4 +- init.example.el | 10 ++- modules/README.org | 7 +- modules/app/email/+gmail.el | 45 ----------- modules/config/default/+emacs-bindings.el | 8 +- modules/{app/email => email/mu4e}/README.org | 8 +- .../email => email/mu4e}/autoload/email.el | 23 +++--- .../email => email/mu4e}/autoload/evil.el | 4 +- modules/{app/email => email/mu4e}/config.el | 63 ++++++++++++--- modules/{app/email => email/mu4e}/packages.el | 3 +- modules/{app => email}/notmuch/autoload.el | 2 +- modules/{app => email}/notmuch/config.el | 2 +- modules/{app => email}/notmuch/packages.el | 2 +- modules/email/wanderlust/autoload.el | 4 + modules/email/wanderlust/config.el | 78 +++++++++++++++++++ modules/email/wanderlust/packages.el | 4 + 16 files changed, 178 insertions(+), 89 deletions(-) delete mode 100644 modules/app/email/+gmail.el rename modules/{app/email => email/mu4e}/README.org (92%) rename modules/{app/email => email/mu4e}/autoload/email.el (81%) rename modules/{app/email => email/mu4e}/autoload/evil.el (89%) rename modules/{app/email => email/mu4e}/config.el (64%) rename modules/{app/email => email/mu4e}/packages.el (71%) rename modules/{app => email}/notmuch/autoload.el (99%) rename modules/{app => email}/notmuch/config.el (97%) rename modules/{app => email}/notmuch/packages.el (86%) create mode 100644 modules/email/wanderlust/autoload.el create mode 100644 modules/email/wanderlust/config.el create mode 100644 modules/email/wanderlust/packages.el diff --git a/core/core-modules.el b/core/core-modules.el index 07fce1326..dee2af2d0 100644 --- a/core/core-modules.el +++ b/core/core-modules.el @@ -30,7 +30,9 @@ (hideshow (:editor fold))) (:ui (doom-modeline (:ui modeline)) (fci (:ui fill-column)) - (evil-goggles (:ui ophints)))) + (evil-goggles (:ui ophints))) + (:app (email (:email mu4e)) + (notmuch (:email notmuch)))) "A tree alist that maps deprecated modules to their replacement(s). Each entry is a three-level tree. For example: diff --git a/init.example.el b/init.example.el index aa17d072c..f90079101 100644 --- a/init.example.el +++ b/init.example.el @@ -143,13 +143,17 @@ ;;web ; the tubes ;;vala ; GObjective-C + :email + (mu4e +gmail) ; WIP + notmuch ; WIP + (wanderlust +gmail) ; WIP + ;; Applications are complex and opinionated modules that transform Emacs ;; toward a specific purpose. They may have additional dependencies and ;; should be loaded late. :app - ;;(email +gmail) ; emacs as an email client - ;;irc ; how neckbeards socialize - ;;(rss +org) ; emacs as an RSS reader + ;;irc ; how neckbeards socialize + ;;rss +org ; emacs as an RSS reader ;;twitter ; twitter client https://twitter.com/vnought ;;(write ; emacs as a word processor (latex + org + markdown) ;; +wordnut ; wordnet (wn) search diff --git a/modules/README.org b/modules/README.org index ac5f405cd..b56844371 100644 --- a/modules/README.org +++ b/modules/README.org @@ -7,6 +7,7 @@ - [[#emacs][:emacs]] - [[#tools][:tools]] - [[#lang][:lang]] +- [[#email][:email]] - [[#app][:app]] - [[#collab][:collab]] - [[#config][:config]] @@ -145,12 +146,16 @@ Modules that bring support for a language or group of languages to Emacs. + web =+lsp=: + vala: +* :email ++ [[file:email/mu4e/README.org][mu4e]] =+gmail=: ++ notmuch: ++ wanderlust =+gmail=: + * :app Large, opinionated modules that transform and take over Emacs, i.e. Doom-specific porcelains. + calendar: -+ [[file:app/email/README.org][email]] =+gmail=: + [[file:app/irc/README.org][irc]]: + rss =+org=: + twitter: diff --git a/modules/app/email/+gmail.el b/modules/app/email/+gmail.el deleted file mode 100644 index 6dbbf924c..000000000 --- a/modules/app/email/+gmail.el +++ /dev/null @@ -1,45 +0,0 @@ -;;; app/email/+gmail.el -*- lexical-binding: t; -*- - -(after! mu4e - ;; don't save message to Sent Messages, Gmail/IMAP takes care of this - (setq mu4e-sent-messages-behavior 'delete - - ;; don't need to run cleanup after indexing for gmail - mu4e-index-cleanup nil - - ;; because gmail uses labels as folders we can use lazy check since - ;; messages don't really "move" - mu4e-index-lazy-check t) - - ;; In my workflow, emails won't be moved at all. Only their flags/labels are - ;; changed. Se we redefine the trash and refile marks not to do any moving. - ;; However, the real magic happens in `+email|gmail-fix-flags'. - ;; - ;; Gmail will handle the rest. - (defun +email--mark-seen (docid msg target) - (mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N")) - - (delq (assq 'delete mu4e-marks) mu4e-marks) - (setf (alist-get 'trash mu4e-marks) - (list :char '("d" . "▼") - :prompt "dtrash" - :dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg)) - :action #'+email--mark-seen) - ;; Refile will be my "archive" function. - (alist-get 'refile mu4e-marks) - (list :char '("d" . "▼") - :prompt "dtrash" - :dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg)) - :action #'+email--mark-seen)) - - ;; This hook correctly modifies gmail flags on emails when they are marked. - ;; Without it, refiling (archiving), trashing, and flagging (starring) email - ;; won't properly result in the corresponding gmail action, since the marks - ;; are ineffectual otherwise. - (defun +email|gmail-fix-flags (mark msg) - (pcase mark - (`trash (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft")) - (`refile (mu4e-action-retag-message msg "-\\Inbox")) - (`flag (mu4e-action-retag-message msg "+\\Starred")) - (`unflag (mu4e-action-retag-message msg "-\\Starred")))) - (add-hook 'mu4e-mark-execute-pre-hook #'+email|gmail-fix-flags)) diff --git a/modules/config/default/+emacs-bindings.el b/modules/config/default/+emacs-bindings.el index eea67f3a3..21d65879c 100644 --- a/modules/config/default/+emacs-bindings.el +++ b/modules/config/default/+emacs-bindings.el @@ -209,10 +209,10 @@ :desc "Add cursor w/mouse" "" #'mc/add-cursor-on-click)) ;; APPs - (:when (featurep! :app email) - (:prefix ("M" . "email") - :desc "Open email app" "M" #'=email - :desc "Compose email" "c" #'+email/compose)) + (:when (featurep! :email mu4e) + (:prefix ("M" . "mu4e") + :desc "Open email app" "M" #'=mu4e + :desc "Compose email" "c" #'+mu4e/compose)) (:when (featurep! :app irc) (:prefix ("I" . "irc") diff --git a/modules/app/email/README.org b/modules/email/mu4e/README.org similarity index 92% rename from modules/app/email/README.org rename to modules/email/mu4e/README.org index 0e4ddb6f7..46b4818ec 100644 --- a/modules/app/email/README.org +++ b/modules/email/mu4e/README.org @@ -1,4 +1,4 @@ -#+TITLE: app/email +#+TITLE: email/mu4e #+DATE: April 8, 2017 #+SINCE: v2.0 #+STARTUP: inlineimages @@ -59,10 +59,10 @@ sudo pacman -S offlineimap * Configuration ** offlineimap -This module uses =mbsync= by default. To change this, change ~+email-backend~: +This module uses =mbsync= by default. To change this, change ~+mu4e-backend~: #+BEGIN_SRC emacs-lisp -(setq +email-backend 'offlineimap) +(setq +mu4e-backend 'offlineimap) #+END_SRC Then you must set up offlineimap and index your mail: @@ -76,7 +76,7 @@ Then you must set up offlineimap and index your mail: Then configure Emacs to use your email address: #+BEGIN_SRC emacs-lisp :tangle no -;; Each path is relative to `+email-mu4e-mail-path', which is ~/.mail by default +;; Each path is relative to `+mu4e-mu4e-mail-path', which is ~/.mail by default (set-email-account! "Lissner.net" '((mu4e-sent-folder . "/Lissner.net/Sent Mail") (mu4e-drafts-folder . "/Lissner.net/Drafts") diff --git a/modules/app/email/autoload/email.el b/modules/email/mu4e/autoload/email.el similarity index 81% rename from modules/app/email/autoload/email.el rename to modules/email/mu4e/autoload/email.el index 5a468abc5..feb14c9ea 100644 --- a/modules/app/email/autoload/email.el +++ b/modules/email/mu4e/autoload/email.el @@ -1,4 +1,4 @@ -;;; app/email/autoload/email.el -*- lexical-binding: t; -*- +;;; email/mu4e/autoload/email.el -*- lexical-binding: t; -*- ;;;###autodef (defun set-email-account! (label letvars &optional default-p) @@ -42,24 +42,24 @@ default/fallback account." -(defvar +email-workspace-name "*mu4e*" +(defvar +mu4e-workspace-name "*mu4e*" "TODO") -(add-hook 'mu4e-main-mode-hook #'+email|init) +(add-hook 'mu4e-main-mode-hook #'+mu4e|init) ;;;###autoload -(defun =email () +(defun =mu4e () "Start email client." (interactive) (require 'mu4e) - (+workspace-switch +email-workspace-name t) + (+workspace-switch +mu4e-workspace-name t) (mu4e~start 'mu4e~main-view) ;; (save-selected-window ;; (prolusion-mail-show)) ) ;;;###autoload -(defun +email/compose () +(defun +mu4e/compose () "Compose a new email." (interactive) ;; TODO Interactively select email account @@ -69,11 +69,10 @@ default/fallback account." ;; ;; Hooks -(defun +email|init () - (add-hook 'kill-buffer-hook #'+email|kill-mu4e nil t)) +(defun +mu4e|init () + (add-hook 'kill-buffer-hook #'+mu4e|kill-mu4e nil t)) -(defun +email|kill-mu4e () +(defun +mu4e|kill-mu4e () ;; (prolusion-mail-hide) - (when (+workspace-exists-p +email-workspace-name) - (+workspace/delete +email-workspace-name))) - + (when (+workspace-exists-p +mu4e-workspace-name) + (+workspace/delete +mu4e-workspace-name))) diff --git a/modules/app/email/autoload/evil.el b/modules/email/mu4e/autoload/evil.el similarity index 89% rename from modules/app/email/autoload/evil.el rename to modules/email/mu4e/autoload/evil.el index be608bda3..2a2153999 100644 --- a/modules/app/email/autoload/evil.el +++ b/modules/email/mu4e/autoload/evil.el @@ -1,8 +1,8 @@ -;; app/email/autoload/evil.el -*- lexical-binding: t; -*- +;; email/mu4e/autoload/evil.el -*- lexical-binding: t; -*- ;;;###if (featurep! :editor evil) ;;;###autoload -(defun +email/mark (&optional beg end) +(defun +mu4e/mark (&optional beg end) "Mark all messages within the current selection in mu4e's header view. Uses `this-command-keys' to see what flag you mean." (interactive) diff --git a/modules/app/email/config.el b/modules/email/mu4e/config.el similarity index 64% rename from modules/app/email/config.el rename to modules/email/mu4e/config.el index 3b8f4b556..54ab82eab 100644 --- a/modules/app/email/config.el +++ b/modules/email/mu4e/config.el @@ -1,15 +1,11 @@ -;;; app/email/config.el -*- lexical-binding: t; -*- +;;; email/mu4e/config.el -*- lexical-binding: t; -*- -;; I want to live in Emacs. Living is incomplete without email, so Emacs needs -;; to give me the ability to read, search, write and send my email. It does so -;; with `mu4e', and requires `offlineimap' and `mu' to be installed. - -(defvar +email-backend 'mbsync +(defvar +mu4e-backend 'mbsync "Which backend to use. Can either be offlineimap, mbsync or nil (manual).") ;; -;; Packages +;;; Packages (add-to-list 'auto-mode-alist '("\\.\\(?:offlineimap\\|mbsync\\)rc\\'" . conf-mode)) @@ -22,7 +18,7 @@ mu4e-attachment-dir "~/.mail/.attachments" mu4e-user-mail-address-list nil) :config - (pcase +email-backend + (pcase +mu4e-backend (`mbsync (setq mu4e-get-mail-command "mbsync -a" mu4e-change-filenames-when-moving t)) @@ -93,8 +89,8 @@ (format "%s" (substring maildir 1 (string-match-p "/" maildir 1))))))) ;; Refresh the current view after marks are executed - (defun +email*refresh (&rest _) (mu4e-headers-rerun-search)) - (advice-add #'mu4e-mark-execute-all :after #'+email*refresh) + (defun +mu4e*refresh (&rest _) (mu4e-headers-rerun-search)) + (advice-add #'mu4e-mark-execute-all :after #'+mu4e*refresh) (when (featurep! :tools flyspell) (add-hook 'mu4e-compose-mode-hook #'flyspell-mode)) @@ -134,6 +130,49 @@ ;; -;; Sub-modules +;;; Gmail integration -(if (featurep! +gmail) (load! "+gmail")) +(when (featurep! +gmail) + (after! mu4e + ;; don't save message to Sent Messages, Gmail/IMAP takes care of this + (setq mu4e-sent-messages-behavior 'delete + + ;; don't need to run cleanup after indexing for gmail + mu4e-index-cleanup nil + + ;; because gmail uses labels as folders we can use lazy check since + ;; messages don't really "move" + mu4e-index-lazy-check t) + + ;; In my workflow, emails won't be moved at all. Only their flags/labels are + ;; changed. Se we redefine the trash and refile marks not to do any moving. + ;; However, the real magic happens in `+mu4e|gmail-fix-flags'. + ;; + ;; Gmail will handle the rest. + (defun +mu4e--mark-seen (docid _msg target) + (mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N")) + + (delq (assq 'delete mu4e-marks) mu4e-marks) + (setf (alist-get 'trash mu4e-marks) + (list :char '("d" . "▼") + :prompt "dtrash" + :dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg)) + :action #'+mu4e--mark-seen) + ;; Refile will be my "archive" function. + (alist-get 'refile mu4e-marks) + (list :char '("d" . "▼") + :prompt "dtrash" + :dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg)) + :action #'+mu4e--mark-seen)) + + ;; This hook correctly modifies gmail flags on emails when they are marked. + ;; Without it, refiling (archiving), trashing, and flagging (starring) email + ;; won't properly result in the corresponding gmail action, since the marks + ;; are ineffectual otherwise. + (defun +mu4e|gmail-fix-flags (mark msg) + (pcase mark + (`trash (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft")) + (`refile (mu4e-action-retag-message msg "-\\Inbox")) + (`flag (mu4e-action-retag-message msg "+\\Starred")) + (`unflag (mu4e-action-retag-message msg "-\\Starred")))) + (add-hook 'mu4e-mark-execute-pre-hook #'+mu4e|gmail-fix-flags))) diff --git a/modules/app/email/packages.el b/modules/email/mu4e/packages.el similarity index 71% rename from modules/app/email/packages.el rename to modules/email/mu4e/packages.el index 0a9efe8e4..d999fbc5c 100644 --- a/modules/app/email/packages.el +++ b/modules/email/mu4e/packages.el @@ -1,5 +1,4 @@ ;; -*- no-byte-compile: t; -*- -;;; app/email/packages.el +;;; email/mu4e/packages.el (package! mu4e-maildirs-extension) - diff --git a/modules/app/notmuch/autoload.el b/modules/email/notmuch/autoload.el similarity index 99% rename from modules/app/notmuch/autoload.el rename to modules/email/notmuch/autoload.el index 340cd40cc..3262e28fc 100644 --- a/modules/app/notmuch/autoload.el +++ b/modules/email/notmuch/autoload.el @@ -1,4 +1,4 @@ -;;; app/notmuch/autoload.el -*- lexical-binding: t; -*- +;;; email/notmuch/autoload.el -*- lexical-binding: t; -*- ;;;###autoload (defun =notmuch () diff --git a/modules/app/notmuch/config.el b/modules/email/notmuch/config.el similarity index 97% rename from modules/app/notmuch/config.el rename to modules/email/notmuch/config.el index c9e6f47a8..4e9813fa0 100644 --- a/modules/app/notmuch/config.el +++ b/modules/email/notmuch/config.el @@ -1,4 +1,4 @@ -;;; app/notmuch/config.el -*- lexical-binding: t; -*- +;;; email/notmuch/config.el -*- lexical-binding: t; -*- ;; FIXME This module is a WIP! diff --git a/modules/app/notmuch/packages.el b/modules/email/notmuch/packages.el similarity index 86% rename from modules/app/notmuch/packages.el rename to modules/email/notmuch/packages.el index 7caea8546..72474420b 100644 --- a/modules/app/notmuch/packages.el +++ b/modules/email/notmuch/packages.el @@ -1,5 +1,5 @@ ;; -*- no-byte-compile: t; -*- -;;; app/notmuch/packages.el +;;; email/notmuch/packages.el (package! notmuch) (package! org-mime) diff --git a/modules/email/wanderlust/autoload.el b/modules/email/wanderlust/autoload.el new file mode 100644 index 000000000..53199cd07 --- /dev/null +++ b/modules/email/wanderlust/autoload.el @@ -0,0 +1,4 @@ +;;; email/wanderlust/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(defalias '=wanderlust #'wl) diff --git a/modules/email/wanderlust/config.el b/modules/email/wanderlust/config.el new file mode 100644 index 000000000..343dfefd2 --- /dev/null +++ b/modules/email/wanderlust/config.el @@ -0,0 +1,78 @@ +;;; app/wanderlust/config.el -*- lexical-binding: t; -*- + +(def-package! wl + :defer t + :config + (setq mail-user-agent 'wl-user-agent + pgg-scheme 'gpg + mime-edit-split-message nil) + + (when (fboundp 'define-mail-user-agent) + (define-mail-user-agent + 'wl-user-agent + 'wl-user-agent-compose + 'wl-draft-send + 'wl-draft-kill + 'mail-send-hook)) + + (setq wl-init-file (expand-file-name "wl.el" doom-private-dir)) + + (setq wl-demo nil + wl-interactive-exit t + wl-interactive-send t + wl-stay-folder-window t + wl-folders-file (expand-file-name "folders.wl" doom-private-dir) + wl-x-face-file (expand-file-name "xface" doom-private-dir) + wl-draft-folder "%INBOX.drafts" + wl-fcc "%INBOX.Sent") + + (setq wl-message-truncate-lines t + wl-summary-width 120 + wl-from (format "%s <%s>" user-full-name user-mail-address) + ;; wl-organization "Secret Conspiracy" + wl-local-domain (cadr (split-string user-mail-address "@")) + wl-message-ignored-field-list + '(".*Received:" + ".*Path:" + ".*Id:" + "^References:" + "^Replied:" + "^Errors-To:" + "^Lines:" + "^Sender:" + ".*Host:" + "^Xref:" + "^Content-Type:" + "^Precedence:" + "^Status:" + "^X.*:" + "^MIME.*:" + "^In-Reply-To:" + "^Content-Transfer-Encoding:" + "^List-.*:")) + + (setq wl-message-visible-field-list '("^Message-Id:" "^User-Agent:" "^X-Mailer:" "^X-Face:")) + + (when (featurep! +gmail) + (setq elmo-imap4-default-server "imap.gmail.com" + elmo-imap4-default-port 993 + elmo-imap4-default-authenticate-type 'clear ; CRAM-MD5 + elmo-imap4-default-user "" + elmo-imap4-default-stream-type 'ssl + elmo-imap4-set-seen-flag-explicitly t) + + (setq wl-smtp-connection-type 'starttls + wl-smtp-posting-port 587 + wl-smtp-authenticate-type "plain" + wl-smtp-posting-user "" + wl-smtp-posting-server "smtp.gmail.com")) + + (setq wl-message-id-domain wl-local-domain) + + (when (featurep! :editor evil) + ;; Neither wl-folder-mode or wl-summary-mode are correctly defined as major + ;; modes, so `evil-set-initial-state' won't work here. + (add-hook! '(wl-folder-mode-hook wl-summary-mode) + #'evil-emacs-state)) + + (add-hook 'mime-edit-mode-hook #'auto-fill-mode)) diff --git a/modules/email/wanderlust/packages.el b/modules/email/wanderlust/packages.el new file mode 100644 index 000000000..b2d336172 --- /dev/null +++ b/modules/email/wanderlust/packages.el @@ -0,0 +1,4 @@ +;; -*- no-byte-compile: t; -*- +;;; app/wanderlust/packages.el + +(package! wanderlust)