about summary refs log tree commit diff
path: root/.emacs.d/init.el
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/init.el')
-rw-r--r--.emacs.d/init.el914
1 files changed, 912 insertions, 2 deletions
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
index e11d303..25db606 100644
--- a/.emacs.d/init.el
+++ b/.emacs.d/init.el
@@ -1,5 +1,915 @@
+;;; init.el --- Venomade's Emacs Config -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;;;
+;;; This is my Emacs config which I rewrote from the ground up in October 2025.
+;;; It is built around these rules:
+;;;   - Performance as a Focus
+;;;   - Don't do with a package what should be done without
+;;;   - Don't replicate functionality of built-in packages
+;;;   - When using a package, take advantage of most of it's features
+
+;;; Code:
+
+;; Package Setup
+(require 'package)
+(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+(package-initialize)
+
+(if (native-comp-available-p)
+    (setq package-native-compile t))
+
+;; Core Functionality
+(setq mac-command-modifier nil) ; disable super on mac
+
+; (add-to-list 'default-frame-alist '(undecorated . t)) ; disable titlebar
+
+(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
+(when (file-exists-p custom-file)
+  (load custom-file))
+
+(use-package gcmh ; Improved Garbage Collection
+  :ensure t
+  :hook (after-init . gcmh-mode)
+  :config
+  (setq gcmh-high-cons-threshold (* 128 1024 1024)  ; 128MB
+        gcmh-idle-delay 10
+        gcmh-verbose nil))
+
+(use-package exec-path-from-shell ; FIXME: Doesn't work with Daemonex
+  :ensure t
+  :config
+  (setq exec-path-from-shell-shell-name "/bin/zsh"
+        exec-path-from-shell-arguments nil)
+  (when (memq window-system '(mac ns x))
+    (exec-path-from-shell-initialize)))
+
+(let* ((backup-dir (expand-file-name "backups/" user-emacs-directory))
+       (autosave-dir (expand-file-name "autosaves/" user-emacs-directory))
+       (lock-dir (expand-file-name "lock/" user-emacs-directory)))
+  (make-directory backup-dir t)
+  (make-directory autosave-dir t)
+  (make-directory lock-dir t)
+
+  (setq backup-directory-alist `((".*" . ,(directory-file-name backup-dir)))
+        auto-save-file-name-transforms `((".*" ,(directory-file-name autosave-dir) t))
+        lock-file-name-transforms `((".*" ,(directory-file-name lock-dir) t))))
+
+(add-to-list 'display-buffer-alist
+             '("\\`\\*\\(Warnings\\|Compile-Log\\)\\*\\'"
+               (display-buffer-no-window)
+               (allow-no-window . t)))
+
+(progn
+  (setq trash-directory "~/.Trash")
+  (defun system-move-file-to-trash (file)
+    "Use \"trash\" to move FILE to the system trash."
+    (cl-assert (executable-find "trash") nil "'trash' must be installed. Needs \"brew install trash\"")
+    (call-process "trash" nil 0 nil "-F"  file)))
+
+;; User Interface
+(setq frame-resize-pixelwise t
+      display-line-numbers-width-start t
+      display-line-numbers-width 4
+      display-line-numbers-grow-only t
+      ring-bell-function 'ignore
+      ns-confirm-quit t)
+
+(setq-default truncate-lines t)
+
+; Replace the $ signs for truncation with spaces
+(set-display-table-slot standard-display-table 'truncation 32)
+
+(tool-bar-mode -1)
+(scroll-bar-mode -1)
+(menu-bar-mode -1)
+
+(add-hook 'emacs-startup-hook #'global-display-line-numbers-mode)
+
+(add-hook 'after-make-frame-functions
+          (lambda (f)
+            (select-frame-set-input-focus f)))
+
+; (use-package kaolin-themes
+;   :ensure t
+;   :config
+;   ; (add-hook 'emacs-startup-hook
+;   ;           (lambda ()
+;   ;             (load-theme 'kaolin-dark t)))
+;   (load-theme 'kaolin-dark t)
+
+;   (defun theme-toggle ()
+;     "Toggle between two Emacs themes."
+;     (interactive)
+;     (let ((theme-a 'kaolin-dark)
+;           (theme-b 'kaolin-light))
+;       (cond
+;        ((member theme-a custom-enabled-themes)
+;         (disable-theme theme-a)
+;         (load-theme theme-b t))
+;        ((member theme-b custom-enabled-themes)
+;         (disable-theme theme-b)
+;         (load-theme theme-a t))
+;        (t
+;         (load-theme theme-a t))))))
+
+; TODO: Redo to be less hacky
+; (defun set-mode-line-box ()
+;   (set-face-attribute
+;    'mode-line-active nil
+;    :box '(:line-width 1 :color "#B4BEFE" :style nil)))
+
+; (with-eval-after-load 'spacious-padding
+;   (add-hook 'spacious-padding-mode-hook #'set-mode-line-box))
+
+(use-package catppuccin-theme
+  :ensure t
+  :config
+  (setq catppuccin-flavor 'mocha)
+  ; (add-hook 'emacs-startup-hook
+  ;           (lambda ()
+                                        ;             (load-theme 'kaolin-dark t)))
+  (load-theme 'catppuccin t)
+  ; (set-mode-line-box)
+
+  (defun theme-toggle ()
+    "Toggle between two Emacs themes."
+    (interactive)
+    (let ((theme-a 'kaolin-dark)
+          (theme-b 'kaolin-light))
+      (cond
+       ((eq catppuccin-flavor 'latte)
+        (disable-theme 'catppuccin)
+        (setq catppuccin-flavor 'mocha)
+        (load-theme 'catppuccin t))
+        ; (set-mode-line-box))
+       ((eq catppuccin-flavor 'mocha)
+        (disable-theme 'catppuccin)
+        (setq catppuccin-flavor 'latte)
+        (load-theme 'catppuccin t))
+        ; (set-mode-line-box))
+       (t
+        (load-theme theme-a t))))))
+
+(use-package ns-auto-titlebar
+  :ensure t
+  :config
+  (when (eq system-type 'darwin) (ns-auto-titlebar-mode)))
+
+(use-package hide-mode-line
+  :ensure t)
+
+; TEMPORARILY DISABLED WHILE FIGURING OUT STIPPLES
+; ------------------------
+;(use-package indent-bars
+;  :ensure t
+;  :hook (prog-mode . indent-bars-mode)
+;  :config
+;  (setq indent-bars-width-frac 0.15
+;        indent-bars-starting-column 0
+;        indent-bars-prefer-character t
+;        indent-bars-color '(font-lock-comment-face :face-bg nil :blend 0.425)
+;        indent-bars-color-by-depth nil))
+;
+;(face-attribute 'default :stipple nil t)
+
+(use-package olivetti
+  :ensure t
+  :after hide-mode-line
+  :config
+  (keymap-global-set "C-c z" 'olivetti-mode)
+  (which-key-add-key-based-replacements "C-c z" "zen-mode")
+  (setq olivetti-minimum-body-width 100)
+
+  (defun zen-toggle-minor-modes ()
+    "Toggle minor modes with `olivetti-mode`."
+    (if olivetti-mode
+        (progn
+          (hide-mode-line-mode 1)
+          (display-line-numbers-mode 0))
+      (progn
+        (setq olivetti-body-width 100) ; HACK: Fixes default being set below minimum
+        (hide-mode-line-mode 0)
+        (unless (eq major-mode 'fundamental-mode)
+          (display-line-numbers-mode 1)))))
+
+  (add-hook 'olivetti-mode-hook #'zen-toggle-minor-modes))
+
+(let ((no-numbers-modes '(fundamental-mode-hook)))
+  (dolist (hk no-numbers-modes)
+    (add-hook hk (lambda () (display-line-numbers-mode 0)))))
+
+(use-package doom-modeline
+  :ensure t
+  :hook (after-init . doom-modeline-mode)
+  :config
+  (setq doom-modeline-height 0 ; minimum
+        doom-modeline-bar-width 0 ; disabled
+        doom-modeline-project-detection 'project ; use project.el
+        doom-modeline-buffer-state-icon nil
+        doom-modeline-highlight-modified-buffer-name nil
+        doom-modeline-percent-position nil
+        line-number-mode nil
+        doom-modeline-buffer-encoding nil
+        doom-modeline-time-live-icon nil
+        doom-modeline-time-icon nil
+        display-time-default-load-average nil
+        display-time-format "%a %d %b | %R"
+        helm-ag-show-status-function nil)) ;HACK: Doom Modeline asks for this but I don't use helm
+  ;(display-battery-mode 1)
+  ;(display-time-mode 1))
+
+(use-package spacious-padding
+  :ensure t
+  :hook (after-init . spacious-padding-mode)
+  :config
+  (setq spacious-padding-widths
+        '( :internal-border-width 8
+           :header-line-width 4
+           :mode-line-width 6
+           :custom-button-width 3
+           :tab-width 4
+           :right-divider-width 30
+           :scroll-bar-width 8
+           :fringe-width 0))
+  (setq spacious-padding-subtle-frame-lines
+      '( :mode-line-active spacious-padding-line-active
+         :mode-line-inactive spacious-padding-line-inactive
+         :header-line-active spacious-padding-line-active
+         :header-line-inactive spacious-padding-line-inactive)))
+
+(use-package nerd-icons
+  :ensure t
+  :if (display-graphic-p))
+
+(use-package nerd-icons-dired
+  :ensure t
+  :after nerd-icons
+  :hook
+  (dired-mode . nerd-icons-dired-mode))
+
+(use-package nerd-icons-ibuffer
+  :ensure t
+  :after nerd-icons
+  :hook (ibuffer-mode . nerd-icons-ibuffer-mode))
+
+(use-package rainbow-delimiters
+  :ensure t
+  :hook (prog-mode . rainbow-delimiters-mode))
+
+(use-package hl-todo
+  :ensure t
+  :hook ((org-mode . hl-todo-mode)
+         (prog-mode . hl-todo-mode))
+  :config
+  (add-to-list 'hl-todo-keyword-faces '("ERROR" . "#8c5353")))
+
+(let* ((quit-messages
+        `(; from Doom 1
+          ,(format "I wouldn't leave if I were you. %s is much worse."
+                   (if (featurep 'windows-nt) "DOS" "UNIX"))
+          "Ya know, next time you come in here I'm gonna toast ya."
+          "Go ahead and leave. See if I care."
+          "Are you sure you want to quit this great editor?"
+          ; from Doom Emacs
+          "(setq nothing t everything 'permitted)"
+          "Emacs will remember that."
+          "Emacs, Emacs never changes."
+          "Hey! Hey, M-x listen!"
+          "Wake up, Mr. Stallman. Wake up and smell the ashes."
+          "You are *not* prepared!"
+          "Please don't go. The drones need you. They look up to you.")))
+  (progn
+    (defun random-quit-message ()
+      "Return a randomly chosen quit message from `quit-messages'."
+      (nth (random (length quit-messages)) quit-messages))
+
+    (defun message-confirm-kill-emacs (&rest _)
+      "Prompt the user with a random message before quitting.
+Returns t to allow kill if the user answers yes; nil otherwise."
+      (let* ((msg (random-quit-message))
+             (prompt (format "%s  Really quit Emacs? " msg)))
+        (yes-or-no-p (propertize prompt 'face '(italic default)))))
+
+    (setq confirm-kill-emacs #'message-confirm-kill-emacs)))
+
+(use-package goggles
+  :ensure t
+  :hook ((prog-mode text-mode) . goggles-mode)
+  :config
+  (setq-default goggles-pulse t))
+
+(add-hook 'emacs-startup-hook #'which-key-mode)
+
+;; Text Editing
+(setq-default indent-tabs-mode nil
+              tab-width 2
+              tab-stop-list (number-sequence 2 100 2)
+              c-basic-offset 2)
+
+(keymap-global-set "C-c r" 'replace-regexp)
+
+(cl-labels
+    ((vi-open-line-above ()
+       "Open line above the current line."
+       (interactive)
+       (unless (bolp) (beginning-of-line))
+       (newline)
+       (forward-line -1)
+       (indent-according-to-mode))
+     (vi-open-line-below ()
+       "Open line below the current line."
+       (interactive)
+       (unless (eolp) (end-of-line))
+       (newline-and-indent)))
+  (define-key (current-global-map) (kbd "C-c o") #'vi-open-line-above)
+  (define-key (current-global-map) (kbd "C-c O") #'vi-open-line-below)
+  (which-key-add-key-based-replacements "C-c o" "open-line-above")
+  (which-key-add-key-based-replacements "C-c O" "open-line-below"))
+
+(use-package move-text
+  :ensure t
+  :config
+  (keymap-global-set "M-p" 'move-text-up)
+  (keymap-global-set "M-n" 'move-text-down)
+  (defun indent-region-advice (&rest ignored)
+    (let ((deactivate deactivate-mark))
+      (if (region-active-p)
+          (indent-region (region-beginning) (region-end))
+        (indent-region (line-beginning-position) (line-end-position)))
+      (setq deactivate-mark deactivate)))
+
+  (advice-add 'move-text-up :after 'indent-region-advice)
+  (advice-add 'move-text-down :after 'indent-region-advice))
+
+(progn
+  (defun smart-beginning-of-line ()
+    "Move the cursor to the beginning of text on the line."
+    (interactive)
+    (let ((initial-point (point)))
+      (back-to-indentation)
+      (when (eq initial-point (point))
+        (move-beginning-of-line 1))))
+  (defun setup-prog-mode-c-a ()
+    (local-set-key (kbd "C-a") 'smart-beginning-of-line))
+  (add-hook 'prog-mode-hook 'setup-prog-mode-c-a)
+  (add-hook 'conf-mode-hook 'setup-prog-mode-c-a))
+
+(progn
+  (defun prog-nuke-trailing-whitespace ()
+    "Removes trailing whitespace at the end of the line."
+    (when (or (derived-mode-p 'prog-mode) (derived-mode-p 'conf-mode))
+      (delete-trailing-whitespace)))
+  (add-hook 'before-save-hook 'prog-nuke-trailing-whitespace))
+
+(use-package smartparens
+  :ensure t
+  :hook (prog-mode text-mode markdown-mode)
+  :config
+  (require 'smartparens-config)
+  (sp-use-paredit-bindings))
+
+(use-package undo-tree
+  :ensure t
+  :init
+  (global-undo-tree-mode 1)
+  :config
+  (setq undo-tree-auto-save-history t
+        undo-tree-history-directory-alist '(("." . "~/.emacs.d/.cache"))))
+
+(use-package gptel
+  :ensure t
+  :config
+  (setq
+   gptel-model 'qwen2.5-coder:7b-instruct-q4_K_M
+   gptel-backend (gptel-make-ollama "Ollama"
+                                    :host "localhost:11434"
+                                    :stream t
+                                    :models '(qwen2.5-coder:7b-instruct-q4_K_M)))
+  (keymap-global-set "C-c g" 'gptel-menu)
+  (which-key-add-key-based-replacements "C-c g" "gptel"))
+
+(use-package delsel
+    :hook (after-init . delete-selection-mode))
+
+(use-package accent
+  :ensure t
+  :bind* (("C-'" . accent-menu))
+  :config
+  (setq accent-diacritics '((a (á ã â à)) ; só para Português
+                            (e (é ê))
+                            (i (í))
+                            (o (ó õ ô))
+                            (u (ú))
+                            (c (ç))
+                            (A (Á Ã Â À))
+                            (E (É Ê))
+                            (I (Í))
+                            (O (Ó Õ Ô))
+                            (U (Ú)))))
+
+;; Emacsing
+(setq scroll-margin 10 ; Doesn't work with smooth-scrolling
+      scroll-conservatively 100
+      scroll-step 1)
+
+(setopt use-short-answers t)
+
+(use-package dired
+  :commands (dired)
+  :hook
+  ((dired-mode . dired-hide-details-mode)
+   (dired-mode . hl-line-mode))
+  :config
+  (setq dired-recursive-copies 'always
+        dired-recursive-deletes 'always
+        ; delete-by-moving-to-trash t ; FIXME: Currently Broken, need to find why
+        dired-dwim-target t
+        dired-listing-switches "-lah"))
+
+(use-package dired-subtree
+  :ensure t
+  :after dired
+  :bind
+  (:map dired-mode-map
+        ("TAB" . dired-subtree-toggle)
+        ("<backtab>" . dired-subtree-remove))
+  :config
+  (setq dired-subtree-use-backgrounds nil))
+
+(add-hook 'emacs-startup-hook #'save-place-mode)
+
+(progn
+  (dolist (spec
+           '((eshell-prompt-user-face        font-lock-keyword-face   "Face for the username in the eshell prompt.")
+             (eshell-prompt-venv-face        font-lock-string-face    "Face for the virtualenv name in the eshell prompt.")
+             (eshell-prompt-dir-face         dired-directory          "Face for the directory path in the eshell prompt.")
+             (eshell-prompt-git-face         magit-tag                "Face for the git branch in the eshell prompt.")
+             (eshell-prompt-git-dirty-face   eshell-prompt-git-face   "Face for the git dirty status in the eshell prompt.")
+             (eshell-prompt-symbol-face      font-lock-builtin-face   "Face for the prompt symbol in the eshell prompt.")))
+    (cl-destructuring-bind (name inherit doc) spec
+      (defface name
+        `((t (:inherit ,inherit)))
+        doc
+        :group 'eshell-prompt)))
+
+  (defun eshell-abbreviate-dir (dir)
+    "Abbreviate directory to show only the first and the last two components."
+    (let* ((abbrev (abbreviate-file-name dir))
+           (components (split-string abbrev "/" t))
+           (num-components (length components)))
+      (if (>= num-components 4)
+          (concat (car components) "/.../"
+                  (mapconcat #'identity (last components 2) "/"))
+        abbrev)))
+
+  (defun eshell-prompt-git-branch ()
+    "Return the current git branch or short commit hash, if available."
+    (when (and (executable-find "git")
+               (locate-dominating-file default-directory ".git"))
+      (with-temp-buffer
+        (let ((ret (call-process "git" nil t nil "symbolic-ref" "--short" "HEAD")))
+          (if (zerop ret)
+              (string-trim (buffer-string))
+            (when (zerop (call-process "git" nil t nil "rev-parse" "--short" "HEAD"))
+              (string-trim (buffer-string))))))))
+
+  (defun eshell-prompt-git-dirty ()
+    "Return a dirty flag (✗ if dirty, ✓ if clean) for the git repository."
+    (when (eshell-prompt-git-branch)
+      (with-temp-buffer
+        (call-process "git" nil t nil "status" "--porcelain")
+        (if (> (buffer-size) 0) "✗" "✓"))))
+
+  (defun eshell-prompt ()
+    "Custom eshell prompt."
+    (let* ((user (propertize (user-login-name) 'face 'eshell-prompt-user-face))
+           (venv (when-let ((venv (getenv "VIRTUAL_ENV")))
+                   (concat (propertize "(" 'face 'eshell-prompt-venv-face)
+                           (propertize (file-name-nondirectory venv) 'face 'eshell-prompt-venv-face)
+                           (propertize ")" 'face 'eshell-prompt-venv-face))))
+           (path (propertize (eshell-abbreviate-dir (eshell/pwd)) 'face 'eshell-prompt-dir-face))
+           (git-branch (eshell-prompt-git-branch))
+           (git-info (when git-branch
+                       (concat " " (propertize "on" 'face 'font-lock-number-face) " "
+                               (propertize git-branch 'face 'eshell-prompt-git-face)
+                               (propertize (eshell-prompt-git-dirty) 'face 'eshell-prompt-git-dirty-face))))
+           (prompt (concat user " " (propertize "in" 'face 'font-lock-number-face) " "
+                           (if venv (concat venv " ") "")
+                           path git-info "\n"
+                           (propertize "λ" 'face 'eshell-prompt-symbol-face) " ")))
+      prompt))
+
+  (setq eshell-prompt-function 'eshell-prompt
+        eshell-prompt-regexp "^[^λ\n]*λ "))
+
+(use-package disproject
+  :ensure t
+  :after project
+  :bind (:map ctl-x-map
+              ("p" . disproject-dispatch)))
+
+(use-package ibuffer-project
+  :ensure t
+  :after project
+  :config
+  (add-hook
+   'ibuffer-hook
+   (lambda ()
+     (setq ibuffer-filter-groups (ibuffer-project-generate-filter-groups))
+     (unless (eq ibuffer-sorting-mode 'project-file-relative)
+       (ibuffer-do-sort-by-project-file-relative))))
+  (keymap-global-set "C-x C-b" 'ibuffer))
+
+(progn
+  (add-hook 'emacs-startup-hook #'recentf-mode)
+  (keymap-global-set "C-x C-r" 'recentf-open)
+  (which-key-add-key-based-replacements "C-x C-r" "Recent Files")
+  (put 'compile-command 'safe-local-variable #'stringp))
+
+(use-package savehist
+  :hook (after-init . savehist-mode))
+
+(add-to-list 'Info-directory-list "/Users/venomade/Documents/Info/")
+
+;; Org Mode
+(setq org-src-window-setup 'current-window
+      org-confirm-babel-evaluate nil
+      org-hide-emphasis-markers t)
+
+(font-lock-add-keywords 'org-mode
+                        '(("^ *\\([-]\\) "
+                           (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
+
+; (use-package org-bullets
+;   :ensure t
+;   :config
+;   (setq org-bullets-bullet-list
+;       '("◉" "○" "◎" "◈" "◆" "▶"))
+;   (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
+
+(use-package org-superstar
+  :ensure t
+  :hook (org-mode . org-superstar-mode)
+  :custom
+  (org-superstar-remove-leading-stars nil)
+  (org-superstar-headline-bullets-list
+   '("◉" "○" "◎" "◈" "◆" "▶")))
+
+(let* ((variable-tuple
+        (cond ((x-list-fonts "Google Sans")     '(:font "Google Sans"))
+              ((x-family-fonts "Sans Serif")    '(:family "Sans Serif"))
+              (nil (warn "Cannot find a Sans Serif Font.  Install Google Sans."))))
+       (base-font-color     (face-foreground 'default nil 'default))
+       (headline           `(:inherit default :weight bold :foreground ,base-font-color)))
+
+  (custom-theme-set-faces
+   'user
+   `(org-level-8 ((t (,@headline ,@variable-tuple))))
+   `(org-level-7 ((t (,@headline ,@variable-tuple))))
+   `(org-level-6 ((t (,@headline ,@variable-tuple))))
+   `(org-level-5 ((t (,@headline ,@variable-tuple))))
+   `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1))))
+   `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.2))))
+   `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.3))))
+   `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.4))))
+   `(org-document-title ((t (,@headline ,@variable-tuple :height 1.6 :underline nil))))))
+
+(add-hook 'org-mode-hook 'variable-pitch-mode)
+(add-hook 'org-mode-hook 'visual-line-mode)
+(add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1)))
+
+(custom-theme-set-faces
+ 'user
+ '(org-block ((t (:inherit fixed-pitch))))
+ '(org-code ((t (:inherit (shadow fixed-pitch)))))
+ '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
+ '(org-indent ((t (:inherit (org-hide fixed-pitch)))))
+ '(org-link ((t (:foreground "royal blue" :underline t))))
+ '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
+ '(org-property-value ((t (:inherit fixed-pitch))) t)
+ '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
+ '(org-table ((t (:inherit fixed-pitch))))
+ '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))))
+ '(org-verbatim ((t (:inherit (shadow fixed-pitch))))))
+
+(require 'org-tempo)
+
+(use-package pdf-tools
+  :ensure t
+  :config
+  (pdf-tools-install)
+  (add-hook 'pdf-view-mode-hook (lambda () (display-line-numbers-mode -1))))
+
+; Open Org Mode links in current window
+(setq org-link-frame-setup
+      '((file . find-file)
+        (wl . wl-other-frame)
+        (vm . vm-visit-folder-other-frame)
+        (gnus . gnus)))
+
+(use-package denote
+  :ensure t
+  :hook (dired-mode . denote-dired-mode)
+  :bind
+  (("C-c n n" . denote)
+   ("C-c n r" . denote-rename-file)
+   ("C-c n l f" . denote-link)
+   ("C-c n b" . denote-backlinks)
+   ("C-c n g" . denote-grep))
+  :config
+  (setq denote-directory (expand-file-name "~/Documents/Denotes/")
+        denote-known-keywords '("politics" "history" "united kingdom"))
+  (denote-rename-buffer-mode 1))
+
+(use-package consult-denote
+  :ensure t
+  :bind
+  (("C-c n f" . consult-denote-find)
+   ("C-c n g" . consult-denote-grep))
+  :config
+  (consult-denote-mode 1))
+
+; TODO: Denote Explore https://lucidmanager.org/productivity/denote-explore/
+
+(use-package denote-menu
+  :ensure t
+  :bind
+  (("C-c n d" . list-denotes))
+  :config
+  (add-hook 'denote-menu-mode-hook (lambda () (display-line-numbers-mode -1))))
+
+(use-package denote-org
+  :ensure t
+  :bind
+  (("C-c n l h" . denote-org-link-to-heading)))
+
+;; Completion
+(use-package orderless
+  :ensure t
+  :config
+  (setq completion-styles '(orderless basic)
+        completion-category-defaults nil
+        completion-category-overrides '((file (styles . (partial-completion))))))
+
+(use-package yasnippet
+  :ensure t
+  :hook (prog-mode . yas-minor-mode)
+  :bind
+  (("C-c y n" . yas-new-snippet)
+   ("C-c y v" . yas-visit-snippet-file)
+   ("C-c y i" . yas-insert-snippet))
+  :config
+  (yas-reload-all))
+
+(use-package yasnippet-snippets
+  :after yasnippet
+  :ensure t)
+
+(use-package cape
+  :ensure t)
+
+(defun eglot-capf-with-yasnippet ()
+  (setq-local completion-at-point-functions
+              (list
+           (cape-capf-super
+        #'eglot-completion-at-point
+        #'yasnippet-capf))))
+(with-eval-after-load 'eglot
+  (add-hook 'eglot-managed-mode-hook #'eglot-capf-with-yasnippet))
+
+(use-package corfu
+  :ensure t
+  :hook (after-init . global-corfu-mode)
+  :bind (:map corfu-map ("<tab>" . corfu-complete)
+              ("RET" . nil))
+  :config
+  (setq corfu-cycle t
+        corfu-auto t
+        corfu-auto-delay 0.2
+        corfu-preview-current nil
+        corfu-quit-at-boundary t
+        corfu-quit-no-match t
+        corfu-scroll-margin 5
+        corfu-tab-always-indent 'complete
+        corfu-preview-current nil
+        corfu-min-width 20
+        corfu-popupinfo-delay '(1.25 . 0.5))
+  (corfu-popupinfo-mode 1)
+  (with-eval-after-load 'savehist
+    (corfu-history-mode 1)
+    (add-to-list 'savehist-additional-variables 'corfu-history)))
+
+(use-package nerd-icons-corfu
+  :ensure t
+  :after nerd-icons corfu
+  :config
+  (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
+
+(use-package vertico
+  :ensure t
+  :hook (after-init . vertico-mode)
+  :bind (:map vertico-map
+              ("DEL" . vertico-directory-delete-char)))
+
+(use-package consult
+  :ensure t
+  :bind (("M-g g" . consult-goto-line)
+         ("M-g M-g" . consult-goto-line)
+         ("C-c s" . consult-line))
+
+  :config
+  (which-key-add-key-based-replacements "C-c s" "search-lines"))
+
+(use-package affe
+  :ensure t
+  :after consult
+  :bind (("C-c f f" . affe-find)
+         ("C-c f g" . affe-grep))
+  :init
+  (which-key-add-key-based-replacements "C-c f" "find-file")
+  (which-key-add-key-based-replacements "C-c f f" "find-fuzzy")
+  (which-key-add-key-based-replacements "C-c f g" "find-greppy"))
+
+(use-package marginalia
+  :ensure t
+  :after vertico
+  :config (marginalia-mode 1))
+
+(use-package nerd-icons-completion
+  :ensure t
+  :after vertico marginalia
+  :hook
+  (marginalia-mode . nerd-icons-completion-marginalia-setup)
+  (after-init . nerd-icons-completion-mode))
+
+;; Version Control
 (setq vc-follow-symlinks t)
-(org-babel-load-file
+
+(use-package magit
+  :ensure t
+  :after nerd-icons
+  :custom
+  (magit-format-file-function #'magit-format-file-nerd-icons))
+
+(use-package magit-todos
+  :ensure t
+  :after magit hl-todo
+  :config
+  (add-hook 'magit-log-wash-summary-hook
+            #'hl-todo-search-and-highlight t)
+  (add-hook 'magit-revision-wash-message-hook
+            #'hl-todo-search-and-highlight t)
+  (magit-todos-mode 1))
+
+;; Programming
+(use-package eglot
+  :ensure t
+  :after cape
+  :config
+  (setq eglot-report-progress nil)
+  (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster)
+  (add-hook 'c-mode-hook #'eglot-ensure))
+
+(use-package eglot-booster
+  :vc (:url "https://github.com/jdtsmith/eglot-booster.git")
+  :ensure t
+	:after eglot
+	:config
+  (setq eglot-booster-io-only t)
+  (eglot-booster-mode))
+
+(use-package consult-eglot
+  :ensure t
+  :after eglot)
+
+(progn
+  (use-package eldoc-box
+    :ensure t)
+
+  (defun markdown-follow-help-or-link-at-point-advice (orig-fun &rest args)
+    "Prefer to use the help-echo property as `browse-url' target."
+    (let* ((event-win (posn-window (event-start last-input-event)))
+           (help-echo (with-selected-frame (window-frame event-win)
+                        (with-current-buffer (window-buffer event-win)
+                          (get-text-property (point) 'help-echo))))
+           (help-is-url (url-type (url-generic-parse-url help-echo))))
+      (message "if %s (browse-url %S)" help-is-url help-echo)
+      (if help-is-url
+          (browse-url help-echo)
+        (apply orig-fun args))))
+
+  (advice-add 'markdown-follow-link-at-point :around #'markdown-follow-help-or-link-at-point-advice))
+
+(transient-define-prefix eglot-transient ()
+  "Transient menu for Eglot."
+  [["Server"
+    ("c" "Reconnect" eglot-reconnect)
+    ("q" "Shutdown" eglot-shutdown)
+    ("I" "Server Info" eglot-show-workspace-configuration)]
+   ["Navigation"
+    ("g" "Go to Definition" xref-find-definitions)
+    ("d" "Describe Thing at Point" eldoc-box-help-at-point)
+    ("D" "Go to Declaration" eglot-find-declaration)
+    ("i" "Go to Implementation" eglot-find-implementation)
+    ("f" "Find References" xref-find-references)
+    ("t" "Type Definition" eglot-find-typeDefinition)
+    ("s" "Search Symbols"
+     (lambda ()
+       (interactive)
+       (if (eq major-mode 'java-mode)
+           (call-interactively 'consult-eglot-jdt-symbols)
+         (call-interactively 'consult-eglot-symbols))))]
+   ["Code Actions"
+    ("a" "Code Actions" eglot-code-actions)
+    ("q" "Quick Fix" eglot-code-action-quickfix)
+    ("=" "Format Buffer" eglot-format-buffer)
+    ("o" "Organize Imports" eglot-code-action-organize-imports)
+    ("r" "Rename Symbol" eglot-rename)]
+   ["Diagnostics"
+    ("l" "List Diagnostics" flycheck-list-errors)
+    ("L" "Project Diagnostics" flymake-show-project-diagnostics)]]
+  (interactive)
+   (transient-setup 'eglot-transient))
+
+(define-key eglot-mode-map (kbd "C-c l") #'eglot-transient)
+
+(use-package flycheck
+  :ensure t
+  :config
+  (global-flycheck-mode 1))
+
+(use-package flycheck-eglot
+  :ensure t
+  :after (flycheck eglot)
+  :custom (flycheck-eglot-exclusive nil)
+  :config
+  (global-flycheck-eglot-mode 1))
+
+(setq-default flycheck-disabled-checkers '(c/c++-clang))
+
+(progn
+  (setq compilation-scroll-output t)
+  (keymap-global-set "C-c m c" 'compile)
+  (keymap-global-set "C-c m r" 'recompile)
+  (which-key-add-key-based-replacements "C-c m" "make"))
+
+(require 'ansi-color)
+(defun colorize-compilation-buffer ()
+  (ansi-color-apply-on-region compilation-filter-start (point)))
+(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
+
+(global-prettify-symbols-mode 1)
+
+;; Languages
+
+; (load-file
+;  (expand-file-name
+;   "lang/java.el"
+;   user-emacs-directory))
+
+(load-file
  (expand-file-name
-  "config.org"
+  "lang/lua.el"
   user-emacs-directory))
+
+; (load-file
+;  (expand-file-name
+;   "lang/lisp.el"
+;   user-emacs-directory))
+
+; (load-file
+;  (expand-file-name
+;   "lang/clojure.el"
+;   user-emacs-directory))
+
+;; Font
+; Putting at the end to test if it fixes this:
+; https://github.com/d12frosted/homebrew-emacs-plus/issues/898
+
+(let* ((fontconf '((fixed-font    . "Google Sans Code")
+                   (variable-font . "Google Sans")
+                   (size          . 12)))
+       (fixed-font    (cdr (assoc 'fixed-font fontconf)))
+       (variable-font (cdr (assoc 'variable-font fontconf)))
+       (pt-size       (cdr (assoc 'size fontconf)))
+       (height        (* pt-size 10))
+       (frame-font    (concat fixed-font "-" (number-to-string pt-size))))
+  ; Fixed-width faces
+  (dolist (face '(default fixed-pitch))
+    (set-face-attribute face nil
+                        :font fixed-font
+                        :height height
+                        :weight 'regular))
+  ; Variable-pitch face
+  (set-face-attribute 'variable-pitch nil
+                      :font variable-font
+                      :height height
+                      :weight 'regular)
+
+  ; Syntax styling
+  (set-face-attribute 'font-lock-comment-face nil :slant 'italic)
+  (set-face-attribute 'font-lock-keyword-face nil :slant 'italic)
+
+  ; Frame font
+  (add-to-list 'default-frame-alist `(font . ,frame-font)))