[Emacs] Mu4e documentation, litterate programming ftw
This commit is contained in:
parent
39d9f0e74b
commit
ac01ba4eaf
@ -576,6 +576,27 @@ prefix them with a comma (I’ve taken this habit from Spacemacs).
|
|||||||
(general-auto-unbind-keys))
|
(general-auto-unbind-keys))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
#+name: general-keybindings-gen
|
||||||
|
#+header: :tangle no :exports none :results value
|
||||||
|
#+begin_src emacs-lisp :var table=mu4e-keybindings-view-tbl
|
||||||
|
(mapconcat (lambda (line)
|
||||||
|
(let ((key (car line))
|
||||||
|
(function (cadr line))
|
||||||
|
(comment (caddr line)))
|
||||||
|
(format "\"%s\" %s" key
|
||||||
|
(if (string= "" comment)
|
||||||
|
(if (string= "nil" function)
|
||||||
|
"nil"
|
||||||
|
(concat "#'" function))
|
||||||
|
(format "'(%s :wk \"%s\")"
|
||||||
|
comment
|
||||||
|
(if (string= "" function)
|
||||||
|
"nil"
|
||||||
|
comment))))))
|
||||||
|
table
|
||||||
|
"\n")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
** Evil
|
** Evil
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package evil
|
(use-package evil
|
||||||
@ -729,12 +750,28 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
*** Elfeed
|
*** Elfeed
|
||||||
*** Email - Mu4e
|
*** Email
|
||||||
|
**** Basic configuration
|
||||||
|
As seen below, I use ~org-msg~ to compose my emails, which includes by
|
||||||
|
default my signature. Therefore, there is no need for Emacs itself to
|
||||||
|
know about it since I don’t want it to include it a second time after
|
||||||
|
~org-msg~ already did.
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(setq message-signature nil
|
(setq message-signature nil
|
||||||
mail-signature nil)
|
mail-signature nil)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
**** Mu4e
|
||||||
|
Mu4e is a very eye-pleasing email client for Emacs, built around ~mu~
|
||||||
|
and which works very well with ~mbsync~ (found in Arch’s ~isync~ package).
|
||||||
|
For me, the main advantage of mu4e is it has a modern interface for
|
||||||
|
emailing, and quite straightforward. I tried a couple of other email
|
||||||
|
clients for Emacs, and I even was for some time a Gnus user, but in
|
||||||
|
the end, mu4e really works best for me. Below you’ll find my
|
||||||
|
configuration for the ~mu4e~ package itself.
|
||||||
|
|
||||||
|
Quick sidenote: on ArchLinux, you’ll need to install either ~mu~ or
|
||||||
|
~mu-git~ from the AUR in order to use mu4e.
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package mu4e
|
(use-package mu4e
|
||||||
:after all-the-icons
|
:after all-the-icons
|
||||||
@ -754,7 +791,11 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
|
|
||||||
:config
|
:config
|
||||||
(progn
|
(progn
|
||||||
<<mu4e-keybindings>>
|
<<mu4e-keybindings-view>>
|
||||||
|
<<mu4e-keybindings-header>>
|
||||||
|
<<mu4e-keybindings-header-no-leader>>
|
||||||
|
<<mu4e-keybindings-message>>
|
||||||
|
|
||||||
(setq mu4e-compose-signature nil)
|
(setq mu4e-compose-signature nil)
|
||||||
|
|
||||||
(when (fboundp 'imagemagick-register-types)
|
(when (fboundp 'imagemagick-register-types)
|
||||||
@ -777,30 +818,22 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
mu4e-refile-folder "/Archive"
|
mu4e-refile-folder "/Archive"
|
||||||
mu4e-sent-folder "/Sent"
|
mu4e-sent-folder "/Sent"
|
||||||
mu4e-drafts-folder "/Drafts"
|
mu4e-drafts-folder "/Drafts"
|
||||||
|
mu4e-change-filenames-when-moving t
|
||||||
mu4e-update-interval 60
|
mu4e-update-interval 60
|
||||||
mu4e-compose-format-flowed t
|
mu4e-compose-format-flowed t
|
||||||
mu4e-view-show-addresses t
|
mu4e-view-show-addresses t
|
||||||
mu4e-sent-messages-behaviour 'sent
|
mu4e-sent-messages-behaviour 'sent
|
||||||
mu4e-hide-index-messages t
|
mu4e-hide-index-messages t
|
||||||
;; try to show images
|
mu4e-view-show-images t ; try to show images
|
||||||
mu4e-view-show-images t
|
|
||||||
mu4e-view-image-max-width 600
|
mu4e-view-image-max-width 600
|
||||||
;; configuration for sending mail
|
message-send-mail-function #'smtpmail-send-it ; how to send an email
|
||||||
message-send-mail-function #'smtpmail-send-it
|
|
||||||
smtpmail-stream-type 'starttls
|
smtpmail-stream-type 'starttls
|
||||||
message-kill-buffer-on-exit t ; close after sending
|
message-kill-buffer-on-exit t ; close after sending
|
||||||
;; start with the first (default) context
|
mu4e-context-policy 'pick-first ; start with first (default) context
|
||||||
mu4e-context-policy 'pick-first
|
mu4e-compose-context-policy 'ask-if-none ; compose with current context, or ask
|
||||||
;; compose with the current context, or ask
|
mu4e-completing-read-function #'ivy-completing-read ; use ivy
|
||||||
mu4e-compose-context-policy 'ask-if-none
|
mu4e-confirm-quit t ; no need to ask
|
||||||
;; use ivy
|
mu4e-header-fields '((:account . 12)
|
||||||
mu4e-completing-read-function #'ivy-completing-read
|
|
||||||
;; no need to ask
|
|
||||||
mu4e-confirm-quit t
|
|
||||||
|
|
||||||
|
|
||||||
mu4e-header-fields
|
|
||||||
'((:account . 12)
|
|
||||||
(:human-date . 12)
|
(:human-date . 12)
|
||||||
(:flags . 4)
|
(:flags . 4)
|
||||||
(:from . 25)
|
(:from . 25)
|
||||||
@ -810,61 +843,19 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
(setq mail-user-agent 'mu4e-user-agent)
|
(setq mail-user-agent 'mu4e-user-agent)
|
||||||
|
|
||||||
;; Use fancy icons
|
;; Use fancy icons
|
||||||
(setq mu4e-use-fancy-chars t
|
<<mu4e-fancy-marks>>
|
||||||
mu4e-headers-draft-mark `("D" . ,(all-the-icons-faicon "pencil":height 0.8))
|
;; Set bookmarks
|
||||||
mu4e-headers-flagged-mark `("F" . ,(all-the-icons-faicon "flag":height 0.8))
|
<<mu4e-bookmarks>>
|
||||||
mu4e-headers-new-mark `("N" . ,(all-the-icons-faicon "rss":height 0.8))
|
|
||||||
mu4e-headers-passed-mark `("P" . ,(all-the-icons-faicon "check":height 0.8))
|
|
||||||
mu4e-headers-replied-mark `("R" . ,(all-the-icons-faicon "reply":height 0.8))
|
|
||||||
mu4e-headers-seen-mark `("S" . ,(all-the-icons-faicon "eye":height 0.8))
|
|
||||||
mu4e-headers-unread-mark `("u" . ,(all-the-icons-faicon "eye-slash":height 0.8))
|
|
||||||
mu4e-headers-trashed-mark `("T" . ,(all-the-icons-faicon "trash":height 0.8))
|
|
||||||
mu4e-headers-attach-mark `("a" . ,(all-the-icons-faicon "paperclip":height 0.8))
|
|
||||||
mu4e-headers-encrypted-mark `("x" . ,(all-the-icons-faicon "lock":height 0.8))
|
|
||||||
mu4e-headers-signed-mark `("s" . ,(all-the-icons-faicon "certificate":height 0.8)))
|
|
||||||
|
|
||||||
(setq mu4e-bookmarks
|
;; mu4e-headers-mode config
|
||||||
`((,(s-join " "
|
<<mu4e-headers-mode>>
|
||||||
'("NOT flag:trashed"
|
|
||||||
"AND (maildir:/Inbox OR maildir:/Junk)"
|
|
||||||
"AND NOT to:CONLANG@LISTSERV.BROWN.EDU"
|
|
||||||
"AND NOT to:AUXLANG@LISTSERV.BROWN.EDU"
|
|
||||||
"AND NOT to:ateliers-emacs@framalistes.org"
|
|
||||||
"AND NOT to:ateliers-paris@emacs-doctor.com"
|
|
||||||
"AND NOT list:ateliers-emacs.framalistes.org"
|
|
||||||
"AND NOT list:ateliers-paris.emacs-doctor.com"))
|
|
||||||
"Inbox" ?i) ;; Inbox without the linguistics mailing lists
|
|
||||||
(,(s-join " "
|
|
||||||
'("NOT flag:trashed"
|
|
||||||
"AND (maildir:/Inbox OR maildir:/Junk)"
|
|
||||||
"AND (f:/.*up8\.edu|.*univ-paris8.*/"
|
|
||||||
"OR c:/.*up8\.edu|.*univ-paris8.*/"
|
|
||||||
"OR t:/.*up8\.edu|.*univ-paris8.*/)"))
|
|
||||||
"University" ?u) ;; University-related emails
|
|
||||||
(,(s-join " "
|
|
||||||
'("to:CONLANG@LISTSERV.BROWN.EDU"
|
|
||||||
"OR to:AUXLANG@LISTSERV.BROWN.EDU"))
|
|
||||||
"Linguistics" ?l) ;; linguistics mailing lists
|
|
||||||
(,(s-join " "
|
|
||||||
'("list:ateliers-emacs.framalistes.org"
|
|
||||||
"OR to:ateliers-paris@emacs-doctor.com"
|
|
||||||
"OR list:ateliers-paris.emacs-doctor.com"))
|
|
||||||
"Emacs" ?e) ;; Emacs mailing list
|
|
||||||
("maildir:/Sent" "Sent messages" ?s)
|
|
||||||
("flag:unread AND NOT flag:trashed" "Unread messages" ?U)
|
|
||||||
("date:today..now AND NOT flag:trashed" "Today's messages" ?t)
|
|
||||||
("date:7d..now AND NOT flag:trashed" "Last 7 days" ?w)
|
|
||||||
("date:1m..now AND NOT flag:trashed" "Last month" ?m)
|
|
||||||
("date:1y..now AND NOT flag:trashed" "Last year" ?y)
|
|
||||||
("flag:trashed AND NOT flag:trashed" "Trash" ?T)
|
|
||||||
("mime:image/* AND NOT flag:trashed" "Messages with images" ?p)))
|
|
||||||
|
|
||||||
;; Add a column to display what email account the email belongs to.
|
;; Add a column to display what email account the email belongs to.
|
||||||
(add-to-list 'mu4e-header-info-custom
|
(add-to-list 'mu4e-header-info-custom
|
||||||
'(:account
|
'(:account
|
||||||
:name "Account"
|
:name "Phundrak Main"
|
||||||
:shortname "Account"
|
:shortname "Phundrak"
|
||||||
:help "Which account this email belongs to"
|
:help "Main email of phundrak"
|
||||||
:function
|
:function
|
||||||
(lambda (msg)
|
(lambda (msg)
|
||||||
(let ((maildir (mu4e-message-field msg :maildir)))
|
(let ((maildir (mu4e-message-field msg :maildir)))
|
||||||
@ -888,23 +879,237 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
(add-to-list 'mu4e-view-actions '("PDF view" . mu4e-action-open-as-pdf) t)))
|
(add-to-list 'mu4e-view-actions '("PDF view" . mu4e-action-open-as-pdf) t)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+name: mu4e-keybindings
|
***** Bookmarks
|
||||||
|
In mu4e, the main focus isn’t really mail directories such as your
|
||||||
|
inbox, your sent messages and such, but instead you manipulate
|
||||||
|
bookmarks which will show you emails depending on tags. This mean you
|
||||||
|
can create some pretty customized bookmarks that go way beyound your
|
||||||
|
simple inbox, outbox and all. Actually, four of my bookmarks have a
|
||||||
|
couple of filtering:
|
||||||
|
- anything in my inbox linked to my university
|
||||||
|
- the [[https://emacs-doctor.com/lists/listinfo][emacs-doctor mailing list]] (French Emacs mailing list)
|
||||||
|
- the conlang mailing lists
|
||||||
|
- and my inbox for any mail not caught by any of these filters
|
||||||
|
And all of them will have the requirement not to display any trashed
|
||||||
|
email. Actually, all of my bookmarks will have this requirement,
|
||||||
|
except for the bookmark dedicated to them as well as my sent emails.
|
||||||
|
I’ll add these latter requirements later.
|
||||||
|
|
||||||
|
Here are the requirements for my university bookmark. The regex
|
||||||
|
matches any email address which contains either ~up8.edu~ or
|
||||||
|
~univ-paris8~, which can be found in email addresses from the University
|
||||||
|
Paris 8 (my university).
|
||||||
|
#+name: mu4e-bookmarks-filter-uni
|
||||||
|
#+headers: :tangle no :exports both :cache yes
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(string-join '("f:/.*up8\.edu|.*univ-paris8.*/"
|
||||||
|
"c:/.*up8\.edu|.*univ-paris8.*/"
|
||||||
|
"t:/.*up8\.edu|.*univ-paris8.*/")
|
||||||
|
" OR ")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[55041e7ce5b7c7b228c9fd6e1c9715f677094c8e]: mu4e-bookmarks-filter-uni
|
||||||
|
: f:/.*up8.edu|.*univ-paris8.*/ OR c:/.*up8.edu|.*univ-paris8.*/ OR t:/.*up8.edu|.*univ-paris8.*/
|
||||||
|
|
||||||
|
As for the Emacs-doctor list, I need to match both the current, modern
|
||||||
|
mailing list address but also its old address.
|
||||||
|
#+name: mu4e-bookmarks-filter-emacs-list
|
||||||
|
#+headers: :tangle no :exports both :cache yes
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(mapconcat (lambda (address)
|
||||||
|
(mapconcat (lambda (flag)
|
||||||
|
(concat flag ":" address))
|
||||||
|
'("list" "to" "from")
|
||||||
|
" OR "))
|
||||||
|
'("ateliers-emacs.framalistes.org" "ateliers-paris.emacs-doctor.com")
|
||||||
|
" OR ")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[463132dbde653749ac07ee8e1263733ee15b5847]: mu4e-bookmarks-filter-emacs-list
|
||||||
|
: list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com
|
||||||
|
|
||||||
|
When it comes to the conlang mailing list, let’s not match anything
|
||||||
|
from or to them. I’ll also include the auxlang mailing list –I’m not
|
||||||
|
subscribed anymore, but it’ll keep my inbox clean.
|
||||||
|
#+name: mu4e-bookmarks-filter-conlang-list
|
||||||
|
#+headers: :tangle no :exports both :cache yes
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(mapconcat (lambda (address)
|
||||||
|
(mapconcat (lambda (flag)
|
||||||
|
(concat flag ":" address))
|
||||||
|
'("from" "to" "list")
|
||||||
|
" OR "))
|
||||||
|
'("CONLANG@LISTSERV.BROWN.EDU" "AUXLANG@LISTSERV.BROWN.EDU")
|
||||||
|
" OR ")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[5565a39c69d99277cffbf4e4be88211ab463543b]: mu4e-bookmarks-filter-conlang-list
|
||||||
|
: from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU
|
||||||
|
|
||||||
|
As I said earlier, something that will often come back in my bookmarks
|
||||||
|
is the emails must not be trashed to appear. I want also to display
|
||||||
|
junk emails, so I end up with the following rule:
|
||||||
|
#+name: mu4e-bookmarks-default-filter
|
||||||
|
#+headers: :tangle no :exports both :cache yes
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(string-join `("NOT flag:trashed"
|
||||||
|
,(format "(%s)" (mapconcat (lambda (maildir) (concat "maildir:" maildir))
|
||||||
|
'("/Inbox" "/Junk")
|
||||||
|
" OR ")))
|
||||||
|
" AND ")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[88f8a5401e240f98fd64fe227699f5ddfe6d5730]: mu4e-bookmarks-default-filter
|
||||||
|
: NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk)
|
||||||
|
|
||||||
|
And for the last string-generating code, let’s describe my main inbox:
|
||||||
|
#+name: mu4e-bookmarks-inbox-filters
|
||||||
|
#+headers: :exports both :tangle no :cache yes
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(string-join (cons
|
||||||
|
<<mu4e-bookmarks-default-filter>>
|
||||||
|
`(
|
||||||
|
,(format "(%s)"
|
||||||
|
<<mu4e-bookmarks-filter-conlang-list>>)
|
||||||
|
,(format "(%s)"
|
||||||
|
<<mu4e-bookmarks-filter-emacs-list>>)
|
||||||
|
,(format "(%s)"
|
||||||
|
<<mu4e-bookmarks-filter-uni>>)))
|
||||||
|
" AND NOT ")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[96218e66b6554a2b8b1f09f016d9af1d238bb79b]: mu4e-bookmarks-inbox-filters
|
||||||
|
: NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu|.*univ-paris8.*/ OR c:/.*up8.edu|.*univ-paris8.*/ OR t:/.*up8.edu|.*univ-paris8.*/)
|
||||||
|
|
||||||
|
We can finally define our bookmarks! The code reads as follows:
|
||||||
|
#+name: mu4e-bookmarks
|
||||||
|
#+begin_src emacs-lisp :tangle no :cache yes
|
||||||
|
(setq mu4e-bookmarks
|
||||||
|
`((:name "Inbox"
|
||||||
|
:key ?i
|
||||||
|
:query ,(format "%s"
|
||||||
|
<<mu4e-bookmarks-inbox-filters>>))
|
||||||
|
(:name "Linguistics"
|
||||||
|
:key ?l
|
||||||
|
:query ,(format "%s AND %s"
|
||||||
|
<<mu4e-bookmarks-inbox-filters>>
|
||||||
|
<<mu4e-bookmarks-filter-conlang-list>>))
|
||||||
|
(:name "Emacs"
|
||||||
|
:key ?e
|
||||||
|
:query ,(format "%s AND %s"
|
||||||
|
<<mu4e-bookmarks-inbox-filters>>
|
||||||
|
<<mu4e-bookmarks-filter-emacs-list>>))
|
||||||
|
(:name "University"
|
||||||
|
:key ?u
|
||||||
|
:query ,(format "%s AND %s"
|
||||||
|
<<mu4e-bookmarks-inbox-filters>>
|
||||||
|
<<mu4e-bookmarks-filter-uni>>))
|
||||||
|
(:name "eshell-info-banner" :key ?E :query ,(format "%s AND %s"
|
||||||
|
<<mu4e-bookmarks-inbox-filters>>
|
||||||
|
"list:eshell-info-banner.el.Phundrak.github.com"))
|
||||||
|
(:name "Sent" :key ?s :query "maildir:/Sent")
|
||||||
|
(:name "All Unread" :key ?U :query "flag:unread AND NOT flag:trashed")
|
||||||
|
(:name "Today" :key ?t :query "date:today..now AND NOT flag:trashed")
|
||||||
|
(:name "This Week" :key ?w :query "date:7d..now AND NOT flag:trashed")
|
||||||
|
(:name "This Month" :key ?m :query "date:1m..now AND NOT flag:trashed")
|
||||||
|
(:name "This Year" :key ?y :query "date:1y..now AND NOT flag:trashed")))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS[3e4e7f607d9f961a27594ddb98037ec25b2c94f7]: mu4e-bookmarks
|
||||||
|
| :name | Inbox | :key | 105 | :query | NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/) | | | |
|
||||||
|
| :name | Linguistics | :key | 108 | :query | NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/) AND from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU | | | |
|
||||||
|
| :name | Emacs | :key | 101 | :query | NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/) AND list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com | | | |
|
||||||
|
| :name | University | :key | 117 | :query | NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/) AND f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/ |
|
||||||
|
| :name | eshell-info-banner | :key | 69 | :query | NOT flag:trashed AND (maildir:/Inbox OR maildir:/Junk) AND NOT (from:CONLANG@LISTSERV.BROWN.EDU OR to:CONLANG@LISTSERV.BROWN.EDU OR list:CONLANG@LISTSERV.BROWN.EDU OR from:AUXLANG@LISTSERV.BROWN.EDU OR to:AUXLANG@LISTSERV.BROWN.EDU OR list:AUXLANG@LISTSERV.BROWN.EDU) AND NOT (list:ateliers-emacs.framalistes.org OR to:ateliers-emacs.framalistes.org OR from:ateliers-emacs.framalistes.org OR list:ateliers-paris.emacs-doctor.com OR to:ateliers-paris.emacs-doctor.com OR from:ateliers-paris.emacs-doctor.com) AND NOT (f:/.*up8.edu | .*univ-paris8.*/ OR c:/.*up8.edu | .*univ-paris8.*/ OR t:/.*up8.edu | .*univ-paris8.*/) AND list:eshell-info-banner.el.Phundrak.github.com | | | |
|
||||||
|
| :name | Sent | :key | 115 | :query | maildir:/Sent | | | | | | |
|
||||||
|
| :name | All Unread | :key | 85 | :query | flag:unread AND NOT flag:trashed | | | | | | |
|
||||||
|
| :name | Today | :key | 116 | :query | date:today..now AND NOT flag:trashed | | | | | | |
|
||||||
|
| :name | This Week | :key | 119 | :query | date:7d..now AND NOT flag:trashed | | | | | | |
|
||||||
|
| :name | This Month | :key | 109 | :query | date:1m..now AND NOT flag:trashed | | | | | | |
|
||||||
|
| :name | This Year | :key | 121 | :query | date:1y..now AND NOT flag:trashed | | | | | | |
|
||||||
|
|
||||||
|
***** Getting Fancy
|
||||||
|
I’m not a huge fan of mu4e’s default icons marking my emails, so I’ll
|
||||||
|
redefine them as follows. Be aware the name of these icons are from
|
||||||
|
/faicon/ in the package ~all-the-icons~.
|
||||||
|
#+name: mu4e-fancy-marks-tbl
|
||||||
|
| Mark | Flag | Icon |
|
||||||
|
|-----------+------+-------------|
|
||||||
|
| draft | D | pencil |
|
||||||
|
| flagged | F | flag |
|
||||||
|
| new | N | rss |
|
||||||
|
| passed | P | check |
|
||||||
|
| replied | R | reply |
|
||||||
|
| seen | S | eye |
|
||||||
|
| unread | u | eye-slash |
|
||||||
|
| trashed | T | trash |
|
||||||
|
| attach | a | paperclip |
|
||||||
|
| encrypted | x | lock |
|
||||||
|
| signed | s | certificate |
|
||||||
|
|
||||||
|
#+name: mu4e-fancy-marks-gen
|
||||||
|
#+header: :tangle no :exports none :results value
|
||||||
|
#+begin_src emacs-lisp :var table=mu4e-fancy-marks-tbl
|
||||||
|
(mapconcat (lambda (line)
|
||||||
|
(let ((mark (car line))
|
||||||
|
(flag (cadr line))
|
||||||
|
(icon (caddr line)))
|
||||||
|
(format "mu4e-headers-%s-mark `(\"%s\" . ,(all-the-icons-faicon \"%s\" :height 0.8))"
|
||||||
|
mark
|
||||||
|
flag
|
||||||
|
icon)))
|
||||||
|
table
|
||||||
|
"\n")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
#+begin_example
|
||||||
|
mu4e-headers-draft-mark `("D" . ,(all-the-icons-faicon "pencil" :height 0.8))
|
||||||
|
mu4e-headers-flagged-mark `("F" . ,(all-the-icons-faicon "flag" :height 0.8))
|
||||||
|
mu4e-headers-new-mark `("N" . ,(all-the-icons-faicon "rss" :height 0.8))
|
||||||
|
mu4e-headers-passed-mark `("P" . ,(all-the-icons-faicon "check" :height 0.8))
|
||||||
|
mu4e-headers-replied-mark `("R" . ,(all-the-icons-faicon "reply" :height 0.8))
|
||||||
|
mu4e-headers-seen-mark `("S" . ,(all-the-icons-faicon "eye" :height 0.8))
|
||||||
|
mu4e-headers-unread-mark `("u" . ,(all-the-icons-faicon "eye-slash" :height 0.8))
|
||||||
|
mu4e-headers-trashed-mark `("T" . ,(all-the-icons-faicon "trash" :height 0.8))
|
||||||
|
mu4e-headers-attach-mark `("a" . ,(all-the-icons-faicon "paperclip" :height 0.8))
|
||||||
|
mu4e-headers-encrypted-mark `("x" . ,(all-the-icons-faicon "lock" :height 0.8))
|
||||||
|
mu4e-headers-signed-mark `("s" . ,(all-the-icons-faicon "certificate" :height 0.8))
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
Let’s enable them and set them:
|
||||||
|
#+name: mu4e-fancy-marks
|
||||||
#+begin_src emacs-lisp :tangle no
|
#+begin_src emacs-lisp :tangle no
|
||||||
;; Unbinding some stuff
|
(setq mu4e-use-fancy-chars t
|
||||||
|
<<mu4e-fancy-marks-gen()>>)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
***** Headers mode
|
||||||
|
#+name: mu4e-headers-mode
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(add-hook 'mu4e-headers-mode-hook (lambda () (visual-line-mode -1)))
|
||||||
|
(add-hook 'mu4e-headers-mode-hook (lambda () (toggle-truncate-lines -1)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
***** Keybindings
|
||||||
|
By default, Evil has some pretty annoying keybindings for users of the
|
||||||
|
bépo layout: ~hjkl~ becomes ~ctsr~ for us. Let’s undefine some of these:
|
||||||
|
#+name: mu4e-keybindings-undef
|
||||||
|
#+begin_src emacs-lisp
|
||||||
(general-define-key
|
(general-define-key
|
||||||
:keymaps '(mu4e-headers-mode-map mu4e-view-mode-map)
|
:keymaps '(mu4e-headers-mode-map mu4e-view-mode-map)
|
||||||
"s" nil)
|
"s" nil)
|
||||||
(general-define-key
|
(general-define-key
|
||||||
:states 'normal
|
:states 'normal
|
||||||
:keymaps '(mu4e-headers-mode-map mu4e-view-mode-map)
|
:keymaps '(mu4e-headers-mode-map mu4e-view-mode-map)
|
||||||
"s" nil)
|
"s" nil
|
||||||
|
"," nil)
|
||||||
(general-define-key
|
(general-define-key
|
||||||
:keymaps 'mu4e-view-mode-map
|
:keymaps 'mu4e-view-mode-map
|
||||||
"SPC" nil
|
"SPC" nil
|
||||||
"S" nil
|
"S" nil
|
||||||
"r" nil
|
"r" nil
|
||||||
"c" nil)
|
"c" nil)
|
||||||
|
|
||||||
(general-define-key
|
(general-define-key
|
||||||
:keymaps 'mu4e-view-mode-map
|
:keymaps 'mu4e-view-mode-map
|
||||||
:states 'normal
|
:states 'normal
|
||||||
@ -913,119 +1118,184 @@ grow the ~mu4e-headers~ buffer when viewing an email.
|
|||||||
"r" nil
|
"r" nil
|
||||||
"c" nil
|
"c" nil
|
||||||
"gu" nil)
|
"gu" nil)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
;; View
|
#+RESULTS: mu4e-keybindings-undef
|
||||||
(general-define-key
|
|
||||||
:keymaps 'mu4e-view-mode-map
|
|
||||||
:states 'normal
|
|
||||||
)
|
|
||||||
|
|
||||||
(general-define-key
|
Now, let’s define some keybindings for mu4e’s view mode, that is when
|
||||||
:states 'motion
|
we are viewing an email. All these keybindings will reside between the
|
||||||
:keymaps 'mu4e-view-mode-map
|
major-mode specific leader key ~,~ and most of these keybindings can be
|
||||||
:prefix ","
|
described with a simple function:
|
||||||
"|" #'mu4e-view-pipe
|
#+name: mu4e-keybindings-view-tbl
|
||||||
"." '(mu4e-headers-split-adjust-width/body :wk "mu4e-headers width")
|
| Keybinding | Function | Description |
|
||||||
|
|------------+--------------------------------------+--------------------|
|
||||||
|
| & | mu4e-view-pipe | |
|
||||||
|
| . | mu4e-headers-split-adjust-width/body | mu4e-headers width |
|
||||||
|
| a | nil | attachments |
|
||||||
|
| a& | mu4e-view-pipe-attachment | |
|
||||||
|
| aa | mu4e-view-attachment-action | |
|
||||||
|
| ao | mu4e-view-open-attachment | |
|
||||||
|
| aO | mu4e-view-open-attachment-with | |
|
||||||
|
| c | nil | compose |
|
||||||
|
| cc | mu4e-compose-new | |
|
||||||
|
| ce | mu4e-compose-edit | |
|
||||||
|
| cf | mu4e-compose-forward | |
|
||||||
|
| cr | mu4e-compose-reply | |
|
||||||
|
| cR | mu4e-compose-resend | |
|
||||||
|
| g | nil | go to |
|
||||||
|
| gu | mu4e-view-go-to-url | |
|
||||||
|
| gX | mu4e-view-fetch-url | |
|
||||||
|
| l | mu4e-show-log | |
|
||||||
|
| m | nil | mark |
|
||||||
|
| md | mu4e-view-mark-for-trash | |
|
||||||
|
| mD | mu4e-view-mark-for-delete | |
|
||||||
|
| mm | mu4e-view-mark-for-move | |
|
||||||
|
| mr | mu4e-view-mark-for-refile | |
|
||||||
|
| mR | mu4e-view-mark-for-read | |
|
||||||
|
| mu | mu4e-view-mark-for-unread | |
|
||||||
|
| mU | mu4e-view-mark-for-unmark | |
|
||||||
|
| t | nil | thread |
|
||||||
|
| T | nil | toggle |
|
||||||
|
| Tc | mu4e-view-toggle-hide-cited | |
|
||||||
|
| Th | mu4e-view-toggle-html | |
|
||||||
|
| n | mu4e-view-headers-next | |
|
||||||
|
| N | mu4e-view-headers-next-unread | |
|
||||||
|
| p | mu4e-view-headers-prev | |
|
||||||
|
| P | mu4e-view-headers-prev-unread | |
|
||||||
|
|
||||||
"a" '(nil :wk "attachments")
|
Some functions are however lambdas. They all are written as actions on
|
||||||
"a|" #'mu4e-view-pipe-attachment
|
the current thread. They all begin with ~,t~, and below you can see each
|
||||||
"aa" #'mu4e-view-attachment-action
|
one of the possible following key can act on a thread:
|
||||||
"ao" #'mu4e-view-open-attachment
|
#+name: mu4e-keybindings-view-lambdas-tbl
|
||||||
"aO" #'mu4e-view-open-attachment-with
|
| Key | Mark thread as |
|
||||||
|
|-----+----------------|
|
||||||
|
| td | trash |
|
||||||
|
| tD | delete |
|
||||||
|
| tm | move |
|
||||||
|
| tr | refile |
|
||||||
|
| tR | read |
|
||||||
|
| tu | unread |
|
||||||
|
| tU | unmark |
|
||||||
|
|
||||||
"c" '(nil :wk "compose")
|
#+name: mu4e-keybindings-view-lambdas-gen
|
||||||
"cc" #'mu4e-compose-new
|
#+header: :tangle no :exports none :results value
|
||||||
"ce" #'mu4e-compose-edit
|
#+begin_src emacs-lisp :var table=mu4e-keybindings-view-lambdas-tbl mode="view"
|
||||||
"cf" #'mu4e-compose-forward
|
(mapconcat (lambda (line)
|
||||||
"cr" #'mu4e-compose-reply
|
(let ((key (car line))
|
||||||
"cR" #'mu4e-compose-resend
|
(mark (cadr line)))
|
||||||
|
(format "\"%s\" '((lambda ()
|
||||||
"g" '(nil :wk "go to")
|
|
||||||
"gu" #'mu4e-view-go-to-url
|
|
||||||
"gX" #'mu4e-view-fetch-url
|
|
||||||
|
|
||||||
"l" #'mu4e-show-log
|
|
||||||
|
|
||||||
"m" '(nil :wk "mark")
|
|
||||||
"md" #'mu4e-view-mark-for-trash
|
|
||||||
"mD" #'mu4e-view-mark-for-delete
|
|
||||||
"mm" #'mu4e-view-mark-for-move
|
|
||||||
"mr" #'mu4e-view-mark-for-refile
|
|
||||||
"mR" #'mu4e-view-mark-for-read
|
|
||||||
"mu" #'mu4e-view-mark-for-unread
|
|
||||||
"mU" #'mu4e-view-mark-for-unmark
|
|
||||||
|
|
||||||
"t" '(nil :wk "thread")
|
|
||||||
"td" '((lambda ()
|
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(trash)))
|
(mu4e-%s-mark-thread '%s))
|
||||||
|
:wk \"Mark as %s\")"
|
||||||
|
key mode mark mark)))
|
||||||
|
table
|
||||||
|
"\n")
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: mu4e-keybindings-view-lambdas-gen
|
||||||
|
#+begin_example
|
||||||
|
"td" '((lambda ()
|
||||||
|
(interactive)
|
||||||
|
(mu4e-view-mark-thread 'trash))
|
||||||
:wk "Mark as trash")
|
:wk "Mark as trash")
|
||||||
"tD" '((lambda ()
|
"tD" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(delete)))
|
(mu4e-view-mark-thread 'delete))
|
||||||
:wk "Mark as delete")
|
:wk "Mark as delete")
|
||||||
"tm" '((lambda ()
|
"tm" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(move)))
|
(mu4e-view-mark-thread 'move))
|
||||||
:wk "Mark as move")
|
:wk "Mark as move")
|
||||||
"tr" '((lambda ()
|
"tr" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(refile)))
|
(mu4e-view-mark-thread 'refile))
|
||||||
:wk "Mark as refile")
|
:wk "Mark as refile")
|
||||||
"tR" '((lambda ()
|
"tR" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(read)))
|
(mu4e-view-mark-thread 'read))
|
||||||
:wk "Mark as read")
|
:wk "Mark as read")
|
||||||
"tu" '((lambda ()
|
"tu" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(unread)))
|
(mu4e-view-mark-thread 'unread))
|
||||||
:wk "Mark as unread")
|
:wk "Mark as unread")
|
||||||
"tU" '((lambda ()
|
"tU" '((lambda ()
|
||||||
(interactive)
|
(interactive)
|
||||||
(mu4e-view-mark-thread '(unmark)))
|
(mu4e-view-mark-thread 'unmark))
|
||||||
:wk "Mark as unmark")
|
:wk "Mark as unmark")
|
||||||
|
#+end_example
|
||||||
|
|
||||||
"T" '(nil :wk "toggle")
|
#+name: mu4e-keybindings-view
|
||||||
"Tc" #'mu4e-view-toggle-hide-cited
|
#+begin_src emacs-lisp
|
||||||
"Th" #'mu4e-view-toggle-html
|
|
||||||
|
|
||||||
|
|
||||||
"n" #'mu4e-view-headers-next
|
|
||||||
"N" #'mu4e-view-headers-next-unread
|
|
||||||
"p" #'mu4e-view-headers-prev
|
|
||||||
"P" #'mu4e-view-headers-prev-unread)
|
|
||||||
|
|
||||||
;; Headers
|
|
||||||
(general-define-key
|
(general-define-key
|
||||||
|
:states 'normal
|
||||||
|
:keymaps 'mu4e-view-mode-map
|
||||||
:prefix ","
|
:prefix ","
|
||||||
|
<<general-keybindings-gen(table=mu4e-keybindings-view-tbl)>>
|
||||||
|
<<mu4e-keybindings-view-lambdas-gen(mode="view")>>)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Some simple keybindings are defined for mu4e’s header mode:
|
||||||
|
#+name: mu4e-keybindings-headers-tbl
|
||||||
|
| Key | Function | Description |
|
||||||
|
|-----+----------+-------------|
|
||||||
|
| s | swiper | |
|
||||||
|
| t | nil | thread |
|
||||||
|
|
||||||
|
The keybindings from table [[mu4e-keybindings-view-lambdas-tbl]] will also
|
||||||
|
be reused for this mode.
|
||||||
|
|
||||||
|
#+name: mu4e-keybindings-header
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(general-define-key
|
||||||
|
:states 'normal
|
||||||
|
:keymaps 'mu4e-headers-mode-map
|
||||||
|
:prefix ","
|
||||||
|
<<general-keybindings-gen(table=mu4e-keybindings-headers-tbl)>>
|
||||||
|
<<mu4e-keybindings-view-lambdas-gen(mode="headers")>>)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: mu4e-keybindings-header
|
||||||
|
|
||||||
|
I will also redefine without a leader key ~ctsr~ in order to be able to
|
||||||
|
move freely (remember, bépo layout for me).
|
||||||
|
#+name: mu4e-keybindings-header-no-leader
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(general-define-key
|
||||||
:keymaps 'mu4e-headers-mode-map
|
:keymaps 'mu4e-headers-mode-map
|
||||||
:states 'normal
|
:states 'normal
|
||||||
"s" '(nil :wk "search")
|
"c" #'evil-backward-char
|
||||||
"ss" #'swiper)
|
|
||||||
|
|
||||||
(general-define-key
|
|
||||||
:keymaps 'mu4e-headers-mode-map
|
|
||||||
:states 'motion
|
|
||||||
"t" #'evil-next-line
|
"t" #'evil-next-line
|
||||||
"s" #'evil-previous-line
|
"s" #'evil-previous-line
|
||||||
"T" '((lambda ()
|
"r" #'evil-forward-char)
|
||||||
(interactive)
|
#+end_src
|
||||||
(mu4e-headers-mark-thread nil '(read)))
|
|
||||||
:wk "Mark as read"))
|
|
||||||
|
|
||||||
;; Message
|
#+RESULTS: mu4e-keybindings-header-no-leader
|
||||||
|
|
||||||
|
Finally, let’s declare a couple of keybindings for when we are
|
||||||
|
composing a message. This time, all my keybindings are prefixed with
|
||||||
|
the major-mode leader and call a simple function.
|
||||||
|
#+name: mu4e-keybindings-message-tbl
|
||||||
|
| Key | Function | Description |
|
||||||
|
|-----+-----------------------+-------------|
|
||||||
|
| , | message-send-and-exit | |
|
||||||
|
| c | message-send-and-exit | |
|
||||||
|
| a | message-kill-buffer | |
|
||||||
|
| k | message-kill-buffer | |
|
||||||
|
| s | message-dont-send | |
|
||||||
|
| f | mml-attach-file) | |
|
||||||
|
|
||||||
|
#+name: mu4e-keybindings-message
|
||||||
|
#+begin_src emacs-lisp :tangle no
|
||||||
(general-define-key
|
(general-define-key
|
||||||
:states 'normal
|
:states 'normal
|
||||||
:keymaps 'message-mode-map
|
:keymaps 'message-mode-map
|
||||||
:prefix ","
|
:prefix ","
|
||||||
"," #'message-send-and-exit
|
<<general-keybindings-gen(table=mu4e-keybindings-message-tbl)>>
|
||||||
"c" #'message-send-and-exit
|
|
||||||
"a" #'message-kill-buffer
|
|
||||||
"k" #'message-kill-buffer
|
|
||||||
"s" #'message-dont-send
|
|
||||||
"f" #'mml-attach-file)
|
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
#+RESULTS: mu4e-keybindings-message
|
||||||
|
|
||||||
|
**** Composing messages
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package org-msg
|
(use-package org-msg
|
||||||
:after (org mu4e)
|
:after (org mu4e)
|
||||||
|
Loading…
Reference in New Issue
Block a user