846 lines
26 KiB
Org Mode
846 lines
26 KiB
Org Mode
#+title: Doom Emacs literal configuration
|
|
#+STARTUP: content
|
|
* Table of Contents :TOC_3:noexport:
|
|
- [[#misc][Misc]]
|
|
- [[#lexical-bindings][Lexical bindings]]
|
|
- [[#dir-local-variables][Dir local variables]]
|
|
- [[#taking-svg-screenshots][Taking SVG screenshots]]
|
|
- [[#theme][Theme]]
|
|
- [[#main-theme][Main theme]]
|
|
- [[#dark-theme-toggle][Dark theme toggle]]
|
|
- [[#font][Font]]
|
|
- [[#line-numbers][Line numbers]]
|
|
- [[#battery-indicator][Battery indicator]]
|
|
- [[#programming][Programming]]
|
|
- [[#tridactyl-mode][Tridactyl mode]]
|
|
- [[#smart-parens][Smart parens]]
|
|
- [[#rust][Rust]]
|
|
- [[#column-width][Column width]]
|
|
- [[#run-clippy-in-rust-analyzer][Run clippy in rust-analyzer]]
|
|
- [[#enable-proc-macro-support][Enable proc macro support]]
|
|
- [[#cc][C/C++]]
|
|
- [[#default-style][Default style]]
|
|
- [[#nix][Nix]]
|
|
- [[#formatting][Formatting]]
|
|
- [[#lilypond][LilyPond]]
|
|
- [[#org-mode][Org mode]]
|
|
- [[#directory][Directory]]
|
|
- [[#appearance][Appearance]]
|
|
- [[#fancier-ellipsis-indicator][Fancier ellipsis indicator]]
|
|
- [[#logging][Logging]]
|
|
- [[#archiving][Archiving]]
|
|
- [[#agenda-setup][Agenda setup]]
|
|
- [[#default-task-keywords][Default task keywords]]
|
|
- [[#org-capture-setup][Org capture setup]]
|
|
- [[#main-agenda-view][Main agenda view]]
|
|
- [[#habits][Habits]]
|
|
- [[#save-all-org-buffers-shortcut][Save all org buffers shortcut]]
|
|
- [[#script-to-open-agenda-window-automatically][Script to open agenda window automatically]]
|
|
- [[#roam][Roam]]
|
|
- [[#roam-directory][Roam Directory]]
|
|
- [[#org-roam-ui][org-roam-ui]]
|
|
- [[#export-backends][Export backends]]
|
|
- [[#doom-specific][Doom specific]]
|
|
- [[#enable-some-link-modules-that-doom-disables-by-default][Enable some link modules that doom disables by default]]
|
|
- [[#bugfix][Bugfix]]
|
|
- [[#magit][Magit]]
|
|
- [[#gitlab-ci-skip-flag][Gitlab CI skip flag]]
|
|
- [[#email][Email]]
|
|
- [[#account-configuration][Account configuration]]
|
|
- [[#sending-mail][Sending mail]]
|
|
- [[#reading-plain-text][Reading plain text]]
|
|
- [[#org-msg-setup][=org-msg= setup]]
|
|
- [[#message-quoting-style][Message quoting style]]
|
|
- [[#disable-formatflowed][Disable format=flowed]]
|
|
- [[#dont-permanently-delete-when-trashing-mails][Don't permanently delete when trashing mails]]
|
|
- [[#add-git-apply-path-to-mu4e-actions][Add git-apply-path to mu4e actions]]
|
|
- [[#enable-auto-updates][Enable auto updates]]
|
|
- [[#ask-which-address-to-send-with-when-composing-a-new-mail][Ask which address to send with when composing a new mail]]
|
|
- [[#only-fetch-main-directories-by-default][Only fetch main directories by default]]
|
|
- [[#headers-view-format][Headers view format]]
|
|
- [[#message-view-fields][Message view fields]]
|
|
- [[#mailing-list-pretty-names][Mailing list pretty names]]
|
|
- [[#fix-attachment-icon-with-light-theme][Fix attachment icon with light theme]]
|
|
- [[#bookmarks][Bookmarks]]
|
|
- [[#apply-marks-on-quit][Apply marks on quit]]
|
|
|
|
* Misc
|
|
|
|
** Lexical bindings
|
|
|
|
Enable lexical binding, of course...
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;; -*- lexical-binding: t; -*-
|
|
#+END_SRC
|
|
|
|
** Dir local variables
|
|
|
|
Disable these because I don't use them and don't want to get prompted by them in
|
|
some projects.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq enable-dir-local-variables nil)
|
|
#+END_SRC
|
|
|
|
** Taking SVG screenshots
|
|
|
|
Since Emacs 27, we can take SVG screenshots! Emacs needs to be built with
|
|
=cairo= to support this.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun my/screenshot-svg ()
|
|
"Save a screenshot of the current frame as an SVG image.
|
|
Saves to a temp file and puts the filename in the kill ring."
|
|
(interactive)
|
|
(let ((filename (make-temp-file "Emacs" nil ".svg"))
|
|
(data (x-export-frames nil 'svg)))
|
|
(with-temp-file filename
|
|
(insert data))
|
|
(kill-new filename)
|
|
(message filename)))
|
|
#+end_src
|
|
|
|
* Theme
|
|
|
|
** Main theme
|
|
|
|
A list of all doom themes can be found here:
|
|
|
|
https://github.com/hlissner/emacs-doom-themes
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq doom-theme 'doom-one-light)
|
|
#+END_SRC
|
|
|
|
** Dark theme toggle
|
|
|
|
I've come to prefer using a light theme during the day, and a dark theme at
|
|
night. Using a dark theme with daylight leads to cranking up the screen
|
|
brightness, which hurts my eyes more than using the light theme.
|
|
|
|
Set my light and dark themes:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq my/light-theme doom-theme
|
|
my/dark-theme 'doom-one)
|
|
#+END_SRC
|
|
|
|
Function to toggle between the two easily:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun my/toggle-dark-theme ()
|
|
(interactive)
|
|
(if (eq my/dark-theme doom-theme)
|
|
(load-theme my/light-theme t)
|
|
(load-theme my/dark-theme t)))
|
|
#+END_SRC
|
|
|
|
Bind this to =SPC t d=:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(map! :leader
|
|
(:prefix-map ("t" . "toggle")
|
|
:desc "Dark theme" "d" #'my/toggle-dark-theme))
|
|
#+END_SRC
|
|
|
|
** Font
|
|
|
|
Doom exposes five (optional) variables for controlling fonts in Doom. Here are
|
|
the three important ones:
|
|
|
|
- =doom-font=
|
|
- =doom-variable-pitch-font=
|
|
- =doom-big-font= -- used for =doom-big-font-mode=; use this for presentations
|
|
or streaming.
|
|
|
|
They all accept either a font-spec, font string (=Input Mono-12=), or xlfd font
|
|
string. You generally only need these two:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq doom-font
|
|
(font-spec :family "Iosevka Fixed" :size 10.0 :weight 'medium))
|
|
#+END_SRC
|
|
|
|
** Line numbers
|
|
|
|
Possible values of =display-line-numbers-type= are =nil=, =t=, and ='relative=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq display-line-numbers-type 'relative)
|
|
#+END_SRC
|
|
|
|
** Battery indicator
|
|
|
|
I'm on a laptop, so let's display my battery in the modeline:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(display-battery-mode 1)
|
|
#+END_SRC
|
|
|
|
* Programming
|
|
|
|
** Tridactyl mode
|
|
|
|
#+begin_src emacs-lisp
|
|
(defvar tridactylrc-font-lock-keywords
|
|
`( ;; Line comment
|
|
("^[\t ]*\\(\"\\)\\(.*\\)$"
|
|
(1 font-lock-comment-delimiter-face)
|
|
(2 font-lock-comment-face))
|
|
|
|
;; Trailing comment
|
|
("[\t ]+\\(\"\\)\\([^\"\r\n]*\\)$"
|
|
(1 font-lock-comment-delimiter-face)
|
|
(2 font-lock-comment-face))
|
|
|
|
;; String start:
|
|
("\\(\"[^\n\r\"]*\"\\)\\|\\('[^\n\r]*'\\)"
|
|
(0 font-lock-string-face)) ;; String end;
|
|
))
|
|
|
|
(defvar tridactylrc-mode-syntax-table
|
|
(let ((table (make-syntax-table)))
|
|
(modify-syntax-entry ?' "\"" table)
|
|
(modify-syntax-entry ?\" "<" table)
|
|
(modify-syntax-entry ?\n ">" table)
|
|
table))
|
|
|
|
(define-derived-mode tridactylrc-mode prog-mode "tridactylrc"
|
|
"Major mode for editing tridactylrc configuration files."
|
|
:group 'tridactylrc-mode
|
|
:syntax-table tridactylrc-mode-syntax-table
|
|
(font-lock-add-keywords nil tridactylrc-font-lock-keywords)
|
|
(setq-local comment-start "\"")
|
|
(setq-local comment-end ""))
|
|
#+end_src
|
|
|
|
** Smart parens
|
|
|
|
Disable smart parens because half of the time it doesn't do what I want:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(remove-hook 'doom-first-buffer-hook #'smartparens-global-mode)
|
|
#+END_SRC
|
|
|
|
** Rust
|
|
|
|
*** Column width
|
|
=rustfmt= limits lines to 100 characters, let's display it correctly.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook! rustic-mode
|
|
(set-fill-column 100))
|
|
#+END_SRC
|
|
|
|
*** Run clippy in rust-analyzer
|
|
|
|
The default is ~"check"~, but I want clippy lints as well.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq lsp-rust-analyzer-cargo-watch-command "clippy")
|
|
#+end_src
|
|
|
|
*** Enable proc macro support
|
|
|
|
By default lsp-mode disable these, I want them.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq lsp-rust-analyzer-experimental-proc-attr-macros t)
|
|
(setq lsp-rust-analyzer-proc-macro-enable t)
|
|
#+end_src
|
|
|
|
** C/C++
|
|
|
|
*** Default style
|
|
|
|
Setup the default format for C/C++ editing.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook! (c-mode c++-mode)
|
|
(setq c-default-style "gnu")
|
|
(setq c-basic-offset 2))
|
|
#+END_SRC
|
|
|
|
** Nix
|
|
|
|
*** Formatting
|
|
|
|
Use [[https://github.com/kamadorueda/alejandra][alejandra]] to format Nix code.
|
|
|
|
#+begin_src emacs-lisp
|
|
(set-formatter! 'alejandra "alejandra --quiet" :modes '(nix-mode))
|
|
#+end_src
|
|
** LilyPond
|
|
|
|
Just load the lilypond mode
|
|
|
|
#+begin_src emacs-lisp
|
|
(require 'lilypond-mode)
|
|
#+end_src
|
|
|
|
* Org mode
|
|
|
|
** Directory
|
|
|
|
Set a default directory for all my org-mode files.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq org-directory "~/org/")
|
|
#+END_SRC
|
|
|
|
** Appearance
|
|
|
|
*** Fancier ellipsis indicator
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq org-ellipsis " ▼ ")
|
|
#+END_SRC
|
|
|
|
** Logging
|
|
|
|
Log state changes in a src_org{:LOGBOOK:} drawer so that it doesn't pollute the main content.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org
|
|
(setq org-log-into-drawer t))
|
|
#+end_src
|
|
|
|
** Archiving
|
|
|
|
I don't want to see archival files appearing when listing files in the current
|
|
directory, so hide them by default.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org
|
|
(setq org-archive-location ".%s_archive::"))
|
|
#+end_src
|
|
|
|
** Agenda setup
|
|
|
|
*** Default task keywords
|
|
|
|
Here are the [[https://orgmode.org/manual/TODO-Extensions.html#TODO-Extensions][keywords]] I'm using to track task progress. I'm also making use of
|
|
some automatic [[https://orgmode.org/manual/Tracking-TODO-state-changes.html#Tracking-TODO-state-changes][state changes]].
|
|
|
|
| keyword | meaning |
|
|
|-------------+----------------------------------------------------------|
|
|
| =TODO= | Self explanatory |
|
|
| =DONE= | This task is finished, no longer displayed in the agenda |
|
|
| =CANCELLED= | This task isn't finished but is no longer relevant |
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org
|
|
(setq org-todo-keywords
|
|
'((sequence
|
|
"TODO(t)"
|
|
"|"
|
|
"DONE(d!)"
|
|
"CANCELLED(c@/!)")
|
|
(sequence
|
|
"[ ](T)"
|
|
"|"
|
|
"[X](D)"))))
|
|
#+END_SRC
|
|
|
|
*** Org capture setup
|
|
|
|
Of course I also need to setup [[https://orgmode.org/manual/Capture-templates.html][capture templates]]:
|
|
|
|
The first one just prompts me for a new task to add to my inbox, I can then
|
|
[[https://orgmode.org/guide/Refile-and-Copy.html][refile]] them where I want later.
|
|
|
|
The second one exists because I like to keep a separate list of articles /
|
|
papers / books to read.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org
|
|
(setq org-capture-templates
|
|
'(("t" "New entry" entry (file "inbox.org")
|
|
"* TODO %?")
|
|
("T" "Task" entry (file+headline "tasks.org" "Misc")
|
|
"* TODO %?")
|
|
("r" "Reading" entry (file "reading.org")
|
|
"* TODO %x"
|
|
:immediate-finish t)
|
|
("w" "Watching" entry (file "watching.org")
|
|
"* TODO %x"
|
|
:immediate-finish t))))
|
|
#+END_SRC
|
|
|
|
I also change [[https://github.com/hlissner/doom-emacs/blob/134554dd69d9b1cea3d2190422de580fddf40ecd/modules/config/default/%2Bevil-bindings.el#L265][the default Doom binding]] for ~#'org-capture~ to be =SPC x= instead
|
|
of =SPC X=. Also need to rebind what was [[https://github.com/hlissner/doom-emacs/blob/134554dd69d9b1cea3d2190422de580fddf40ecd/modules/config/default/%2Bevil-bindings.el#L264][previously bound]] to =SPC x=, to =SPC
|
|
X=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(map! :leader
|
|
:desc "Org Capture" "x" #'org-capture
|
|
:desc "Pop up scratch buffer" "X" #'doom/open-scratch-buffer)
|
|
#+END_SRC
|
|
|
|
*** Main agenda view
|
|
|
|
All these tasks, once captured, are then centralized in my [[https://orgmode.org/guide/Agenda-Views.html][agenda view]].
|
|
|
|
I'm using multiple categories to organize tasks, depending on their triage /
|
|
status (inspired by [[https://blog.jethro.dev/posts/org_mode_workflow_preview/]]).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org-agenda
|
|
(setq org-agenda-custom-commands
|
|
'((" " "Agenda"
|
|
((agenda ""
|
|
((org-agenda-span 'day)
|
|
(org-agenda-start-day nil)
|
|
(org-deadline-warning-days 365)))
|
|
(todo "TODO"
|
|
((org-agenda-overriding-header "Triage")
|
|
(org-agenda-files '("~/org/inbox.org"))))
|
|
(todo "TODO"
|
|
((org-agenda-overriding-header "Job")
|
|
(org-agenda-files '("~/org/job.org"))
|
|
(org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline
|
|
'scheduled))))
|
|
(todo "TODO"
|
|
((org-agenda-overriding-header "Tasks")
|
|
(org-agenda-files '("~/org/tasks.org"))
|
|
(org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline
|
|
'scheduled))))
|
|
)))))
|
|
#+END_SRC
|
|
|
|
I want the default agenda view to be a weekly view, with a log of what I've done
|
|
during the day.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org-agenda
|
|
(setq org-agenda-span 'week)
|
|
(setq org-agenda-start-on-weekday 1)
|
|
(setq org-agenda-start-with-log-mode '(clock)))
|
|
#+END_SRC
|
|
|
|
I also remove the block separators in the agenda view:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org-agenda
|
|
(setq org-agenda-block-separator ""))
|
|
#+END_SRC
|
|
|
|
*** Habits
|
|
|
|
Let's enable the =org-habit= module:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'org-modules 'org-habit)
|
|
(after! org-agenda
|
|
(setq org-habit-show-all-today t))
|
|
#+END_SRC
|
|
|
|
*** Save all org buffers shortcut
|
|
|
|
By default bound to =C-x C-s=, rebind it to =SPC m s= in =org-agenda-mode= :
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(map! :after org-agenda
|
|
:map org-agenda-mode-map
|
|
:localleader
|
|
"s" #'org-save-all-org-buffers)
|
|
#+END_SRC
|
|
|
|
*** Script to open agenda window automatically
|
|
|
|
I use this script to automatically open the agenda when pressing a specific key binding in my window manager.
|
|
|
|
#+begin_src emacs-lisp :tangle "launch-agenda.el"
|
|
(find-file org-directory)
|
|
(with-selected-window (split-window-horizontally)
|
|
;; need to wait for the window to appear
|
|
(sleep-for 0.1)
|
|
(org-agenda nil " "))
|
|
#+end_src
|
|
|
|
** Roam
|
|
|
|
Setup for [[https://github.com/jethrokuan/org-roam][org-roam]].
|
|
|
|
*** Roam Directory
|
|
|
|
First, set a directory where =org-roam= will index things.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq org-roam-directory (expand-file-name "notes/" org-directory))
|
|
#+END_SRC
|
|
|
|
*** org-roam-ui
|
|
|
|
Setup [[https://github.com/org-roam/org-roam-ui][org-roam-ui]]
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! websocket
|
|
:after org-roam)
|
|
|
|
(use-package! org-roam-ui
|
|
:after org-roam
|
|
:config (setq org-roam-ui-sync-theme t
|
|
org-roam-ui-follow t
|
|
org-roam-ui-update-on-save t
|
|
org-roam-ui-open-on-start t))
|
|
#+end_src
|
|
|
|
** Export backends
|
|
|
|
Sometimes I need to export an Org subtree to a file, which is quite easy with
|
|
the =org= export backend. It doesn't seem to be enabled by default, so let's add
|
|
it to the list:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! org
|
|
(add-to-list 'org-export-backends 'org))
|
|
#+END_SRC
|
|
|
|
** Doom specific
|
|
|
|
Doom makes some changes to org-id behaviour which I don't like / think are necessary.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org
|
|
(setq org-id-locations-file (expand-file-name "~/.config/emacs/.org-id-locations"))
|
|
(setq org-id-locations-file-relative nil))
|
|
#+end_src
|
|
|
|
Doom replaces the default tab behavior on headings, this restores the default
|
|
one. Taken from [[https://github.com/hlissner/doom-emacs/tree/develop/modules/lang/org#hacks][here]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! evil-org
|
|
(remove-hook 'org-tab-first-hook #'+org-cycle-only-current-subtree-h))
|
|
#+END_SRC
|
|
|
|
*** Enable some link modules that doom disables by default
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'org-modules 'ol-info)
|
|
(add-to-list 'org-modules 'ol-doi)
|
|
#+end_src
|
|
|
|
*** Bugfix
|
|
|
|
Fix a bug with capture mode not working correctly when agenda is opened, stolen
|
|
from https://github.com/hlissner/doom-emacs/issues/5714#issuecomment-1018788028
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org
|
|
(defadvice! dan/+org--restart-mode-h-careful-restart (fn &rest args)
|
|
:around #'+org--restart-mode-h
|
|
(let ((old-org-capture-current-plist (and (bound-and-true-p org-capture-mode)
|
|
(bound-and-true-p org-capture-current-plist))))
|
|
(apply fn args)
|
|
(when old-org-capture-current-plist
|
|
(setq-local org-capture-current-plist old-org-capture-current-plist)
|
|
(org-capture-mode +1)))))
|
|
#+end_src
|
|
|
|
* Magit
|
|
|
|
** Gitlab CI skip flag
|
|
|
|
This option tells GitLab to skip the CI run for this push, in case I know it's
|
|
not ready yet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(after! magit
|
|
(transient-append-suffix 'magit-push "-n"
|
|
'(4 "-s" "Skip GitLab CI" "--push-option=ci.skip")))
|
|
#+END_SRC
|
|
|
|
GitLab push options are documented [[https://docs.gitlab.com/ee/user/project/push_options.html][here]].
|
|
|
|
* Email
|
|
|
|
#+begin_src emacs-lisp :noweb no-export
|
|
(after! mu4e
|
|
<<after-mu4e>>)
|
|
#+end_src
|
|
|
|
** Account configuration
|
|
|
|
Setup my main email account.
|
|
|
|
#+begin_src emacs-lisp
|
|
(set-email-account! "alarsyo"
|
|
'((mu4e-sent-folder . "/alarsyo/Sent")
|
|
(mu4e-drafts-folder . "/alarsyo/Drafts")
|
|
(mu4e-refile-folder . "/alarsyo/Archive")
|
|
(mu4e-trash-folder . "/alarsyo/Trash")
|
|
(user-mail-address . "antoine@alarsyo.net")
|
|
(user-full-name . "Antoine Martin")
|
|
(mu4e-compose-signature . "Antoine Martin"))
|
|
t)
|
|
|
|
(set-email-account! "lrde"
|
|
'((mu4e-sent-folder . "/lrde/Sent")
|
|
(mu4e-drafts-folder . "/lrde/Drafts")
|
|
(mu4e-trash-folder . "/lrde/Trash")
|
|
(user-mail-address . "amartin@lrde.epita.fr")
|
|
(user-full-name . "Antoine Martin")
|
|
(mu4e-compose-signature . "Antoine Martin"))
|
|
nil)
|
|
|
|
(set-email-account! "prologin"
|
|
'((mu4e-sent-folder . "/prologin/Sent")
|
|
(mu4e-drafts-folder . "/prologin/Drafts")
|
|
(mu4e-trash-folder . "/prologin/Trash")
|
|
(user-mail-address . "antoine.martin@prologin.org")
|
|
(user-full-name . "Antoine Martin")
|
|
(mu4e-compose-signature . "Antoine Martin"))
|
|
nil)
|
|
#+end_src
|
|
|
|
** Sending mail
|
|
|
|
I use =msmtp= as a SMTP forwarder
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq sendmail-program (executable-find "msmtp")
|
|
send-mail-function #'smtpmail-send-it
|
|
message-sendmail-f-is-evil t
|
|
message-sendmail-extra-arguments '("--read-envelope-from")
|
|
message-send-mail-function #'message-send-mail-with-sendmail)
|
|
#+end_src
|
|
|
|
I don't want something like ~ws-butler~ to mess with my formatting, especially
|
|
the trailing space after a signature delimiter:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook! mu4e-compose-mode
|
|
(ws-butler-mode -1))
|
|
#+END_SRC
|
|
|
|
** Reading plain text
|
|
|
|
Ask the =gnus-view= (default viewer used by =mu4e=) to avoid HTML whenever
|
|
possible.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(add-to-list 'mm-discouraged-alternatives "text/html")
|
|
(add-to-list 'mm-discouraged-alternatives "text/richtext")
|
|
#+end_src
|
|
|
|
** =org-msg= setup
|
|
|
|
Add =-:nil= to the export options list, otherwise the =--= in the signature gets
|
|
converted to a single hyphen when exporting to utf-8. See [[info:org#Export settings]]
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq org-msg-options (concat org-msg-options " -:nil"))
|
|
#+end_src
|
|
|
|
Setup signature as well. The double backslashes are there to make sure that the
|
|
linebreak is preserved even in the html export, which otherwise wraps the
|
|
signature lines as a single paragraph.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq org-msg-signature "\n#+begin_signature\n-- \\\\\nAntoine Martin\n#+end_signature")
|
|
#+end_src
|
|
|
|
I don't want to send HTML emails at all unless I choose to explicitely.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq org-msg-default-alternatives '((new utf-8)
|
|
(reply-to-text utf-8)
|
|
(reply-to-html utf-8)))
|
|
#+end_src
|
|
|
|
** Message quoting style
|
|
|
|
Has to be duplicated because =mu4e= doesn't use ~message-cite-style~'s values.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defconst message-cite-style-custom
|
|
'((message-cite-function 'message-cite-original-without-signature)
|
|
(message-citation-line-function 'message-insert-formatted-citation-line)
|
|
(message-cite-reply-position 'traditional)
|
|
(message-yank-prefix "> ")
|
|
(message-yank-cited-prefix "> ")
|
|
(message-yank-empty-prefix ">")
|
|
(message-citation-line-format "%f writes:"))
|
|
"Message citation style used for email. Use with `message-cite-style'.")
|
|
|
|
(after! message
|
|
(setq message-cite-style message-cite-style-custom
|
|
message-cite-function 'message-cite-original-without-signature
|
|
message-citation-line-function 'message-insert-formatted-citation-line
|
|
message-cite-reply-position 'traditional
|
|
message-yank-prefix "> "
|
|
message-yank-cited-prefix "> "
|
|
message-yank-empty-prefix ">"
|
|
message-citation-line-format "%f writes:"))
|
|
#+end_src
|
|
|
|
** Disable format=flowed
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-compose-format-flowed nil)
|
|
#+end_src
|
|
|
|
** Don't permanently delete when trashing mails
|
|
|
|
By default =mu4e= sets the =trashed= flag on emails trashed using the =d=
|
|
keybinding. This just replaces the action to just move the message to the trash
|
|
instead.
|
|
|
|
See https://github.com/djcb/mu/issues/1136#issuecomment-1066303788, the code
|
|
will have to be adapted soon.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setf (alist-get 'trash mu4e-marks)
|
|
(list :char '("d" . "▼")
|
|
:prompt "dtrash"
|
|
:dyn-target (lambda (target msg)
|
|
(mu4e-get-trash-folder msg))
|
|
:action (lambda (docid msg target)
|
|
(mu4e--server-move
|
|
docid (mu4e--mark-check-target target) "-N"))))
|
|
#+end_src
|
|
|
|
** Add git-apply-path to mu4e actions
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
;; TODO: upstream this, Doom emacs adds a view in browser action but it seems
|
|
;; to be present by default now.
|
|
(setq mu4e-view-actions
|
|
(remove '("View in browser" . mu4e-action-view-in-browser) mu4e-view-actions))
|
|
(add-to-list 'mu4e-view-actions
|
|
'("GitApply" . mu4e-action-git-apply-patch) t)
|
|
(add-to-list 'mu4e-view-actions
|
|
'("MboxGitApply" . mu4e-action-git-apply-mbox) t)
|
|
#+end_src
|
|
|
|
** Enable auto updates
|
|
=mu4e= refreshes my email in the background.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-update-interval 900)
|
|
#+end_src
|
|
|
|
If it fetches new mail while I'm browsing some messages, it will refresh the
|
|
headers view, potentially loosing context (like some messages that got marked as
|
|
read because I skimmed over them, but that I don't want to see disappear yet).
|
|
So let's disable this automatic update of headers:
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-auto-update nil)
|
|
#+end_src
|
|
|
|
Additionally, don't show all new mail in the modeline, only relevant ones:
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-alert-interesting-mail-query "flag:unread AND NOT flag:list")
|
|
#+end_src
|
|
|
|
** Ask which address to send with when composing a new mail
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-compose-context-policy 'ask)
|
|
#+end_src
|
|
|
|
** Only fetch main directories by default
|
|
|
|
I have a lot (100+) directories on my main email account, I only want to fetch
|
|
the "important" ones (i.e. those coming from real individuals, addressed to me
|
|
directly) when I ask for a refresh explicitely (updating everything in the
|
|
background is fine the rest of the time).
|
|
|
|
Let's define a new function that does just that:
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(defun my/mu4e-update-main-mail-and-index (run-in-background)
|
|
"Get mail for all folders, not just the main ones"
|
|
(interactive "P")
|
|
(let ((mu4e-get-mail-command "mbsync alarsyo-main lrde prologin-main"))
|
|
(mu4e-update-mail-and-index run-in-background)))
|
|
#+end_src
|
|
|
|
Let's also bind it to =u= in the main view, overriding the default binding
|
|
(which I'll remap to =U=).
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(map! :map mu4e-main-mode-map
|
|
:ne "u" #'my/mu4e-update-main-mail-and-index
|
|
:ne "U" #'mu4e-update-mail-and-index)
|
|
#+end_src
|
|
|
|
** Headers view format
|
|
|
|
Use "french" date format in header view:
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-date-format "%d/%m/%y")
|
|
#+end_src
|
|
|
|
Set the time display to 24h:
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-time-format "%T")
|
|
#+end_src
|
|
|
|
Setup the headers view columns how I like them
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-fields '((:account-stripe . 1)
|
|
;; just enough room for dd/mm/yy or hh:mm:ss
|
|
(:human-date . 8)
|
|
(:flags . 6)
|
|
(:mailing-list . 30)
|
|
(:from-or-to . 30)
|
|
(:subject)))
|
|
#+end_src
|
|
|
|
** Message view fields
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-view-fields '(:from :to :cc :subject :flags :date :mailing-list :maildir :path :size :tags :attachments :user-agent :signature :decryption))
|
|
#+end_src
|
|
|
|
** Mailing list pretty names
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-mailing-list-patterns '("[0-9]+\\.\\(.+\\)\\.gitlab\\.lrde\\.epita\\.fr"
|
|
"[0-9]+\\.\\(.+\\)\\.gitlab\\.com"
|
|
"\\(.+\\)\\.github\\.com")
|
|
mu4e-user-mailing-lists '(("info.prologin.org" . "Infos Prologin")
|
|
("membres.ml.prologin.org" . "Membres Prologin")))
|
|
#+end_src
|
|
|
|
** Fix attachment icon with light theme
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-attach-mark (cons "a" (+mu4e-normalised-icon "file-text-o" :color "cyan")))
|
|
#+end_src
|
|
|
|
** Bookmarks
|
|
|
|
Let's not display messages from mailing lists in main views, leave them to specific bookmarks.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-bookmarks '((:name "Unread messages" :query "flag:unread AND NOT flag:list" :key ?u)
|
|
(:name "Today's messages" :query "date:today..now AND NOT flag:list" :key ?t)
|
|
(:name "Last 7 days" :query "date:7d..now AND NOT flag:list" :hide-unread t :key ?w)
|
|
(:name "Messages with images" :query "mime:image/* AND NOT flag:list" :key ?p)
|
|
(:name "All unread messages" :query "flag:unread AND NOT list:emacs-orgmode.gnu.org" :key ?U)
|
|
(:name "Today's messages (lists included)" :query "date:today..now" :key ?T)
|
|
(:name "Last 7 days (lists included)" :query "date:7d..now" :hide-unread t :key ?W)
|
|
(:name "Orgmode mailing list new posts" :query "list:emacs-orgmode.gnu.org AND flag:unread" :key ?o)
|
|
(:name "All messages with images" :query "mime:image/*" :key ?P)))
|
|
#+end_src
|
|
|
|
** Apply marks on quit
|
|
|
|
I don't want confirm to apply marks everytime I quit the headers view.
|
|
|
|
#+begin_src emacs-lisp :noweb-ref after-mu4e :tangle no
|
|
(setq mu4e-headers-leave-behavior 'apply)
|
|
#+end_src
|