.emacs.d/config.org
2024-10-11 21:45:08 -04:00

622 lines
17 KiB
Org Mode

#+TITLE: Emacs Configuration
#+AUTHOR: Mars (@pupbrained)
#+EMAIL: mars@pupbrained.xyz
* Basic Setup
** Server
#+begin_src emacs-lisp
(require 'bind-key)
(load "server")
(unless (server-running-p) (server-start))
#+end_src
** Disable Built-In Auto-Save and Backup
#+begin_src emacs-lisp
(setq auto-save-default nil
make-backup-files nil)
#+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
** Dirvish
#+begin_src emacs-lisp
(add-hook 'dired-mode-hook 'dired-omit-mode)
(use-package ethan-wspace
:ensure t
:config
(setq mode-require-final-newline nil)
(global-ethan-wspace-mode 1))
(defun my/dirvish-create-file ()
"Create a new file in the current directory."
(interactive)
(let ((new-file (read-file-name "New file name: " (dired-current-directory))))
(if (file-exists-p new-file)
(message "File already exists!")
(write-region "" nil new-file)
(revert-buffer) ;; Refresh the directory listing
(message "File created: %s" new-file))))
(use-package dirvish
:ensure t
:init
(dirvish-override-dired-mode)
:config
(dirvish-peek-mode)
(dirvish-side-follow-mode)
(setq dired-listing-switches "-al --human-readable --group-directories-first"
dired-mouse-drag-files t
dired-omit-files (rx (or (seq bol (? ".") "#")
(seq bol "." eol)
(seq bol ".git" eol)))
dirvish-emerge-groups '(("Recent files" (predicate . recent-files-2h))
("Documents" (extensions "pdf" "tex" "bib" "epub"))
("Video" (extensions "mp4" "mkv" "webm"))
("Pictures" (extensions "jpg" "png" "svg" "gif"))
("Audio" (extensions "mp3" "flac" "wav" "ape" "aac"))
("Archives" (extensions "gz" "rar" "zip")))
dirvish-attributes '(vc-state subtree-state nerd-icons collapse git-msg file-time file-size)
dirvish-mode-line-format '(:left (sort symlink) :right (omit yank index))
dirvish-mode-line-height 25
dirvish-subtree-state-style 'nerd
mouse-drag-and-drop-region-cross-program t))
;; Addtional syntax highlighting for dired
(use-package diredfl
:ensure t
:hook
((dired-mode . diredfl-mode)
(dirvish-directory-view-mode . diredfl-mode))
:config
(set-face-attribute 'diredfl-dir-name nil :bold t))
(use-package nerd-icons
:ensure t
:custom
(nerd-icons-font-family "Maple Mono NF"))
(use-package ns-auto-titlebar
:ensure t
:config
(when (eq system-type 'darwin) (ns-auto-titlebar-mode)))
#+end_src
** Doom Modeline
#+begin_src emacs-lisp
(use-package doom-modeline
:ensure t
:config
(doom-modeline-mode))
#+end_src
** VTerm
#+begin_src emacs-lisp
(use-package vterm
:ensure t
:config
(setq vterm-timer-delay 0.01))
(use-package shackle
:ensure t
:config
(setq shackle-rules
'(("\\*vterm\\*" :regexp t :popup t :align 'below :size 0.4 :select t)))
(shackle-mode 1))
(use-package vterm-toggle
:ensure t)
#+end_src
** Nix
#+begin_src emacs-lisp
(use-package nix-mode
:mode "\\.nix\\'")
#+end_src
** Indents and Autopairs
#+begin_src emacs-lisp
(electric-indent-mode -1)
(electric-pair-mode 1)
#+end_src
** Evil Mode
#+begin_src emacs-lisp
(setq-default evil-auto-indent t
indent-line-function 'evil-indent-line
indent-tabs-mode nil
tab-width 2
org-src-tab-acts-natively t
org-indent-indentation-per-level 2
org-indent-mode-turns-on-hiding-stars nil)
(defun indent-tabs-hook ()
(setq tab-width 2
indent-tabs-mode t
evil-auto-indent t
c-basic-offset 2))
(dolist (hook '(c++-mode-hook c-mode-hook c++-ts-mode-hook c-ts-mode-hook)) (add-hook hook 'indent-tabs-hook))
(use-package evil
:ensure t
:init
(setq evil-split-window-below t
evil-undo-system 'undo-tree
evil-vsplit-window-right t
evil-want-C-i-jump nil
evil-want-C-u-scroll t
evil-want-integration t
evil-want-integration t
evil-want-keybinding nil)
:config
(evil-mode 1)
(setq-default evil-shift-width 2)
(evil-define-key 'insert 'global (kbd "TAB") 'tab-to-tab-stop)
(evil-define-key 'insert 'global (kbd "C-c") 'cua-copy-region)
(evil-define-key 'insert 'global (kbd "C-v") 'cua-paste)
(evil-define-key 'insert 'global (kbd "C-x") 'cua-cut-region)
(evil-define-key 'normal 'global (kbd "gm") 'magit-status)
(evil-define-key 'normal 'global (kbd "gp") 'diff-hl-show-hunk)
(evil-define-key 'normal 'global (kbd "gr") 'diff-hl-revert-hunk)
(evil-define-key 'normal 'global (kbd "gs") 'diff-hl-stage-current-hunk))
;; Set whitespace actions.
(setq-default whitespace-action
'(cleanup auto-cleanup))
(use-package general
:ensure t
:config
(general-define-key
:states '(normal visual emacs)
:keymaps 'override
"K" '(eldoc-box-help-at-point :wk "Hover")
"C-t" '(vterm-toggle :wk "Toggle VTerm")))
(use-package evil-collection
:ensure t
:config
(evil-collection-init))
(use-package evil-leader
:ensure t
:config
(global-evil-leader-mode)
(setq evil-leader/leader "<SPC>")
(evil-leader/set-key "bb" #'switch-to-buffer)
(evil-leader/set-key "bd" #'kill-this-buffer)
(evil-leader/set-key "e" #'dirvish-side)
(evil-leader/set-key "d" #'flymake-show-diagnostic)
(evil-leader/set-key "n" #'flymake-goto-next-error)
(evil-leader/set-key "N" #'flymake-goto-prev-error)
(evil-leader/set-key "n" #'flymake-goto-next-error)
(evil-leader/set-key "a" #'eglot-code-actions))
#+end_src
** Catppuccin Theme
#+begin_src emacs-lisp
(use-package catppuccin-theme
:ensure t
:demand t
:config
(load-theme 'catppuccin t))
#+end_src
** Disable Autosave and Backup Files
#+begin_src emacs-lisp
(setq auto-save-default nil
make-backup-files nil)
#+end_src
** Ligatures
#+begin_src emacs-lisp
(use-package ligature
:config
(let ((common-ligatures '("<---" "<--" "<<-" "<-" "->" "-->" "--->" "<->" "<-->" "<--->" "<---->" "<!--"
"<==" "<===" "<=" "=>" "=>>" "==>" "===>" ">=" "<=>" "<==>" "<===>" "<====>" "<!---"
"<~~" "<~" "~>" "~~>" "::" ":::" "==" "!=" "===" "!=="
":=" ":-" ":+" "<*" "<*>" "*>" "<|" "<|>" "|>" "+:" "-:" "=:" "<******>" "++" "+++")))
(dolist (mode '(prog-mode org-mode))
(ligature-set-ligatures mode common-ligatures)))
(global-ligature-mode t))
#+end_src
** LSP
*** Eglot
#+begin_src emacs-lisp
(use-package markdown-mode
:ensure t
:mode ("README\\.md\\'" . gfm-mode)
:init (setq markdown-command "multimarkdown")
:bind (:map markdown-mode-map
("C-c C-e" . markdown-do)))
(use-package eglot-booster
:after eglot
:ensure (eglot-booster :type git :host github :repo "jdtsmith/eglot-booster")
:config (eglot-booster-mode))
(use-package eglot
:ensure nil
:config
(defun my-eglot-rename (newname)
"Rename the current symbol to NEWNAME with initial input a."
(interactive
(list (read-from-minibuffer
(format "Rename `%s' to: " (or (thing-at-point 'symbol t)
(error "no symbol at point")))
(or (thing-at-point 'symbol t) "") nil nil nil
(symbol-name (symbol-at-point)))))
(eglot--server-capable-or-lose :renameProvider)
(eglot--apply-workspace-edit
(jsonrpc-request (eglot--current-server-or-lose)
:textDocument/rename `(,@(eglot--TextDocumentPositionParams)
:newName ,newname))
current-prefix-arg))
(fset #'jsonrpc--log-event #'ignore)
(setopt eglot-events-buffer-size 0)
(defun eglot-format-buffer-on-save ()
(when (not (derived-mode-p 'python-ts-mode))
(add-hook 'before-save-hook #'eglot-format-buffer -10 t)))
(add-hook 'eglot-managed-mode-hook #'eglot-format-buffer-on-save)
(add-to-list 'eglot-server-programs '(nix-mode . ("nixd")))
(add-to-list 'eglot-server-programs
`(c++-mode . ("clangd" "--clang-tidy" "--completion-style=detailed" "--header-insertion=never")))
:hook
(rust-mode . eglot-ensure)
(rust-ts-mode . eglot-ensure)
(sh-script-mode . eglot-ensure)
(python-mode . eglot-ensure)
(python-ts-mode . eglot-ensure)
(json-mode . eglot-ensure)
(json-ts-mode . eglot-ensure)
(nix-mode . eglot-ensure)
(yaml-mode . eglot-ensure)
(yaml-ts-mode . eglot-ensure)
(c-mode . eglot-ensure)
(c-ts-mode . eglot-ensure)
(c++-mode . eglot-ensure)
(c++-ts-mode . eglot-ensure)
(c3-ts-mode . eglot-ensure)
(rust-mode . eglot-ensure)
(go-mode . eglot-ensure)
(go-ts-mode . eglot-ensure))
(use-package rust-mode
:ensure t)
(use-package tuareg
:ensure t
:mode ("\\.ml\\'" . tuareg-mode)
:hook (tuareg-mode . eglot-ensure))
(use-package merlin
:ensure t
:hook (tuareg-mode . merlin-mode))
(use-package glsl-mode
:ensure t
:mode ("\\.vert\\'" "\\.frag\\'" "\\.geom\\'"))
(use-package eldoc-box
:custom
(eldoc-box-max-pixel-width 1024)
:config
(setq eldoc-message-function #'ignore)
(setq eldoc-idle-delay 0)
(custom-set-faces
'(eldoc-box-body ((t (:background "#11111b" :foreground "#cdd6f4"))))))
#+end_src
*** Apheleia
#+begin_src emacs-lisp
(use-package apheleia
:ensure t
:config
(add-to-list 'apheleia-formatters
'(alejandra "alejandra" "--quiet" "-"))
(add-to-list 'apheleia-formatters
'(clang-format "clang-format"))
(add-to-list 'apheleia-mode-alist
'(nix-mode . alejandra))
(add-to-list 'apheleia-mode-alist
'(c-mode . clang-format))
(add-to-list 'apheleia-mode-alist
'(c++-mode . clang-format))
(apheleia-global-mode +1))
#+end_src
*** TreeSitter
#+begin_src emacs-lisp
(use-package tree-sitter
:ensure t
:hook
(prog-mode . tree-sitter-hl-mode)
:config
(global-tree-sitter-mode))
(use-package tree-sitter-langs
:ensure t)
#+end_src
*** GitHub Copilot
#+begin_src emacs-lisp
(use-package copilot
:ensure (:host github :repo "copilot-emacs/copilot.el" :files ("*.el"))
:hook (prog-mode . copilot-mode)
:bind (("C-<tab>" . 'copilot-complete)
:map copilot-completion-map
("<tab>" . 'copilot-accept-completion)
("C-<tab>" . 'copilot-accept-completion-by-word)
("C-<return>" . 'copilot-accept-completion-by-line)))
(use-package copilot-chat
:ensure (:host github :repo "chep/copilot-chat.el" :files ("*.el"))
:after (request))
#+end_src
*** Corfu
#+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 ("<escape>" . 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
** 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
org-mode-hook
dirvish-setup-hook
eshell-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-conservatively 9999)
#+end_src
** Sticky Headers
#+begin_src emacs-lisp
(use-package breadcrumb
:ensure t
:hook
(prog-mode . breadcrumb-mode))
#+end_src
** System-Specific Settings
#+begin_src emacs-lisp
(defun apply-my-fonts (frame)
(with-selected-frame frame
(cond
((eq system-type 'darwin)
(set-face-attribute 'default frame :font "Iosevka Comfy-14")
(set-face-attribute 'fixed-pitch frame :font "Iosevka Comfy-14")
(set-face-attribute 'variable-pitch frame :font "Iosevka Comfy Motion Duo-16")
(modify-frame-parameters frame
'((font . "Iosevka Comfy-14")
(vertical-scroll-bars . nil))))
((eq system-type 'gnu/linux)
(set-face-attribute 'default frame :font "Iosevka Comfy Medium-12")
(set-face-attribute 'fixed-pitch frame :font "Iosevka Comfy Medium-12")
(set-face-attribute 'variable-pitch frame :font "Iosevka Comfy Motion Duo Md-14")
(modify-frame-parameters frame
'((font . "Iosevka Comfy Medium-12")
(undecorated . t)
(vertical-scroll-bars . nil)))))))
;; Apply the settings for both regular Emacs and emacsclient frames
(if (daemonp)
(add-hook 'after-make-frame-functions 'apply-my-fonts)
(apply-my-fonts (selected-frame)))
#+end_src
** Use Short Answers
#+begin_src emacs-lisp
(setq use-short-answers t)
#+end_src
** Undo Tree
#+begin_src emacs-lisp
(use-package undo-tree
:ensure t
:demand t
:config
(global-undo-tree-mode)
(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))))
#+end_src
** Dashboard
#+begin_src emacs-lisp
(use-package dashboard
:ensure t
:config
(dashboard-setup-startup-hook)
(setq dashboard-startup-banner 'logo
dashboard-center-content t
dashboard-vertically-center-content t
dashboard-startup-banner 'logo
initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))))
#+end_src
** Git Integration
#+begin_src emacs-lisp
(use-package transient :ensure t)
(use-package magit
:ensure t
:commands magit-status magit-blame magit-version
:init
(defadvice magit-status (around magit-fullscreen activate)
(window-configuration-to-register :magit-fullscreen) ad-do-it
(delete-other-windows))
:config
(setq magit-branch-arguments nil
magit-default-tracking-name-function 'magit-default-tracking-name-branch-only
magit-push-always-verify nil
magit-restore-window-configuration t))
(use-package diff-hl
:ensure t
:hook ((magit-post-refresh . diff-hl-magit-post-refresh))
:config
(global-diff-hl-mode))
(use-package git-gutter
:ensure t
:config
(global-git-gutter-mode +1))
#+end_src
** Direnv
#+begin_src emacs-lisp
(use-package envrc
:ensure t
:config
(envrc-global-mode))
#+end_src
** Better M-x
*** Ivy Mode (Completions)
#+begin_src emacs-lisp
(setq ivy-ignore-buffers '("\\` " "\\`\\*"))
(use-package ivy
:ensure t
:config
(ivy-mode)
(setq ivy-use-virtual-buffers t
enable-recursive-minibuffers t))
#+end_src
*** Amx Mode (Better Interface)
#+begin_src emacs-lisp
(use-package amx
:ensure t
:config
(amx-mode))
#+end_src
** Org Mode Improvements
#+begin_src emacs-lisp
(add-hook 'org-mode-hook 'visual-line-mode)
(use-package mixed-pitch
:hook
(org-mode . mixed-pitch-mode))
(use-package org-modern
:ensure t
:hook (org-mode . org-modern-mode)
:config
(setq org-ellipsis "")
(setq org-modern-star 'replace))
(use-package org-modern-indent
:ensure (org-modern-indent :type git :host github :repo "jdtsmith/org-modern-indent")
:config
(add-hook 'org-mode-hook #'org-modern-indent-mode 90))
;; 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))))))
(defun org-babel-edit-prep:emacs-lisp (babel-info)
(setq-local buffer-file-name (->> babel-info caddr (alist-get :tangle)))
(lsp))
(add-hook 'eglot-managed-mode-hook #'flymake-mode)
#+end_src