;;; EMACS init file -*- lexical-binding:t -*- (eval-and-compile (defconst my-is-nixos (file-exists-p "/nix") "Whether or not Emacs is running on NixOS.")) (when my-is-nixos (setq auth-sources '("/run/agenix/authinfo"))) (require 'cl-lib) (with-eval-after-load 'package (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (package-initialize)) (setq use-package-always-ensure (not my-is-nixos) use-package-always-defer t use-package-expand-minimally t) (require 'use-package) (let ((emacs-tmp-dir (expand-file-name (format "emacs%d" (user-uid)) temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,emacs-tmp-dir t)) auto-save-list-file-prefix emacs-tmp-dir backup-directory-alist (setq undo-tree-history-directory-alist `((".*" . ,emacs-tmp-dir))) org-preview-latex-image-directory (expand-file-name "ltximg" emacs-tmp-dir))) (setq backup-by-copying t inhibit-splash-screen t custom-file (expand-file-name "custom.el" temporary-file-directory)) (use-package f :demand t) (use-package dash :demand t :hook (emacs-lisp-mode . dash-fontify-mode) :init (with-eval-after-load 'info-look (dash-register-info-lookup))) (use-package undo-fu :demand t :config (global-unset-key (kbd "C-z")) (global-set-key (kbd "C-z") #'undo-fu-only-undo) (global-set-key (kbd "C-S-z") #'undo-fu-only-redo)) (cl-defun my-meow-undo (arg) "Uses undo-fu to undo, but cancels region first unless negative prefix." (interactive "*p") (let ((undo-fu-allow-undo-in-region t)) (pcase (cons (< arg 0) (region-active-p)) ('(t . t) (setq arg (abs arg))) ('(t . nil) (cl-return-from my-meow-undo)) ('(nil . t) (setq undo-fu-allow-undo-in-region nil))) (undo-fu-only-undo arg))) (defun my-meow-forward-paragraph () (interactive) (meow--execute-kbd-macro "M-}")) (defun my-meow-backward-paragraph () (interactive) (meow--execute-kbd-macro "M-{")) (use-package meow :demand t :bind ("C-S-h" . help-command) ("C-h" . (lambda () (interactive) (meow--execute-kbd-macro "DEL"))) :config (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty) (meow-motion-overwrite-define-key '("j" . meow-next) '("k" . meow-prev) '("" . ignore)) (meow-leader-define-key '("j" . "H-j") '("k" . "H-k") '("1" . meow-digit-argument) '("2" . meow-digit-argument) '("3" . meow-digit-argument) '("4" . meow-digit-argument) '("5" . meow-digit-argument) '("6" . meow-digit-argument) '("7" . meow-digit-argument) '("8" . meow-digit-argument) '("9" . meow-digit-argument) '("0" . meow-digit-argument) '("/" . meow-keypad-describe-key) '("?" . meow-cheatsheet) '("(" . insert-pair) '("[" . insert-pair) '("{" . insert-pair) '("<" . insert-pair) '("yy" . meow-clipboard-save) '("ys" . meow-clipboard-kill) '("yp" . meow-clipboard-yank)) (meow-normal-define-key '("0" . meow-expand-0) '("9" . meow-expand-9) '("8" . meow-expand-8) '("7" . meow-expand-7) '("6" . meow-expand-6) '("5" . meow-expand-5) '("4" . meow-expand-4) '("3" . meow-expand-3) '("2" . meow-expand-2) '("1" . meow-expand-1) '("-" . negative-argument) '(";" . meow-reverse) '("," . meow-inner-of-thing) '("." . meow-bounds-of-thing) '("[" . meow-beginning-of-thing) '("]" . meow-end-of-thing) '("a" . meow-append) '("A" . meow-open-below) '("b" . meow-back-word) '("B" . meow-back-symbol) '("c" . meow-change) '("d" . meow-delete) '("D" . meow-backward-delete) '("e" . meow-next-word) '("E" . meow-next-symbol) '("f" . meow-find) '("F" . meow-find-expand) '("g" . meow-cancel-selection) '("G" . meow-grab) '("h" . meow-left) '("H" . meow-left-expand) '("i" . meow-insert) '("I" . meow-open-above) '("j" . meow-next) '("J" . meow-next-expand) '("k" . meow-prev) '("K" . meow-prev-expand) '("l" . meow-right) '("L" . meow-right-expand) '("m" . meow-join) '("n" . meow-search) '("N" . meow-pop-search) '("o" . meow-block) '("O" . meow-to-block) '("p" . meow-yank) '("q" . meow-quit) '("r" . meow-replace) '("R" . meow-swap-grab) '("s" . meow-kill) '("t" . meow-till) '("T" . meow-till-expand) '("u" . my-meow-undo) '("U" . undo-fu-only-redo) '("v" . meow-page-down) '("V" . meow-page-up) '("w" . meow-mark-word) '("W" . meow-mark-symbol) '("x" . meow-line) '("X" . meow-find-ref) '("y" . meow-save) '("Y" . meow-sync-grab) '("z" . meow-pop-selection) '("Z" . meow-goto-line) '("'" . repeat) '("/" . meow-visit) '(">" . meow-forward-slurp) '("<" . meow-forward-barf) '("C-<" . meow-backward-slurp) '("C->" . meow-backward-barf) '("}" . my-meow-forward-paragraph) '("{" . my-meow-backward-paragraph) '(":" . meow-comment) '("=" . meow-indent) '("" . ignore)) (with-eval-after-load 'catppuccin-theme (setq meow-cursor-type-insert 'box) (face-spec-set 'meow-insert-cursor `((t (:background ,(catppuccin-get-color 'mauve) :inherit unspecified)))) (face-spec-set 'meow-unknown-cursor `((t (:background ,(catppuccin-get-color 'rosewater) :inherit unspecified)))) (dolist (meow-cursor-face '(meow-normal-cursor meow-motion-cursor meow-beacon-cursor)) (face-spec-set meow-cursor-face '((t (:inherit meow-unknown-cursor))))) (add-to-list 'meow-update-cursor-functions-alist (cons (lambda () (and (meow-insert-mode-p) (not (display-graphic-p)))) (lambda () (meow--set-cursor-type '(hbar 2)))))) (meow-global-mode)) (use-package avy :bind ("C-'" . avy-goto-char) ("C-," . avy-goto-char-2) ("C-\"" . avy-goto-char-timer) ("M-g f" . avy-goto-line) ("M-g w" . avy-goto-word-1) ("M-g e" . avy-goto-word-0) :custom (avy-timeout-seconds 0.3) :init (with-eval-after-load 'meow (meow-normal-define-key '("?" . avy-goto-char-timer)))) (use-package puni :hook prog-mode tex-mode :bind (:map puni-mode-map ("C-)" . puni-slurp-forward) ("C-}" . puni-barf-forward) ("C-(" . puni-slurp-backward) ("C-{" . puni-barf-backward) ("C-c p t" . puni-transpose) ("C-c p r" . puni-raise) ("C-c p C-s" . puni-splice) ("C-c p s" . puni-split) ("C-c p z" . puni-squeeze)) :config (with-eval-after-load 'goggles (defun my--disable-goggles-for-puni (oldfun &rest r) (let ((old-goggles-mode goggles-mode)) (goggles-mode 0) (prog1 (apply oldfun r) (when old-goggles-mode (goggles-mode))))) (dolist (fun '(puni-slurp-forward puni-barf-forward puni-slurp-backward puni-barf-backward puni-raise)) (advice-add fun :around #'my--disable-goggles-for-puni)))) (use-package ace-window :bind ("C-c w" . ace-window) :custom (aw-keys '(?a ?w ?e ?r ?g ?h ?j ?k ?l ?p)) (aw-dispatch-always t) (aw-scope 'frame) :config (dolist (c aw-dispatch-alist) (cl-case (car c) (?j (setcar c ?J)) (?v (setcar c ?s) (setcar (nthcdr 2 c) "Split Window")) (?b (setcar c ?v) (setcar (nthcdr 2 c) "Vertical Split")))) (with-eval-after-load 'catppuccin-theme (face-spec-set 'aw-leading-char-face `((t (:foreground ,(catppuccin-get-color 'crust) :background ,(catppuccin-get-color 'red) :weight bold)))) (face-spec-set 'aw-background-face `((t (:foreground ,(catppuccin-get-color 'overlay1))))))) (use-package goggles :hook prog-mode :config (setq-default goggles-pulse t) (with-eval-after-load 'catppuccin-theme (let ((new-spec `((t (:background ,(catppuccin-get-color 'surface1)))))) (dolist (f '(goggles-added goggles-removed goggles-changed)) (face-spec-set f new-spec)))) (setcar (cdr (assq 'goggles-mode minor-mode-alist)) " O-O")) (use-package treesit :ensure nil :init (add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode)) (add-to-list 'major-mode-remap-alist '(css-mode . css-ts-mode)) (add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode)) (add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode)) (add-to-list 'major-mode-remap-alist '(csharp-mode . csharp-ts-mode)) (add-to-list 'major-mode-remap-alist '(java-mode . java-ts-mode)) (add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode)) (add-to-list 'major-mode-remap-alist '(ruby-mode . ruby-ts-mode)) (add-to-list 'major-mode-remap-alist '(js-mode . js-ts-mode)) (add-to-list 'major-mode-remap-alist '(js-json-mode . json-ts-mode)) :custom (treesit-extra-load-path (list (expand-file-name "tree-sitter-module/dist/" user-emacs-directory)))) (use-package dtrt-indent :demand t :config (dtrt-indent-global-mode) (setcar (cdr (assq 'dtrt-indent-mode minor-mode-alist)) " dtrt")) (use-package aggressive-indent :custom (aggressive-indent-sit-for-time 0.1) :hook emacs-lisp-mode ielm-mode lisp-mode lisp-interaction-mode scheme-mode clojure-mode nix-mode :config (with-eval-after-load 'meow (setq aggressive-indent-protected-commands (append aggressive-indent-protected-commands '(my-meow-undo meow-undo meow-undo-in-selection))))) (use-package rainbow-delimiters :hook prog-mode) (use-package which-key :demand t :custom (which-key-idle-delay 0.2) :config (which-key-mode)) (use-package flymake :ensure nil :bind (:map flymake-mode-map ("M-n" . flymake-goto-next-error) ("M-p" . flymake-goto-prev-error))) (use-package eglot :ensure nil :bind (:map eglot-mode-map ("C-c e c" . eglot-code-actions) ("C-c e r" . eglot-rename) ("C-c e f" . eglot-format) ("C-c e s" . eglot-shutdown) ("C-c e S" . eglot-shutdown-all) ("C-c e R" . eglot-reconnect)) :hook (c-mode . eglot-ensure) (c-ts-mode . eglot-ensure) (c++-mode . eglot-ensure) (c++-ts-mode . eglot-ensure) (java-mode . eglot-ensure) (java-ts-mode . eglot-ensure) (lua-mode . eglot-ensure) (nix-mode . eglot-ensure) :custom (eglot-events-buffer-size 0) (eglot-autoshutdown t)) (use-package eglot-java :hook java-mode java-ts-mode) (use-package yasnippet :config (yas-global-mode) (advice-add #'yas-expand-snippet :around (lambda (oldfun &rest r) (let ((org-src-tab-acts-natively nil)) (apply oldfun r))) '((name . my--yas-expand-disable-org-tab-native)))) (use-package yasnippet-snippets) (use-package consult :bind ("M-s r" . consult-ripgrep) ("M-s d" . consult-find) ("C-x M-:" . consult-complex-command) ("C-x b" . consult-buffer) ("C-x r b" . consult-bookmark)) (use-package consult-yasnippet :bind ("C-c s" . consult-yasnippet) ("C-c S" . consult-yasnippet-visit-snippet-file)) (use-package embark :bind ("C-." . embark-act) ("C-;" . embark-dwim)) (use-package embark-consult) (use-package orderless :demand t :custom (completion-styles '(orderless basic)) (completion-category-defaults nil) (completion-category-overrides '((file (styles basic partial-completion))))) (use-package marginalia :demand t :after vertico :bind (:map minibuffer-local-map ("M-a" . marginalia-cycle)) :config (marginalia-mode)) (use-package vertico :demand t :config (vertico-mode) (vertico-mouse-mode)) (use-package corfu :demand t :custom (corfu-auto t) (corfu-cycle t) (corfu-preselect-first nil) (corfu-scroll-margin 3) (tab-always-indent 'complete) :config (global-corfu-mode) (add-hook 'minibuffer-setup-hook (lambda () (when (where-is-internal #'completion-at-point (list (current-local-map))) (setq-local corfu-echo-display nil corfu-popupinfo-delay nil) (corfu-mode)))) (with-eval-after-load 'meow (add-hook 'meow-insert-exit-hook #'corfu-quit))) (use-package cape) (use-package all-the-icons :demand t) (use-package all-the-icons-completion :after marginalia all-the-icons :hook (marginalia-mode . all-the-icons-completion-marginalia-setup) :init (all-the-icons-completion-mode)) (use-package treemacs) (use-package treemacs-all-the-icons :demand t :after treemacs :config (treemacs-load-theme 'all-the-icons)) (use-package doom-modeline :demand t :custom (doom-modeline-continuous-word-count-modes '(markdown-mode gfm-mode org-mode)) (doom-modeline-indent-info t) (doom-modeline-minor-modes t) (doom-modeline-battery nil) :config (doom-modeline-mode)) (use-package minions :demand t :config (minions-mode)) (use-package dirvish :demand t :after dired :custom (dirvish-attributes '(all-the-icons)) :config (dirvish-override-dired-mode)) (use-package alert :ensure nil :custom (alert-default-style 'libnotify) (alert-libnotify-command (expand-file-name "scripts/emacs-hyprland-notify" user-emacs-directory))) (use-package pdf-tools :mode ("\\.pdf\\'" . pdf-view-mode) :bind (:map pdf-view-mode-map ("/" . #'isearch-forward)) :config (pdf-tools-install)) (use-package org :hook (org-mode . auto-fill-mode) (org-mode . my-inhibit-hl-line-mode) :custom (org-startup-indented t) (org-special-ctrl-a/e t) (org-insert-heading-respect-content t) (org-list-allow-alphabetical t) (org-hide-emphasis-markers t) (org-pretty-entities t) (org-babel-load-languages '((emacs-lisp . t) (ruby . t) (python . t) (shell . t) (C . t))) (org-agenda-files '("~/Agenda")) ;; NixOS minimal LaTeX setup (org-latex-compiler "lualatex") (org-preview-latex-default-process 'dvisvgm) :config (setq org-format-latex-options (plist-put org-format-latex-options :scale 1.1) org-modules (append '(org-tempo org-habit) org-modules)) (with-eval-after-load 'catppuccin-theme (face-spec-set 'org-block `((t (:foreground ,(catppuccin-get-color 'text))))))) (use-package org-alert :init (when (daemonp) (run-with-idle-timer 10 nil #'require 'org-alert)) :config (setq org-alert-notification-title "org-alert" org-alert-notify-cutoff 30) (org-alert-enable)) (use-package org-modern :hook org-mode (org-agenda-finalize . org-modern-agenda) :config (with-eval-after-load 'catppuccin-theme (face-spec-set 'org-modern-done `((t (:foreground ,(catppuccin-get-color 'text) :background ,(catppuccin-get-color 'surface0))))) (face-spec-set 'org-modern-date-inactive `((t (:foreground ,(catppuccin-get-color 'subtext0) :background ,(catppuccin-get-color 'surface0))))) (face-spec-set 'org-modern-horizontal-rule `((t (:strike-through ,(catppuccin-get-color 'overlay1))))) (face-spec-set 'org-modern-tag `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'sapphire))))) (face-spec-set 'org-modern-time-active `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'overlay2))))) (face-spec-set 'org-modern-time-inactive `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'surface0))))))) (use-package org-modern-indent :ensure nil :hook org-modern-mode) (use-package org-pdftools :hook (org-mode . org-pdftools-setup-link)) (use-package editorconfig :demand t :config (editorconfig-mode) (setcar (cdr (assq 'editorconfig-mode minor-mode-alist)) " EdConf")) (use-package envrc :bind ("C-c v" . envrc-command-map) :hook (after-init . envrc-global-mode)) (defun my-slime-repl-set-parens () (rainbow-delimiters-mode) (puni-mode) (electric-pair-local-mode) (define-key slime-repl-mode-map (kbd "DEL") nil) (local-set-key (kbd "DEL") #'backward-delete-char-untabify)) (use-package slime :hook (slime-repl-mode . my-slime-repl-set-parens) :custom (slime-contribs '(slime-fancy slime-repl)) (slime-lisp-implementations '((sbcl ("sbcl") :coding-system utf-8-unix))) :config (setq inferior-lisp-program "sbcl") (with-eval-after-load 'meow (add-to-list 'meow-mode-state-list '(sldb-mode . motion)))) (use-package lua-mode :custom (lua-indent-level 4) (lua-indent-nested-block-content-align nil) (lua-indent-close-paren-align nil)) (use-package nix-mode) (use-package markdown-mode :mode ("README\\.md\\'" . gfm-mode) :custom (markdown-command '("pandoc" "--from=markdown" "--to=html5"))) (use-package meson-mode) (defun my-org-spell-fu-faces-exclude () (setq spell-fu-faces-exclude '(org-block-begin-line org-block-end-line org-code org-date org-drawer org-document-info-keyword org-ellipsis org-link org-meta-line org-properties org-properties-value org-special-keyword org-src org-tag org-verbatim))) (use-package spell-fu :hook text-mode (org-mode . my-org-spell-fu-faces-exclude)) (use-package minimap :custom-face (minimap-active-region-background ((t (:background unspecified :inherit hl-line)))) :hook (minimap-sb-mode . turn-on-solaire-mode)) (defun my-magit-commit-text-setup () (git-commit-turn-on-auto-fill) (spell-fu-mode) (setq-local spell-fu-check-range #'my-magit-spell-fu-check-range) (spell-fu--time-ensure t)) (defun my-magit-spell-fu-check-range (pos-beg pos-end) (spell-fu--overlays-remove pos-beg pos-end) (with-syntax-table spell-fu-syntax-table (save-match-data (save-excursion (goto-char (point-min)) (let ((check-end (-> (format "^%s -+ >8 -+$" comment-start) (re-search-forward pos-end t) (or pos-end))) (comment-start-char (aref comment-start 0))) (goto-char pos-beg) (while (< (point) check-end) (unless (= (char-after) comment-start-char) (let ((pos-line-end (pos-eol))) (while (re-search-forward spell-fu-word-regexp pos-line-end t) (let ((word-beg (match-beginning 0)) (word-end (match-end 0))) (spell-fu-check-word word-beg word-end (match-string-no-properties 0)))))) (forward-line))))))) (use-package magit :hook (git-commit-setup . my-magit-commit-text-setup)) (use-package forge :after magit :demand t) (use-package tramp :custom (remote-file-name-inhibit-cache nil) (tramp-verbose 1) :config (setq vc-ignore-dir-regexp (format "%s\\|%s" vc-ignore-dir-regexp tramp-file-name-regexp))) (defun my-inhibit-hl-line-mode () "Disable `gobal-hl-line-mode' for the current buffer." (setq-local global-hl-line-mode nil)) (use-package vterm :bind ("C-c t" . vterm) ("C-c T" . vterm-other-window) :hook (vterm-mode . my-inhibit-hl-line-mode) :config (with-eval-after-load 'meow (defvar meow-vterm-normal-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "RET") #'vterm-send-return) map)) (setq vterm-keymap-exceptions '("C-c")) (define-key vterm-mode-map (kbd "C-c ESC") #'vterm-send-escape) (dolist (c '((yank . vterm-yank) (xterm-paste . vterm-xterm-paste) (yank-pop . vterm-yank-pop) (mouse-yank-primary . vterm-yank-primary) (self-insert-command . vterm--self-insert) (beginning-of-defun . vterm-previous-prompt) (end-of-defun . vterm-next-prompt))) (define-key meow-vterm-normal-mode-map (vector 'remap (car c)) (cdr c))) (add-hook 'vterm-mode-hook (lambda () (add-hook 'meow-insert-enter-hook (lambda () (use-local-map vterm-mode-map) (vterm-goto-char (point))) nil t) (add-hook 'meow-insert-exit-hook (lambda () (use-local-map meow-vterm-normal-mode-map)) nil t))) (add-to-list 'meow-mode-state-list '(vterm-mode . insert)))) (use-package circe :hook (circe-channel-mode . enable-lui-autopaste) :custom (circe-default-nick "eriedaberrie") (circe-default-user "eriedaberrie") (circe-default-realname "eriedaberrie") (circe-format-self-say ">>> {body}") (lui-time-stamp-position 'right-margin) (lui-fill-type nil) (lui-time-stamp-format "%H:%M") :config (--when-let (nth 0 (auth-source-search :max 1 :require '(:user :secret) :host "irc.libera.chat" :port 6697)) (let ((user (plist-get it :user)) (secret (plist-get it :secret))) (setq circe-network-options `(("Libera Chat" :tls t :nick ,user :sasl-username ,user :sasl-password ,(if (functionp secret) (funcall secret) secret) :channels ("#guix" "#nonguix" "#shirakumo" "#emacs")))))) (add-hook 'lui-mode-hook (lambda () (visual-line-mode) (setq-local fringes-outside-margins t right-margin-width 5 wrap-prefix " ") (setcdr (assoc 'continuation fringe-indicator-alist) nil)))) (use-package circe-notifications :hook (circe-server-connected . enable-circe-notifications)) (use-package elfeed :custom (elfeed-feeds '(("https://archlinux.org/feeds/news/" arch-linux)))) (use-package xkcd) (use-package page-break-lines :hook emacs-lisp-mode lisp-mode scheme-mode compilation-mode outline-mode help-mode) (use-package hl-todo :hook prog-mode) (use-package ligature :hook prog-mode (ligature-mode . prettify-symbols-mode) :custom (prettify-symbols-unprettify-at-point t) :config (ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "" "---" "-<<" "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" "://"))) (use-package gruvbox-theme) (use-package catppuccin-theme :demand t :custom-face (line-number-current-line ((t (:inherit hl-line)))) :custom (catppuccin-flavor 'mocha) (catppuccin-highlight-matches t) (catppuccin-italic-comments t) (catppuccin-italic-variables t)) (defun my-load-theme-with-solaire () (load-theme 'catppuccin t) (catppuccin-reload) (face-spec-set 'font-lock-variable-name-face `((t (:foreground ,(catppuccin-get-color 'flamingo))))) (solaire-global-mode) (when (daemonp) (remove-hook 'server-after-make-frame-hook #'my-load-theme-with-solaire))) (use-package solaire-mode :demand t :custom (solaire-mode-real-buffer-fn (lambda () (and (solaire-mode-real-buffer-p) (or (custom-theme-enabled-p 'gruvbox) (not (memq 'minimap-sb-mode local-minor-modes)))))) :config (if (daemonp) (add-hook 'server-after-make-frame-hook #'my-load-theme-with-solaire) (my-load-theme-with-solaire))) (use-package with-editor :bind ([remap async-shell-command] . with-editor-async-shell-command) ([remap shell-command] . with-editor-shell-command) :hook (shell-mode . with-editor-export-editor) (eshell-mode . with-editor-export-editor) (term-exec . with-editor-export-editor) (vterm-mode . with-editor-export-editor)) (use-package nyan-mode :custom (nyan-animate-nyancat t) (nyan-wavy-trail t)) (use-package smtpmail :ensure nil :custom (smtpmail-smtp-service 587) (smtpmail-stream-type 'starttls) (smtpmail-default-smtp-server "smtp.gmail.com") (message-send-mail-function #'smtpmail-send-it) (message-citation-line-function #'message-insert-formatted-citation-line) (message-kill-buffer-on-exit t)) (use-package mu4e :if my-is-nixos :ensure nil :bind ("C-c M m" . mu4e) ("C-c M c" . mu4e-compose-new) ("C-c M u" . mu4e-update-mail-and-index) :hook (mu4e-view-mode . my-inhibit-hl-line-mode) :custom (mail-user-agent 'mu4e-user-agent) (mu4e-get-mail-command "mbsync -a") (mu4e-sent-messages-behavior 'delete) (mu4e-change-filenames-when-moving t) (mu4e-view-show-images t) (mu4e-use-fancy-chars t) (mu4e-attachment-dir "~/Downloads") (mu4e-context-policy 'ask) (mu4e-compose-context-policy 'ask-if-none) (mu4e-confirm-quit nil) (mu4e-completing-read-function #'completing-read) :init (let ((age-file "/run/agenix/email.json")) (when (file-exists-p age-file) (defvar my--agenix-email-json-data (with-temp-buffer (insert-file-contents age-file) (json-parse-buffer :object-type 'alist))) (pcase-let ((`((address . ,address) (name . ,name) ,_) (alist-get 'personal my--agenix-email-json-data))) (setq user-mail-address address user-full-name name)))) :config (when (boundp 'my--agenix-email-json-data) (setq mu4e-contexts (--map (pcase-let ((`(,type (address . ,address) (name . ,name) ,_) it)) (make-mu4e-context :name (symbol-name type) :enter-func (lambda () (mu4e-message (format "Entering \"%s\" context" type))) :leave-func (lambda () (mu4e-message (format "Leaving \"%s\" context" type))) :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg :to address))) :vars (cl-labels ((folder-name (folder-type) (format "/%s/[Gmail]/%s" type folder-type))) `((user-mail-address . ,address) (user-full-name . ,name) (mu4e-drafts-folder . ,(folder-name "Drafts")) (mu4e-sent-folder . ,(folder-name "Sent Mail")) (mu4e-trash-folder . ,(folder-name "Trash")) (smtpmail-smtp-server . "smtp.gmail.com") (smtpmail-smtp-user . ,address))))) my--agenix-email-json-data))) (when (fboundp 'imagemagick-register-types) (imagemagick-register-types)) (with-eval-after-load 'meow (add-to-list 'meow-mode-state-list '(mu4e-view-mode . motion)))) (use-package emacs-everywhere :ensure nil :commands emacs-everywhere :custom (emacs-everywhere-frame-parameters '((name . "emacs-everywhere") (alpha-background . 1.0))) :config (setq emacs-everywhere-frame-parameters (append '((alpha-background . 1.0) (width . 120) (height . 20)) emacs-everywhere-frame-parameters))) (use-package ffap :ensure nil :demand t :config (ffap-bindings)) (use-package eldoc :ensure nil :custom (eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)) (use-package ibuffer :ensure nil :bind ("C-x C-b" . ibuffer)) (use-package tool-bar :ensure nil :config (tool-bar-mode 0)) (use-package menu-bar :ensure nil :config (menu-bar-mode 0)) (use-package scroll-bar :ensure nil :config (scroll-bar-mode 0)) (setq pixel-scroll-precision-large-scroll-height 40 fast-but-imprecise-scrolling t) (pixel-scroll-precision-mode) (setcar mouse-wheel-scroll-amount 3) (setq server-client-instructions nil scroll-step 1 scroll-margin 8 scroll-conservatively 9999 python-indent-guess-indent-offset nil read-file-name-completion-ignore-case t read-buffer-completion-ignore-case t completion-ignore-case t sentence-end-double-space nil custom-safe-themes t x-stretch-cursor t) (setq-default c-basic-offset 4 c-ts-mode-indent-offset 4 json-ts-mode-indent-offset 4 tab-width 4 fill-column 80) (add-hook 'python-mode-hook (lambda () (setq tab-width 4))) (column-number-mode) (size-indication-mode) (global-hl-line-mode) (defun my-relative-linenum () "Simply enables relative line numbers." (setq display-line-numbers 'relative)) (dolist (hook '(prog-mode-hook conf-mode-hook)) (add-hook hook #'my-relative-linenum)) (defun my-use-spaces-for-indent () "Simply turnoff `indent-tabs-mode'." (setq indent-tabs-mode nil)) (dolist (hook '(emacs-lisp-mode-hook lisp-mode-hook scheme-mode-hook clojure-mode-hook)) (add-hook hook #'my-use-spaces-for-indent)) (add-hook 'prog-mode-hook #'electric-pair-local-mode) (add-hook 'eval-expression-minibuffer-setup-hook #'electric-pair-local-mode) (add-hook 'text-mode-hook #'word-wrap-whitespace-mode) (add-hook 'text-mode-hook #'visual-line-mode) (defun scroll-down-3 () "Scroll down by 3." (interactive) (scroll-down 3)) (defun scroll-up-3 () "Scroll up by 3." (interactive) (scroll-up 3)) (defun frame-make-detect-term (&optional frame) "Check when FRAME are made in order to make terminal-only configurations." (unless (display-graphic-p frame) (xterm-mouse-mode) (global-set-key (kbd "") #'scroll-down-3) (global-set-key (kbd "") #'scroll-up-3) (remove-hook 'after-make-frame-functions #'frame-make-detect-term))) (if (daemonp) (add-to-list 'after-make-frame-functions #'frame-make-detect-term) (frame-make-detect-term)) (defun my-sudo-edit () "Edit current file as root." (interactive) (unless (and buffer-file-name (file-writable-p buffer-file-name)) (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) (setq auto-mode-alist (append '(("\\.yuck\\'" . lisp-mode) ("flake\\.lock\\'" . js-json-mode)) auto-mode-alist '(("/qutebrowser-editor-" . text-mode)))) (when (daemonp) (with-current-buffer "*scratch*" (cd "~/"))) (defvar my-ac-previous-status t "Whether battery was not in use on last check.") (require 'battery) (defun my-bat-check () "Check if battery status has changed. Used to toggle `goggles-pulse', `pixel-scroll-precision-mode', and `nyan-mode'." (let ((ac-status (not (string= (cdr (assq ?L (funcall battery-status-function))) "BAT")))) (unless (eq ac-status my-ac-previous-status) (setq my-ac-previous-status ac-status) (when (boundp 'goggles-pulse) (setq goggles-pulse ac-status)) (when nyan-mode (if ac-status (nyan-start-animation) (nyan-stop-animation))) (setq nyan-animate-nyancat ac-status nyan-wavy-trail ac-status) (pixel-scroll-precision-mode (if ac-status 1 0))))) (when battery-status-function (run-with-timer 0 30 #'my-bat-check))