Created
July 17, 2026 11:44
-
-
Save Tracnac/ae6a09851e95af27b0a805d28e458ae9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;; 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