Skip to content

Instantly share code, notes, and snippets.

@reflechant
Last active August 3, 2026 10:34
Show Gist options
  • Select an option

  • Save reflechant/c900eb968fc75a16a676428f29ed2138 to your computer and use it in GitHub Desktop.

Select an option

Save reflechant/c900eb968fc75a16a676428f29ed2138 to your computer and use it in GitHub Desktop.
new Emacs config
;;; init.el --- Personal Emacs config -*- lexical-binding: t; -*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Package Management ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; use-package is built-in in Emacs 30 but :ensure needs this module
(require 'use-package-ensure)
(setq use-package-always-ensure t)
;; Keep Custom's auto-generated stuff out of init.el
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Sane Defaults ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setopt use-short-answers t) ; y/n instead of yes/no
(setq inhibit-startup-message t) ; skip splash screen
(menu-bar-mode -1) ; hide File/Edit/… menu bar
(tool-bar-mode -1) ; hide icon toolbar
(setq column-number-mode t) ; show column in modeline
;; Fill column indicator at 80 chars
(setopt display-fill-column-indicator-column 80)
(global-display-fill-column-indicator-mode t)
;; Line numbers in code
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
;; Remember cursor position in files
(save-place-mode 1)
;; Remember recent files
(recentf-mode 1)
(setq recentf-max-saved-items 50)
;; Remember minibuffer history (Vertico sorts by this)
(savehist-mode 1)
;; Auto-reload files changed by external programs (git, AI tools, etc.)
(global-auto-revert-mode 1)
(setq auto-revert-verbose nil) ; Don't spam "Reverting buffer" messages
;; Auto-pair brackets (disabled in paredit buffers below)
(electric-pair-mode t)
;; Smooth pixel scrolling
(pixel-scroll-precision-mode t)
;; Shift + arrow keys to move between windows
(windmove-default-keybindings)
;; Store backups in a dedicated directory
(setq backup-directory-alist
`(("." . ,(expand-file-name "backups" user-emacs-directory))))
;; Hide commands in M-x that don't apply to current mode
(setq read-extended-command-predicate #'command-completion-default-include-p)
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Leader Key (C-c) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; C-c acts as global leader key (reserved by Emacs standards for user bindings)
(use-package general
:config
(general-create-definer my-leader-def
:prefix "C-c")
(my-leader-def
"" '(nil :which-key "leader")
"SPC" '(execute-extended-command :which-key "M-x")
"u" '(universal-argument :which-key "universal arg")
"TAB" '(mode-line-other-buffer :which-key "last buffer")
"!" '(shell-command :which-key "shell command")
"/" '(consult-ripgrep :which-key "ripgrep")
";" '(eval-expression :which-key "eval expression")
"'" '(eshell :which-key "eshell")
;; Files
"f" '(:ignore t :which-key "file")
"f f" '(find-file :which-key "find file")
"f r" '(consult-recent-file :which-key "recent files")
"f s" '(save-buffer :which-key "save")
"f S" '(write-file :which-key "save as")
"f R" '(rename-visited-file :which-key "rename current file")
;; Buffers
"b" '(:ignore t :which-key "buffer")
"b b" '(consult-buffer :which-key "switch buffer")
"b d" '(kill-current-buffer :which-key "kill buffer")
"b l" '(ibuffer :which-key "list buffers")
"b n" '(next-buffer :which-key "next buffer")
"b p" '(previous-buffer :which-key "previous buffer")
"b r" '(revert-buffer-quick :which-key "revert buffer")
"b s" '(scratch-buffer :which-key "scratch buffer")
"b m" '(bookmark-set :which-key "set bookmark")
"b M" '(consult-bookmark :which-key "jump to bookmark")
;; Project (built-in project.el)
"p" '(:ignore t :which-key "project")
"p f" '(project-find-file :which-key "find file in project")
"p p" '(project-switch-project :which-key "switch project")
"p s" '(project-find-regexp :which-key "grep in project")
"p b" '(consult-project-buffer :which-key "project buffers")
"p c" '(project-compile :which-key "compile")
"p e" '(project-eshell :which-key "eshell in project root")
"p d" '(project-dired :which-key "dired in project root")
"p k" '(project-kill-buffers :which-key "kill project buffers")
"p r" '(project-query-replace-regexp :which-key "replace in project")
;; Search
"s" '(:ignore t :which-key "search")
"s s" '(consult-line :which-key "search in buffer")
"s S" '(isearch-forward :which-key "isearch forward")
"s r" '(consult-ripgrep :which-key "ripgrep from here")
"s f" '(consult-find :which-key "find file by name")
"s i" '(consult-imenu :which-key "imenu symbols")
"s I" '(consult-imenu-multi :which-key "imenu all buffers")
"s l" '(consult-line-multi :which-key "search all open buffers")
"s o" '(consult-outline :which-key "outline headings")
"s R" '(query-replace :which-key "search & replace in buffer")
;; Code / LSP
"c" '(:ignore t :which-key "code")
"c a" '(eglot-code-actions :which-key "code actions")
"c r" '(eglot-rename :which-key "rename symbol")
"c f" '(eglot-format-buffer :which-key "format buffer")
"c d" '(xref-find-definitions :which-key "go to definition")
"c D" '(xref-find-references :which-key "find references")
"c e" '(consult-flymake :which-key "list diagnostics")
"c j" '(flymake-goto-next-error :which-key "next error")
"c k" '(flymake-goto-prev-error :which-key "prev error")
"c o" '(eglot-code-action-organize-imports :which-key "organize imports")
"c x" '(eglot-code-action-quickfix :which-key "quickfix")
"c h" '(eldoc :which-key "docs at point")
;; Git
"g" '(:ignore t :which-key "git")
"g g" '(magit-status :which-key "status")
"g b" '(magit-blame :which-key "blame")
"g l" '(magit-log-current :which-key "log current branch")
"g L" '(magit-log-all :which-key "log all branches")
"g d" '(diff-hl-show-hunk :which-key "show hunk diff")
"g r" '(diff-hl-revert-hunk :which-key "revert hunk")
"g n" '(diff-hl-next-hunk :which-key "next changed hunk")
"g p" '(diff-hl-previous-hunk :which-key "prev changed hunk")
"g f" '(magit-file-dispatch :which-key "file actions")
"g s" '(magit-stage-file :which-key "stage current file")
;; Window management
"w" '(:ignore t :which-key "window")
"w v" '(split-window-right :which-key "split vertical")
"w s" '(split-window-below :which-key "split horizontal")
"w d" '(delete-window :which-key "close window")
"w w" '(ace-window :which-key "select window")
"w m" '(delete-other-windows :which-key "maximize")
"w =" '(balance-windows :which-key "balance windows")
"w r" '(window-swap-states :which-key "swap windows")
"w h" '(windmove-left :which-key "go left")
"w j" '(windmove-down :which-key "go down")
"w k" '(windmove-up :which-key "go up")
"w l" '(windmove-right :which-key "go right")
;; Toggles
"t" '(:ignore t :which-key "toggle")
"t d" '(my/load-dark-theme :which-key "dark theme")
"t l" '(my/load-light-theme :which-key "light theme")
"t T" '(consult-theme :which-key "browse themes")
"t n" '(display-line-numbers-mode :which-key "line numbers")
"t w" '(whitespace-mode :which-key "whitespace")
"t f" '(display-fill-column-indicator-mode :which-key "fill column")
"t v" '(visual-line-mode :which-key "word wrap")
;; Help
"h" '(:ignore t :which-key "help")
"h k" '(describe-key :which-key "describe key")
"h f" '(describe-function :which-key "describe function")
"h v" '(describe-variable :which-key "describe variable")
"h m" '(describe-mode :which-key "describe mode")
"h p" '(describe-package :which-key "describe package")
"h i" '(info :which-key "info manual")
"h a" '(apropos :which-key "search all help")
"h b" '(embark-bindings :which-key "all keybindings")
;; Org
"o" '(:ignore t :which-key "org")
"o a" '(org-agenda :which-key "agenda")
"o c" '(org-capture :which-key "capture")
"o l" '(org-store-link :which-key "store link")
"o t" '(org-todo-list :which-key "global todo list")
;; Evaluate elisp
"e" '(:ignore t :which-key "eval")
"e b" '(eval-buffer :which-key "eval buffer")
"e r" '(eval-region :which-key "eval region")
"e e" '(eval-last-sexp :which-key "eval last sexp")
;; Quit
"q" '(:ignore t :which-key "quit")
"q q" '(save-buffers-kill-terminal :which-key "quit emacs")
"q r" '(restart-emacs :which-key "restart emacs")
;; Packages
"P" '(:ignore t :which-key "packages")
"P r" '(package-refresh-contents :which-key "refresh archives")
"P u" '(package-upgrade-all :which-key "upgrade all")
"P l" '(package-list-packages :which-key "list packages")))
;; Show available keys after pressing a prefix
(use-package which-key
:ensure nil
:diminish
:config
(which-key-mode))
(use-package diminish)
;; Fast window switching with ace-window (M-o)
(use-package ace-window
:bind (("M-o" . ace-window))
:custom
(aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
(aw-scope 'frame))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Appearance ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Font
(set-face-attribute 'default nil :family "Fira Code" :height 120)
;; Dark theme (Spacemacs-like)
(use-package doom-themes
:config
(load-theme 'doom-one t)
(doom-themes-visual-bell-config)
(doom-themes-org-config))
;; Light themes for daytime
(use-package ef-themes
:defer t)
;; Quick theme switching
(defun my/load-dark-theme ()
"Switch to dark theme."
(interactive)
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'doom-one t))
(defun my/load-light-theme ()
"Switch to light theme."
(interactive)
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'ef-light t))
;; Icons (run M-x nerd-icons-install-fonts on first launch)
(use-package nerd-icons)
;; Modeline
(use-package doom-modeline
:init (doom-modeline-mode 1)
:custom
(doom-modeline-height 35))
;; Font ligatures (Fira Code)
(use-package ligature
:config
(ligature-set-ligatures
'prog-mode
'("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\"
"{-" "::" ":::" ":=" "!!" "!=" "!==" "-}" "----" "-->" "->" "->>"
"-<" "-<<" "-~" "#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_("
".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*" "/**"
"/=" "/==" "/>" "//" "///" "&&" "||" "||=" "|=" "|>" "^=" "$>"
"++" "+++" "+>" "=:=" "==" "===" "==>" "=>" "=>>" "<="
"=<<" "=/=" ">-" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "<*"
"<*>" "<|" "<|>" "<$" "<$>" "<!--" "<-" "<--" "<->" "<+"
"<+>" "<=" "<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<"
"<~" "<~~" "</" "</>" "~@" "~-" "~>" "~~" "~~>" "%%"))
(global-ligature-mode t))
;; Colorful parentheses
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Completion Framework ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Vertical completion UI
(use-package vertico
:custom
(vertico-count 20)
(vertico-resize t)
:config
(vertico-mode))
;; Fuzzy/orderless matching
(use-package orderless
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
;; Enhanced commands (search, buffer switch, etc.)
(use-package consult
:bind (("C-x b" . consult-buffer)
("M-y" . consult-yank-pop)
("M-g g" . consult-goto-line)
("M-g M-g" . consult-goto-line)
("M-g i" . consult-imenu))
:hook (completion-list-mode . consult-preview-at-point-mode)
:init
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:config
(consult-customize
consult-theme :preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep consult-bookmark
consult-recent-file consult-xref
consult-source-bookmark consult-source-file-register
consult-source-recent-file consult-source-project-recent-file
:preview-key '(:debounce 0.4 any))
(setq consult-narrow-key "<"))
;; Annotations in minibuffer completions
(use-package marginalia
:init (marginalia-mode))
;; Context-dependent action palette (Tier 2)
(use-package embark
:bind (("C-." . embark-act) ; Pick context action on target at point / minibuffer
("M-." . embark-dwim) ; Do-what-I-mean default action on target
("C-h B" . embark-bindings)) ; Show keybindings for target / mode
:init
;; Replace standard prefix help (C-h after a prefix key) with Embark
(setq prefix-help-command #'embark-prefix-help-command)
:config
;; Hide mode line in Embark collect buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
(use-package embark-consult
:ensure t
:after (embark consult)
:hook (embark-collect-mode . consult-preview-at-point-mode))
;; Inline completion popup (replaces company-mode)
(use-package corfu
:custom
(corfu-auto t) ; show completions automatically
(corfu-auto-delay 0.1)
(corfu-cycle t) ; cycle through candidates
:init
(global-corfu-mode))
;; Extra completion sources for corfu
(use-package cape
:init
(add-hook 'completion-at-point-functions #'cape-dabbrev)
(add-hook 'completion-at-point-functions #'cape-file))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Development Tools ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Import PATH and environment from shell (needed for nvm, etc.)
(use-package exec-path-from-shell
:config
(when (memq window-system '(mac ns x pgtk))
(exec-path-from-shell-initialize)))
;; Tree-sitter grammar management
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:config
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
;; LSP via built-in eglot
(use-package eglot
:ensure nil
:hook ((go-ts-mode rust-ts-mode python-ts-mode python-mode
js-ts-mode typescript-ts-mode zig-mode) . eglot-ensure)
:config
(add-to-list 'eglot-server-programs '(odin-mode . ("ols")))
(setq eglot-autoshutdown t)) ; shut down server when last buffer is closed
;; Git porcelain
(use-package magit
:defer t)
;; Git gutter indicators
(use-package diff-hl
:config
(global-diff-hl-mode)
(add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh)
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Clojure + CIDER ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package clojure-mode
:mode (("\\.clj\\'" . clojure-mode)
("\\.edn\\'" . clojure-mode)
("\\.cljs\\'" . clojurescript-mode)
("\\.cljc\\'" . clojurec-mode)))
(use-package cider
:defer t
:diminish subword-mode
:custom
(cider-repl-pop-to-buffer-on-connect t)
(cider-show-error-buffer t)
(cider-auto-select-error-buffer t))
(use-package clj-deps-new
:defer t)
;; Structural editing for Lisps — paredit handles parens, so disable electric-pair
(use-package paredit
:hook ((clojure-mode . paredit-mode)
(clojurescript-mode . paredit-mode)
(clojurec-mode . paredit-mode)
(cider-repl-mode . paredit-mode)
(emacs-lisp-mode . paredit-mode)
(lisp-interaction-mode . paredit-mode))
:config
(add-hook 'paredit-mode-hook
(lambda () (electric-pair-local-mode -1))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Languages ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Go
(use-package go-ts-mode
:ensure nil
:mode "\\.go\\'")
(use-package flymake-golangci
:after go-ts-mode
:hook (go-ts-mode . flymake-golangci-load))
;; Odin
(use-package odin-mode
:vc (:url "https://github.com/mattt-b/odin-mode")
:defer t
:hook (odin-mode . eglot-ensure))
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs '(odin-mode . ("ols"))))
;; Zig
(use-package zig-mode
:defer t)
;; Racket
(use-package racket-mode
:defer t)
(use-package geiser-racket
:defer t)
;; Web (HTML, JSX, TSX)
(use-package web-mode
:mode ("\\.html\\'" "\\.jsx\\'" "\\.tsx\\'"))
;; Markdown
(use-package markdown-mode
:mode ("\\.md\\'" ("README\\.md\\'" . gfm-mode))
:custom
(markdown-command "multimarkdown"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Org Mode ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package org
:ensure nil ; built-in
:custom
(org-directory "~/org")
(org-agenda-files '("~/org"))
(org-startup-indented t)
(org-hide-emphasis-markers t)
(org-return-follows-link t)
:config
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/org/inbox.org" "Tasks")
"* TODO %?\n %i\n %a")
("n" "Note" entry (file+headline "~/org/inbox.org" "Notes")
"* %?\n %i\n %a"))))
;; Pretty org headers, bullets, tables
(use-package org-modern
:hook (org-mode . org-modern-mode))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Project Management ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package project
:ensure nil
:config
;; Automatically remember the project when you open any file in it
(defun my-project-remember-current ()
(when-let ((pr (project-current)))
(project-remember-project pr)))
(add-hook 'find-file-hook #'my-project-remember-current))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dired ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package dired
:ensure nil
:custom
;; Always copy/delete recursively
(dired-recursive-copies 'always)
(dired-recursive-deletes 'top)
;; Quickly copy/move file in dired to the other split window
(dired-dwim-target t)
:hook
;; Hide file details by default for a cleaner workspace (press '(' to toggle)
(dired-mode . dired-hide-details-mode))
;; Add beautiful icons to dired
(use-package nerd-icons-dired
:hook
(dired-mode . nerd-icons-dired-mode))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Load custom.el ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when (file-exists-p custom-file)
(load custom-file))
;;; init.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment