1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
|
;; Copyright (C) 2016-Ω Miquel Sabaté Solà <mikisabate@gmail.com>
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;
;; Early checks: force Linux and a recent GNU Emacs.
(unless (string= system-type 'gnu/linux)
(error "You are supposed to be running Linux!"))
(unless (>= emacs-major-version 30)
(error "You are supposed to be running an up-to-date GNU Emacs"))
;;;
;; Package manager: straight.el.
;; Change the repo url for nongnu-elpa as savannah is unreliable. This has been
;; changed in straight.el `develop` branch, but it's not there in the stable
;; branch.
(custom-set-variables
'(straight-recipe-overrides '((nil
(nongnu-elpa :type git
:repo "https://github.com/emacsmirror/nongnu_elpa"
:depth (full single-branch)
:local-repo "nongnu-elpa"
:build nil)))))
;; As taken from the documentation, this is some fancy Emacs Lisp code to
;; bootstrap straight.el in case it isn't available on the system already.
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name
"straight/repos/straight.el/bootstrap.el"
(or (bound-and-true-p straight-base-dir)
user-emacs-directory)))
(bootstrap-version 7))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
;; But we are actually going to use `use-package' always, so let's integrate
;; straight.el into it.
(straight-use-package 'use-package)
(setq straight-use-package-by-default t)
;;;
;; Core
;; There are some packages that expect us to have a `user-full-name' and a
;; `user-mail-address' defined.
(setq user-full-name "Miquel Sabaté Solà"
user-mail-address "mikisabate@gmail.com")
;;;
;; Key bindings: using Evil mode and general.el for the key binding shenanigans.
;; Forgive me Father, for I have sinned.
(use-package evil
:custom
(evil-want-keybinding nil) ; Defer Evil's default keybindings, let evil-collection handle it or define manually.
(evil-want-C-u-scroll t)
(evil-want-C-u-delete t)
(evil-want-C-d-scroll t)
(evil-want-C-w-delete t)
:config
(evil-mode 1))
;; Add the surround object.
(use-package evil-surround
:after evil
:config
(global-evil-surround-mode 1))
;; Carelessly comment out stuff in multiple languages.
(use-package evil-commentary
:after evil
:config
(evil-commentary-mode t))
;; Evil +everywhere.
(use-package evil-collection
:after evil
:config
(evil-collection-init))
;; Allow me to use C-z as my escape input.
(use-package evil-escape
:after general
:config
(general-define-key
:states '(insert normal)
"C-z" #'evil-escape))
(defun run-q-macro (n)
"Run the macro stored on the 'q' key `N' times."
(interactive "p")
(evil-execute-macro n "@q"))
;; Sane key-binding management.
(use-package general
:after evil
:config
;; Small C-<> mappings.
(general-define-key
:states 'normal
"C-s" #'save-buffer
"C-e" #'evil-end-of-line
"C-2" #'run-q-macro
"C-@" #'run-q-macro)
;; And being cheeky with a C-s for saving even in insert mode.
(general-define-key
:states 'insert
"C-s" (lambda () (interactive) (save-buffer) (evil-force-normal-state)))
;; Expansions for the Emacs' C-x prefix, handling windows, buffers, etc.
(general-define-key
:prefix "C-x"
"k" #'kill-this-buffer
"K" #'kill-buffer-and-window
"v" #'split-window-right
"V" (lambda () (interactive) (split-window-right) (other-window 1)))
;; Expansions for the Emacs' C-c prefix.
(general-define-key
:prefix "C-c"
;; The least-ambitious use of org-mode ever, I know.
"C-o"
(lambda ()
(interactive)
(find-file (concat (file-name-as-directory org-directory) "index.org"))))
;; Define my leader key.
(general-create-definer mssola/leader-def
:prefix "SPC")
;; Define mappings based on a <leader>.
(mssola/leader-def
:states 'normal
:keymaps 'override
"j" 'xref-find-definitions
"m" 'mssola/mu4e
"p" 'project-switch-project
"s" 'consult-ripgrep
"u" 'xref-find-references ; TODO: in vertico buffer
"SPC" 'project-find-file))
;;;
;; General
;; Follow symlinks.
(setq vc-follow-symlinks t)
;; Default to y/n instead of full yes/no.
(fset 'yes-or-no-p 'y-or-n-p)
;; Revert buffers automatically when underlying files are changed externally.
(global-auto-revert-mode t)
;; No backups: they are more of a nuisance that an actual help…
(setq-default make-backup-files nil)
(setq-default auto-save-default nil)
;; Save custom variables somewhere else
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
(load custom-file))
;; The crux package offers quite a few goodies, and I'm particularly interested
;; on the `crux-delete-file-and-buffer', which will delete the file related to
;; the current buffer as well as the buffer itself.
(use-package crux
:bind (("C-c D" . crux-delete-file-and-buffer))
:general ([remap move-beginning-of-line] #'crux-move-beginning-of-line))
;; Show me which functions are available for the key I half-pressed.
(use-package which-key
:custom
(which-key-idle-delay 0.3)
(which-key-side-window-location 'bottom)
:hook (after-init . which-key-mode))
;;;
;; UI
;; Some time ago I created this title format, and now I prefer it over other
;; options.
(setq frame-title-format
(setq icon-title-format '((:eval (concat (user-real-login-name) ": "
(if (buffer-file-name)
(abbreviate-file-name (buffer-file-name))
"%b"))))))
;; I’m using “Droid Sans Mono” simply because I’ve grown used to it.
(defconst mssola-font
"Droid Sans Mono Dotted for Powerline-10"
"The font to be used.")
(add-to-list 'default-frame-alist `(font . ,mssola-font))
;; Emacs in daemon mode does not like `set-face-attribute` because this is only
;; applied if there is a frame in place, which doesn't happen when starting the
;; daemon. Thus, we should call that after the frame has been created (e.g. by
;; emacsclient). See:
;; https://lists.gnu.org/archive/html/help-gnu-emacs/2015-03/msg00016.html
(add-hook 'after-make-frame-functions-hook
(lambda ()
(set-face-attribute 'default t :font mssola-font)))
;; Remove the initial message from the scratch buffer.
(setq initial-scratch-message nil)
;; No welcome screen
(setq-default inhibit-startup-message t)
;; Minimalistic UI.
(menu-bar-mode -1)
(when (fboundp 'set-scroll-bar-mode)
(set-scroll-bar-mode nil))
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
(when (fboundp 'tooltip-mode)
(tooltip-mode 0))
;; Display helpful information on where we are.
(line-number-mode 1)
(column-number-mode 1)
(size-indication-mode 1)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'org-mode-hook 'display-line-numbers-mode)
;; Let's make scrolling suck less.
(setq scroll-margin 0
scroll-conservatively 100000
scroll-preserve-screen-position 1)
;; There is somewhere someone who likes to be interrupted with stupid beep
;; sounds. That sorry soul is not me.
(setq ring-bell-function 'ignore)
;; Use the modeline for Doom, which is simply superior to whatever I can
;; half-ass.
(use-package doom-modeline
:custom
(doom-modeline-height 20)
(doom-modeline-persp-name nil)
(doom-modeline-major-mode-icon nil)
(doom-modeline-modal-icon t)
(doom-modeline-icon t)
(doom-modeline-buffer-file-name-style 'relative-from-project)
:hook (after-init . doom-modeline-mode))
;; Color theme: try to use my own theme called `soria'. There are two paths
;; where the `soria' theme might reside. The first path we are going to try is
;; my local dev environment, otherwise we will try the global installation path
;; (as pointed out on the documentation of the RPM package).
(let ((dev-dir (concat (getenv "HOME") "/src/github.com/mssola/soria"))
(global-dir "/usr/share/emacs/site-lisp/themes"))
(if (file-exists-p dev-dir)
(add-to-list 'custom-theme-load-path dev-dir)
(when (file-exists-p global-dir)
(add-to-list 'custom-theme-load-path global-dir)))
;; If soria could be loaded as a theme, let's set the
;; `soria-theme-purple-identifiers' hook for the relevant modes.
(when (load-theme 'soria t)
(dolist (lang-hook '(ruby-mode-hook
php-mode-hook
perl-mode-hook
emacs-lisp-mode-hook))
(add-hook lang-hook 'soria-theme-purple-identifiers))))
;; When in Evil mode, it just makes sense to have line numbers relatively.
(setq display-line-numbers-type 'relative)
;; For whatever reason someone thought that having the tilde fringe as it
;; happens to vi was a good idea. I disagree.
(remove-hook 'text-mode-hook #'vi-tilde-fringe-mode)
;; Enable number highlighting.
(use-package highlight-numbers
:hook ((prog-mode-hook conf-mode-hook) . highlight-numbers-mode))
;; Highlight todos, warnings, et al.
(use-package hl-todo
:hook ((prog-mode yaml-mode) . hl-todo-mode))
;;;
;; Core editor.
;; UTF-8 everywhere.
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-language-environment 'utf-8)
;; GNU Emacs modes typically provide a standard means to change the indentation
;; width (e.g. c-basic-offset), and that will inevitably conflict with the “tabs
;; vs spaces” question and the myriad of code conventions for each programming
;; language. We will deal with all this later.
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
;; If an .editorconfig is around, use that.
(editorconfig-mode 1)
;; As for word wrapping and filling we will take a conservative default, and
;; later we will discard it for some modes. For example, it makes sense to
;; perform auto-fill in text-mode (which includes org-mode), but there is no
;; point of doing it in source code.
(setq-default fill-column 80)
(setq-default auto-fill-function 'do-auto-fill)
;; Do not break lines
(set-default 'truncate-lines t)
;; It’s pretty bananas that I have to say it, but if I’ve pressed a key when
;; selecting text, I want that text to be nuked and replaced with whatever I’ve
;; typed. This will be overriden anyways with evil-mode, but let’s do this now
;; just in case evil-mode is disabled or something. Delete the selection with a
;; keypress.
(delete-selection-mode t)
;; There are uncivilized barbarians that do not delete trailing
;; whitespaces. This is not my case.
(add-hook 'before-save-hook #'delete-trailing-whitespace)
;; And finally, let’s make the cursor a little more relevant. For starters, the
;; default of the cursor blinking is plain idiotic. Secondly, I don’t want
;; special highlighting for the current line. And finally, I’d like matching
;; parenthesis to say something whenever the cursor is on top of one of them.
(blink-cursor-mode 0)
(global-hl-line-mode -1)
(show-paren-mode 1)
;;;
;; Completion.
;; Ignore case on completion.
(setq read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t
completion-ignore-case t)
;; Code completion.
(use-package company
:hook (after-init . global-company-mode))
;; Vertico: vertical completion for search elements.
(use-package vertico
:after general
:custom
(vertico-count 20)
(vertico-resize nil)
(vertico-cycle t)
:init
(vertico-mode)
:bind
(:map vertico-map
("C-k" . vertico-previous)
("C-j" . vertico-next)))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
;; Emacs minibuffer configurations.
(use-package emacs
:custom
;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer
;; to switch display modes.
(context-menu-mode t)
;; Support opening new minibuffers from inside existing minibuffers.
(enable-recursive-minibuffers t)
;; Hide commands in M-x which do not work in the current mode. Vertico
;; commands are hidden in normal buffers. This setting is useful beyond
;; Vertico.
(read-extended-command-predicate #'command-completion-default-include-p)
;; Do not allow the cursor in the minibuffer prompt
(minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt)))
;; Optionally use the `orderless' completion style.
(use-package orderless
:custom
;; Configure a custom style dispatcher (see the Consult wiki)
;; (orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch))
;; (orderless-component-separator #'orderless-escapable-split-on-space)
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles partial-completion)))))
;; Needed in order to get `consult-ripgrep', which is great for searching text
;; on the current project.
(use-package consult
:after vertico)
;; Put abbrevs into my emacs directory so it can be tracked on Git.
(setq abbrev-file-name (expand-file-name "abbrevs.el" user-emacs-directory)
save-abbrevs 'silent)
;; And apply abbrevs.el where relevant.
(dolist (hook '(org-mode-hook text-mode-hook))
(add-hook hook #'abbrev-mode))
;;;
;; org
;; Basic variables.
(setq org-directory "~/org/"
org-return-follows-link t)
;; Make sure org follows links even in evil mode and that the `org-cycle'
;; mapping is preserved.
(with-eval-after-load 'general
(general-define-key
:keymaps '(org-mode-map)
:states '(normal motion)
"RET" 'org-open-at-point
"TAB" 'org-cycle))
;;;
;; Tools
;; Enable spelling checks (only on text, not on code).
(use-package flyspell
:defer t
:config
(setq flyspell-issue-welcome-flag nil
flyspell-issue-message-flag nil)
(general-define-key "<f8>" 'ispell-word))
;; And integrate it with vertico.
(use-package flyspell-correct
:defer t
:commands flyspell-correct-previous
:general ([remap ispell-word] #'flyspell-correct-at-point))
(defun mssola/git-commit-hook ()
"Things to run upon entering git-commit mode."
(setq fill-column 72)
(when (and (bound-and-true-p evil-local-mode)
(not (evil-emacs-state-p))
(bobp) (eolp))
(evil-insert-state)))
;; I mostly stick to Git CLI, but it's really nice when staging chunks, checking
;; diffs, showing logs; and similar scenarios where Git can be tedious.
(use-package magit
:defer t
:config
(setq magit-diff-refine-hunk t ; show granular diffs in selected hunk
;; Don't autosave repo buffers. This is too magical, and saving can
;; trigger a bunch of unwanted side-effects, like save hooks and
;; formatters. Trust the user to know what they're doing.
magit-save-repository-buffers nil
;; Don't display parent/related refs in commit buffers; they are rarely
;; helpful and only add to runtime costs.
magit-revision-insert-related-refs nil
;; If two projects have the same project name (e.g. A/src and B/src will
;; both resolve to the name "src"), Magit will treat them as the same
;; project and destructively hijack each other's magit buffers. This is
;; especially problematic if you use workspaces and have magit open in
;; each, and the two projects happen to have the same name! By unsetting
;; `magit-uniquify-buffer-names', magit uses the project's full path as
;; its name, preventing such naming collisions.
magit-uniquify-buffer-names nil)
;; Turn ref links into clickable buttons.
(add-hook 'magit-process-mode-hook #'goto-address-mode)
;; Git commit mode.
(setq git-commit-summary-max-length 50
git-commit-style-convention-checks '(overlong-summary-line non-empty-second-line))
(add-hook 'git-commit-mode-hook 'mssola/git-commit-hook))
;; Nicer diffs.
(use-package magit-delta
:when (executable-find "git-delta")
:hook (magit-mode . magit-delta-mode))
;; Highlighting for git-related files.
(use-package git-modes
:defer t)
;;;
;; Languages
;; I'm fine with the basic support from GNU Emacs for most languages. Here I'm
;; adding support from modes which are not installed by default.
(use-package markdown-mode
:defer t
:hook (markdown-mode . display-line-numbers-mode))
(use-package adoc-mode
:defer t
:hook (adoc-mode . display-line-numbers-mode))
(use-package yaml-mode
:defer t)
(use-package dockerfile-mode
:defer t)
(use-package haml-mode
:defer t)
;; I don't want to go LSP all the way, but for certain languages is almost
;; required (e.g. Go). In any case, let's keep it simple.
(use-package lsp-mode
:defer t
:config
(setq lsp-enable-folding nil
lsp-enable-text-document-color nil
lsp-enable-on-type-formatting nil
lsp-headerline-breadcrumb-enable nil))
;; Better LSP integration, configuration taken from Doom.
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:config
(setq lsp-ui-peek-enable nil
lsp-ui-doc-max-height 8
lsp-ui-doc-max-width 72
lsp-ui-doc-delay 0.75
lsp-ui-doc-show-with-mouse nil
lsp-ui-doc-position 'at-point
lsp-ui-sideline-ignore-duplicate t
lsp-ui-sideline-show-hover nil
lsp-ui-sideline-actions-icon lsp-ui-sideline-actions-icon-default))
(defun mssola/golang-before-save-hooks ()
"Setup before-save-hooks relevant to Go."
(add-hook 'before-save-hook #'lsp-format-buffer nil t)
(add-hook 'before-save-hook #'lsp-organize-imports nil t))
;; Support for Go with LSP integration.
(use-package go-mode
:defer t
:hook ((go-mode . lsp-deferred)
(go-mode . mssola/golang-before-save-hooks)))
;; Rust development environment with everything already cooked in.
(use-package rustic
:mode ("\\.rs\\'" . rust-mode)
:mode ("\\.rs\\'" . rustic-mode)
:custom
(rustic-analyzer-command '("rustup" "run" "stable" "rust-analyzer"))
(rustic-format-trigger 'on-save))
;; Utils
;; Provide the `xref-find-definitions' interactive function which can be used to
;; jump between definitions in any language. It's basically `rg' on steroids but
;; it works remarkably well for what it is.
(use-package dumb-jump
:defer t)
;;;
;; Email
;; I take mu4e not from MELPA but from the openSUSE repositories. Hence,
;; instead of using `use-package' we are going to pin point the installation
;; path and configure `mu4e' whenever I try to launch it.
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
;; Set the maildir directory in any case.
(setq mu4e-maildir "~/data/mail")
(defun mssola/mu4e ()
"Configure mu4e in-place and launch it."
(interactive)
(progn
(require 'mu4e)
;; Use `msmtp' as the program for sending email.
(setq sendmail-program (executable-find "msmtp")
send-mail-function #'smtpmail-send-it
starttls-use-gnutls t
message-sendmail-f-is-evil t
message-sendmail-extra-arguments '("--read-envelope-from")
message-send-mail-function #'message-send-mail-with-sendmail)
;; The default bookmarks are cool and all, but they lack a proper sink that
;; gathers all inboxes.
(add-to-list 'mu4e-bookmarks
'(:name "Inbox"
:query "maildir:/gmail/inbox OR maildir:/comsuse/inbox OR maildir:/sindicat/inbox OR maildir:/uoc/inbox"
:key ?n))
;; For whatever reason I lost the "messages sent" bookmark. Let's re-add it.
(add-to-list 'mu4e-bookmarks
'(:name "Sent"
:query "from:mikisabate@gmail.com OR from:msabate@suse.com"
:key ?s))
;; General mu4e settings.
(setq message-kill-buffer-on-exit t
mu4e-get-mail-command "mbsync --all"
mu4e-update-interval 600
mu4e-use-fancy-chars nil
gnus-treat-display-smileys nil
mu4e-sent-messages-behavior 'sent
mu4e-notification-support t
mu4e-hide-index-messages t
mu4e-confirm-quit nil
mu4e-headers-date-format "%Y-%m-%d %H:%M"
mu4e-headers-skip-duplicates t
mu4e-headers-include-related t
mu4e-headers-auto-update t
mu4e-headers-fields
'((:human-date . 8)
(:from-or-to . 25)
(:subject))
message-user-organization nil
message-organization nil
message-citation-line-format "%N @ %Y-%m-%d %H:%M %Z:\n"
message-citation-line-function 'message-insert-formatted-citation-line
message-kill-buffer-on-exit t
mu4e-view-show-addresses t
mu4e-context-policy 'ask-if-none
mu4e-compose-context-policy 'always-ask
mu4e-compose-dont-reply-to-self t
mu4e-completing-read-function #'completing-read
mail-user-agent 'mu4e-user-agent
message-mail-user-agent 'mu4e-user-agent
mu4e-attachment-dir (concat (expand-file-name (or (getenv "XDG_DOWNLOAD_DIR") "www") "~") "/")
mu4e-change-filenames-when-moving t)
;; PGP thingies.
(setq mml-secure-openpgp-signers '("0x96BE8C6FD89D6565")
mml-secure-openpgp-sign-with-sender t)
(add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime)
;; And here comes the account shenanigans.
(setq mu4e-contexts
`(
;; GMail
,(make-mu4e-context
:name "gmail"
:enter-func (lambda ()
(mu4e-message "Switching to gmail.com")
(setq mu4e-sent-messages-behavior 'delete))
:match-func
(lambda (msg)
(when msg
(string-prefix-p "/gmail" (mu4e-message-field msg :maildir))))
:vars '(
(user-mail-address . "mikisabate@gmail.com")
(mu4e-reply-to-address . "mikisabate@gmail.com")
(mu4e-drafts-folder . "/gmail/Drafts")
(mu4e-sent-folder . "/gmail/Sent")
(mu4e-refile-folder . "/gmail/All")
(mu4e-trash-folder . "/gmail/Trash")))
;; suse.com
,(make-mu4e-context
:name "suse"
:enter-func (lambda ()
(mu4e-message "Switching to suse.com")
(setq mu4e-sent-messages-behavior 'delete))
:match-func
(lambda (msg)
(when msg
(string-prefix-p "/comsuse" (mu4e-message-field msg :maildir))))
:vars `(
(user-mail-address . "msabate@suse.com")
(mu4e-reply-to-address . "msabate@suse.com")
(mu4e-drafts-folder . "/comsuse/Esborranys")
(mu4e-sent-folder . "/comsuse/Elements enviats")
(mu4e-refile-folder . "/comsuse/All")
(mu4e-trash-folder . "/comsuse/Elements suprimits")))))
)
;; And finally call the real deal.
(mu4e))
;; Nice highlighting for patches inside of emails.
(use-package message-view-patch
:hook (gnus-part-display . message-view-patch-highlight))
|