|
|
|
|
@ -805,112 +805,114 @@ |
|
|
|
|
** mu4e |
|
|
|
|
These are some standard config items |
|
|
|
|
#+begin_src emacs-lisp |
|
|
|
|
(require 'smtpmail) |
|
|
|
|
(require 'mu4e) |
|
|
|
|
(require 'helm-mu) |
|
|
|
|
(global-set-key (kbd "C-x μ") 'mu4e) |
|
|
|
|
(global-set-key (kbd "C-x 5 μ") (eval-with-new-frame (mu4e))) |
|
|
|
|
|
|
|
|
|
(defalias 'μ 'mu4e) |
|
|
|
|
|
|
|
|
|
(setq mu4e-maildir "~/.mail" |
|
|
|
|
mu4e-attachment-dir "~/attachments" |
|
|
|
|
mu4e-html2text-command "w3m -dump -T text/html -cols 72 -o display_link_number=true -o auto_image=false -o display_image=false -o ignore_null_img_alt=true" |
|
|
|
|
mu4e-headers-show-threads nil |
|
|
|
|
mu4e-headers-sort-direction "descending" |
|
|
|
|
mail-user-agent 'mu4e-user-agent |
|
|
|
|
read-mail-command 'mu4e |
|
|
|
|
mu4e-update-interval 120 |
|
|
|
|
mu4e-view-use-gnus t |
|
|
|
|
message-kill-buffer-on-exit t |
|
|
|
|
mu4e-compose-format-flowed t |
|
|
|
|
fill-flowed-encode-column 998 |
|
|
|
|
mm-text-html-renderer 'gnus-w3m |
|
|
|
|
mu4e-read-option-use-builtin nil |
|
|
|
|
mu4e-completing-read-function 'completing-read |
|
|
|
|
mu4e-modeline-support nil) |
|
|
|
|
|
|
|
|
|
(let (p1 p2 myLine) |
|
|
|
|
(setq p1 (line-beginning-position) ) |
|
|
|
|
(setq p2 (line-end-position) ) |
|
|
|
|
(setq myLine (buffer-substring-no-properties p1 p2))) |
|
|
|
|
|
|
|
|
|
(defun get-buffer-current-line () |
|
|
|
|
(let ((p (line-beginning-position)) |
|
|
|
|
(q (line-end-position))) |
|
|
|
|
(buffer-substring-no-properties p q))) |
|
|
|
|
|
|
|
|
|
(defun get-buffer-to-eol () |
|
|
|
|
(let ((p (point)) |
|
|
|
|
(q (line-end-position))) |
|
|
|
|
(buffer-substring-no-properties p q))) |
|
|
|
|
|
|
|
|
|
(defun format-zoom-meeting () |
|
|
|
|
(if (boundp 'zoom-link) |
|
|
|
|
(if (boundp 'zoom-passcode) |
|
|
|
|
(concat zoom-summary |
|
|
|
|
" [[" zoom-link "][link]] (" zoom-passcode ")\n SCHEDULED: " zoom-scheduled-time) |
|
|
|
|
(concat zoom-summary |
|
|
|
|
" [[" zoom-link "][link]]\n SCHEDULED: " zoom-scheduled-time)) |
|
|
|
|
(concat zoom-summary "\n SCHEDULED: " zoom-scheduled-time))) |
|
|
|
|
|
|
|
|
|
(defun create-item-for-meeting (msg) |
|
|
|
|
"Search for messages sent by the sender of the message at point." |
|
|
|
|
(makunbound 'zoom-link) |
|
|
|
|
(makunbound 'zoom-passcode) |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-buffer) |
|
|
|
|
(cond ((search-forward "Join Zoom Meeting" nil t) |
|
|
|
|
(message "found zoom meeting") |
|
|
|
|
(right-char) |
|
|
|
|
(setq zoom-link (get-buffer-current-line)) |
|
|
|
|
(when (search-forward "Passcode:" nil t) |
|
|
|
|
(setq zoom-passcode (get-buffer-current-line))) |
|
|
|
|
(beginning-of-buffer) |
|
|
|
|
(search-forward "Time:") |
|
|
|
|
(search-forward "<") |
|
|
|
|
(left-char) |
|
|
|
|
(setq zoom-scheduled-time (get-buffer-to-eol)) |
|
|
|
|
(search-backward "Summary:") |
|
|
|
|
(right-word) |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (get-buffer-to-eol)) |
|
|
|
|
(org-capture nil "z")) |
|
|
|
|
((search-forward "Accept ]") |
|
|
|
|
(message "found generic meeting") |
|
|
|
|
(search-forward "Summary:") |
|
|
|
|
(right-word) |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (get-buffer-to-eol)) |
|
|
|
|
(search-forward "Location:") |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (concat zoom-summary " @" (get-buffer-to-eol))) |
|
|
|
|
(search-forward "Time:") |
|
|
|
|
(search-forward "<") |
|
|
|
|
(left-char) |
|
|
|
|
(setq zoom-scheduled-time (get-buffer-to-eol)) |
|
|
|
|
(org-capture nil "z"))))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; define 'z' as the shortcut |
|
|
|
|
(add-to-list 'mu4e-view-actions |
|
|
|
|
'("zCreate agenda item for meeting" . create-item-for-meeting) t) |
|
|
|
|
(advice-add 'mu4e-update-mail-and-index :around |
|
|
|
|
(lambda (orig-fun &rest args) |
|
|
|
|
"Only trigger an update if the server is the one that should |
|
|
|
|
currently be active; otherwise each mu4e instance will trigger an |
|
|
|
|
update" |
|
|
|
|
(when (string-equal server-name (kde-current-activity-name)) |
|
|
|
|
(apply orig-fun args)))) |
|
|
|
|
|
|
|
|
|
(advice-add 'mu4e~header-line-format :around |
|
|
|
|
(lambda (orig-fun &rest args) |
|
|
|
|
(let ((mu4e-use-fancy-chars t) |
|
|
|
|
(mu4e--mark-fringe-len 5)) |
|
|
|
|
(apply orig-fun args)))) |
|
|
|
|
(require 'smtpmail) |
|
|
|
|
(require 'mu4e) |
|
|
|
|
(require 'helm-mu) |
|
|
|
|
(global-set-key (kbd "C-x μ") 'mu4e) |
|
|
|
|
(global-set-key (kbd "C-x 5 μ") (eval-with-new-frame (mu4e))) |
|
|
|
|
|
|
|
|
|
(defalias 'μ 'mu4e) |
|
|
|
|
|
|
|
|
|
(setq mu4e-maildir "~/.mail" |
|
|
|
|
mu4e-attachment-dir "~/attachments" |
|
|
|
|
mu4e-html2text-command "w3m -dump -T text/html -cols 72 -o display_link_number=true -o auto_image=false -o display_image=false -o ignore_null_img_alt=true" |
|
|
|
|
mu4e-headers-show-threads nil |
|
|
|
|
mu4e-headers-sort-direction "descending" |
|
|
|
|
mail-user-agent 'mu4e-user-agent |
|
|
|
|
read-mail-command 'mu4e |
|
|
|
|
mu4e-update-interval 120 |
|
|
|
|
mu4e-view-use-gnus t |
|
|
|
|
message-kill-buffer-on-exit t |
|
|
|
|
mu4e-compose-format-flowed t |
|
|
|
|
fill-flowed-encode-column 998 |
|
|
|
|
mm-text-html-renderer 'gnus-w3m |
|
|
|
|
mu4e-read-option-use-builtin nil |
|
|
|
|
mu4e-completing-read-function 'completing-read |
|
|
|
|
mu4e-modeline-support nil |
|
|
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
(let (p1 p2 myLine) |
|
|
|
|
(setq p1 (line-beginning-position) ) |
|
|
|
|
(setq p2 (line-end-position) ) |
|
|
|
|
(setq myLine (buffer-substring-no-properties p1 p2))) |
|
|
|
|
|
|
|
|
|
(defun get-buffer-current-line () |
|
|
|
|
(let ((p (line-beginning-position)) |
|
|
|
|
(q (line-end-position))) |
|
|
|
|
(buffer-substring-no-properties p q))) |
|
|
|
|
|
|
|
|
|
(defun get-buffer-to-eol () |
|
|
|
|
(let ((p (point)) |
|
|
|
|
(q (line-end-position))) |
|
|
|
|
(buffer-substring-no-properties p q))) |
|
|
|
|
|
|
|
|
|
(defun format-zoom-meeting () |
|
|
|
|
(if (boundp 'zoom-link) |
|
|
|
|
(if (boundp 'zoom-passcode) |
|
|
|
|
(concat zoom-summary |
|
|
|
|
" [[" zoom-link "][link]] (" zoom-passcode ")\n SCHEDULED: " zoom-scheduled-time) |
|
|
|
|
(concat zoom-summary |
|
|
|
|
" [[" zoom-link "][link]]\n SCHEDULED: " zoom-scheduled-time)) |
|
|
|
|
(concat zoom-summary "\n SCHEDULED: " zoom-scheduled-time))) |
|
|
|
|
|
|
|
|
|
(defun create-item-for-meeting (msg) |
|
|
|
|
"Search for messages sent by the sender of the message at point." |
|
|
|
|
(makunbound 'zoom-link) |
|
|
|
|
(makunbound 'zoom-passcode) |
|
|
|
|
(save-excursion |
|
|
|
|
(beginning-of-buffer) |
|
|
|
|
(cond ((search-forward "Join Zoom Meeting" nil t) |
|
|
|
|
(message "found zoom meeting") |
|
|
|
|
(right-char) |
|
|
|
|
(setq zoom-link (get-buffer-current-line)) |
|
|
|
|
(when (search-forward "Passcode:" nil t) |
|
|
|
|
(setq zoom-passcode (get-buffer-current-line))) |
|
|
|
|
(beginning-of-buffer) |
|
|
|
|
(search-forward "Time:") |
|
|
|
|
(search-forward "<") |
|
|
|
|
(left-char) |
|
|
|
|
(setq zoom-scheduled-time (get-buffer-to-eol)) |
|
|
|
|
(search-backward "Summary:") |
|
|
|
|
(right-word) |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (get-buffer-to-eol)) |
|
|
|
|
(org-capture nil "z")) |
|
|
|
|
((search-forward "Accept ]") |
|
|
|
|
(message "found generic meeting") |
|
|
|
|
(search-forward "Summary:") |
|
|
|
|
(right-word) |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (get-buffer-to-eol)) |
|
|
|
|
(search-forward "Location:") |
|
|
|
|
(right-word) |
|
|
|
|
(left-word) |
|
|
|
|
(setq zoom-summary (concat zoom-summary " @" (get-buffer-to-eol))) |
|
|
|
|
(search-forward "Time:") |
|
|
|
|
(search-forward "<") |
|
|
|
|
(left-char) |
|
|
|
|
(setq zoom-scheduled-time (get-buffer-to-eol)) |
|
|
|
|
(org-capture nil "z"))))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; define 'z' as the shortcut |
|
|
|
|
(add-to-list 'mu4e-view-actions |
|
|
|
|
'("zCreate agenda item for meeting" . create-item-for-meeting) t) |
|
|
|
|
(advice-add 'mu4e-update-mail-and-index :around |
|
|
|
|
(lambda (orig-fun &rest args) |
|
|
|
|
"Only trigger an update if the server is the one that should |
|
|
|
|
currently be active; otherwise each mu4e instance will trigger an |
|
|
|
|
update" |
|
|
|
|
(when (string-equal server-name (kde-current-activity-name)) |
|
|
|
|
(apply orig-fun args)))) |
|
|
|
|
|
|
|
|
|
(advice-add 'mu4e~header-line-format :around |
|
|
|
|
(lambda (orig-fun &rest args) |
|
|
|
|
(let ((mu4e-use-fancy-chars t) |
|
|
|
|
(mu4e--mark-fringe-len 5)) |
|
|
|
|
(apply orig-fun args)))) |
|
|
|
|
|
|
|
|
|
#+end_src |
|
|
|
|
*** Recipient handling |
|
|
|
|
@ -979,80 +981,83 @@ |
|
|
|
|
|
|
|
|
|
Customize ~mu4e~ contexts |
|
|
|
|
#+begin_src emacs-lisp |
|
|
|
|
(setq mu4e-contexts |
|
|
|
|
`( ,(make-mu4e-context |
|
|
|
|
:name "Work" |
|
|
|
|
:enter-func (lambda () (mu4e-message "Switch to the Work context")) |
|
|
|
|
;; no leave-func |
|
|
|
|
;; we match based on the maildir of the message |
|
|
|
|
:match-func (lambda (msg) |
|
|
|
|
(when msg |
|
|
|
|
(string-match-p "^/math/INBOX" (mu4e-message-field |
|
|
|
|
msg :maildir)))) |
|
|
|
|
:vars '( ( user-mail-address . "jacopods@math.utoronto.ca" ) |
|
|
|
|
( user-full-name . "Jacopo De Simoi" ) |
|
|
|
|
( mu4e-sent-folder . "/math/Sent") |
|
|
|
|
( mu4e-drafts-folder . "/math/Drafts") |
|
|
|
|
( mu4e-trash-folder . "/math/Trash") |
|
|
|
|
( mu4e-refile-folder . "/math/Archive") |
|
|
|
|
( smtpmail-stream-type . starttls ) |
|
|
|
|
( smtpmail-smtp-service . 587 ) |
|
|
|
|
( mu4e-compose-signature . (concat |
|
|
|
|
"Jacopo De Simoi (he · him)\n" |
|
|
|
|
"Professor · U Toronto\n")))) |
|
|
|
|
|
|
|
|
|
,(make-mu4e-context |
|
|
|
|
:name "CMP Editor" |
|
|
|
|
:enter-func (lambda () (mu4e-message "Switch to the CMP Editor context")) |
|
|
|
|
:leave-func (lambda () (mu4e-message "Leave the CMP Editor context")) |
|
|
|
|
;; we match based on the maildir of the message |
|
|
|
|
:match-func (lambda (msg) |
|
|
|
|
(when msg |
|
|
|
|
(string-match-p "^/math/editorial.CMP" (mu4e-message-field |
|
|
|
|
msg :maildir)))) |
|
|
|
|
:vars '( ( user-mail-address . "jacopods@math.utoronto.ca" ) |
|
|
|
|
( user-full-name . "Jacopo De Simoi" ) |
|
|
|
|
( mu4e-sent-folder . "/math/Sent") |
|
|
|
|
( mu4e-drafts-folder . "/math/Drafts") |
|
|
|
|
( mu4e-trash-folder . "/math/Trash") |
|
|
|
|
( mu4e-refile-folder . "/math/editorial.CMP.Archive") |
|
|
|
|
( smtpmail-stream-type . starttls ) |
|
|
|
|
( smtpmail-smtp-service . 587 ) |
|
|
|
|
( mu4e-compose-signature . (concat |
|
|
|
|
"Jacopo De Simoi (he · him)\n" |
|
|
|
|
"Associate Editor for CMP\n" |
|
|
|
|
"Professor · U Toronto\n")))))) |
|
|
|
|
|
|
|
|
|
;; set `mu4e-context-policy` and `mu4e-compose-policy` to tweak when mu4e should |
|
|
|
|
;; guess or ask the correct context, e.g. |
|
|
|
|
|
|
|
|
|
;; start with the first (default) context; |
|
|
|
|
;; default is to ask-if-none (ask when there's no context yet, and none match) |
|
|
|
|
(setq mu4e-context-policy 'pick-first) |
|
|
|
|
|
|
|
|
|
;; compose with the current context is no context matches; |
|
|
|
|
;; default is to ask |
|
|
|
|
(setq mu4e-compose-context-policy 'pick-first) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(add-hook 'mu4e-headers-mode-hook |
|
|
|
|
#'(lambda () (setq-local show-trailing-whitespace nil))) |
|
|
|
|
(add-hook 'mu4e-view-mode-hook |
|
|
|
|
#'(lambda () (setq-local show-trailing-whitespace nil))) |
|
|
|
|
(add-hook 'mu4e-compose-mode-hook |
|
|
|
|
#'(lambda () |
|
|
|
|
(auto-fill-mode -1) |
|
|
|
|
(visual-line-mode) |
|
|
|
|
;; flyspell does not want to work with buffers that |
|
|
|
|
;; start with a "*", but this includes compose buffers |
|
|
|
|
;; (that are called *draft*) |
|
|
|
|
(let ((flyspell-lazy-disallow-buffers nil)) |
|
|
|
|
(flyspell-mode)))) |
|
|
|
|
(setq mu4e-contexts |
|
|
|
|
`( ,(make-mu4e-context |
|
|
|
|
:name "Work" |
|
|
|
|
:enter-func |
|
|
|
|
(lambda () (mu4e-message "Switch to the Work context")) |
|
|
|
|
;; no leave-func |
|
|
|
|
;; we match based on the maildir of the message |
|
|
|
|
:match-func (lambda (msg) |
|
|
|
|
(when msg |
|
|
|
|
(string-match-p "^/math/INBOX" (mu4e-message-field |
|
|
|
|
msg :maildir)))) |
|
|
|
|
:vars '( ( user-mail-address . "jacopods@math.utoronto.ca" ) |
|
|
|
|
( user-full-name . "Jacopo De Simoi" ) |
|
|
|
|
( mu4e-sent-folder . "/math/Sent") |
|
|
|
|
( mu4e-drafts-folder . "/math/Drafts") |
|
|
|
|
( mu4e-trash-folder . "/math/Trash") |
|
|
|
|
( mu4e-refile-folder . "/math/Archive") |
|
|
|
|
( smtpmail-stream-type . starttls ) |
|
|
|
|
( smtpmail-smtp-service . 587 ) |
|
|
|
|
( mu4e-compose-signature . (concat |
|
|
|
|
"Jacopo De Simoi (he · him)\n" |
|
|
|
|
"Professor · U Toronto\n")))) |
|
|
|
|
|
|
|
|
|
,(make-mu4e-context |
|
|
|
|
:name "CMP Editor" |
|
|
|
|
:enter-func |
|
|
|
|
(lambda () (mu4e-message "Switch to the CMP Editor context")) |
|
|
|
|
:leave-func |
|
|
|
|
(lambda () (mu4e-message "Leave the CMP Editor context")) |
|
|
|
|
;; we match based on the maildir of the message |
|
|
|
|
:match-func (lambda (msg) |
|
|
|
|
(when msg |
|
|
|
|
(string-match-p "^/math/editorial.CMP" (mu4e-message-field |
|
|
|
|
msg :maildir)))) |
|
|
|
|
:vars '( ( user-mail-address . "jacopods@math.utoronto.ca" ) |
|
|
|
|
( user-full-name . "Jacopo De Simoi" ) |
|
|
|
|
( mu4e-sent-folder . "/math/Sent") |
|
|
|
|
( mu4e-drafts-folder . "/math/Drafts") |
|
|
|
|
( mu4e-trash-folder . "/math/Trash") |
|
|
|
|
( mu4e-refile-folder . "/math/editorial.CMP.Archive") |
|
|
|
|
( smtpmail-stream-type . starttls ) |
|
|
|
|
( smtpmail-smtp-service . 587 ) |
|
|
|
|
( mu4e-compose-signature . (concat |
|
|
|
|
"Jacopo De Simoi (he · him)\n" |
|
|
|
|
"Associate Editor for CMP\n" |
|
|
|
|
"Professor · U Toronto\n")))))) |
|
|
|
|
|
|
|
|
|
;; set `mu4e-context-policy` and `mu4e-compose-policy` to tweak when mu4e should |
|
|
|
|
;; guess or ask the correct context, e.g. |
|
|
|
|
|
|
|
|
|
;; start with the first (default) context; |
|
|
|
|
;; default is to ask-if-none (ask when there's no context yet, and none match) |
|
|
|
|
(setq mu4e-context-policy 'ask-if-none) |
|
|
|
|
|
|
|
|
|
;; compose with the current context is no context matches; |
|
|
|
|
;; default is to ask |
|
|
|
|
(setq mu4e-compose-context-policy 'ask-if-none) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(add-hook 'mu4e-headers-mode-hook |
|
|
|
|
#'(lambda () (setq-local show-trailing-whitespace nil))) |
|
|
|
|
(add-hook 'mu4e-view-mode-hook |
|
|
|
|
#'(lambda () (setq-local show-trailing-whitespace nil))) |
|
|
|
|
(add-hook 'mu4e-compose-mode-hook |
|
|
|
|
#'(lambda () |
|
|
|
|
(auto-fill-mode -1) |
|
|
|
|
(visual-line-mode) |
|
|
|
|
;; flyspell does not want to work with buffers that |
|
|
|
|
;; start with a "*", but this includes compose buffers |
|
|
|
|
;; (that are called *draft*) |
|
|
|
|
(let ((flyspell-lazy-disallow-buffers nil)) |
|
|
|
|
(flyspell-mode)))) |
|
|
|
|
|
|
|
|
|
(define-key-alist message-mode-map |
|
|
|
|
'(("M-\"" . (lambda (r-begin r-end) |
|
|
|
|
(interactive "r") |
|
|
|
|
(add-delimiter "“" "”" r-begin r-end))))) |
|
|
|
|
(define-key-alist message-mode-map |
|
|
|
|
'(("M-\"" . (lambda (r-begin r-end) |
|
|
|
|
(interactive "r") |
|
|
|
|
(add-delimiter "“" "”" r-begin r-end))))) |
|
|
|
|
|
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
@ -1061,7 +1066,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Get mail |
|
|
|
|
(setq mu4e-get-mail-command " mbsync math-fast; mbsync proton-capture" |
|
|
|
|
(setq mu4e-get-mail-command "mbsync math-fast; mbsync proton-capture" |
|
|
|
|
mu4e-change-filenames-when-moving t ; needed for mbsync |
|
|
|
|
mu4e-headers-include-related nil ;do not include threaded |
|
|
|
|
;sent messages in inbox queries |
|
|
|
|
|