;;; Init.el --- Daniel's Emacs Configuration -*- lexical-binding: t -*- ;;; Commentary: ;; This is the main entry point for Emacs to load this configuration. The ;; structure is roughly as follows: ;; * first comes some preliminary setup, mostly setting up `package’; ;; * the main activation of the configuration is done in the function ;; `db/run-init’, which is installed in `after-init-hook’; it is thus run ;; after init.el has been read ;; * then comes setting up all the packages that can be used by this ;; configuration; most of these packages are not loaded however, and only ;; configuration hooks are installed (using `use-package’); this way a user ;; can choose in `db/run-init’ which configruation to activate without ;; changing much of the rest of the file. ;; * this file also introduces a new customization group `personal-settings’ ;; containing variables (mostly file paths) that must be set to enable some ;; of the provied functionality. ;;; Code: ;; * Constants (defconst emacs-d (file-name-directory (file-chase-links load-file-name)) "The giant turtle on which the world rests.") (defconst on-windows (memq system-type '(windows-nt cygwin)) "Non-nil if and only if this instance of Emacs runs on Windows.") ;; * Packages (require 'package) (setq package-user-dir (expand-file-name "elpa" emacs-d)) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") ("melpa-stable" . "https://stable.melpa.org/packages/") ("org" . "https://orgmode.org/elpa/"))) (setq package-enable-at-startup nil load-prefer-newer t) (package-initialize) (eval-when-compile (dolist (package '(diminish use-package bind-key)) (unless (package-installed-p package) (package-install package)) (require package))) (put 'use-package 'lisp-indent-function 1) (setq use-package-verbose t use-package-minimum-reported-time 0.01) (add-to-list 'load-path (expand-file-name "site-lisp" emacs-d)) ;; * Mode activation (defun db/run-init () "Run main initialization after everything is set up." ;; Load customizations (when (file-exists-p custom-file) (load-file custom-file)) ;; Activate modes (builtin) (show-paren-mode 1) (transient-mark-mode 1) (global-font-lock-mode 1) (column-number-mode 1) ;; (display-time) (delete-selection-mode 1) (dolist (mode '(tool-bar-mode scroll-bar-mode menu-bar-mode blink-cursor-mode tooltip-mode)) (when (fboundp mode) (funcall mode 0))) (when (<= 24 emacs-major-version) (electric-indent-mode -1)) (appt-activate +1) (savehist-mode 1) (quietly-read-abbrev-file) (size-indication-mode 1) (display-battery-mode -1) (electric-pair-mode +1) (recentf-mode t) (winner-mode 1) (global-auto-revert-mode -1) (which-function-mode +1) ;; Activate modes (packages) (dolist (mode '(global-undo-tree-mode ace-window-display-mode key-chord-mode sml/setup ivy-mode which-key-mode eyebrowse-mode)) (with-demoted-errors "Cannot activate mode: %s" (funcall mode +1))) (projectile-mode +1) (unless on-windows (with-demoted-errors "Error: %s" (pdf-tools-install))) ;; Global Hooks (add-hook 'minibuffer-setup-hook 'conditionally-enable-lispy) (add-hook 'minibuffer-setup-hook 'cursor-intangible-mode) (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) (add-hook 'text-mode-hook 'turn-on-auto-fill) (add-hook 'prog-mode-hook 'page-break-lines-mode) (when (<= 24 emacs-major-version) (add-hook 'prog-mode-hook 'electric-indent-local-mode)) (add-hook 'lisp-mode-hook 'lispy-mode) (unless (eq system-type 'windows-nt) ;; flyspell doesn’t work on windows right now, need to further investigate ;; what is happening here (add-hook 'text-mode-hook 'turn-on-flyspell)) (add-hook 'text-mode-hook 'yas-minor-mode-on) (add-hook 'text-mode-hook 'electric-quote-mode) ;; Auto-Modes (dolist (mode-spec '(("\\.clj\\'" . clojure-mode) ("\\.cl\\'" . lisp-mode) ("\\.lisp\\'" . lisp-mode) ("\\.plx\\’" . cperl-mode) ("\\.hs\\'" . haskell-mode) ("\\.lhs\\'" . haskell-mode) ("\\.md\\'" . markdown-mode) ("\\.html\\'" . nxml-mode) ("\\.xml\\'" . nxml-mode))) (add-to-list 'auto-mode-alist mode-spec)) ;; Top-Level Keybindings (bind-key "" #'winner-undo) (bind-key "" #'winner-redo) (bind-key "" #'db/run-or-hide-eshell) (bind-key " i" #'counsel-info-lookup-symbol) (bind-key " u" #'counsel-unicode-char) (bind-key "" #'rgrep) (bind-key "" #'hydra-zoom/body) (bind-key "" #'dictcc) (bind-key "" #'counsel-locate) (bind-key "" #'helm-org-agenda-files-headings) (bind-key "" #'magit-status) (bind-key "" #'org-capture) (bind-key "" #'db/helm-shortcuts) (bind-key "C-;" #'iedit-mode) (bind-key "C-<" #'mc/mark-previous-like-this) (bind-key "C->" #'mc/mark-next-like-this) (bind-key "C-." #'mc/skip-to-next-like-this) (bind-key "C-," #'mc/skip-to-previous-like-this) (bind-key "C-@" #'er/expand-region) (bind-key "C-M-\\" #'crux-cleanup-buffer-or-region) (bind-key "C-S-c C-S-c" #'mc/edit-lines) (bind-key "C-Z" #'undo-tree-redo) (bind-key "C-c C-<" #'mc/mark-all-like-this) (bind-key "C-c C-r" #'ivy-resume) (bind-key "C-c D" #'define-word) (bind-key "C-c J" #'avy-goto-word-or-subword-1) (bind-key "C-c P" #'ivy-pages) (bind-key "C-c a" #'org-agenda) (bind-key "C-c c" #'org-capture) (bind-key "C-c d" #'define-word-at-point) (bind-key "C-c e" #'crux-eval-and-replace) (bind-key "C-c i" #'hydra-ispell/body) (bind-key "C-c j" #'avy-goto-char-timer) (bind-key "C-c l" #'org-store-link) (bind-key "C-c m" #'emms-control/body) (bind-key "C-c o" #'hydra-org-clock/body) (bind-key "C-c s" #'synonyms) (bind-key "C-h C-f" #'find-function) (bind-key "C-h C-k" #'find-function-on-key) (bind-key "C-s" #'isearch-forward) (bind-key "M-i" #'swiper-from-isearch isearch-mode-map) (bind-key "C-x C-d" #'dired) (bind-key "C-x C-r" #'revert-buffer) (bind-key "C-x g" #'db/helm-shortcuts) (bind-key "C-x SPC" #'hydra-rectangle/body) (bind-key "C-x r v" #'list-registers) (bind-key "C-x t" #'hydra-toggle/body) (bind-key "C-z" #'undo) (bind-key "M-/" #'hippie-expand) (bind-key "M-:" #'pp-eval-expression) (bind-key "M-=" #'count-words) (bind-key "M-SPC" #'cycle-spacing) (bind-key "M-Z" #'zap-to-char) (bind-key "M-g M-g" #'avy-goto-line) (bind-key "M-g g" #'avy-goto-line) (bind-key "M-g j b" #'dumb-jump-back) (bind-key "M-g j g" #'dumb-jump-go) (bind-key "M-j" #'(lambda () (interactive) (join-line -1))) (bind-key "M-o" nil) (bind-key "M-z" #'zap-up-to-char) (bind-key [insert] nil) (bind-key [kp-insert] nil) (bind-key [remap fill-paragraph] #'endless/fill-or-unfill) ;; Overwrite certain keybindings only if packages are avilable (when (package-installed-p 'counsel) (bind-key "M-x" #'counsel-M-x) ; gets nicer sorting with smex installed (bind-key "C-c r" #'counsel-recentf) (bind-key "C-x C-f" #'counsel-find-file) (bind-key "C-h f" #'counsel-describe-function) (bind-key "C-h v" #'counsel-describe-variable) (bind-key "C-S-s" #'counsel-grep-or-swiper)) (when (package-installed-p 'helm) (bind-key "M-y" #'helm-show-kill-ring)) (when (package-installed-p 'crux) (bind-key [remap kill-whole-line] #'crux-kill-whole-line) (bind-key [remap open-line] #'crux-smart-open-line-above)) (when (package-installed-p 'ace-window) (bind-key "C-x o" #'ace-window)) (when (executable-find "ag") (bind-key "" #'counsel-ag)) ;; Environment Variables (unless on-windows (with-demoted-errors "Cannot import environment variables: %s" (exec-path-from-shell-copy-envs '("SSH_AUTH_SOCK" "SSH_AGENT_PID" "PATH" "TEXMFHOME" "PERL5LIB" "PERL_LOCAL_LIB_ROOT" "PERL_MB_OPT" "PERL_MM_OPT")))) ;; Fixes (with-eval-after-load 'enriched (defun enriched-decode-display-prop (start end &optional params) (ignore params) (list start end))) ;; Start Server when not running already (unless (server-running-p) (server-start)) t) (add-hook 'after-init-hook #'db/run-init) ;; * Personal customization (defgroup personal-settings nil "A bunch of functions and variables for personalizing emacs." :prefix "db/" :group 'convenience :group 'help :tag "Personal settings") (defcustom db/additional-mail-addresses nil "List of additional email addresses (apart from `user-mail-address’)." :group 'personal-settings :type '(repeat string)) (defcustom db/jabber-id "" "Personal XMPP ID." :group 'personal-settings :type 'string) ;; * Builtin Variables (setq custom-file (expand-file-name "private/custom.el" emacs-d)) (use-package cl-lib) (use-package subr-x) (use-package warnings :config (cl-pushnew '(undo discard-info) warning-suppress-types :test #'equal)) (set-default-coding-systems 'utf-8) (prefer-coding-system 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (setq buffer-file-coding-system 'utf-8) (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) (setq inhibit-startup-message t initial-scratch-message nil initial-major-mode 'fundamental-mode ring-bell-function #'ignore garbage-collection-messages nil load-prefer-newer nil) ; t breaks `org-reload' (fset 'yes-or-no-p 'y-or-n-p) (setq-default fill-column 80) (setq-default indent-tabs-mode nil) (setq frame-title-format "emacs") (setq select-enable-clipboard t select-enable-primary t save-interprogram-paste-before-kill t mouse-yank-at-point t require-final-newline nil sentence-end-double-space t recenter-positions '(top middle bottom) scroll-conservatively 10 message-log-max t inhibit-eol-conversion nil tab-always-indent 'complete enable-recursive-minibuffers t set-mark-command-repeat-pop t large-file-warning-threshold 10000000 echo-keystrokes 0.1 delete-by-moving-to-trash t delete-trailing-lines nil x-underline-at-descent-line t search-whitespace-regexp "[ \t\r\n]+" visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow)) (when on-windows ;; treat memory for display time ... but hey, this is Windows, memory doesn’t ;; matter! (setq inhibit-compacting-font-caches t)) (setq-default cursor-type 'bar) (setq visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow)) ;; don't let the cursor go into minibuffer prompt (setq minibuffer-prompt-properties '(read-only t face minibuffer-prompt cursor-intangible t)) ;; Make M-v undo C-v (setq scroll-preserve-screen-position 'always) ;; Backups and Autosave (defvar backup-dir (expand-file-name "ebackup/" emacs-d)) (defvar autosave-dir (expand-file-name "eautosave/" emacs-d)) (setq make-backup-files t backup-directory-alist (list (cons ".*" backup-dir)) auto-save-list-file-prefix autosave-dir auto-save-file-name-transforms `((".*" ,autosave-dir t)) version-control t kept-old-versions 2 kept-new-versions 4 delete-old-versions t vc-make-backup-files t) (setq-default async-shell-command-buffer 'new-buffer) (add-to-list 'display-buffer-alist '("^\*Async Shell Command*" . (display-buffer-no-window))) (put 'set-goal-column 'disabled nil) (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) (put 'narrow-to-region 'disabled nil) (use-package calendar :init (setq calendar-date-style 'iso calendar-bahai-all-holidays-flag nil calendar-chinese-all-holidays-flag nil calendar-christian-all-holidays-flag t calendar-islamic-all-holidays-flag nil calendar-hebrew-all-holidays-flag nil holiday-other-holidays '((holiday-fixed 5 1 "Labour Day") (holiday-fixed 10 3 "German Unity Day") (holiday-fixed 10 31 "Reformation Day") (holiday-float 11 3 -1 "Day of Repentance and Prayer" 22)) diary-show-holidays-flag t calendar-view-holidays-initially-flag t)) (setq-default font-lock-maximum-decoration '((t . t))) (setq-default savehist-file (expand-file-name "savehist" emacs-d)) (use-package tramp :config (setq tramp-save-ad-hoc-proxies t)) (use-package re-builder :commands (re-builder) :config (setq reb-re-syntax 'string)) (setq lisp-indent-function #'lisp-indent-function) (setq custom-theme-directory (expand-file-name "themes/" emacs-d)) ;; https://florian.adamsky.it/2016/03/31/emacs-calc-for-programmers-and-cs.html (setq math-additional-units '((bit nil "Bit") (byte "8 * bit" "Byte") (bps "bit / s" "Bit per second")) math-units-table nil) (setq default-input-method "TeX") (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "firefox") ;; * Basic Builtin Packages (use-package misc :commands (zap-up-to-char zap-to-char)) (use-package grep :commands (rgrep zrgrep) :config (progn (bind-key "C-x C-q" #'wgrep-change-to-wgrep-mode grep-mode-map) (bind-key "C-c C-c" #'wgrep-finish-edit grep-mode-map))) (use-package winner :commands (winner-mode winner-undo winner-redo)) (use-package abbrev :commands (quietly-read-abbrev-file) :init (progn (setq-default abbrev-mode t) (setq save-abbrevs 'silently)) :diminish abbrev-mode) (use-package appt :commands (appt-activate) :init (setq appt-display-mode-line nil)) (use-package ediff :defer t :init (setq ediff-diff-options "-w" ediff-window-setup-function 'ediff-setup-windows-plain ediff-split-window-function 'split-window-horizontally) :config (progn (add-hook 'ediff-keymap-setup-hook '(lambda () (bind-key "j" #'ediff-next-difference ediff-mode-map) (bind-key "k" #'ediff-previous-difference ediff-mode-map))) (add-hook 'ediff-after-quit-hook-internal 'winner-undo))) (use-package ispell :commands (ispell-change-directory hydra-ispell/body) :init (setq ispell-dictionary "en_US" ispell-really-hunspell t) :config (defhydra hydra-ispell (:color blue) "ispell" ("g" (lambda () (interactive) (setq ispell-dictionary "de_DE") (ispell-change-dictionary "de_DE")) "german") ("e" (lambda () (interactive) (setq ispell-dictionary "en_US") (ispell-change-dictionary "en_US")) "english"))) (use-package mailcap :defer t :config (progn ;; Remove doc-view so pdf will open with default viewer (setcdr (assoc "application" mailcap-mime-data) (remove '("pdf" (viewer . doc-view-mode) (type . "application/pdf") (test eq window-system 'x)) (cdr (assoc "application" mailcap-mime-data)))))) (use-package quail :defer t :config (add-hook 'input-method-activate-hook #'db/add-symbols-to-TeX-input-method)) (defun db/add-symbols-to-TeX-input-method () "Add some new symbols to TeX input method." (when (string= current-input-method "TeX") (let ((quail-current-package (assoc "TeX" quail-package-alist))) (quail-define-rules ((append . t)) ("\\land" ?∧) ("\\lor" ?∨) ("\\lnot" ?¬) ("\\implies" ?⇒) ("\\powerset" ?𝔓) ("\\mathbbK" ?𝕂) ("\\mathbbR" ?ℝ) ("\\mathbbN" ?ℕ) ("\\mathbbZ" ?ℤ) ("\\mathbbP" ?ℙ) ("\\mathcalA" ?𝒜) ("\\mathcalB" ?ℬ) ("\\mathcalC" ?𝒞) ("\\mathcalD" ?𝒟) ("\\mathcalE" ?ℰ) ("\\mathcalH" ?ℋ) ("\\mathcalI" ?ℐ) ("\\mathcalJ" ?𝒥) ("\\mathcalK" ?𝒦) ("\\mathcalL" ?ℒ) ("\\mathcalM" ?ℳ) ("\\mathcalR" ?ℛ) ("\\mathcalQ" ?𝒬) ("\\mathcalS" ?𝒮) ("\\mathfrakP" ?𝔓))))) (use-package server :commands (server-running-p server-start)) (use-package rect :commands (hydra-rectangle/body) :config (defhydra hydra-rectangle (:body-pre (rectangle-mark-mode 1) :color pink :post (deactivate-mark)) " ^_k_^ _d_elete _s_tring _h_ _l_ _o_k _y_ank ^_j_^ _n_ew-copy _r_eset ^^^^ _e_xchange _u_ndo ^^^^ ^ ^ _p_aste " ("h" backward-char nil) ("l" forward-char nil) ("k" previous-line nil) ("j" next-line nil) ("n" copy-rectangle-as-kill nil) ("d" delete-rectangle nil) ("r" (if (region-active-p) (deactivate-mark) (rectangle-mark-mode 1)) nil) ("y" yank-rectangle nil) ("u" undo nil) ("s" string-rectangle nil) ("p" kill-rectangle nil) ("e" rectangle-exchange-point-and-mark nil) ("o" nil nil))) ;; * Some essential packages (use-package db-utils :commands (endless/fill-or-unfill db/delete-trailing-whitespace-maybe db/go-dark db/go-light db/show-current-org-task db/run-or-hide-shell db/run-or-hide-eshell db/run-or-hide-ansi-term db/helm-shortcuts db/hex-to-ascii conditionally-enable-lispy db/export-diary)) (use-package db-emacsclient) (use-package hydra :commands (defhydra hydra-toggle/body hydra-zoom/body) :config (defhydra hydra-toggle (:color blue) "toggle" ("c" column-number-mode "column") ("d" toggle-debug-on-error "debug-on-error") ("e" toggle-debug-on-error "debug-on-error") ("f" auto-fill-mode "auto-fill") ("l" toggle-truncate-lines "truncate lines") ("q" toggle-debug-on-quit "debug-on-quit") ("r" read-only-mode "read-only")) ;; zooming with single keystrokes (from oremacs) (defhydra hydra-zoom (:color red) "zoom" ("g" text-scale-increase "increase") ("l" text-scale-decrease "decrease"))) (use-package magit :commands (magit-status) :init (setq magit-diff-refine-hunk t magit-commit-show-diff nil magit-popup-use-prefix-argument 'default magit-completing-read-function 'ivy-completing-read) :config (progn (global-magit-file-mode -1) (with-demoted-errors "Non-Fatal Error: %s" (eval-when-compile (require 'projectile)) (setq magit-repository-directories (mapcar (lambda (dir) (cons (substring dir 0 -1) 0)) (cl-remove-if-not (lambda (project) (unless (file-remote-p project) (file-exists-p (concat project "/.git")))) projectile-known-projects)))))) (use-package projectile :commands (projectile-mode) :defines (projectile-known-projects) :bind (:map projectile-mode-map ("C-c p" . projectile-command-map)) :init (setq projectile-switch-project-action 'projectile-dired projectile-completion-system 'ivy projectile-ignored-project-function #'file-remote-p projectile-create-missing-test-files t) :config (projectile-cleanup-known-projects) :diminish projectile-mode) (use-package counsel-projectile :commands counsel-projectile) (use-package exec-path-from-shell :commands (exec-path-from-shell-copy-envs)) ;; * Org (use-package db-org :commands (db/find-parent-task db/ensure-running-clock db/save-current-org-task-to-file)) (use-package org :commands (org-agenda org-capture org-store-link hydra-org-clock/body) :bind (:map org-mode-map ([remap org-return] . org-return-indent)) :config (progn (require 'db-org) ;; avoid important buffers to end up in `org-agenda-new-buffers’ by ;; opening them manually (mapc #'find-file-noselect org-agenda-files) (unless (memq #'org-clock-save (mapcar #'timer--function timer-list)) (run-with-timer 0 3600 #'org-clock-save)) (unless (memq #'db/export-diary (mapcar #'timer--function timer-idle-list)) (run-with-idle-timer 20 t #'db/export-diary)))) ;; Default Tasks for Working, Home, Breaks (defcustom org-working-task-id "" "Task ID of default working task." :group 'personal-settings :type 'string) (defcustom org-break-task-id "" "Task ID of default break task." :group 'personal-settings :type 'string) (defcustom org-home-task-id "" "Task ID of default home task." :group 'personal-settings :type 'string) (defcustom db/org-clock-current-task-file "~/.org-current-task" "File to save the currently clocked in task to." :group 'personal-settings :type 'string) (use-package org-clock :init (setq org-clock-history-length 23 org-clock-in-resume t org-clock-into-drawer t org-clock-idle-time nil org-clock-out-remove-zero-time-clocks t org-clock-out-when-done '("DONE" "CANC" "WAIT" "HOLD") org-clock-auto-clock-resolution 'when-no-clock-is-running org-clock-mode-line-total 'auto org-clock-report-include-clocking-task t org-clock-in-switch-to-state (lambda (_) (when (not (and (boundp 'org-capture-mode) org-capture-mode)) (cond ((member (org-get-todo-state) (list "TODO" "READ")) "CONT") ((member (org-get-todo-state) (list "GOTO")) "ATTN")))) org-clock-persist t org-clock-persist-query-resume nil org-duration-format 'h:mm org-time-stamp-rounding-minutes '(1 1)) :config (progn (org-clock-persistence-insinuate) (add-hook 'org-clock-in-hook ; mark current default task (lambda () (let ((current-id (org-id-get org-clock-marker))) (when (member current-id (list org-working-task-id org-home-task-id)) (org-clock-mark-default-task))))) ;; Clock in default task if no other task is given (add-hook 'org-clock-out-hook #'db/ensure-running-clock 'append) ;; Communicate the currently clocked in task to the outside world (add-hook 'org-clock-in-hook #'db/save-current-org-task-to-file))) (use-package ox-icalendar :commands (org-icalendar-combine-agenda-files) :init (setq org-icalendar-include-body nil org-icalendar-store-UID t org-icalendar-use-deadline nil org-icalendar-use-scheduled nil org-icalendar-include-todo nil org-icalendar-exclude-tags '("NO_EXPORT"))) (use-package ox :defer t :init (setq org-export-with-broken-links 'mark org-export-with-sub-superscripts '{} org-export-with-author nil org-export-with-date nil org-export-with-toc nil org-export-with-archived-trees nil org-export-with-tags t org-export-with-priority nil org-export-with-creator nil org-export-with-entities t org-export-with-special-strings t org-export-with-todo-keywords nil org-export-exclude-tags '("NO_EXPORT")) :config (with-demoted-errors "Cannot load package: %s" (require 'ox-md) (require 'ox-pandoc))) (use-package ox-latex :defer t :config (progn (setq org-latex-default-class "scrartcl" org-latex-listings t org-latex-compiler "lualatex") (add-to-list 'org-latex-classes `("scrartcl" ,(concat "\\documentclass[parskip=half,colorlinks]{scrartcl}\n" "[DEFAULT-PACKAGES]" "[PACKAGES]" " \\lstset{ basewidth=0.5em, keywordstyle=\\textcolor{blue!80!white}, basicstyle=\\ttfamily, commentstyle={\\itshape}, frame=tb, showspaces=false, showtabs=false, showstringspaces=false, } " "[EXTRA]\n") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) (add-to-list 'org-latex-classes `("beamer" ,(concat "\\documentclass[presentation]{beamer}\n" "[DEFAULT-PACKAGES]" "[PACKAGES]" " \\lstset{ basewidth=0.5em, keywordstyle=\\textcolor{blue!80!white}, basicstyle=\\ttfamily, commentstyle={\\itshape}, frame=tb, showspaces=false, showtabs=false, showstringspaces=false, } " "[EXTRA]\n") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))) (add-to-list 'org-latex-packages-alist '("" "listings")) (add-to-list 'org-latex-packages-alist '("" "xcolor")))) (use-package ox-html :defer t :init (setq org-html-postamble nil)) ;; * Mail (use-package bbdb :commands (bbdb-search-name bbab-initialize bbdb-mua-auto-update-init bbdb-save) :init (setq bbdb-completion-display-record nil bbdb-complete-mail-allow-cycling t bbdb-mua-auto-update-p 'query bbdb-default-country "Germany" bbdb-user-mail-address-re (regexp-opt (cons user-mail-address db/additional-mail-addresses))) :config (progn (add-hook 'message-setup-hook 'bbdb-mail-aliases) (add-hook 'mail-setup-hook 'bbdb-mail-aliases) (run-with-timer 0 3600 #'bbdb-save))) (use-package gnus :defines (gnus-init-file) :commands (gnus) :init (setq gnus-init-file (expand-file-name "gnus.el" emacs-d) gnus-home-directory (expand-file-name "~/Mail/news/") gnus-directory (expand-file-name "~/Mail/news/") gnus-kill-files-directory gnus-directory gnus-startup-file (expand-file-name "~/Mail/gnus-newsrc") gnus-cache-directory (expand-file-name "cache/" gnus-directory)) :config (progn (eval-when-compile (require 'gnus-start)) (bbdb-initialize 'gnus 'message) (bbdb-mua-auto-update-init 'message))) ;; * Crypto (use-package nsm :defer t :init (setq network-security-level 'high nsm-save-host-names t) :config (advice-add 'nsm-write-settings :before #'db/sort-nsm-permanent-settings)) (defun db/sort-nsm-permanent-settings () "Sort values in `nsm-permanent-host-settings’." (setq nsm-permanent-host-settings (cl-sort nsm-permanent-host-settings #'string< :key #'second))) (use-package gnutls :defer t :init (setq gnutls-log-level 0 ; too noisy otherwise gnutls-min-prime-bits 1024 gnutls-verify-error t)) (defun db/update-cert-file-directory (symbol new-value) "Set SYMBOL to NEW-VALUE and add all certificate in it to `gnutls-trustfiles’. Assumes that NEW-VALUE points to a directory, and certificates are assumed to be of the form *.crt." (set symbol new-value) (when (file-directory-p new-value) (dolist (cert-file (directory-files new-value t ".crt$")) (add-to-list 'gnutls-trustfiles cert-file)))) (defcustom db/cert-file-directory "~/.local/etc/certs/" "Local directory with additional certificates." :group 'personal-settings :type 'string :set #'db/update-cert-file-directory) (use-package epg :defer t :init (setq epg-debug t epg-gpg-program "gpg")) ;; * Appearance (use-package solarized-theme :defer t :init (setq solarized-use-less-bold t solarized-emphasize-indicators t solarized-use-variable-pitch nil)) (use-package smart-mode-line :init (setq sml/mode-width 'full sml/name-width 30 sml/theme 'respectful) :commands (sml/setup)) ;; * Dired (use-package dired :defer t :bind (:map dired-mode-map ("e" . ora-ediff-files) ("z" . dired-get-size) ([remap beginning-of-buffer] . dired-back-to-top) ([remap end-of-buffer] . dired-jump-to-bottom) ("" . nil)) :init (progn (setq dired-dwim-target t dired-listing-switches "-alh" dired-hide-details-hide-information-lines t dired-hide-details-hide-symlink-targets t dired-recursive-copies 'top dired-recursive-deletes 'top ;; Don’t use obsolete diredx local variables dired-enable-local-variables nil dired-local-variables-file nil dired-omit-files "^\\.?#\\|^\\.$\\|^\\.\\.$\\|^\\..*$" diredp-hide-details-initially-flag t) (if on-windows (setq dired-guess-shell-alist-user '((".*" "cmd /c"))) (setq dired-guess-shell-alist-user '(("\\.pdf\\'" "evince") ("\\.ps\\'" "evince") ("\\.\\(?:djvu\\|eps\\)\\'" "evince") ("\\.\\(?:jpg\\|jpeg\\|png\\|gif\\|xpm\\)\\'" "eog") ("\\.\\(?:xcf\\)\\'" "gimp") ("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\|ogv\\|webm\\)\\(?:\\.part\\)?\\'" "vlc") ("\\.\\(?:mp3\\|flac\\|ogg\\)\\'" "mplayer") ("\\.html?\\'" "firefox") ("\\.docx?\\'" "loffice")))) (when on-windows (setq directory-free-space-program nil))) :config (progn (put 'dired-find-alternate-file 'disabled nil) (require 'dired-x) (with-demoted-errors "Non-Fatal Error: %s" (require 'dired+) (when (and (eq system-type 'windows-nt) (not (package-installed-p 'w32-browser))) (warn "`w32-browser’ not installed, dired will have reduced functionality.")) (when (and (require 'dired-open) (eq system-type 'gnu/linux)) (bind-key "M-RET" #'dired-open-xdg dired-mode-map))) ;; Gnus support in dired (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) ;; omitting files (add-hook 'dired-mode-hook 'dired-omit-mode) (dolist (extension '(".out" ".synctex.gz" ".thm")) (add-to-list 'dired-latex-unclean-extensions extension)) ;; disable exaggerated fontification of dired+ (require 'font-lock) (add-to-list 'font-lock-maximum-decoration '(wdired-mode . 1)) (add-to-list 'font-lock-maximum-decoration '(dired-mode . 1)) (defun ora-ediff-files () "Compare marked files in dired with ediff." ;; from: https://oremacs.com/2017/03/18/dired-ediff/ (interactive) (lexical-let ((files (dired-get-marked-files)) (wnd (current-window-configuration))) (if (<= (length files) 2) (lexical-let ((file1 (car files)) (file2 (if (cdr files) (cadr files) (read-file-name "file: " (dired-dwim-target-directory))))) (if (file-newer-than-file-p file1 file2) (ediff-files file2 file1) (ediff-files file1 file2)) (add-hook 'ediff-after-quit-hook-internal (lambda () (setq ediff-after-quit-hook-internal nil) (set-window-configuration wnd)))) (error "No more than 2 files should be marked")))) (defun dired-back-to-top () "Jump to first non-trivial line in dired." (interactive) (goto-char (point-min)) (dired-next-line 1)) (defun dired-jump-to-bottom () "Jump to last non-trivial line in dired." (interactive) (goto-char (point-max)) (dired-next-line -1)) (defun dired-get-size () ; from emacswiki, via oremacs "Print size of all files marked in the current dired buffer." (interactive) (let ((files (dired-get-marked-files))) (with-temp-buffer (apply 'call-process "/usr/bin/du" nil t nil "-sch" files) (message "size of all marked files: %s" (progn (re-search-backward "\\(^[0-9.,]+[a-za-z]+\\).*total$") (match-string 1)))))))) (use-package find-dired :commands (find-dired) :init (setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld"))) (use-package dired-open :config (add-to-list 'dired-open-functions #'dired-open-guess-shell-alist)) (use-package gnus-dired :commands (turn-on-gnus-dired-mode)) ;; * Completion (use-package hippie-exp :commands (hippie-expand)) (use-package helm-config :init (setq helm-command-prefix-key "C-c h")) (use-package helm :commands (helm-show-kill-ring helm-org-agenda-files-headings) :diminish helm-mode :bind (:map helm-command-map ("#" . helm-emms) ("P" . helm-pages)) :init (setq helm-input-idle-delay 0.0 helm-buffers-fuzzy-matching t helm-mode-fuzzy-match t helm-autoresize-min-height 20 helm-ff-auto-update-initial-value t helm-ff-file-name-history-use-recentf t helm-ff-search-library-in-sexp t helm-ff-skip-boring-files nil helm-split-window-inside-p t helm-move-to-line-cycle-in-source nil helm-scroll-amount nil helm-locate-command nil helm-candidate-number-limit 100 helm-follow-mode-persistent t helm-buffer-details-flag t helm-buffer-skip-remote-checking t helm-mini-default-sources '(helm-source-buffers-list helm-source-recentf db/helm-frequently-used-features db/helm-frequently-visited-locations helm-source-buffer-not-found helm-source-bookmarks helm-source-bookmark-set)) :config (progn (eval-when-compile (require 'helm-mode) (require 'helm-buffers) (require 'helm-ring) (require 'helm-org)) (bind-key "" #'helm-execute-persistent-action helm-map) (bind-key "C-i" #'helm-execute-persistent-action helm-map) (bind-key "C-z" #'helm-select-action helm-map) ;; Add action to clock in at current heading to ;; `helm-org-agenda-files-headings’ (defun helm-org--clock-in-at-heading (marker) "Clock in to current heading at MARKER." (org-with-point-at marker (org-clock-in))) (defun helm-org-clock-in-at-heading () (interactive) (with-helm-alive-p (helm-exit-and-execute-action 'helm-org--clock-in-at-heading))) (add-to-list 'helm-org-headings-actions '("Clock in to this heading" . helm-org--clock-in-at-heading) t) (bind-key "C-c c" #'helm-org-clock-in-at-heading helm-org-headings-map))) (use-package ivy :commands (ivy-mode ivy-resume) :diminish ivy-mode :init (setq ivy-use-virtual-buffers t enable-recursive-minibuffers t ivy-magic-tilde nil ivy-count-format "(%d/%d) " ivy-format-function #'(lambda (cands) (ivy--format-function-generic (lambda (str) (concat "→ " str)) (lambda (str) (concat " " str)) cands "\n")) ivy-initial-inputs-alist '((counsel-describe-function . "^") (counsel-describe-variable . "^") (man . "^") (woman . "^"))) :config (add-to-list 'ivy-completing-read-handlers-alist '(org-capture . completing-read-default))) (use-package counsel :commands (counsel-org-goto-all counsel-ag counsel-M-x counsel-find-file counsel-info-lookup-symbol counsel-unicode-char counsel-describe-variable counsel-describe-function counsel-recentf)) (use-package swiper :commands (swiper swiper-from-isearch)) (use-package recentf :commands (recentf-mode recentf-save-list) :init (setq recentf-max-saved-items 1000) :config (run-with-timer 0 3600 #'recentf-save-list)) (use-package company :commands (company-mode global-company-mode) :init (setq company-show-numbers t)) ;; * Navigation (use-package ace-window :commands (ace-window ace-window-display-mode) :config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) aw-background nil aw-leading-char-style 'char aw-scope 'frame)) (use-package avy :commands (avy-goto-char-timer avy-goto-word-or-subword-1 avy-goto-line)) (use-package dumb-jump :commands (dumb-jump-go-other-window dumb-jump-go dumb-jump-back dumb-jump-quick-look dumb-jump-go-prefer-external dumb-jump-go-prefer-external-other-window) :config (setq dumb-jump-selector 'helm)) (use-package helm-pages :commands (helm-pages)) (use-package eyebrowse :commands (eyebrowse-mode) :init (setq eyebrowse-keymap-prefix (kbd "C-c w"))) ;; * Media (use-package emms-source-file :config (require 'db-emms)) (use-package db-emms :commands (db/play-playlist emms-control/body)) (use-package helm-emms :commands (helm-emms) :init (setq helm-emms-use-track-description-function t helm-emms-default-sources '(helm-source-emms-streams helm-source-emms-dired helm-source-emms-files)) :config (progn (require 'db-emms) (require 'helm-adaptive))) ;; * Shells and such (use-package comint :defer t :init (setq comint-scroll-to-bottom-on-input t comint-scroll-to-bottom-on-output nil comint-scroll-show-maximum-output t comint-completion-addsuffix t comint-buffer-maximum-size 100000 comint-input-ring-size 5000)) (use-package term :commands (term-send-string) :init (setq explicit-shell-file-name shell-file-name) :config (progn (add-hook 'term-exec-hook ; oremacs.com (lambda () (let* ((buff (current-buffer)) (proc (get-buffer-process buff))) (set-process-sentinel proc `(lambda (process event) (if (string= event "finished\n") (kill-buffer ,buff))))))) ;; does not work; C-c is shadowed by some minor modes like semantic, ;; projectile, and winner (bind-key "C-c" #'term-send-raw term-raw-map) ;; unbind some keys to allow the global keymap to handle them (unbind-key "M-:" term-raw-map) (unbind-key "C-h" term-raw-map) (unbind-key "M-x" term-raw-map) (unbind-key "M-o" term-raw-map) ;; we need to set keys starting with C-x after `ansi-term' has been ;; called, as it resets the escape character to C-x. (defadvice ansi-term (after ansi-term-set-keys activate) (unbind-key "C-x C-j" term-raw-map) (unbind-key "C-x g" term-raw-map)) (add-hook 'term-mode-hook (lambda () (yas-minor-mode -1))))) ;; http://endlessparentheses.com/ansi-colors-in-the-compilation-buffer-output.html (defun endless/colorize-compilation () "Colorize from `compilation-filter-start' to `point'." (let ((inhibit-read-only t)) (ansi-color-apply-on-region compilation-filter-start (point)))) (use-package ansi-color :commands (ansi-color-for-comint-mode-on ansi-color-apply-on-region) :config (progn (add-hook 'compilation-filter-hook 'endless/colorize-compilation))) (use-package shell :commands (shell) :config (progn (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on) (add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m) (add-hook 'shell-mode-hook 'with-editor-export-editor))) (use-package eshell :commands (eshell) :config (require 'db-eshell)) (use-package with-editor :commands (with-editor-export-editor)) ;; * Lisp ;; General Stuff first (use-package lispy :commands (lispy-mode) :diminish lispy-mode) (use-package eldoc :commands (eldoc-mode) :diminish eldoc-mode) ;; Lisp Dialects (use-package elisp-mode :defer t :config (progn (add-hook 'emacs-lisp-mode-hook 'lispy-mode) (add-hook 'emacs-lisp-mode-hook 'db/add-use-package-to-imenu) (add-hook 'ielm-mode-hook 'eldoc-mode) (add-hook 'emacs-lisp-mode-hook 'eldoc-mode))) (defun db/add-use-package-to-imenu () "Add `use-package’ statements to `imenu-generic-expression." (add-to-list 'imenu-generic-expression '("Used Packages" "\\(^\\s-*(use-package +\\)\\(\\_<.+\\_>\\)" 2))) (use-package geiser :commands (geiser-mode)) (use-package cider :commands (cider-jack-in) :init (setq nrepl-hide-special-buffers t cider-auto-select-error-buffer t cider-stacktrace-default-filters '(tooling dup) cider-stacktrace-fill-column 80 cider-save-file-on-load nil cider-repl-result-prefix ";; => " cider-repl-use-clojure-font-lock t cider-repl-wrap-history t cider-repl-history-size 1000 ;;cider-lein-parameters "trampoline repl :headless" cider-lein-parameters "repl :headless" cider-repl-history-file (expand-file-name ".cider-history" emacs-d) cider-repl-display-help-banner nil cider-cljs-lein-repl "(cemerick.piggieback/cljs-repl (cljs.repl.rhino/repl-env))") :config (progn (add-hook 'cider-repl-mode-hook 'subword-mode) (add-hook 'cider-repl-mode-hook 'lispy-mode) (add-hook 'cider-repl-mode-hook 'cider-repl-toggle-pretty-printing) (add-hook 'cider-repl-mode-hook 'company-mode) (add-hook 'cider-mode-hook 'eldoc-mode))) (use-package clojure-mode :defer t :config (progn (define-clojure-indent (forall 'defun) (exists 'defun) (dopar 'defun)) (add-hook 'clojure-mode-hook 'lispy-mode) (add-hook 'clojure-mode-hook 'clj-refactor-mode) (add-hook 'clojure-mode-hook 'yas-minor-mode) (add-hook 'clojure-mode-hook 'company-mode))) (use-package clj-refactor :commands (clj-refactor-mode) :config (progn (cljr-add-keybindings-with-prefix "C-c C-m") (setq cljr-eagerly-build-asts-on-startup nil cljr-warn-on-eval nil))) (use-package slime :commands (slime slime-mode slime-connect) :init (progn (setq inferior-lisp-program "sbcl --noinform --no-linedit" slime-compile-file-options '(:fasl-directory "/tmp/slime-fasls/") slime-net-coding-system 'utf-8-unix slime-completion-at-point-functions 'slime-fuzzy-complete-symbol slime-lisp-implementations '((sbcl ("sbcl") :coding-system utf-8-unix) (cmucl ("cmucl") :coding-system utf-8-unix) (ccl ("ccl") :coding-system utf-8-unix)) slime-repl-history-remove-duplicates t slime-repl-history-trim-whitespaces t) (add-hook 'lisp-mode-hook '(lambda () (slime-mode +1)) t)) :config (progn (make-directory "/tmp/slime-fasls/" t) (slime-setup '(slime-repl slime-fancy slime-autodoc)) (add-hook 'slime-mode-hook 'slime-redirect-inferior-output))) (use-package hy-mode :commands (hy-mode) :config (progn (add-hook 'hy-mode-hook 'lispy-mode) (add-hook 'hy-mode-hook 'inferior-lisp))) ;; * TeX (use-package reftex :commands (turn-on-reftex) :config (progn (with-eval-after-load 'helm-mode (add-to-list 'helm-completing-read-handlers-alist '(reftex-citation . nil))) (setq reftex-plug-into-AUCTeX t))) (use-package tex :defer t :config (require 'db-latex)) (use-package ebib :commands (ebib)) (use-package helm-bibtex :commands (helm-bibtex)) ;; * Various Mode Configurations ;; These are packages that are not essential, but still nice to have. They ;; provide optional functionality and may redefine builtin commands. (use-package cperl-mode :commands (cperl-mode) :init (progn ;; replace perl-mode with cperl-mode (mapc (lambda (pair) (if (eq (cdr pair) 'perl-mode) (setcdr pair 'cperl-mode))) (append auto-mode-alist interpreter-mode-alist)) (setq cperl-hairy nil)) :config (progn (add-hook 'cperl-mode-hook 'flycheck-mode) (add-hook 'cperl-mode-hook 'prettify-symbols-mode))) (use-package crux :commands (crux-eval-and-replace crux-smart-open-line-above crux-kill-whole-line crux-cleanup-buffer-or-region crux-delete-buffer-and-file)) (use-package db-projects :commands (projects-add-project projects-archive-project)) (use-package define-word :commands (define-word-at-point define-word)) (use-package dictcc :commands (dictcc) :config (require 'gnutls)) (use-package edit-list :commands edit-list) (use-package electric :commands (electric-quote-mode)) (use-package elec-pair :commands (electric-pair-mode) :config (progn (add-to-list 'electric-pair-pairs '(?“ . ?”)) (add-to-list 'electric-pair-text-pairs '(?“ . ?”)) (add-to-list 'electric-pair-pairs '(?„ . ?“)) (add-to-list 'electric-pair-text-pairs '(?„ . ?“)))) (defun db/turn-off-local-electric-pair-mode () "Locally turn off electric pair mode." (interactive) (electric-pair-local-mode -1)) (use-package expand-region :commands (er/expand-region)) (use-package flycheck :commands (global-flycheck-mode flycheck-mode)) (use-package flyspell :commands (flyspell-mode turn-on-flyspell) :config (progn (unbind-key "C-M-i" flyspell-mode-map) (unbind-key "C-c $" flyspell-mode-map))) (use-package haskell-mode :defer t :defines (haskell-program-name) :init (setq haskell-program-name "ghci") :config (progn (add-hook 'haskell-mode-hook 'haskell-doc-mode) (add-hook 'haskell-mode-hook 'turn-on-haskell-indent) (add-hook 'haskell-mode-hook (lambda () (company-mode +1) (set (make-local-variable 'company-backends) (append '((company-capf company-dabbrev-code)) company-backends)))) (add-hook 'haskell-mode-hook 'flycheck-mode) (with-demoted-errors "Non-Fatal Error: %s" (require 'haskell-indentation) (add-hook 'haskell-mode-hook 'haskell-indentation-mode)) (add-hook 'haskell-mode-hook 'interactive-haskell-mode))) (use-package ivy-pages :commands (ivy-pages)) (use-package highlight-indentation :commands highlight-indentation-mode) (use-package iedit :commands (iedit-mode)) (use-package key-chord :commands (key-chord-mode) :config (progn (key-chord-define-global "``" "“") (key-chord-define-global "''" "”") (key-chord-define-global ",," "„"))) (use-package mastodon :commands (mastodon)) (use-package multiple-cursors :commands (mc/edit-lines mc/mark-next-like-this mc/mark-previous-like-this mc/mark-all-like-this)) (use-package org-ref :defer t :config (progn (require 'org-ref-pdf) (require 'org-ref-url-utils))) (use-package page-break-lines :commands (page-break-lines-mode) :diminish page-break-lines-mode) (use-package python :defer t :init (setq python-indent-offset 2) :config (progn (add-hook 'python-mode-hook 'highlight-indentation-mode) (when (package-installed-p 'elpy) (elpy-enable)))) (use-package semantic :commands (semantic-mode) :config (progn (require 'semantic/ia) (require 'semantic/bovine/el) ;; recognize `use-package' as include statement; the function seems ;; to have to be a byte-compiled function, for otherwise it just ;; won’t work … ? (eval `(semantic-elisp-setup-form-parser ,(lambda (form start end) (ignore start end) (semantic-tag-new-include (symbol-name (nth 1 form)) nil)) use-package)))) (use-package sh-scripts :defer t :init (setq sh-basic-offset 2 sh-indentation 2)) (use-package synonyms :commands (synonyms)) (use-package timeline-tools :load-path "site-lisp" :commands (timeline-tools-format-timeline timeline-tools-format-timeline-of-day timeline-tools-copy-clocklines)) (use-package typing :commands (typing-of-emacs) :init (setq toe-highscore-file nil)) (use-package undo-tree :commands (global-undo-tree-mode undo undo-tree-redo) :init (setq undo-tree-visualizer-timestamps t undo-tree-visualizer-diff t) :diminish undo-tree-mode) (use-package vlf-setup) (use-package wgrep :commands (wgrep-finish-edit wgrep-change-to-wgrep-mode)) (use-package which-key :commands (which-key-mode) :diminish which-key-mode :init (setq which-key-side-window-max-width 0.33 which-key-side-window-max-height 0.25) :config (which-key-setup-side-window-bottom)) (use-package yasnippet :commands (yas-minor-mode-on yas-minor-mode) :diminish yas-minor-mode :config (yas-reload-all)) ;;; init.el ends here