nixos/home/emacs/init.org

1024 lines
36 KiB
Org Mode

#+TITLE: Emacs Config
#+AUTHOR: Evie Litherland-Smith
#+EMAIL: evie@xenia.me.uk
#+FILETAGS: :emacs:config:org:
#+PROPERTY: header-args:emacs-lisp :tangle yes :mkdirp yes :results output silent
* Common defaults
#+BEGIN_SRC emacs-lisp :results output silent
(setq custom-file (locate-user-emacs-file "custom.el"))
(when (and custom-file (file-exists-p custom-file))
(load custom-file nil 'nomessage))
(setq user-full-name "Evie Litherland-Smith"
user-mail-address "evie@xenia.me.uk"
use-short-answers t
load-prefer-newer t
indent-tabs-mode nil
even-window-sizes nil
global-auto-revert-non-file-buffers t
dired-auto-revert-buffer t
dired-dwim-target t
tab-always-indent 'complete
completion-cycle-threshold 3
completions-detailed t
xref-show-definitions-function #'xref-show-definitions-completing-read
kill-do-not-save-duplicates t
auto-window-vscroll nil
fast-but-imprecise-scrolling t
scroll-conservatively 101
scroll-margin 0
scroll-preserve-screen-position 1)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(global-auto-revert-mode +1)
(delete-selection-mode)
(recentf-mode -1)
(keymap-global-set "M-#" #'dictionary-lookup-definition)
;; turn on spell checking, if available.
(when (and (require 'ispell nil :noerror) (executable-find ispell-program-name))
(add-hook 'text-mode-hook #'flyspell-mode)
(add-hook 'prog-mode-hook #'flyspell-prog-mode))
;; Make shebang (#!) file executable when saved
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
#+END_SRC
** package-archive with priorities
#+begin_src emacs-lisp :results output silent
(when (require 'package nil :noerror)
(add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(setq package-archive-priorities '(("gnu" . 99)
("nongnu" . 80)
("stable" . 70)
("melpa" . 0))))
#+end_src
** Authentication
#+begin_src emacs-lisp
(when (require 'auth-source nil :noerror)
(setq auth-sources '("secrets:Login"))
(when (require 'auth-source-pass nil :noerror)
(auth-source-pass-enable)))
#+end_src
** Helpful
#+begin_src emacs-lisp
;; Make `describe-*' screens more helpful
(use-package helpful
:ensure t
:bind (("<remap> <describe-command>" . helpful-command)
("<remap> <describe-function>" . helpful-callable)
("<remap> <describe-key>" . helpful-key)
("<remap> <describe-symbol>" . helpful-symbol)
("<remap> <describe-variable>" . helpful-variable)
("C-h F" . helpful-function)
:map helpful-mode-map
("<remap> <revert-buffer>" . helpful-update)))
;; Bind extra `describe-*' commands
(keymap-global-set "C-h K" #'describe-keymap)
#+end_src
** ibuffer
#+begin_src emacs-lisp
(use-package ibuffer
:ensure t
:bind (("C-c b" . ibuffer)))
(use-package ibuffer-project
:ensure t
:after ibuffer
:hook ((ibuffer . (lambda ()
(setq ibuffer-filter-groups (ibuffer-project-generate-filter-groups))
(unless (eq ibuffer-sorting-mode 'project-file-relative)
(ibuffer-do-sort-by-project-file-relative))))))
#+end_src
** Link hint keymaps
#+begin_src emacs-lisp
(use-package link-hint
:ensure t
:bind (("C-c l o" . link-hint-open-link)
("C-c l c" . link-hint-copy-link)
("C-c l C-o" . link-hint-open-all-link)
("C-c l C-c" . link-hint-copy-all-link)))
#+end_src
** Avy keymaps
#+begin_src emacs-lisp
(use-package avy
:ensure t
:bind (("C-c j w" . avy-goto-word-0)
("C-c j c" . avy-goto-char)
("C-c j l" . avy-goto-line)))
#+end_src
* UI
#+begin_src emacs-lisp
(setq use-dialog-box nil
fill-column 80
truncate-lines nil
truncate-partial-width-windows nil)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tab-bar-mode -1)
(global-display-line-numbers-mode -1)
(global-prettify-symbols-mode +1)
(global-visual-line-mode +1)
(use-package which-key
:ensure t
:config (which-key-mode +1))
(use-package page-break-lines
:ensure t
:config (global-page-break-lines-mode +1))
;; add visual pulse when changing focus, like beacon but built-in
;; from from https://karthinks.com/software/batteries-included-with-emacs/
(defun pulse-line (&rest _)
"Pulse the current line."
(pulse-momentary-highlight-one-line (point)))
(dolist (command '(scroll-up-command
scroll-down-command
recenter-top-bottom
other-window))
(advice-add command :after #'pulse-line))
#+end_src
** Theme, font and nerd-icons
#+begin_src emacs-lisp
(set-frame-parameter nil 'alpha-background 80)
(set-frame-font "Fira Code-12")
;; Theme
(use-package modus-themes
:ensure t
:config (load-theme 'modus-vivendi-tinted :noconfirm))
;; Nerd-Icons modes
(use-package nerd-icons
:ensure t
:config (nerd-icons-set-font "Symbols Nerd Font Mono"))
(use-package nerd-icons-dired
:ensure t
:hook (dired-mode))
(use-package nerd-icons-ibuffer
:ensure t
:hook (ibuffer-mode))
(use-package nerd-icons-completion
:ensure t
:config (nerd-icons-completion-mode +1))
(use-package nerd-icons-corfu
:ensure t
:after corfu
:config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
(keymap-global-set "C-c i n" #'nerd-icons-insert)
#+end_src
** Window management
*** winner
#+begin_src emacs-lisp
(use-package winner
:config
(winner-mode))
#+end_src
** Font ligatures
#+begin_src emacs-lisp
(use-package ligature
:ensure t
:config
;; Enable the "www" ligature in every possible major mode
(ligature-set-ligatures 't '("www"))
;; Enable traditional ligature support in eww-mode, if the
;; `variable-pitch' face supports it
(ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
;; Enable all Cascadia and Fira Code ligatures in programming modes
(ligature-set-ligatures 'prog-mode
'(;; == === ==== => =| =>>=>=|=>==>> ==< =/=//=// =~
;; =:= =!=
("=" (rx (+ (or ">" "<" "|" "/" "~" ":" "!" "="))))
;; ;; ;;;
(";" (rx (+ ";")))
;; && &&&
("&" (rx (+ "&")))
;; !! !!! !. !: !!. != !== !~
("!" (rx (+ (or "=" "!" "\." ":" "~"))))
;; ?? ??? ?: ?= ?.
("?" (rx (or ":" "=" "\." (+ "?"))))
;; %% %%%
("%" (rx (+ "%")))
;; |> ||> |||> ||||> |] |} || ||| |-> ||-||
;; |->>-||-<<-| |- |== ||=||
;; |==>>==<<==<=>==//==/=!==:===>
("|" (rx (+ (or ">" "<" "|" "/" ":" "!" "}" "\]"
"-" "=" ))))
;; \\ \\\ \/
("\\" (rx (or "/" (+ "\\"))))
;; ++ +++ ++++ +>
("+" (rx (or ">" (+ "+"))))
;; :: ::: :::: :> :< := :// ::=
(":" (rx (or ">" "<" "=" "//" ":=" (+ ":"))))
;; // /// //// /\ /* /> /===:===!=//===>>==>==/
("/" (rx (+ (or ">" "<" "|" "/" "\\" "\*" ":" "!"
"="))))
;; .. ... .... .= .- .? ..= ..<
("\." (rx (or "=" "-" "\?" "\.=" "\.<" (+ "\."))))
;; -- --- ---- -~ -> ->> -| -|->-->>->--<<-|
("-" (rx (+ (or ">" "<" "|" "~" "-"))))
;; *> */ *) ** *** ****
("*" (rx (or ">" "/" ")" (+ "*"))))
;; www wwww
("w" (rx (+ "w")))
;; <> <!-- <|> <: <~ <~> <~~ <+ <* <$ </ <+> <*>
;; <$> </> <| <|| <||| <|||| <- <-| <-<<-|-> <->>
;; <<-> <= <=> <<==<<==>=|=>==/==//=!==:=>
;; << <<< <<<<
("<" (rx (+ (or "\+" "\*" "\$" "<" ">" ":" "~" "!"
"-" "/" "|" "="))))
;; >: >- >>- >--|-> >>-|-> >= >== >>== >=|=:=>>
;; >> >>> >>>>
(">" (rx (+ (or ">" "<" "|" "/" ":" "=" "-"))))
;; #: #= #! #( #? #[ #{ #_ #_( ## ### #####
("#" (rx (or ":" "=" "!" "(" "\?" "\[" "{" "_(" "_"
(+ "#"))))
;; ~~ ~~~ ~= ~- ~@ ~> ~~>
("~" (rx (or ">" "=" "-" "@" "~>" (+ "~"))))
;; __ ___ ____ _|_ __|____|_
("_" (rx (+ (or "_" "|"))))
;; Fira code: 0xFF 0x12
("0" (rx (and "x" (+ (in "A-F" "a-f" "0-9")))))
;; Fira code:
"Fl" "Tl" "fi" "fj" "fl" "ft"
;; The few not covered by the regexps.
"{|" "[|" "]#" "(*" "}#" "$>" "^="))
;; Enables ligature checks globally in all buffers. You can also do it
;; per mode with `ligature-mode'.
(global-ligature-mode t))
#+end_src
** Modeline
#+begin_src emacs-lisp
(line-number-mode +1)
(column-number-mode +1)
(size-indication-mode +1)
(display-time-mode -1)
(display-battery-mode -1)
#+end_src
*** Doom Modeline
#+begin_src emacs-lisp
(setq doom-modeline-icon t
doom-modeline-minor-modes t
doom-modeline-buffer-encoding 'nondefault
doom-modeline-enable-word-count t
doom-modeline-continuous-word-count-modes '(org-mode
markdown-mode
gfm-mode))
(use-package doom-modeline
:ensure t
:config
(doom-modeline-mode +1))
#+end_src
*** Minions
#+begin_src emacs-lisp :tangle yes
(use-package minions
:ensure t
:config
(minions-mode +1))
#+end_src
** Darkroom
#+begin_src emacs-lisp
(use-package darkroom
:ensure t
:bind (("C-c d" . darkroom-mode)))
#+end_src
* Org-mode
For reference information, see [[https://orgmode.com][Org-mode website]]
#+BEGIN_SRC emacs-lisp :results output silent
(setq org-directory "~/Org"
org-default-notes-file (expand-file-name "notes.org" org-directory)
org-pretty-entities-include-sub-superscripts t
org-pretty-entities-include-sub-superscripts t
org-tags-column 0
org-modern-tag nil
org-outline-path-complete-in-steps nil
org-return-follows-link t
org-mouse-1-follows-link t
org-link-descriptive t
org-refile-use-outline-path t
org-refile-allow-creating-parent-nodes t
org-refile-use-outline-path 'file
org-refile-targets '((nil :maxlevel . 3)
(org-agenda-files :maxlevel . 3)))
;; Visually indent org-mode files to a given header level
(add-hook 'org-mode-hook #'org-indent-mode)
#+END_SRC
** Keymaps
#+begin_src emacs-lisp :results output silent
(keymap-global-set "C-c o e" #'org-edit-src-code)
(keymap-global-set "C-c o a" #'org-agenda)
(keymap-global-set "C-c o n" #'org-capture)
(keymap-global-set "C-c o l" #'org-capture-goto-last-stored)
(keymap-global-set "C-c o j j" #'org-journal-new-entry)
(keymap-global-set "C-c o j n" #'org-journal-new-date-entry)
(keymap-global-set "C-c o j s" #'org-journal-new-scheduled-entry)
(use-package org-modern
:ensure t
:hook ((org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda)))
#+end_src
** org-agenda
#+begin_src emacs-lisp :results output silent
(setq org-agenda-span 'week
org-agenda-start-on-weekday 1
org-agenda-files (list (expand-file-name org-directory)
(expand-file-name "journal" org-directory)
(expand-file-name "projects" org-directory))
org-agenda-sticky t
org-agenda-window-setup 'current-window
org-agenda-prefix-format '((agenda . " %-12:c%?-12t% s")
(todo . " %-12:c")
(tags . " %-12:c")
(search . " %-12:c")))
#+end_src
** org-journal
#+BEGIN_SRC emacs-lisp :results output silent
(setq org-journal-dir (expand-file-name "journal" org-directory)
org-journal-file-type 'monthly
org-journal-file-format "%Y-%m.org")
#+END_SRC
** Capture templates
#+BEGIN_SRC emacs-lisp :results output silent
(setq org-capture-templates
'(("n" "Note" entry
(file+headline "inbox.org" "Note")
"* %?"
:prepend t
:empty-lines 1)
("t" "Task" entry
(file+headline "inbox.org" "Task")
"* TODO %?"
:prepend t
:empty-lines 1)
("m" "Email Workflow")
("mf" "Follow Up" entry (file+olp "mail.org" "Follow Up")
"* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i")
("mr" "Read Later" entry (file+olp "mail.org" "Read Later")
"* TODO Read %:subject\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%a\n\n%i")
))
#+END_SRC
** Citar
#+begin_src emacs-lisp :results output silent
(let ((citar-base-directory "~/References"))
(setq citar-bibliography (expand-file-name "main.bib" citar-base-directory)
citar-library-paths (list (expand-file-name "library" citar-base-directory))
citar-notes-paths (list (expand-file-name "notes" citar-base-directory))))
(use-package citar
:ensure t
:bind (("C-c o c o" . citar-open))
:config
(defvar citar-indicator-files-icons
(citar-indicator-create
:symbol (nerd-icons-octicon
"nf-oct-file"
:face 'nerd-icons-green
:v-adjust -0.1)
:function #'citar-has-files
:padding " " ; need this because the default padding is too low for these icons
:tag "has:files"))
(defvar citar-indicator-links-icons
(citar-indicator-create
:symbol (nerd-icons-octicon
"nf-oct-link"
:face 'nerd-icons-orange
:v-adjust 0.01)
:function #'citar-has-links
:padding " "
:tag "has:links"))
(defvar citar-indicator-notes-icons
(citar-indicator-create
:symbol (nerd-icons-octicon
"nf-oct-note"
:face 'nerd-icons-blue
:v-adjust -0.3)
:function #'citar-has-notes
:padding " "
:tag "has:notes"))
(defvar citar-indicator-cited-icons
(citar-indicator-create
:symbol (nerd-icons-octicon
"nf-oct-circle"
:face 'nerd-icon-green)
:function #'citar-is-cited
:padding " "
:tag "is:cited"))
(setq citar-indicators (list citar-indicator-files-icons
citar-indicator-links-icons
citar-indicator-notes-icons
citar-indicator-cited-icons)))
#+end_src
** Khalel
#+begin_src emacs-lisp :results output silent
(setq khalel-import-org-file (expand-file-name "calendar.org" org-directory)
khalel-import-org-file-read-only nil
khalel-import-org-file-confirm-overwrite nil
khalel-import-start-date "-30d"
khalel-import-end-date "+30d")
(when (require 'khalel nil :noerror)
(add-hook 'org-agenda-mode-hook #'khalel-import-events)
(khalel-add-capture-template "e"))
#+end_src
** TODO Crafted config
#+BEGIN_SRC emacs-lisp
;; Disable auto-pairing of "<" in org-mode with electric-pair-mode
(defun crafted-org-enhance-electric-pair-inhibit-predicate ()
"Disable auto-pairing of \"<\" in `org-mode' when using `electric-pair-mode'."
(when (and electric-pair-mode (eql major-mode #'org-mode))
(setq-local electric-pair-inhibit-predicate
`(lambda (c)
(if (char-equal c ?<)
t
(,electric-pair-inhibit-predicate c))))))
;; Add hook to both electric-pair-mode-hook and org-mode-hook
;; This ensures org-mode buffers don't behave weirdly,
;; no matter when electric-pair-mode is activated.
(add-hook 'electric-pair-mode-hook #'crafted-org-enhance-electric-pair-inhibit-predicate)
(add-hook 'org-mode-hook #'crafted-org-enhance-electric-pair-inhibit-predicate)
#+END_SRC
* Development Environment
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:ensure t
:hook (prog-mode))
(setq apheleia-remote-algorithm 'local)
(use-package apheleia
:ensure t
:defer nil
:bind (("C-c c f" . apheleia-format-buffer))
:config (apheleia-global-mode +1))
(use-package treesit-auto
:config (global-treesit-auto-mode +1))
(setq direnv-always-show-summary nil)
(use-package direnv
:ensure t
:config (direnv-mode +1))
#+END_SRC
** Eglot LSP
#+BEGIN_SRC emacs-lisp
(setq eglot-extend-to-xref t
eglot-autoshutdown t
eglot-autoreconnect nil)
(when (require 'eglot nil :noerror)
(add-hook 'prog-mode-hook #'eglot-ensure)
(keymap-global-set "C-c c e" #'eglot))
#+END_SRC
** Project
#+BEGIN_SRC emacs-lisp
(setq project-switch-use-entire-map t
project-switch-commands
'((project-dired "Browse directory")
(project-find-file "Find file")
(project-find-regexp "Find regexp")
(project-find-dir "Find directory")
(project-eshell "Eshell")))
#+END_SRC
** Version control
*** Magit
#+begin_src emacs-lisp
(setq magit-define-global-key-bindings nil
magit-clone-default-directory "~/Projects/"
magit-commit-show-diff nil
magit-commit-diff-inhibit-same-window t)
(use-package magit
:ensure t
:bind (("C-c g g" . magit-status)
("C-c g d" . magit-dispatch)
("C-c g f" . magit-file-dispatch)
("C-c g p" . magit-pull)
("C-c g P" . magit-push)
("<remap> <project-vc-dir" . magit-project-status)
:map project-prefix-map
("m" . magit-project-status))
:config
(add-to-list 'project-switch-commands '(magit-project-status "Magit") t))
#+end_src
** Completion
*** Vertico
#+begin_src emacs-lisp
(setq vertico-cycle t)
(use-package vertico
:ensure t
:config
(require 'vertico-directory)
(vertico-mode +1))
#+end_src
*** Marginalia
#+begin_src emacs-lisp
(setq marginalia-annotators '(marginalia-annotators-heavy
marginalia-annotators-light
nil))
(use-package marginalia
:ensure t
:config (marginalia-mode +1))
#+end_src
*** Orderless
#+begin_src emacs-lisp
(use-package orderless
:ensure t
:config (setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles . (partial-completion))))))
#+end_src
*** Corfu and Cape
#+begin_src emacs-lisp
(setq corfu-cycle t
corfu-auto t
corfu-auto-prefix 3)
(use-package corfu
:ensure t
:config
(global-corfu-mode +1)
(when (require 'corfu-popupinfo nil :noerror)
(corfu-popupinfo-mode 1)
(eldoc-add-command #'corfu-insert)
(keymap-set corfu-map "M-p" #'corfu-popupinfo-scroll-down)
(keymap-set corfu-map "M-n" #'corfu-popupinfo-scroll-up)
(keymap-set corfu-map "M-d" #'corfu-popupinfo-toggle))
(defun crafted-completion-corfu-eshell ()
"Special settings for when using corfu with eshell."
(setq-local corfu-quit-at-boundary t
corfu-quit-no-match t
corfu-auto nil)
(corfu-mode))
(add-hook 'eshell-mode-hook #'crafted-completion-corfu-eshell))
(use-package cape
:ensure t
:config
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify))
#+end_src
*** Consult
#+begin_src emacs-lisp
(use-package consult
:ensure t
:bind (("C-s" . consult-line)
("<remap> <imenu>" . consult-imenu )
("<remap> <switch-to-buffer>" . consult-buffer)
("<remap> <project-switch-to-buffer>" . consult-project-buffer)
("<remap> <org-goto>" . consult-org-heading)
("C-c s f" . consult-fd)
("C-c s g" . consult-ripgrep)
("C-c s e" . consult-flymake)
("C-c s t" . consult-theme)
:map minibuffer-local-map
("C-r" . consult-history))
:config (setq completion-in-region-function #'consult-completion-in-region))
(use-package consult-yasnippet
:ensure t
:after consult
:commands (consult-yasnippet)
:bind (("C-c s s" . consult-yasnippet)))
#+end_src
*** Embark
#+begin_src emacs-lisp
(use-package embark
:ensure t
:bind (("<remap> <describe-bindings>" . embark-bindings)
("C-." . embark-act))
:config (setq prefix-help-command #'embark-prefix-help-command))
(use-package embark-consult
:ensure t
:after (embark consult)
:hook (embark-collect-mode . consult-preview-at-point-mode))
#+end_src
** Snippets
#+begin_src emacs-lisp
(use-package yasnippet
:ensure t
:hook ((prog-mode org-mode) . yas-minor-mode))
(use-package yasnippet-snippets
:ensure t
:after yasnippet
:config (yas-reload-all))
(use-package yasnippet-capf
:ensure t
:after cape
:config
(add-to-list 'completion-at-point-functions #'yasnippet-capf))
#+end_src
** Aggressive Indent
#+begin_src emacs-lisp
(use-package aggressive-indent
:ensure t
:hook prog-mode)
#+end_src
** Language-specific settings
*** kmonad
#+begin_src emacs-lisp
(unless (package-installed-p 'kbd-mode)
(package-vc-install
'(kbd-mode . (:url "https://github.com/kmonad/kbd-mode"))))
(use-package kbd-mode)
#+end_src
* Internet
** Email
#+BEGIN_SRC emacs-lisp
(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
message-kill-buffer-on-exit t
mail-user-agent 'mu4e-user-agent
read-mail-command 'mu4e
mu4e-completing-read-function #'completing-read-default
mu4e-split-view 'horizontal
mu4e-maildir "~/Mail"
mu4e-attachment-dir "~/Downloads"
mu4e-get-mail-command "mbsync -a"
mu4e-update-interval (* 5 60) ; Every 5 minutes
mu4e-sent-messages-behavior 'sent
mu4e-change-filenames-when-moving t
mu4e-context-policy 'pick-first
mu4e-use-fancy-chars t
mu4e-headers-thread-single-orphan-prefix '("─>" . "─▶")
mu4e-headers-thread-orphan-prefix '("┬>" . "┬▶")
mu4e-headers-thread-connection-prefix '("" . "")
mu4e-headers-thread-first-child-prefix '("├>" . "├▶")
mu4e-headers-thread-child-prefix '("├>" . "├▶")
mu4e-headers-thread-last-child-prefix '("└>" . "╰▶")
mu4e-modeline-all-read '("R:" . "󰑇 ")
mu4e-modeline-all-clear '("C:" . "󰚭 ")
mu4e-modeline-new-items '("N:" . "󰎔 ")
mu4e-modeline-unread-items '("U:" . "󰶊 ")
mu4e-search-full-label '("F" . "󱊖 ")
mu4e-search-hide-label '("H" . "󰘓 ")
mu4e-search-related-label '("R" . "󰌹 ")
mu4e-search-skip-duplicates-label '("D" . "󰆑 ")
mu4e-search-threaded-label'("T" . "󱇫 ")
mu4e-alert-modeline-formatter 'mu4e-alert-default-mode-line-formatter
mu4e-headers-fields '((:human-date . 12)
(:flags . 6)
(:from-or-to . 25)
(:subject))
mu4e-headers-actions '(("org capture message" . mu4e-org-store-and-capture)
("capture message" . mu4e-action-capture-message)
("show this thread" . mu4e-action-show-thread))
mu4e-maildir-shortcuts '((:maildir "/Proton/Inbox/" :key ?p)
(:maildir "/iCloud/Inbox/" :key ?i)
(:maildir "/Outlook/Inbox/" :key ?w)))
(use-package mu4e
:bind (("C-c o m" . mu4e))
:config
(require 'mu4e-org)
(setq mu4e-contexts
(list
(make-mu4e-context
:name "Xenia"
:vars '((user-mail-address . "evie@xenia.me.uk")
(mu4e-sent-folder . "/Proton/Sent")
(mu4e-drafts-folder . "/Proton/Drafts")
(mu4e-trash-folder . "/Proton/Trash")
(mu4e-refile-folder . "/Proton/Archive")))
(make-mu4e-context
:name "Proton"
:match-func (lambda (msg) (when msg (string-prefix-p "/Proton" (mu4e-message-field msg :maildir))))
:vars '((user-mail-address . "e.litherlandsmith@proton.me")
(mu4e-sent-folder . "/Proton/Sent")
(mu4e-drafts-folder . "/Proton/Drafts")
(mu4e-trash-folder . "/Proton/Trash")
(mu4e-refile-folder . "/Proton/Archive")))
(make-mu4e-context
:name "iCloud"
:match-func (lambda (msg) (when msg (string-prefix-p "/iCloud" (mu4e-message-field msg :maildir))))
:vars '((user-mail-address . "e.litherlandsmith@icloud.com")
(mu4e-sent-folder . "/iCloud/Sent Messages")
(mu4e-drafts-folder . "/iCloud/Drafts")
(mu4e-trash-folder . "/iCloud/Deleted Messages")
(mu4e-refile-folder . "/iCloud/Archive")))
(make-mu4e-context
:name "Work"
:match-func (lambda (msg) (when msg (string-prefix-p "/Outlook" (mu4e-message-field msg :maildir))))
:vars '((user-mail-address . "evie.litherland-smith@ukaea.uk")
(mu4e-sent-folder . "/Outlook/Sent")
(mu4e-drafts-folder . "/Outlook/Drafts")
(mu4e-trash-folder . "/Outlook/Trash")
(mu4e-refile-folder . "/Outlook/Archive"))))))
(use-package mu4e-alert
:after mu4e
:config
(mu4e-alert-set-default-style 'libnotify)
(mu4e-alert-enable-notifications)
(mu4e-alert-enable-mode-line-display))
#+END_SRC
** Feeds
#+BEGIN_SRC emacs-lisp
(let ((elfeed-base-directory "~/.elfeed"))
(setq elfeed-db-directory (expand-file-name "db" elfeed-base-directory)
elfeed-enclosure-default-dir (expand-file-name "enclosures" elfeed-base-directory)
rmh-elfeed-org-files (list (expand-file-name "feeds.org" elfeed-base-directory))))
(use-package elfeed
:bind (("C-c f f" . elfeed)
("C-c f u" . elfeed-update))
:hook (elfeed-search-mode . elfeed-update)
:config
(use-package elfeed-org
:ensure t
:config (elfeed-org))
(use-package elfeed-tube
:ensure t
:config (elfeed-tube-setup)))
#+END_SRC
** Social
*** Mastodon
#+BEGIN_SRC emacs-lisp
(setq mastodon-instance-url "https://tech.lgbt"
mastodon-active-user "Tux922")
(use-package mastodon
:commands mastodon)
#+END_SRC
*** Matrix / Ement.el
#+begin_src emacs-lisp
(setq ement-save-sessions t)
(defun my/ement-connect-pantalaimon ()
"Connect to ement.el by calling `ement-connect' with pantalaimon service as uri-prefix"
(interactive)
(ement-connect
:user-id "@tux922:tchncs.de"
:uri-prefix "http://localhost:8008"))
(use-package ement
:ensure t
:commands ement-connect
:bind (("C-c m m" . ement-list-rooms)
("C-c m n" . ement-notifications)
("C-c m j" . ement-room-join)
("C-c m l" . ement-room-leave)
("C-c m v" . ement-room-view)
("C-c m c" . my/ement-connect-pantalaimon)))
#+end_src
* TODO Media
#+BEGIN_SRC emacs-lisp
(when (require 'emms-setup nil :noerror)
(setq emms-player-list '(emms-player-mpv)
emms-info-functions '(emms-info-native)
emms-source-file-default-directory "~/Music"
emms-lyrics-dir "~/Music/lyrics"
emms-mode-line-icon-color "white")
(emms-all)
(add-hook 'emms-player-started-hook #'emms-show)
(add-hook 'emms-player-paused-hook #'emms-show)
(when (require 'hydra nil :noerror)
(defhydra emms (global-map "C-c e")
"emms"
("b" emms-smart-browse)
("d" emms-show)
("s" emms-start)
("S" emms-stop)
("n" emms-next)
("p" emms-previous)
("P" emms-pause))))
#+END_SRC
* TODO Writing
#+BEGIN_SRC emacs-lisp
;;; Whitespace
(defun crafted-writing-configure-whitespace (use-tabs &optional use-globally &rest enabled-modes)
"Helper function to configure `whitespace' mode.
Enable using TAB characters if USE-TABS is non-nil. If
USE-GLOBALLY is non-nil, turn on `global-whitespace-mode'. If
ENABLED-MODES is non-nil, it will be a list of modes to activate
whitespace mode using hooks. The hooks will be the name of the
mode in the list with `-hook' appended. If USE-GLOBALLY is
non-nil, ENABLED-MODES is ignored.
Configuring whitespace mode is not buffer local. So calling this
function twice with different settings will not do what you
think. For example, if you wanted to use spaces instead of tabs
globally except for in Makefiles, doing the following won't work:
;; turns on global-whitespace-mode to use spaces instead of tabs
(crafted-writing-configure-whitespace nil t)
;; overwrites the above to turn to use tabs instead of spaces,
;; does not turn off global-whitespace-mode, adds a hook to
;; makefile-mode-hook
(crafted-writing-configure-whitespace t nil 'makefile-mode)
Instead, use a configuration like this:
;; turns on global-whitespace-mode to use spaces instead of tabs
(crafted-writing-configure-whitespace nil t)
;; turn on the buffer-local mode for using tabs instead of spaces.
(add-hook 'makefile-mode-hook #'indent-tabs-mode)
For more information on `indent-tabs-mode', See the info
node `(emacs)Just Spaces'
Example usage:
;; Configuring whitespace mode does not turn on whitespace mode
;; since we don't know which modes to turn it on for.
;; You will need to do that in your configuration by adding
;; whitespace mode to the appropriate mode hooks.
(crafted-writing-configure-whitespace nil)
;; Configure whitespace mode, but turn it on globally.
(crafted-writing-configure-whitespace nil t)
;; Configure whitespace mode and turn it on only for prog-mode
;; and derived modes.
(crafted-writing-configure-whitespace nil nil 'prog-mode)"
(if use-tabs
(customize-set-variable 'whitespace-style
'(face empty trailing indentation::tab
space-after-tab::tab
space-before-tab::tab))
;; use spaces instead of tabs
(customize-set-variable 'whitespace-style
'(face empty trailing tab-mark
indentation::space)))
(if use-globally
(global-whitespace-mode 1)
(when enabled-modes
(dolist (mode enabled-modes)
(add-hook (intern (format "%s-hook" mode)) #'whitespace-mode))))
;; cleanup whitespace
(customize-set-variable 'whitespace-action '(cleanup auto-cleanup)))
;;; parentheses
(electric-pair-mode 1) ; auto-insert matching bracket
(show-paren-mode 1) ; turn on paren match highlighting
;;; LaTeX configuration
(with-eval-after-load 'latex
(customize-set-variable 'TeX-auto-save t)
(customize-set-variable 'TeX-parse-self t)
(setq-default TeX-master nil)
;; compile to pdf
(tex-pdf-mode)
;; correlate the source and the output
(TeX-source-correlate-mode)
;; set a correct indentation in a few additional environments
(add-to-list 'LaTeX-indent-environment-list '("lstlisting" current-indentation))
(add-to-list 'LaTeX-indent-environment-list '("tikzcd" LaTeX-indent-tabular))
(add-to-list 'LaTeX-indent-environment-list '("tikzpicture" current-indentation))
;; add a few macros and environment as verbatim
(add-to-list 'LaTeX-verbatim-environments "lstlisting")
(add-to-list 'LaTeX-verbatim-environments "Verbatim")
(add-to-list 'LaTeX-verbatim-macros-with-braces "lstinline")
(add-to-list 'LaTeX-verbatim-macros-with-delims "lstinline")
;; electric pairs in auctex
(customize-set-variable 'TeX-electric-sub-and-superscript t)
(customize-set-variable 'LaTeX-electric-left-right-brace t)
(customize-set-variable 'TeX-electric-math (cons "$" "$"))
;; open all buffers with the math mode and auto-fill mode
(add-hook 'LaTeX-mode-hook #'auto-fill-mode)
(add-hook 'LaTeX-mode-hook #'LaTeX-math-mode)
;; add support for references
(add-hook 'LaTeX-mode-hook #'turn-on-reftex)
(customize-set-variable 'reftex-plug-into-AUCTeX t)
;; to have the buffer refresh after compilation
(add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer))
(defun crafted-latex-use-pdf-tools ()
"Use PDF Tools instead of docview, requires a build environment
to compile PDF Tools.
Depends on having `pdf-tools'."
(with-eval-after-load 'latex
(customize-set-variable 'TeX-view-program-selection '((output-pdf "PDF Tools")))
(customize-set-variable 'TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)))
(customize-set-variable 'TeX-source-correlate-start-server t)))
;; message the user if the latex executable is not found
(defun crafted-writing-tex-warning-if-no-latex-executable ()
"Print a message to the minibuffer if the \"latex\" executable cannot be found."
(unless (executable-find "latex")
(message "latex executable not found")))
(add-hook 'tex-mode-hook #'crafted-writing-tex-warning-if-no-latex-executable)
(when (and (executable-find "latex")
(executable-find "latexmk"))
(with-eval-after-load 'latex
(when (require 'auctex-latexmk nil 'noerror)
(with-eval-after-load 'auctex-latexmk
(auctex-latexmk-setup)
(customize-set-variable 'auctex-latexmk-inherit-TeX-PDF-mode t))
(defun crafted-writing-tex-make-latexmk-default-command ()
"Set `TeX-command-default' to \"LatexMk\"."
(setq TeX-command-default "LatexMk"))
(add-hook 'TeX-mode-hook #'crafted-writing-tex-make-latexmk-default-command))))
;;; Markdown
(when (fboundp 'markdown-mode)
;; because the markdown-command variable may not be loaded (yet),
;; check manually for the other markdown processors. If it is
;; loaded, the others are superfluous but `or' fails fast, so they
;; are not checked if `markdown-command' is set and the command is
;; indeed found.
(unless (or (and (boundp 'markdown-command)
(executable-find markdown-command))
(executable-find "markdown")
(executable-find "pandoc"))
(message "No markdown processor found, preview may not possible."))
(with-eval-after-load 'markdown-mode
(customize-set-variable 'markdown-enable-math t)
(customize-set-variable 'markdown-enable-html t)
(add-hook 'markdown-mode-hook #'conditionally-turn-on-pandoc)))
;;; PDF Support when using pdf-tools
(when (locate-library "pdf-tools")
;; load pdf-tools when going into doc-view-mode
(defun crafted-writing-load-pdf-tools ()
"Attempts to require pdf-tools, but for attaching to hooks."
(require 'pdf-tools nil :noerror))
(add-hook 'doc-view-mode-hook #'crafted-writing-load-pdf-tools)
;; when pdf-tools is loaded, apply settings.
(with-eval-after-load 'pdf-tools
(setq-default pdf-view-display-size 'fit-width)))
#+END_SRC