#+TITLE: Emacs Configuration #+AUTHOR: Mars (@pupbrained) #+EMAIL: mars@pupbrained.xyz #+PROPERTY: header-args:emacs-lisp :tangle yes * Basic Setup ** Server #+begin_src emacs-lisp (require 'bind-key) (load "server") (unless (server-running-p) (server-start)) #+end_src ** Disable Auto-Save and Backup *** (I don't like having ~#file#~ and ~file~~ everywhere in my directories) #+begin_src emacs-lisp (setq auto-save-default nil) (setq make-backup-files nil) #+end_src ** Enable Real Auto Save #+begin_src emacs-lisp (use-package real-auto-save :ensure t :config (setq real-auto-save-interval 1) (add-hook 'prog-mode-hook 'real-auto-save-mode)) #+end_src ** No Scratch On Open #+begin_src emacs-lisp (setq initial-scratch-message nil) (setq initial-buffer-choice nil) (add-hook 'emacs-startup-hook (lambda () (when (and (get-buffer "*scratch*") (not (eq (current-buffer) (get-buffer "*scratch*")))) (kill-buffer "*scratch*")))) #+end_src ** Fix Indents + Enable Autopairs #+begin_src emacs-lisp (electric-indent-mode 1) (electric-pair-mode 1) (setq c-basic-offset 2) (setq-default indent-tabs-mode nil) #+end_src ** Show Whitespace #+begin_src emacs-lisp (setq whitespace-style '(face tabs spaces trailing lines-tail)) (setq whitespace-display-mappings '((space-mark ?\ [?\u00B7] [?.]) (tab-mark ?\t [?\u00BB ?\t]))) (add-hook 'prog-mode-hook 'whitespace-mode) (add-hook 'org-src-mode-hook 'whitespace-mode) (add-hook 'before-save-hook 'whitespace-cleanup) #+end_src ** Rainbow Delimiters #+begin_src emacs-lisp (use-package rainbow-delimiters :ensure t :config (add-hook 'prog-mode-hook 'rainbow-delimiters-mode)) #+end_src ** Disable Bars #+begin_src emacs-lisp (menu-bar-mode -1) (scroll-bar-mode -1) (tool-bar-mode -1) #+end_src ** Line Numbers #+begin_src emacs-lisp (global-display-line-numbers-mode t) (setq display-line-numbers-type 'relative) (dolist (mode '(term-mode-hook vterm-mode-hook shell-mode-hook eshell-mode-hook treemacs-mode-hook)) (add-hook mode (lambda () (display-line-numbers-mode 0)))) #+end_src ** Vim-Style Scrolling #+begin_src emacs-lisp (setq scroll-step 3 scroll-margin 3 scroll-conservatively 9999) #+end_src ** System-Specific Settings #+begin_src emacs-lisp (when (eq system-type 'darwin) (ns-auto-titlebar-mode)) (cond ((eq system-type 'darwin) (setq default-frame-alist '((font . "Iosevka Comfy-14")))) ((eq system-type 'gnu/linux) (setq default-frame-alist '((font . "Maple Mono NF-12") (undecorated . t))))) #+end_src ** Use Short Answers #+begin_src emacs-lisp (setq use-short-answers t) #+end_src * Package Management ** Ligatures #+begin_src emacs-lisp (defvar ligatures-MapleMono '("--" "---" "==" "===" "!=" "!==" "=!=" "=:=" "=/=" "<=" ">=" "&&" "&&&" "&=" "++" "+++" "***" ";;" "!!" "??" "?:" "?." "?=" "<:" ":<" ":>" ">:" "<>" "<<<" ">>>" "<<" ">>" "||" "-|" "_|_" "|-" "||-" "|=" "||=" "##" "###" "####" "#{" "#[" "]#" "#(" "#?" "#_" "#_(" "#:" "#!" "#=" "^=" "<$>" "<$" "$>" "<+>" "<+ +>" "<*>" "<* *>" "" "/>" "" "->" "->>" "<<-" "<-" "<=<" "=<<" "<<=" "<==" "<=>" "<==>" "==>" "=>" "=>>" ">=>" ">>=" ">>-" ">-" ">--" "-<" "-<<" ">->" "<-<" "<-|" "<=|" "|=>" "|->" "<-" "<~~" "<~" "<~>" "~~" "~~>" "~>" "~-" "-~" "~@" "[||]" "|]" "[|" "|}" "{|" "[<" ">]" "|>" "<|" "||>" "<||" "|||>" "|||>" "<|>" "..." ".." ".=" ".-" "..<" ".?" "::" ":::" ":=" "::=" ":?" ":?>" "//" "///" "/*" "*/" "/=" "//=" "/==" "@_" "__")) (use-package ligature :config (ligature-set-ligatures 'prog-mode ligatures-MapleMono) (global-ligature-mode t)) #+end_src ** Theme #+begin_src emacs-lisp (use-package catppuccin-theme :ensure t :demand t) (load-theme 'catppuccin t) #+end_src ** Dashboard #+begin_src emacs-lisp (use-package dashboard :ensure t :config (dashboard-setup-startup-hook) (setq dashboard-startup-banner 'logo) (setq dashboard-center-content t) (setq dashboard-vertically-center-content t) (setq dashboard-startup-banner 'logo) (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))) (setq recentf-exclude '("~/.emacs.d/.cache/treemacs-persist"))) #+end_src ** Better M-x *** Ivy Mode (Completions) #+begin_src emacs-lisp (use-package ivy :ensure t :hook (after-init . ivy-mode) :config (setq ivy-use-virtual-buffers t) (setq enable-recursive-minibuffers t)) #+end_src *** Amx Mode (Better Interface) #+begin_src emacs-lisp (use-package amx :ensure t :hook (after-init . amx-mode)) #+end_src ** Modeline #+begin_src emacs-lisp (use-package doom-modeline :ensure t :hook (after-init . doom-modeline-mode)) #+end_src ** Emoji Support #+begin_src emacs-lisp (use-package emojify :hook (after-init . global-emojify-mode)) #+end_src ** Undo Tree #+begin_src emacs-lisp (use-package undo-tree :demand t :config (global-undo-tree-mode) (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))) #+end_src * Development Tools ** Direnv #+begin_src emacs-lisp (use-package direnv :config (direnv-mode)) #+end_src ** Nix #+begin_src emacs-lisp (use-package nix-mode :mode "\\.nix\\'") (use-package lua-mode :mode "\\.lua\\'") #+end_src ** Treesitter #+begin_src emacs-lisp (use-package treesit-auto :requires treesit :config (setq treesit-auto-install 'prompt) (global-treesit-auto-mode)) (use-package treesit :requires treesit :ensure nil :config (mapc #'exordium--add-forward-ts-hook '( LaTeX bash c c++ cmake csharp css elisp go go-mod haskell java js json lua markdown python ruby rust scala toml typescript vue yaml )) (setq treesit-font-lock-level 4)) (use-package tree-sitter-langs) (use-package tree-sitter :diminish :after (tree-sitter-langs) :hook (tree-sitter-after-on . tree-sitter-hl-mode) :custom (font-lock-maximum-decoration t) :config (when-let ((language-name (alist-get 'ruby-mode tree-sitter-major-mode-language-alist))) (add-to-list 'tree-sitter-major-mode-language-alist (cons 'enh-ruby-mode language-name))) (add-to-list 'tree-sitter-major-mode-language-alist (cons 'forge-post-mode 'markdown)) (global-tree-sitter-mode)) #+end_src ** Eglot #+begin_src emacs-lisp (add-hook 'prog-mode-hook 'eglot-ensure) (use-package haskell-mode :ensure t :hook (haskell-mode . eglot-ensure)) (setq-default eglot-workspace-configuration '((haskell (plugin (stan (globalOn . :json-false)))))) ;; disable stan (defun my/eglot-format-buffer-on-save () "Format the current buffer if Eglot is active." (when (bound-and-true-p eglot--managed-p) (eglot-format-buffer))) (add-hook 'before-save-hook #'my/eglot-format-buffer-on-save) (use-package web-mode :ensure t :mode (("\\.phtml\\'" . web-mode) ("\\.php\\'" . web-mode) ("\\.tpl\\'" . web-mode) ("\\.[agj]sp\\'" . web-mode) ("\\.as[cp]x\\'" . web-mode) ("\\.erb\\'" . web-mode) ("\\.mustache\\'" . web-mode) ("\\.djhtml\\'" . web-mode) ("\\.vue\\'" . web-mode))) (use-package vue-mode :config (setq mmm-submode-decoration-level 2)) (add-hook 'c-mode-hook 'hide-ifdef-mode) (add-hook 'c++-mode-hook 'hide-ifdef-mode) (setq hide-ifdef-initially t) (setq hide-ifdef-shadow 'font-lock-comment-face) #+end_src ** Corfu Completions #+begin_src emacs-lisp (use-package corfu :ensure t :custom (corfu-cycle t) ;;cycle through all things (corfu-auto t) ;;autocomplete (corfu-auto-prefix 1) ;; 2 letters to start autocomplete (corfu-auto-delay 0.0) ;; idk 0s to start? :bind (:map corfu-map ("" . corfu-quit)) :init (global-corfu-mode)) (use-package cape :ensure t) ;; get eglot to play nice with corfu (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster) (use-package kind-icon :ensure t :after corfu :custom (kind-icon-use-icons t) (kind-icon-default-face 'corfu-default) (kind-icon-blend-background nil) (kind-icon-blend-frac 0.08) :config (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)) #+end_src ** Sideline #+begin_src emacs-lisp (use-package sideline-flycheck :hook (flycheck-mode . sideline-mode) :init (setq sideline-backends-right '(sideline-flycheck))) (use-package sideline-flycheck :hook (flycheck-mode . sideline-flycheck-setup)) (use-package sideline-eglot :init (setq sideline-backends-right '(sideline-eglot))) (use-package eglot :hook (eglot-mode . sideline-mode)) #+end_src ** VTerm Toggle #+begin_src emacs-lisp (use-package vterm-toggle :ensure t) (global-set-key (kbd "C-t") 'vterm-toggle) #+end_src * Evil Mode and Keybindings ** Evil Mode #+begin_src emacs-lisp (use-package evil :ensure t :init (setq evil-split-window-below t) (setq evil-undo-system 'undo-tree) (setq evil-vsplit-window-right t) (setq evil-want-C-i-jump nil) (setq evil-want-C-u-scroll t) (setq evil-want-integration t) (setq evil-want-integration t) (setq evil-want-keybinding nil) :config (evil-mode 1)) #+end_src ** Evil Collection #+begin_src emacs-lisp (use-package evil-collection :after evil :ensure t :config (evil-collection-init)) #+end_src ** Evil Leader #+begin_src emacs-lisp (use-package evil-leader :after evil :config (global-evil-leader-mode) (setq evil-leader/leader "") (evil-leader/set-key "a" #'eglot-code-actions) (evil-leader/set-key "bd" #'kill-this-buffer) (evil-leader/set-key "e" #'treemacs)) #+end_src ** Evil Surround #+begin_src emacs-lisp (use-package evil-surround :ensure t :config (global-evil-surround-mode 1)) #+end_src ** Easier Copy/Paste #+begin_src emacs-lisp (global-set-key (kbd "C-S-c") 'kill-ring-save) (global-set-key (kbd "C-S-v") 'yank) ;; Load posframe for popups (use-package eldoc-box :ensure t) (evil-define-key 'normal 'global (kbd "SPC k") #'eldoc-box-help-at-point) #+end_src ** Org Mode Templates #+begin_src emacs-lisp ;; Inhibits autopairs from running for <> in org mode (add-hook 'org-mode-hook (lambda () (setq-local electric-pair-inhibit-predicate `(lambda (c) (if (char-equal c ?<) t (,electric-pair-inhibit-predicate c)))))) (require 'org-tempo) (add-to-list 'org-modules 'org-tempo t) (defun org-babel-edit-prep:emacs-lisp (babel-info) (setq-local buffer-file-name (->> babel-info caddr (alist-get :tangle))) (lsp)) #+end_src * Tab Management ** Intuitive Tabline #+begin_src emacs-lisp (use-package powerline) (use-package intuitive-tab-line :load-path "git/intuitive-tab-line-mode" :custom (tab-line-tabs-function 'intuitive-tab-line-buffers-list) (tab-line-switch-cycling t) :config (global-tab-line-mode 1) (recentf-mode 1) (setq tab-line-separator "") (setq tab-line-new-button-show nil) (setq tab-line-close-button-show nil) (defvar my/tab-height 24) (defvar my/tab-left (powerline-wave-right 'tab-line nil my/tab-height)) (defvar my/tab-right (powerline-wave-left nil 'tab-line my/tab-height)) (defun my/tab-line-tab-name-buffer (buffer &optional _buffers) (powerline-render (list my/tab-left (format "%s" (buffer-name buffer)) my/tab-right))) (setq tab-line-tab-name-function #'my/tab-line-tab-name-buffer) (global-set-key (kbd "C-S-") 'tab-line-switch-to-prev-tab) (global-set-key (kbd "C-") 'tab-line-switch-to-next-tab) (global-set-key (kbd "C-S-t") 'recentf-open-most-recent-file)) #+end_src