;; See early-init.el for further package stuff (require 'package) (setq package-archives '(("melpa-stable" . "https://stable.melpa.org/packages/") ("melpa-unstable" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/")) ;; Use melpa-unstable only when explicitly requested package-archive-priorities '(("melpa-stable" . 1) ("gnu" . 1))) (package-initialize) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure t use-package-verbose t use-package-always-defer t) (let ((--backup-directory (locate-user-emacs-file "backups"))) (unless (file-exists-p --backup-directory) (make-directory --backup-directory t)) (setq backup-directory-alist `(("." . ,--backup-directory)))) (setq make-backup-files t ; backup of a file the first time it is saved. backup-by-copying t ; don't clobber symlinks version-control t ; version numbers for backup files delete-old-versions t ; delete excess backup files silently delete-by-moving-to-trash t kept-old-versions 6 ; oldest versions to keep when a new numbered backup is made (default: 2) kept-new-versions 9 ; newest versions to keep when a new numbered backup is made (default: 2) auto-save-default t ; auto-save every buffer that visits a file auto-save-timeout 20 ; number of seconds idle time before auto-save (default: 30) auto-save-interval 200 ; number of keystrokes between auto-saves (default: 300) ) (defun qsx-backup-enable-predicate (name) (let ((directory (file-name-directory (file-truename (expand-file-name name)))) (auto-save-list-directory (file-truename (expand-file-name (file-name-as-directory (locate-user-emacs-file "auto-save-list")))))) (if (string= directory auto-save-list-directory) nil (normal-backup-enable-predicate name)))) (setq backup-enable-predicate #'qsx-backup-enable-predicate) (let ((default-directory (locate-user-emacs-file "elisp"))) (normal-top-level-add-to-load-path '(".")) (normal-top-level-add-subdirs-to-load-path)) (load "server") (unless (server-running-p) (server-start)) (setq custom-file (locate-user-emacs-file "custom.el")) (load custom-file :noerror) (use-package modus-themes :defer nil :config (load-theme 'modus-vivendi-tinted)) (setq display-time-day-and-date t display-time-24hr-format t) (display-time-mode) (display-battery-mode) (when (eq system-type 'darwin) (use-package exec-path-from-shell :ensure t :init (exec-path-from-shell-initialize)) (setenv "LANG" "de_DE.UTF-8")) (use-package yasnippet) (use-package company :bind (:map company-mode-map ([remap completion-at-point] . #'company-complete)) :config (setq company-tooltip-align-annotations t) :hook ((company-mode . yas-minor-mode) (prog-mode . company-mode))) (use-package company-math :config (add-hook 'TeX-mode-hook (defun qsx-TeX-mode-hook-company () (setq-local company-backends (append '((company-math-symbols-latex company-latex-commands)) company-backends))))) (use-package company-auctex :if (display-graphic-p) :ensure nil :config (company-auctex-init)) (use-package company-bibtex :if (display-graphic-p) :config (add-to-list 'company-backends 'company-bibtex)) (use-package company-reftex :if (display-graphic-p) :config (add-to-list 'company-backends 'company-reftex)) (use-package company-ansible :config (add-to-list 'company-backends 'company-ansible)) (use-package company-shell :config (add-to-list 'company-backends '(company-shell company-shell-env))) (semantic-mode 1) (use-package srefactor :bind (:map c-mode-map ("M-RET" . #'srefactor-refactor-at-point)) :after project) (use-package python :ensure nil :hook ((python-mode python-ts-mode) . lsp)) (use-package pet :init (add-hook 'python-base-mode-hook 'pet-mode -10) (add-hook 'python-base-mode-hook (defun qsx-python-pet-hook () (setq-local lsp-pylsp-server-command (list (pet-executable-find "pylsp")))))) (use-package highlight-indentation :hook python-base-mode) (use-package jinja2-mode :mode "\\.html.j2\\'" :config (keymap-unset jinja2-mode-map "M-o")) (defun qsx-no-indent-tabs-mode () (setq indent-tabs-mode nil)) (use-package cperl-mode :ensure nil :init (add-to-list 'major-mode-remap-alist '(perl-mode . cperl-mode)) (add-hook 'cperl-mode-hook #'qsx-no-indent-tabs-mode)) (use-package flymake-perlcritic :pin melpa-unstable ; Last release in 2012 :config (dolist (h '(flymake-mode flymake-perlcritic-setup)) (add-hook 'cperl-mode-hook h)) (setq flymake-perlcritic-severity 1)) (use-package treesit-auto :demand t :custom (treesit-auto-install 'prompt) :config (setq treesit-auto-langs (seq-difference treesit-auto-langs '(c cpp go gomod yaml php jsdoc phpdoc))) (treesit-auto-add-to-auto-mode-alist 'all) (global-treesit-auto-mode)) (setq treesit-language-source-alist (append treesit-language-source-alist '((astro "https://github.com/virchau13/tree-sitter-astro") (css "https://github.com/tree-sitter/tree-sitter-css") (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")))) (use-package astro-ts-mode :mode "\\.astro\\'" :config (keymap-unset astro-ts-mode-map "M-o")) (use-package editorconfig :defer nil :config (editorconfig-mode 1)) (use-package tide :after (company flycheck) :hook ((typescript-ts-mode . tide-setup) (tsx-ts-mode . tide-setup) (typescript-ts-mode . tide-hl-identifier-mode))) (use-package lsp-mode :pin melpa-unstable :commands lsp :bind-keymap ("s-l" . lsp-command-map) ;; https://emacs-lsp.github.io/lsp-mode/page/performance/ :init (setq read-process-output-max (* 1024 1024) ;; 1 MiB gc-cons-threshold 6400000 lsp-clients-clangd-args '("--header-insertion=never")) :config (add-to-list 'lsp-language-id-configuration '(LaTeX-mode . "latex")) ;; ugly hack to add #'LaTeX-mode ;; TODO: ⛔ Error (use-package): lsp-mode/:config: Symbol’s value as variable is void: lsp-clients-digestif-executable (with-eval-after-load 'lsp-tex (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection lsp-clients-digestif-executable) :major-modes '(plain-tex-mode latex-mode context-mode texinfo-mode LaTeX-mode) :priority (if (eq lsp-tex-server 'digestif) 1 -1) :server-id 'digestif)))) (use-package lsp-ui :commands lsp-ui-mode) (use-package helm-lsp :commands helm-lsp-workspace-symbol) (use-package mercurial :ensure nil :bind-keymap ("C-c H" . hg-global-map)) (use-package magit :defer 10) (use-package magit-gh :ensure t :after magit) (use-package info-nav) (use-package elsqlite) (use-package transpose-frame :init (dolist (i '(("j" . transpose-frame) ("i" . flip-frame) ("o" . flop-frame) ("r" . rotate-frame) ("c" . rotate-frame-clockwise) ("C" . rotate-frame-anticlockwise))) (dolist (p '("s-j " "s-j s-")) (bind-key (concat p (car i)) (cdr i))))) (use-package ace-window :bind ("M-o" . ace-window) :config (setq aw-scope 'frame)) (use-package mhtml-mode :ensure nil :config (keymap-unset html-mode-map "M-o")) (use-package avy :bind (("C-." . avy-goto-char-timer) ("C-:" . avy-goto-char-2) ("C-," . avy-goto-line)) :custom (avy-keys '(?c ?t ?i ?e ?n ?r ?s ?g))) (use-package helm :demand t :bind-keymap ("C-c h" . helm-command-map) :bind (("M-x" . #'helm-M-x) ("s-x" . #'execute-extended-command) ("M-y" . #'helm-show-kill-ring) ("C-x b" . #'helm-mini) ("C-x C-f" . #'helm-find-files) ("C-h SPC" . #'helm-all-mark-rings) :map helm-command-map ("o" . #'helm-occur)) :config (helm-mode 1) (helm-autoresize-mode t) (setq helm-split-window-inside-p t ;; helm-split-window-default-side 'other helm-M-x-fuzzy-match t helm-buffers-fuzzy-matching t helm-recentf-fuzzy-match t helm-ff-file-name-history-use-recentf t helm-echo-input-in-header-line t)) (use-package helm-rg :after helm) (use-package form-feed) (use-package vdirel :bind (:map message-mode-map ("C-c TAB" . vdirel-helm-select-email))) (use-package apache-mode) (use-package meson-mode) (use-package systemd) (setq-default display-line-numbers 'relative) (use-package stripe-buffer :init (defun qsx-stripe-listify-buffer-hook () (stripe-listify-buffer)) (dolist (h '(gnus-group-mode-hook gnus-summary-mode-hook package-menu-mode-hook)) (add-hook h #'qsx-stripe-listify-buffer-hook))) (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode-enable)) (show-paren-mode 1) (use-package ansible) (use-package poly-ansible) (use-package yaml-mode :config (add-hook 'yaml-mode-hook (defun qsx-yaml-hl-indent-mode-hook () (highlight-indentation-mode) (highlight-indentation-set-offset yaml-indent-offset))) (add-hook 'yaml-mode-hook #'qsx-no-indent-tabs-mode)) (defun qsx-disable-show-trailing-whitespace () (setq show-trailing-whitespace nil)) (add-hook 'Info-mode-hook #'qsx-disable-show-trailing-whitespace) (use-package k8s-mode :hook (k8s-mode . yas-minor-mode)) (use-package kubedoc :hook ((kubedoc-mode . qsx-dont-show-line-numbers-hook) (kubedoc-mode . qsx-disable-show-trailing-whitespace))) (use-package elisp-mode :ensure nil :config (add-hook 'emacs-lisp-mode-hook #'qsx-no-indent-tabs-mode) (add-hook 'lisp-data-mode-hook #'qsx-no-indent-tabs-mode)) (use-package macrostep :bind (:map emacs-lisp-mode-map ("C-c e" . macrostep-expand))) (use-package dockerfile-mode) (defun qsx-dont-show-line-numbers-hook () (setq display-line-numbers nil)) (dolist (h '(Man-mode-hook eshell-mode-hook ledger-report-mode-hook special-mode-hook)) (add-hook h #'qsx-dont-show-line-numbers-hook)) (use-package pdf-tools :if (and (display-graphic-p) (not (eq system-type 'darwin))) :config (pdf-tools-install) (setq-default pdf-view-display-size 'fit-page) (add-hook 'pdf-view-mode-hook #'qsx-dont-show-line-numbers-hook)) (setq-default show-trailing-whitespace t) (setq require-final-newline 'ask) (add-to-list 'auto-mode-alist '("/mutt" . mail-mode)) (add-to-list 'auto-mode-alist '("/neomutt" . mail-mode)) (add-hook 'mail-mode-hook #'turn-on-auto-fill) (add-hook 'mail-mode-hook #'mail-text) (defun qsx-enable-TeX-fold-mode () (TeX-fold-mode 1)) (use-package tex :if (display-graphic-p) :ensure nil :config (setq TeX-auto-save nil TeX-parse-self t ;; TeX-fold-mode font-latex-fontify-sectioning 'color font-latex-fontify-script 'multi-level fill-column 80) (dolist (f '(qsx-enable-TeX-fold-mode turn-on-auto-fill TeX-source-correlate-mode)) (add-hook 'TeX-mode-hook f)) (TeX-add-symbols '("cref" TeX-arg-ref) '("Cref" TeX-arg-ref) '("cpageref" TeX-arg-ref) '("Cpageref" TeX-arg-ref)) (TeX-ispell-skip-setcar '(("\\\\[cC]ref" ispell-tex-arg-end 1) ("\\\\cite" ispell-tex-arg-end) ("\\\\iac" ispell-tex-arg-end) ("\\\\\\(text\\)?tt" ispell-tex-arg-end)))) (use-package reftex :if (display-graphic-p) :after (tex) :hook (TeX-mode . reftex-mode) :config (setq reftex-plug-into-AUCTeX t) (add-hook 'TeX-mode-hook #'reftex-mode) (TeX-add-style-hook "cleveref" (lambda () (if (boundp 'reftex-ref-style-alist) (add-to-list 'reftex-ref-style-alist '("Cleveref" "cleveref" (("\\cref" ?c) ("\\Cref" ?C) ("\\cpageref" ?d) ("\\Cpageref" ?D))))) (reftex-ref-style-activate "Cleveref")))) (use-package auctex-latexmk :if (display-graphic-p) :ensure nil :config (auctex-latexmk-setup) (setq TeX-command-default "LatexMk")) (use-package go-mode :hook (go-mode . lsp)) (use-package toml-mode) (use-package rust-ts-mode :ensure nil :hook (rust-ts-mode . lsp)) ;; Add keybindings for interacting with Cargo (use-package cargo :hook ((rust-mode rust-ts-mode) . cargo-minor-mode)) (setq c-default-style "linux") (setq tramp-default-method "ssh" tramp-terminal-type "tramp") (setq column-number-mode t) (global-set-key (kbd "C-x C-k") #'kill-current-buffer) (global-set-key (kbd "C-M-y") #'(lambda () (interactive) (insert (gui-get-primary-selection)))) (use-package org :ensure nil :init (require 'org-loaddefs) :config (add-hook 'org-mode-hook #'turn-on-auto-fill) (setq org-list-allow-alphabetical t) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (dot . t) (sqlite . t) (plantuml . t))) (add-to-list 'org-latex-packages-alist '("AUTO" "polyglossia" t ("xelatex" "lualatex"))) (add-to-list 'org-latex-packages-alist '("AUTO" "babel" t ("pdflatex"))) (add-to-list 'org-latex-packages-alist '("" "booktabs" nil)) (with-eval-after-load 'ox-latex (add-to-list 'org-latex-classes '("scrartcl" "\\documentclass{scrartcl}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) (setq org-latex-default-class "scrartcl"))) (setq-default fill-column 80) (add-hook 'text-mode-hook #'turn-on-auto-fill) (use-package json-mode) (use-package adoc-mode) (use-package dpkg-dev-el ;; In Debian, it’s provided by a debian package, no need to install from MELPA :if (not (file-exists-p "/etc/debian_version"))) (use-package haskell-mode) (use-package ledger-mode :pin melpa-unstable ; Last release 4.0.0 is incompatible :config (setq ledger-default-date-format "%Y-%m-%d" ledger-use-iso-dates t)) ;; Use keypad comma as decimal separator (use-package calc :config (define-key calc-digit-map (kbd "") ".")) (use-package gnuplot :mode ("\\.gp\\'" . gnuplot-mode) :hook ((gnuplot-comint-mode . qsx-disable-show-trailing-whitespace))) ;; RP PIO (progn (define-hostmode poly-pio-hostmode :mode 'asm-mode) (define-innermode poly-pio-c-innermode :mode 'c-mode :head-matcher "^% c-sdk {$" :tail-matcher "^%}$" :head-mode 'host :tail-mode 'host) (define-polymode poly-pio-mode :hostmode 'poly-pio-hostmode :innermodes '(poly-pio-c-innermode)) (add-to-list 'auto-mode-alist '("\\.pio\\'" . poly-pio-mode))) (use-package arduino-mode) (use-package arduino-cli-mode) ;;; Mail (use-package gnus :defer t :config (setq message-kill-buffer-on-exit t message-sendmail-envelope-from 'header message-send-mail-function 'message-send-mail-with-sendmail message-elide-ellipsis "[…]" message-forward-as-mime t ;; message-alternative-emails message-confirm-send t mail-user-agent 'gnus-user-agent read-mail-command 'gnus gnus-gcc-mark-as-read t gnus-user-date-format-alist `((,(gnus-seconds-today) . " T%H:%M:%S") (,(gnus-seconds-month) . " %dT%H:%M:%S") (,(gnus-seconds-year) . " %m-%dT%H:%M:%S") (t . "%Y-%m-%dT%H:%M:%S")) gnus-summary-line-format "%U%R %&user-date; %(%[%5k: %-23,23f%]%)%B%s\n" gnus-sum-thread-tree-single-indent " " gnus-sorted-header-list '("^From:" "^Organization:" "^Sender:" "^To:" "^Newsgroups:" "^.?Cc:" "^Subject:" "^Date:" "^Resent-.*:" "^Reply-To:" "^Followup-To:" "^X-Clacks-Overhead:" "Openpgp:" "^Authentication-Results:" "^Message-ID:") gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^[BGF]?Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Mail-Followup-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-From:\\|^Message-ID:\\|^Authentication-Results:\\|^Sender:\\|^Resent-.*:\\|^X-Clacks-Overhead:\\|^Openpgp:\\|^User-Agent:\\|X-Mailer:\\|^List-Id:\\|^X-Spam-Score:" mm-verify-option 'known mml-secure-smime-encrypt-to-self t mml-secure-smime-sign-with-sender t gnus-buttonized-mime-types '("multipart/signed") smime-CA-directory "/etc/ssl/certs" gnus-select-method '(nntp "news.cis.dfn.de" (nntp-open-connection-function nntp-open-ssl-stream) (nntp-port-number 563))) (let ((maildir (cl-find-if #'file-directory-p (mapcar (lambda (x) (concat (getenv "HOME") x)) '("/.nnmaildir" "/.maildir" "/Maildir")))) (notmuch (let ((notmuch-gnus (concat (getenv "HOME") "/.local/bin/notmuch-gnus"))) (if (file-executable-p notmuch-gnus) notmuch-gnus "notmuch"))) (notmuch-database-path (car (process-lines "notmuch" "config" "get" "database.path")))) (setq gnus-secondary-select-methods `((nnmaildir "mail" (directory ,maildir) (gnus-search-engine gnus-search-notmuch (program ,notmuch) (remove-prefix ,(concat notmuch-database-path "/"))))))) (add-hook 'message-setup-hook (defun qsx-message-add-my-headers () (message-add-header "Openpgp: id=E384009D3B54DCD321BF953295EE94A432583DB1; url=https://keys.openpgp.org/vks/v1/by-fingerprint/E384009D3B54DCD321BF953295EE94A432583DB1; preference=signencrypt")))) (use-package gnus-alias :ensure t :bind (:map message-mode-map ("C-c i" . #'gnus-alias-select-identity)) :config (setq gnus-alias-identity-alist '(("Chaotikum" nil "Thomas Schneider " nil (("Gcc" . "nnmaildir+mail:Chaotikum.Sent")) nil nil) ("RWTH" "Chaotikum" "Thomas Schneider " "RWTH Aachen" nil nil nil) ("FSMPI" nil "Thomas Schneider " "Fachschaft I/1 der RWTH Aachen" (("Gcc" . "nnmaildir+mail:FSMPI.Sent")) nil "~/.signature-fsmpi") ("AStA" nil "Thomas Schneider " "AStA der RWTH Aachen" (("Gcc" . "nnmaildir+mail:AStA.Sent")) nil "~/.signature-asta") ("Automata" nil "Thomas Schneider " "Lehrstuhl für Informatik 7, RWTH Aachen" (("Gcc" . "\"nnmaildir+mail:Automata.Sent Items\"")) nil "~/.signature-automata") ("CCCAC" nil "qsx " nil (("Gcc" . "nnmaildir+mail:CCCAC.Sent")) nil nil)) gnus-alias-default-identity "Chaotikum" gnus-alias-identity-rules '(("FSMPI" ("from" "fsmpi" both) "FSMPI") ("AStA" ("from" "asta" both) "AStA") ("Automata" ("from" "automata" both) "Automata") ("RWTH" ("from" "rwth-aachen" both) "RWTH") ("CCCAC" ("from" "aachen\.ccc\.de" both) "CCCAC"))) (add-hook 'message-setup-hook #'gnus-alias-determine-identity))