14 KiB
14 KiB
Doom Emacs Config
Main
Help
;; Here are some additional functions/macros that could help you configure Doom:
;; - `load!' for loading external *.el files relative to this one
;; - `use-package!' for configuring packages
;; - `after!' for running code after a package has loaded
;; - `add-load-path!' for adding directories to the `load-path', relative to
;; this file. Emacs searches the `load-path' when you load packages with
;; `require' or `use-package'.
;; - `map!' for binding new keys
Overall config
Doom specific settings
(setq user-full-name "Julian Mutter"
user-mail-address "julian.mutter@comumail.de")
(setq doom-font (font-spec :family "Source Code Pro" :size 14))
(setq doom-theme 'doom-one)
(setq display-line-numbers-type 'relative)
My custom keybindings
;; Open external terminal
(map! :leader :desc "Open external terminal" "o t" (cmd! (call-process-shell-command "alacritty &" nil 0)))
;; Open external file manager
(map! :leader :desc "Open external file explorer" "o e" (cmd! (call-process-shell-command "thunar &" nil 0)))
;; Remap font scaling keybindings to make more sense
(map! :desc "Increase font size" :n "C-+" #'text-scale-increase)
(map! :desc "Decrease font size" :n "C--" #'text-scale-decrease)
(map! :desc "Reset font size" :n "C-=" #'doom/reset-font-size)
(map! :desc "Flycheck next error" :nv "g n" #'flycheck-next-error)
(map! :desc "Flycheck previous error" :nv "g N" #'flycheck-previous-error)
(map! :leader "c X" #'flycheck-list-errors)
(map! :desc "Format and save" :g "C-s" #'fd-format-and-save)
(map! :leader "w 1" #'delete-other-windows)
(map! :leader "t p" #'+popup/toggle)
(dotimes (counter 9)
(let ((command (format "(map! :leader \"%d\" #'winum-select-window-%d)"
(1+ counter) (1+ counter))))
(eval (read command))))
(map! :leader "r" #'quickrun)
(setq-default evil-escape-key-sequence "kj")
(defun fd-format-and-save()
(interactive)
(company-abort)
(evil-force-normal-state)
;; (without-minibuffer '+format/buffer) ; Skip if no formatter is defined (e.g. in text mode)
(+format/buffer) ; Skip if no formatter is defined (e.g. in text mode)
(save-buffer))
(defmacro without-minibuffer (&rest body)
"Like `progn', but stop and return nil if any of BODY forms tries to use the minibuffer.
Also disable dialogs while evaluating BODY forms, since dialogs
are just an alternative to the minibuffer."
`(catch 'tried-to-use-minibuffer
(minibuffer-with-setup-hook
(lambda (&rest args) (throw 'tried-to-use-minibuffer nil))
(let ((use-dialog-box)) ; No cheating by using dialogs instead of minibuffer
,@body))))
;; Do not ask before exiting emacs
(setq confirm-kill-emacs nil)
Openwith
(openwith-mode t)
(setq openwith-associations '(("\\.pdf\\'" "evince" (file))))
Org
(setq org-directory "~/Nextcloud/org"
org-roam-directory "~/Nextcloud/org/roam")
;; Make all org files agenda files
(setq org-agenda-files (list org-directory "~/dev/bachelor-thesis/notes"))
(setq org-export-allow-bind-keywords t)
;; Insert timestamp when marking task as done
(setq org-log-done #'time)
(add-hook 'org-clock-in-hook #'save-buffer)
(add-hook 'org-clock-out-hook #'save-buffer)
(setq org-pomodoro-manual-break t)
;; Max volume is 65536 since player is paplay
(let ((volume "--volume=40000"))
(setq org-pomodoro-start-sound-args volume)
(setq org-pomodoro-killed-sound-args volume)
(setq org-pomodoro-ticking-sound-args volume)
(setq org-pomodoro-finished-sound-args volume)
(setq org-pomodoro-overtime-sound-args volume)
(setq org-pomodoro-long-break-sound-args volume)
(setq org-pomodoro-short-break-sound-args volume)
)
(setq org-agenda-custom-commands
'(("." "Clocking today" agenda ""
((org-agenda-span 1)
(org-agenda-start-day "today")
(org-agenda-start-with-clockreport-mode t)
(org-agenda-start-with-log-mode 'clockcheck)
))))
(setq org-agenda-clockreport-parameter-plist '(:link t :maxlevel 2 :fileskip0 t)) ;; :stepskip0 t
(setq org-clock-mode-line-total 'today)
(map! :map org-mode-map :nvi "C-k" #'org-backward-element)
(map! :map org-mode-map :nvi "C-j" #'org-forward-element)
(map! :map org-mode-map :nvi "C-h" #'org-up-element)
(map! :map org-mode-map :nvi "C-l" #'org-down-element)
(map! :map org-mode-map :nvi "M-i" #'org-roam-node-insert)
(map! :map org-mode-map :nvi "M-@" #'org-cite-insert)
(map! :map doom-leader-notes-map "r r" #'org-roam-node-find)
(map! :map doom-leader-notes-map "r t" #'org-roam-buffer-toggle)
(map! :map doom-leader-notes-map "s" #'fd-org-notes-search-follow-symlinks)
(after! org
(add-to-list 'org-capture-templates
'("b" "Bachelor todo" entry
(file+headline "bachelor/todo.org" "Inbox")
"* IDEA %?\n%i\n%T\n%a" :prepend t)
))
(defun fd-org-notes-search-follow-symlinks (query)
"Alternative to +default/org-notes-search which follows symbolic links for better project inlusion"
(interactive
(list (if (doom-region-active-p)
(buffer-substring-no-properties
(doom-region-beginning)
(doom-region-end))
"")))
(require 'org)
(+vertico-file-search :query query :in org-directory :args '("-L")))
(defun fd-org-latex-preview-buffer ()
"Show latex preview for whole buffer by running org-latex-preview with C-u C-u"
(interactive)
(let ((current-prefix-arg '(16)))
(call-interactively 'org-latex-preview)
))
TeX
;; Enable org mode like header navigation
(map! :map TeX-mode-map :nvi "<backtab>" #'outline-cycle-buffer)
(map! :map TeX-mode-map :nv "C-k" #'outline-backward-same-level)
(map! :map TeX-mode-map :nv "C-j" #'outline-forward-same-level)
(map! :map TeX-mode-map :nv "C-h" #'outline-up-heading)
(map! :map TeX-mode-map :nv "C-l" #'outline-next-heading)
;; Fixes latexindent not finding perl libraries
(setenv "PERL5LIB" "~/perl5/lib/perl5")
(setq +latex-viewers '(evince))
Spell Checking
(use-package! lsp-ltex
:init
(setq lsp-ltex-enabled t)
(setq lsp-ltex-language "en-US")
(setq lsp-ltex-mother-tongue "de-DE"))
;; Do not automatically enable writegood mode
(remove-hook! '(org-mode-hook markdown-mode-hook rst-mode-hook asciidoc-mode-hook latex-mode-hook LaTeX-mode-hook) #'writegood-mode)
;; Removing hooks for automatic spell checking set here: https://github.com/hlissner/doom-emacs/blob/develop/modules/checkers/spell/config.el
(remove-hook! '(org-mode-hook
markdown-mode-hook
TeX-mode-hook
rst-mode-hook
mu4e-compose-mode-hook
message-mode-hook
git-commit-mode-hook)
#'flyspell-mode)
(remove-hook! '(yaml-mode-hook
conf-mode-hook
prog-mode-hook)
#'flyspell-prog-mode)
;; (setq ispell-dictionary "english")
(setq ispell-personal-dictionary "~/ispell-personal-dictionary")
(map! :map doom-leader-toggle-map :desc "Toggle dictionary" "d" #'fd-switch-dictionary)
(defun fd-switch-dictionary()
(interactive)
(let* ((dic ispell-current-dictionary)
(change (if (string= dic "german") "english" "german")))
(ispell-change-dictionary change)
(message "Dictionary switched from %s to %s" dic change)
))
(set-flyspell-predicate! '(latex-mode)
#'+latex-flyspell-word-p)
(defun +latex-flyspell-word-p ()
"Return t if point is on a word that should be spell checked.
Return nil if on a link url, markup, html, or references."
(let ((faces (ensure-list (get-text-property (point) 'face))))
(or (and (memq 'font-lock-comment-face faces)
(memq 'markdown-code-face faces))
(not (cl-loop with unsafe-faces = '(font-lock-comment-face
;; font-latex-math-face
;; font-latex-string-face
font-lock-keyword-face
font-lock-constant-face
font-lock-function-name-face
font-lock-variable-name-face
font-lock-type-face ;; figure captions
)
for face in faces
if (memq face unsafe-faces)
return t)))))
Flutter
;; (setq lsp-dart-flutter-sdk-dir "~/snap/flutter/common/flutter")
;; (map! :mode dart-mode :leader "r" #'flutter-run-or-hot-reload)
Evil snipe
;; Make sniping simpler for german keyboard
(setq evil-snipe-scope 'visible)
(map! :map evil-snipe-override-mode-map :m "," #'evil-snipe-repeat)
(map! :map evil-snipe-override-mode-map :m ";" #'evil-snipe-repeat-reverse)
(map! :map evil-snipe-parent-transient-map "," #'evil-snipe-repeat)
(map! :map evil-snipe-parent-transient-map ";" #'evil-snipe-repeat-reverse)
Matlab
(add-hook 'matlab-mode-hook (lambda () (add-to-list 'quickrun-file-alist '("\\.m\\'" . "octave"))))
;; (assq-delete-all "objc" quickrun-file-alist)
(quickrun-add-command "matlab"
'((:command . "octave"))
:mode #'matlab-mode
)
(quickrun-add-command "octave"
'((:command . "octave"))
:mode #'octave-mode
)
;; (autoload 'matlab-mode "matlab" "Matlab Editing Mode" t)
(add-to-list
'auto-mode-alist
'("\\.m$" . matlab-mode))
;; (setq matlab-indent-function t)
;; (setq matlab-shell-command "/urs/local/bin/matlab")
Features
Toggle word case
(map! :desc "Toggle case of word" :nv "g C" #'toggle-word-case)
(defun toggle-word-case ()
"Toggle the case of current word or text selection."
(interactive)
(let (
(deactivate-mark nil)
$p1 $p2)
(if (use-region-p)
(setq $p1 (region-beginning) $p2 (region-end))
(save-excursion
(skip-chars-backward "[:alpha:]")
(setq $p1 (point))
(skip-chars-forward "[:alpha:]")
(setq $p2 (point))))
(let ((first-char-prop (get-char-code-property (char-after $p1) 'general-category)))
(cond ((string= "Ll" first-char-prop) ; Lower case
(upcase-region $p1 (+ $p1 1)))
((string= "Lu" first-char-prop) ; Upper case
(downcase-region $p1 (+ $p1 1)))
(t (message "Word does not start with a alphabetic character"))))))
Tetris
(add-hook 'tetris-mode-hook #'turn-off-evil-mode)
Projectile
(map! :map 'doom-leader-project-map :desc "Repeat last command" "SPC" #'projectile-repeat-last-command)
More
(defun fd-pretty-print-dirty-json()
(interactive)
(let ((new-buffer-contents (shell-command-to-string (format "echo '%s' | newliner" (buffer-string)))))
(erase-buffer)
(insert new-buffer-contents)
(evil-indent (buffer-end -1) (buffer-end +1)))
)
Inventory
(defun fd-inventory-transfer()
(interactive)
(fd-inventory-transfer-check-if-valid-table)
(let ((location-from (string-trim (org-table-get 1 2)))
(location-to (string-trim (org-table-get 1 3)))
(item-name (string-trim (org-table-get-field 1))))
(let (transfer-amount)
(setq transfer-amount (read-number (concat "Transfer from " location-from " to " location-to ": ")))
(fd-inventory-transfer-log-transfer transfer-amount item-name location-from location-to)
(fd-inventory-transfer-do-transfer transfer-amount)
(org-table-align)
)))
(defun fd-inventory-transfer-check-if-valid-table ()
(unless (org-at-table-p) (error "You are not inside a table"))
(unless (and (string-match-p "^[[:blank:]]*-?[0-9]+[[:blank:]]*$" (org-table-get-field 2))
(string-match-p "^[[:blank:]]*-?[0-9]+[[:blank:]]*$" (org-table-get-field 3)))
(error "Amounts in table are not numbers"))
(if (or (string= "" (org-table-get 1 2))
(string= "" (org-table-get 1 3)))
(error "No valid table header")))
(defun fd-inventory-transfer-do-transfer(amount)
(let* ((amount-from-location (string-to-number (org-table-get-field 2)))
(amount-to-location (string-to-number (org-table-get-field 3)))
(amount-from-location-new (- amount-from-location amount))
(amount-to-location-new (+ amount-to-location amount)))
(progn (org-table-get-field 2 (number-to-string amount-from-location-new))
(org-table-get-field 3 (number-to-string amount-to-location-new)))))
(defun fd-inventory-transfer-log-transfer(amount item-name from-location to-location)
(save-excursion
(let* ((log-heading-point (or (org-find-exact-headline-in-buffer "Transfer log" nil t)
(progn (goto-char (org-table-end))
(org-insert-heading)
(insert "Transfer log")
(point)))))
(goto-char log-heading-point)
(forward-line)
(let ((message (concat "- " (format-time-string "%d.%m.%Y") ": *" (number-to-string amount) "* =" item-name "= from " from-location " to " to-location "\n")))
(insert message))
)))
Python
(defun fd-python-to-latex(regionBegin regionEnd)
(interactive (if (use-region-p)
(list (region-beginning) (region-end))
(list (point-min) (point-max))))
(shell-command-on-region regionBegin regionEnd "python2latex"))
Haskell
(set-docsets! 'haskell-mode "Haskell")
Citations
(setq! citar-bibliography '("~/Nextcloud/zotero-sources.bib"))