- Fix benchmark-deactivate on init - defer loading aidermacs and gptel - also set evil-want-keybinding to nil: https://github.com/emacs-evil/evil-collection/issues/6
My Emacs Configuration
- Settings
 - Packages
 - Mode specific hooks
 - Random eye candy stuff
 - Custom mode line
 - Pop-up terminal
 - LLMs
 - Keybinds
 
Settings
Setting the default face
 ; -*- lexical-binding: t; -*-
(set-frame-font "Fira Code 13" nil t)
(add-to-list 'default-frame-alist '(font . "Fira Code-13"))
Some mode settings based on personal preferences
(add-hook 'prog-mode-hook #'hl-line-mode)
(add-hook 'text-mode-hook #'hl-line-mode)
(scroll-bar-mode 0)
(tool-bar-mode 0)
(menu-bar-mode 0)
(fringe-mode 0)
(global-display-line-numbers-mode 1)
(xterm-mouse-mode 1)
(electric-pair-mode)
(setq ring-bell-function 'ignore
      gc-cons-threshold most-positive-fixnum
      initial-major-mode 'fundamental-mode)
Setting some variables
(setq initial-major-mode 'emacs-lisp-mode
      frame-resize-pixelwise t
      auto-window-vscroll nil
      scroll-step 1
      display-line-numbers-type 'relative
      confirm-kill-processes nil
      inhibit-startup-screen t)
(setq-default tab-width 2
              indent-tabs-mode nil)
Emacs startup hook
(add-hook 'emacs-startup-hook
          (lambda () (delete-other-windows)) t)
Packages
Add Melpa to package archives
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(package-initialize)
(require 'use-package)
Profiling
(use-package benchmark-init
  :config
  (add-hook 'after-init-hook 'benchmark-init/deactivate) )
Visual packages
Add solaire mode
(use-package solaire-mode
  :config
  (solaire-mode))
Set theme
(use-package catppuccin-theme
  :config
  (load-theme 'catppuccin t)
  :custom
  (dark-theme t))
Minibuffer
Enable vertico
(use-package vertico
  :init
  (vertico-mode)
  :bind (:map vertico-map
              ("C-j" . vertico-next)
              ("C-k" . vertico-previous)))
Save history over restarts
(use-package savehist
  :init
  (savehist-mode))
Marginalia for description
(use-package marginalia
  :after vertico
  :config
  (marginalia-mode 1))
Orderless
(use-package orderless
  :after vertico
  :config
  (setq completion-styles '(orderless basic)))
Consult
(use-package consult
  :bind (("M-s M-g" . consult-grep)
         ("M-s M-f" . consult-find)
         ("M-s M-b" . consult-buffer)))
Evil
Configure evil mode
(defun my/evil-shift-right ()
  (interactive)
  (evil-shift-right evil-visual-beginning evil-visual-end)
  (evil-normal-state)
  (evil-visual-restore))
(defun my/evil-shift-left ()
  (interactive)
  (evil-shift-left evil-visual-beginning evil-visual-end)
  (evil-normal-state)
  (evil-visual-restore))
(use-package evil
  :init
  (setq-default evil-shift-width 2)
  (setq evil-want-keybinding nil)
  :config
  (evil-set-initial-state 'vterm-mode 'insert)
  (evil-set-undo-system 'undo-tree)
  (evil-define-key 'visual global-map (kbd ">") 'my/evil-shift-right)
  (evil-define-key 'visual global-map (kbd "<") 'my/evil-shift-left)
  (evil-mode 1))
Evil related packages
(use-package evil-collection
  :after evil
  :ensure t
  :config
  (evil-collection-init))
(use-package evil-terminal-cursor-changer
  :after evil
  :if (not (display-graphic-p))
  :config
  (evil-terminal-cursor-changer-activate))
(use-package evil-anzu :after evil)
Configure undo tree
To undo and redo easily like vi
(use-package undo-tree
  :init
  (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
  :config
  (global-undo-tree-mode 1))
Treemacs
Configure treemacs
(use-package treemacs
  :defer t
  :config
  (treemacs-project-follow-mode))
(use-package treemacs-evil :after treemacs)
(use-package treemacs-projectile :after treemacs)
(use-package treemacs-all-the-icons :after treemacs)
LSP
Configure lsp-mode
(use-package lsp-mode
  :defer t
  :commands lsp
  :init
  (setq lsp-enable-on-type-formatting nil))
Configure lsp-ui
(use-package lsp-ui
  :defer t
  :init
  (setq lsp-ui-doc-delay 1.0
        lsp-ui-doc-show-with-mouse t
        pgtk-wait-for-event-timeout nil
        lsp-ui-doc-show-with-cursor t)
  :config
  (lsp-ui-peek-enable 1)
  (lsp-ui-doc-enable 1)
  :hook (lsp-mode . lsp-ui-mode))
Configure flycheck
(use-package flycheck
  :defer t)
Configure dap-mode
(use-package dap-mode
  :defer t
  :hook ((lsp-mode . dap-mode)
         (lsp-mode . dap-ui-mode)))
Company
Configure company
For autocomplete
(use-package company
  :after lsp-mode
  :config
  (add-to-list 'company-backends 'company-dabbrev)
  (setq company-backends (append '(company-files) (remove 'company-files company-backends)))
  :hook (after-init . global-company-mode))
Configure company-quickhelp
(use-package company-quickhelp
  :hook (company-mode . company-quickhelp-mode))
Treesitter
(use-package tree-sitter-langs :defer t)
(use-package tree-sitter
  :after tree-sitter-langs
  :defer t
  :config
  (global-tree-sitter-mode)
  :init
  (add-to-list 'tree-sitter-major-mode-language-alist '(fundamental-mode . bash))
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))
Direnv
(use-package direnv
 :config
 (direnv-mode))
Languages
(use-package dts-mode
  :mode ("\\.dts\\'" "\\.dtsi\\'" "\\.overlay\\'"))
(use-package lsp-haskell
  :mode "\\.hs\\'")
(use-package lsp-latex
  :mode "\\.tex\\'")
(use-package rustic
  :mode "\\.rs\\'")
(use-package typescript-mode
  :mode ("\\.ts\\'" "\\.tsx\\'"))
(use-package wgsl-mode
  :mode "\\.wgsl\\'")
(use-package nix-mode
  :mode "\\.nix\\'")
(use-package hcl-mode
  :mode
  "\\.hcl\\'"
  "\\.nomad\\'")
(use-package go-mode
  :mode "\\.go\\'")
Git
magit for git operations
(use-package magit :defer t)
blamer for git blame
(use-package blamer
  :defer 20
  :custom
  (blamer-idle-time 0.3)
  (blamer-min-offset 70)
  :config
  (global-blamer-mode 1)
  :init
  (setq blamer-show-avatar-p nil
        blamer-max-commit-message-length 72))
VTerm
Configure vterm
(use-package vterm
  :config
  (evil-define-key 'normal vterm-mode-map (kbd "p") 'vterm-yank)
  (evil-define-key 'insert vterm-mode-map (kbd "C-y") 'vterm-yank)
  (setq vterm-timer-delay 0.005))
(use-package vterm-toggle
  :after vterm
  :config
  (setq vterm-toggle-fullscreen-p nil)
  (add-to-list 'display-buffer-alist
               '((lambda (buffer-or-name _)
                      (let ((buffer (get-buffer buffer-or-name)))
                        (with-current-buffer buffer
                          (or (equal major-mode 'vterm-mode)
                              (string-prefix-p vterm-buffer-name (buffer-name buffer))))))
               (display-buffer-reuse-window display-buffer-in-side-window)
               (side . bottom)
               (reusable-frames . visible)
               (window-height . 0.4))))
Centaur Tabs
Do not use centaur tabs for now
(use-package centaur-tabs
  :defer t
  :custom
  (centaur-tabs-style "rounded")
	(centaur-tabs-height 18)
	(centaur-tabs-set-modified-marker t)
	(centaur-tabs-set-icons t)
  :config
  (centaur-tabs-mode t)
  (centaur-tabs-group-by-projectile-project)
  (set-face-attribute 'tab-line nil :inherit 'centaur-tabs-unselected)
  (centaur-tabs-headline-match)
  :bind
  (:map evil-normal-state-map
    ("M-," . centaur-tabs-forward)
    ("M-." . centaur-tabs-backward))
  (:map evil-motion-state-map
    ("M-," . centaur-tabs-forward)
    ("M-." . centaur-tabs-backward)))
Misc packages
Icons
For installing icons
(use-package all-the-icons
  :defer t
  :if (display-graphic-p))
Projectile
For tracking project root
(use-package projectile
  :defer t
  :config
  (define-key projectile-mode-map (kbd "C-x p") 'projectile-command-map)
  (projectile-mode +1))
Rainbow
For highlighting colors
(use-package rainbow-mode :defer t)
Rainbow delimiters
To make distinguishing parens easier
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))
Org
Add org-mode
(use-package org
  :defer t
  :after evil
  :config
  (define-key org-mode-map (kbd "RET") 'org-return-and-maybe-indent)
  (evil-define-key 'normal org-mode-map (kbd "TAB") 'org-cycle)
  :custom
  (evil-want-C-i-jump nil)
  (org-adapt-indentation t)
  (org-src-fontify-natively t)
  (org-src-strip-leading-and-trailing-blank-lines t)
  (org-src-preserve-indentation t)
  (org-src-tab-acts-natively t))
Add org-bullets
 (use-package org-bullets
  :defer t
  :hook ((org-mode . org-bullets-mode)))
Babel and exports
(use-package htmlize :defer t)
(setq org-latex-listings 'minted
      org-latex-packages-alist '(("" "minted"))
      org-latex-pdf-process
      '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
(setq org-src-fontify-natively t)
(setq org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (C . t)
   (sql . t)
   (latex . t)))
Mode specific hooks
(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)
(add-hook 'haskell-mode-hook #'lsp)
(add-hook 'haskell-literate-mode-hook #'lsp)
Random eye candy stuff
Custom mode line
switched to doom modeline after using my own modeline for a while
(use-package doom-modeline
  :init (doom-modeline-mode 1))
Pop-up terminal
Stolen from this reddit post
(defun run-in-vterm-kill (process event)
  "A process sentinel. Kills PROCESS's buffer if it is live."
  (let ((b (process-buffer process)))
    (and (buffer-live-p b)
         (kill-buffer b))))
(defun run-in-vterm (command)
  (interactive
   (list
    (let* ((f (cond (buffer-file-name)
                    ((eq major-mode 'dired-mode)
                     (dired-get-filename nil t))))
           (filename (concat " " (shell-quote-argument (and f (file-relative-name f))))))
      (read-shell-command "Terminal command: "
                          (cons filename 0)
                          (cons 'shell-command-history 1)
                          (list filename)))))
  (with-current-buffer (vterm-toggle)
    (set-process-sentinel vterm--process #'run-in-vterm-kill)
    (vterm-send-string (concat command))
    (vterm-send-return)))
Compilation shortcuts for standalone files
(defun candrun ()
  (let ((full buffer-file-name)
        (file (file-name-sans-extension buffer-file-name)))
    (pcase (file-name-extension full)
           ("c" (concat "gcc " full " -lm -pthread -o " file " && " file " && rm " file))
           ("java" (concat "java " full))
           ("py" (concat "python " full))
           ("cpp" (concat "g++ " full " -o " file " && " file " && rm " file))
           ("cc" (concat "g++ " full " -o " file " && " file " && rm " file))
           ("hs" (concat "runhaskell " full))
           ("sh" (concat "sh " full))
           ("js" (concat "node " full))
           ("ts" (concat "tsc " full " && node " file ".js && rm " file ".js" ))
           ("rs" (concat "rustc " full " -o " file " && " file " && rm " file)))))
LLMs
gptel
(use-package gptel
  :defer t
  :config
  (setq  gptel-model 'claude-sonnet-4-20250514
         gptel-backend (gptel-make-anthropic "Claude"
                        :stream t
                        :protocol "https"
                        :key (getenv "ANTHROPIC_API_KEY")
                        :host (getenv "ANTHROPIC_API_BASE_DOMAIN")))
  (setq gptel-default-mode 'org-mode)
  :bind (("C-c g" . gptel)))
Aidermacs
(use-package aidermacs
  :defer t
  :bind (("C-c a" . aidermacs-transient-menu))
  :custom
  ; See the Configuration section below
  (aidermacs-default-chat-mode 'architect)
  (aidermacs-default-model "sonnet"))
Keybinds
General
Colemak translations
not using this anymore
(use-package evil-colemak-basics
  :init
  (setq evil-colemak-basics-layout-mod 'mod-dh)
  :config
  (global-evil-colemak-basics-mode))
Misc binds
(use-package general
  :ensure t)
(setq evil-states
  '(visual normal motion))
(with-eval-after-load 'general
  (general-define-key
    :states evil-states
    "M-c" 'comment-line
    "C-c M-c" 'comment-box)
  (general-define-key
    :states '(normal insert)
    "M-C-f" 'lsp-format-buffer
    "C-S-v" 'yank)
  (general-define-key
    :keymaps '(global override vterm-mode-map)
    :states evil-states
    "M-o" 'treemacs
    "M-s-v" 'split-window-vertically
    "M-s-h" 'split-window-horizontally
    "M-h" 'windmove-left
    "M-j" 'windmove-down
    "M-k" 'windmove-up
    "M-l" 'windmove-right
    "M-C-h" 'shrink-window-horizontally
    "M-C-l" 'enlarge-window-horizontally
    "M-C-j" 'shrink-window
    "M-C-k" 'enlarge-window
    "C-q"  'delete-window
    "M-C-S-q"  'kill-buffer-and-window
    "M-w"  (lambda () (interactive) (kill-buffer (current-buffer)))
    "M-S-w"  'kill-window)
Pop-up terminal specific keybinds
  (with-eval-after-load 'vterm-toggle
    (general-define-key
      :keymaps '(global override vterm-mode-map)
      :states evil-states
      "<f4>"  (lambda () (interactive) (vterm t))
      "C-S-t" 'vterm-toggle-cd
      "C-t" 'vterm-toggle
      "<f1>" 'vterm-toggle
      "<f5>" (lambda () (interactive) (run-in-vterm (candrun))))
    (general-define-key
      :keymaps 'vterm-mode-map
      "<f3>" 'vterm-toggle-forward
      "<f2>" 'vterm-toggle-backward)))