Skip to content

Instantly share code, notes, and snippets.

@Tracnac
Created July 17, 2026 11:44
Show Gist options
  • Select an option

  • Save Tracnac/ae6a09851e95af27b0a805d28e458ae9 to your computer and use it in GitHub Desktop.

Select an option

Save Tracnac/ae6a09851e95af27b0a805d28e458ae9 to your computer and use it in GitHub Desktop.
;;; init.el --- A small, sane Emacs configuration -*- lexical-binding: t; -*-
;;; Commentary:
;; This configuration deliberately starts with Emacs' built-in features. It is
;; fast, portable, and does not download packages while Emacs is starting.
;;; Code:
;; Keep Custom's generated settings out of this file.
(setq custom-file (locate-user-emacs-file "custom.el"))
(when (file-exists-p custom-file)
(load custom-file nil 'nomessage))
;; Package sources. Install the selected extras with M-x
;; package-install-selected-packages. This file never downloads packages at
;; startup, so Emacs remains quick and works offline.
(require 'package)
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
(package-initialize)
(setq package-selected-packages '(catppuccin-theme nyan-mode change-inner vertico orderless consult ghostel corfu go-mode))
;; A quiet, focused interface.
(setq inhibit-startup-screen t
initial-scratch-message nil
ring-bell-function #'ignore
use-short-answers t
visible-bell nil
frame-title-format '(:eval (format "%s — Emacs" (buffer-name))))
;; Default size for the first GUI frame and every frame opened afterwards.
(dolist (setting '((width . 132) (height . 48)))
(add-to-list 'initial-frame-alist setting)
(add-to-list 'default-frame-alist setting))
;; French macOS layouts use right Option (normally called right Meta in Emacs)
;; to type characters such as @, #, {, [, and |. Leave it to macOS; left
;; Option remains Meta for Emacs commands.
(when (eq system-type 'darwin)
(setq ns-left-option-modifier 'meta
ns-right-option-modifier 'none))
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(column-number-mode 1)
(global-display-line-numbers-mode 1)
(global-hl-line-mode 1)
(show-paren-mode 1)
(pixel-scroll-precision-mode 1)
;; Use the installed IBM Plex Mono family throughout Emacs. The height is in
;; tenths of a point; change 140 to taste.
(dolist (face '(default fixed-pitch variable-pitch))
(set-face-attribute face nil :family "IBM Plex Mono" :height 140))
;; Text buffers read more naturally without line numbers or hard wrapping.
(dolist (hook '(text-mode-hook org-mode-hook))
(add-hook hook (lambda ()
(display-line-numbers-mode -1)
(visual-line-mode 1))))
;; Editing behavior.
(setq-default indent-tabs-mode nil
tab-width 4
fill-column 88
truncate-lines nil)
(delete-selection-mode 1)
(electric-pair-mode 1)
(electric-indent-mode 1)
(global-so-long-mode 1) ; Keep huge minified files responsive.
(cua-mode 1) ; C-c/C-x/C-v/C-z: copy/cut/paste/undo.
;; CUA remaps those commands to its own paste implementation. Keep C-v as
;; CUA paste, but let C-y and M-y use Emacs's real kill ring.
;; C-y pastes immediately; pressing C-y again cycles the just-pasted text
;; through older kill-ring entries. M-y continues to cycle in the same way.
(defun my/yank-cycle (arg)
"Yank, or cycle the previous yank through the kill ring."
(interactive "*P")
(if (memq last-command '(yank yank-pop))
(progn
(setq this-command 'yank-pop)
(yank-pop arg))
(setq this-command 'yank)
(yank arg)))
(global-set-key (kbd "C-y") #'my/yank-cycle)
(let ((cua-map (cdr (assq 'cua-mode cua--keymap-alist))))
(define-key cua-map [remap yank] nil)
(define-key cua-map [remap yank-pop] nil))
(global-set-key (kbd "<escape>") #'keyboard-quit)
;; Better completion in the minibuffer, built in since Emacs 28.
(setq completion-cycle-threshold 3
completions-detailed t
read-buffer-completion-ignore-case t
read-file-name-completion-ignore-case t)
;; Remember useful state between sessions.
(recentf-mode 1)
(save-place-mode 1)
(savehist-mode 1)
(setq recentf-max-saved-items 200
history-length 200)
;; Refresh files changed outside Emacs, without noisy confirmations.
(global-auto-revert-mode 1)
(setq auto-revert-verbose nil
auto-revert-use-notify nil)
;; Safer files: backups and auto-saves go in one place, rather than beside
;; project files. Emacs creates this directory if it does not exist.
(let ((state-dir (locate-user-emacs-file "var/")))
(make-directory state-dir t)
(setq backup-directory-alist `(("." . ,state-dir))
auto-save-file-name-transforms `((".*" ,state-dir t))
create-lockfiles nil))
;; Convenient window movement with Shift+arrow keys.
(windmove-default-keybindings)
(winner-mode 1) ; C-c left/right undoes/redoes layouts.
;; Catppuccin follows the macOS appearance: Latte for Light Mode and Mocha for
;; Dark Mode.
(if (package-installed-p 'catppuccin-theme)
(progn
(require 'catppuccin-theme)
(defun my/catppuccin-load-flavor (appearance)
"Load the Catppuccin flavor matching APPEARANCE."
(setq catppuccin-flavor (if (eq appearance 'dark) 'mocha 'latte))
(when (memq 'catppuccin custom-enabled-themes)
(disable-theme 'catppuccin))
(load-theme 'catppuccin t))
(defun my/catppuccin-system-appearance ()
"Return the current macOS appearance as `light' or `dark'."
(cond
((boundp 'ns-system-appearance) ns-system-appearance)
((fboundp 'mac-application-state)
(if (equal (plist-get (mac-application-state) :appearance)
"NSAppearanceNameDarkAqua")
'dark 'light))
((and (eq system-type 'darwin) (executable-find "defaults"))
(if (string-match-p "Dark"
(shell-command-to-string
"defaults read -g AppleInterfaceStyle 2>/dev/null"))
'dark 'light))
(t 'dark)))
(defun my/catppuccin-follow-system (&optional appearance)
"Apply Catppuccin for APPEARANCE, or the current system appearance."
(my/catppuccin-load-flavor
(or appearance (my/catppuccin-system-appearance))))
(my/catppuccin-follow-system)
(cond
;; Emacs Plus: hook receives `light' or `dark' as its argument.
((boundp 'ns-system-appearance-change-functions)
(add-hook 'ns-system-appearance-change-functions
#'my/catppuccin-follow-system))
;; Emacs Mac port: read the appearance from `mac-application-state'.
((boundp 'mac-effective-appearance-change-hook)
(add-hook 'mac-effective-appearance-change-hook
#'my/catppuccin-follow-system))
;; Standard Cocoa Emacs has no appearance-change hook. Check every
;; 30 seconds so scheduled system changes are still reflected.
((eq system-type 'darwin)
(run-at-time 30 30 #'my/catppuccin-follow-system))))
(load-theme 'modus-vivendi t))
(when (package-installed-p 'nyan-mode)
(require 'nyan-mode)
(nyan-mode 1))
;; Quickly select the surrounding syntactic unit, such as a quoted string or
;; parenthesized expression.
(when (package-installed-p 'change-inner)
(require 'change-inner)
(global-set-key (kbd "C-c i") #'change-inner)
(global-set-key (kbd "C-c o") #'change-outer))
;; Vertico replaces the built-in Fido UI once installed. Until then, Fido is
;; a capable fallback.
(if (package-installed-p 'vertico)
(progn
(require 'vertico)
(vertico-mode 1))
(fido-vertical-mode 1))
(when (package-installed-p 'orderless)
(require 'orderless)
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
(when (package-installed-p 'consult)
(require 'consult)
(global-set-key (kbd "C-x b") #'consult-buffer)
(global-set-key (kbd "C-s") #'consult-line)
(global-set-key (kbd "M-y") #'consult-yank-pop))
;; Ghostty-powered terminal emulator. Its native module downloads on first
;; use; start one with C-c t (or M-x ghostel).
(when (package-installed-p 'ghostel)
(require 'ghostel)
(global-set-key (kbd "C-c t") #'ghostel)
(add-hook 'ghostel-mode-hook
(lambda () (display-line-numbers-mode -1))))
;; In-buffer completion popup (works for both symbols and LSP completions).
(when (package-installed-p 'corfu)
(require 'corfu)
(global-corfu-mode 1)
(setq corfu-auto t
corfu-auto-delay 0.2
corfu-auto-prefix 2))
;; LSP support for C and Go, using Emacs' built-in client.
(require 'eglot)
(add-hook 'c-mode-hook #'eglot-ensure)
(add-hook 'c++-mode-hook #'eglot-ensure)
(add-hook 'go-mode-hook #'eglot-ensure) ; needs go-mode
(setq eglot-autoshutdown t) ; kill server when last buffer closes
;; Local customizations belong here, so this starter stays easy to update.
(setq user-full-name "Tracnac"
user-mail-address "tracnac@github.com")
(provide 'init)
;;; init.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment