;;; EMACS init file -*- lexical-binding:t -*- (with-eval-after-load 'package (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (package-initialize)) (setq use-package-always-ensure t 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 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)) (defun my-meow-undo (arg) "Same as meow-undo, but uses undo-fu to redo if negative prefix." (interactive "P") (when (region-active-p) (meow--cancel-selection)) (let ((numeric-prefix (prefix-numeric-value arg))) (if (meow--with-negative-argument-p arg) (undo-fu-only-redo (abs numeric-prefix)) (undo-fu-only-undo numeric-prefix)))) (use-package meow :demand t :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) '("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) '("Q" . meow-goto-line) '("r" . meow-replace) '("R" . meow-swap-grab) '("s" . meow-kill) '("t" . meow-till) '("u" . my-meow-undo) '("U" . meow-undo-in-selection) '("v" . meow-page-down) '("V" . meow-page-up) '("w" . meow-mark-word) '("W" . meow-mark-symbol) '("x" . meow-line) '("X" . meow-goto-line) '("y" . meow-save) '("Y" . meow-sync-grab) '("z" . meow-pop-selection) '("'" . repeat) '("/" . meow-visit) '(">" . meow-forward-slurp) '("<" . meow-forward-barf) '("C-<" . meow-backward-slurp) '("C->" . meow-backward-barf) '(":" . 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 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) (let ((ret (apply oldfun r))) (when old-goggles-mode (goggles-mode)) ret))) (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 ?f ?g ?h ?j ?k ?l ?p)) (aw-dispatch-always t) (aw-scope 'frame) :config (require 'cl-lib) (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 (face-spec-set 'goggles-added `((t (:background ,(catppuccin-get-color 'green))))) (face-spec-set 'goggles-removed `((t (:background ,(catppuccin-get-color 'red))))) (face-spec-set 'goggles-changed `((t (:background ,(catppuccin-get-color 'blue)))))) (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 (add-to-list 'aggressive-indent-protected-commands #'my-meow-undo) (add-to-list 'aggressive-indent-protected-commands #'meow-undo) (add-to-list 'aggressive-indent-protected-commands #'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 lsp-mode :hook ((c-ts-mode . lsp-deferred) (c++-ts-mode . lsp-deferred) (html-mode . lsp-deferred) (lsp-mode . lsp-enable-which-key-integration)) :custom (read-process-output-max (* 1024 1024)) ; 1 MB (lsp-keymap-prefix "M-o")) (use-package lsp-java :hook (java-ts-mode . lsp-deferred)) (use-package lsp-ui) (use-package lsp-treemacs :hook (lsp-mode . lsp-treemacs-sync-mode)) (use-package dap-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 . (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 1)))) (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 :disabled t :demand t :custom (doom-modeline-fn-alist (--map (cons (remove-pos-from-symbol (car it)) (cdr it)) doom-modeline-fn-alist)) :config (doom-modeline-mode)) (use-package dirvish :demand t :after dired :custom (dirvish-attributes '(all-the-icons)) :config (dirvish-override-dired-mode)) (use-package pdf-tools :mode ("\\.pdf\\'" . pdf-view-mode) :config (pdf-tools-install)) (defun set-text-modes-font () (interactive) (setq buffer-face-mode-face '(:family "DejaVu Sans Mono" :height 105) line-spacing 0.4) (buffer-face-mode)) (use-package org :hook ((org-mode . org-indent-mode) (org-mode . auto-fill-mode) (org-mode . set-text-modes-font)) :custom (org-list-allow-alphabetical t) (org-hide-emphasis-markers t) (org-pretty-entities t) ;; 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)) (add-to-list 'org-modules 'org-tempo)) (use-package org-superstar :custom (org-superstar-leading-bullet ?\s) :hook org-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 nix-mode) (use-package markdown-mode :mode ("README\\.md\\'" . gfm-mode) :custom (markdown-command '("pandoc" "--from=markdown" "--to=html5"))) (use-package meson-mode) (use-package minimap :commands minimap-mode :custom-face (minimap-active-region-background ((t (:background nil :inherit hl-line)))) :hook (minimap-sb-mode . turn-on-solaire-mode)) (use-package magit :hook ((git-commit-setup . git-commit-turn-on-flyspell) (git-commit-setup . git-commit-turn-on-auto-fill))) (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))) (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 elfeed :commands (elfeed elfeed-update) :custom (elfeed-feeds '(("https://archlinux.org/feeds/news/" arch-linux)))) (use-package xkcd :commands xkcd) (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 (mode-line ((t (:font "DejaVu Sans Mono")))) :custom (catppuccin-flavor 'mocha)) (defun load-theme-with-solaire () (load-theme 'catppuccin t) (catppuccin-reload) (solaire-global-mode) (when (daemonp) (remove-hook 'server-after-make-frame-hook #'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 (member 'minimap-sb-mode local-minor-modes)))))) :config (if (daemonp) (add-hook 'server-after-make-frame-hook #'load-theme-with-solaire) (load-theme-with-solaire))) (use-package emacs-everywhere :load-path "~/emacs-everywhere" :commands emacs-everywhere) (use-package flyspell :ensure nil :hook (org-mode text-mode) :custom (flyspell-auto-correct-binding (kbd "C-:")) :config (keymap-unset flyspell-mode-map "C-.")) (use-package ffap :demand t :config (ffap-bindings)) (use-package ibuffer :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) (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 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-inhibit-hl-line-mode () (setq-local global-hl-line-mode nil)) (defun my-relative-linenum () (setq display-line-numbers 'relative)) (dolist (hook '(prog-mode-hook text-mode-hook conf-mode-hook org-mode-hook)) (add-hook hook #'my-relative-linenum)) (defun my-use-spaces-for-indent () (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) (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 frames 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)))) (add-to-list 'auto-mode-alist '("\\.yuck\\'" . lisp-mode)) (add-to-list 'auto-mode-alist '("flake\\.lock\\'" . js-json-mode)) (add-to-list 'auto-mode-alist '("/qutebrowser-editor-" . text-mode) t) (when (daemonp) (with-current-buffer "*scratch*" (cd "~/"))) (defvar my-bat-previous-status nil "Whether battery was in use on last check.") (require 'battery) (defun my-bat-check () "Check if battery status has changed in order to toggle goggles-pulse and pixel-scroll-precision-mode." (let ((bat-status (string-equal (cdr (assq ?L (funcall battery-status-function))) "BAT"))) (unless (eq bat-status my-bat-previous-status) (setq my-bat-previous-status bat-status) (when (boundp 'goggles-pulse) (setq goggles-pulse (not bat-status))) (pixel-scroll-precision-mode (if bat-status 0 1))))) (when battery-status-function (run-with-timer 30 30 #'my-bat-check) (add-hook 'emacs-startup-hook #'my-bat-check))