From f3f9f56e416b816fd18da10e897bcf7a5492e079 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Wed, 28 Oct 2026 08:03:32 +0200 Subject: [PATCH] Overall cleanup for emacs, trimmed alot to get to basics. --- config/emacs/init.el | 182 +++++++----------------------------- config/emacs/modules/dev.el | 14 +-- config/emacs/modules/git.el | 40 +++----- config/emacs/modules/org.el | 15 +-- 4 files changed, 53 insertions(+), 198 deletions(-) diff --git a/config/emacs/init.el b/config/emacs/init.el index ae0475c..3606d44 100644 --- a/config/emacs/init.el +++ b/config/emacs/init.el @@ -1,53 +1,38 @@ -;;; init.el --- Minimal Emacs: built-ins + evil + consult -*- lexical-binding: t; -*- -;; Learning: F1 k KEY, F1 f FUNCTION, F1 v VARIABLE, F1 m (modes), F1 b (bindings). -;; C-h works too, except in normal/motion state where it moves to the window on the left. - +;;; init.el --- Minimal Emacs: built-ins + evil -*- lexical-binding: t; -*- +;; Learning: C-h k KEY, f FUNCTION, v VARIABLE, m (modes), b (bindings). ;;; Code: -;;;; 1. Emac setup, gc, files, packages +;;;; 1. Setup: gc, PATH, var/, packages (add-hook 'emacs-startup-hook - (lambda () (setq gc-cons-threshold (* 16 1024 1024)))) + (lambda () (setq gc-cons-threshold (* 16 1024 1024)))) (dolist (bin (list (expand-file-name "~/.local/bin") (expand-file-name "~/.go/bin"))) (add-to-list 'exec-path bin) (setenv "PATH" (concat bin path-separator (getenv "PATH")))) -;; Add the themes directory to the load path (add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory)) -;; all the emacs runtime files live in var/. -;; early-init.el redirects eln-cache and elpa. +;; All runtime files live in var/. early-init.el redirects eln-cache and elpa. (defvar my/var (locate-user-emacs-file "var/")) (make-directory (concat my/var "transient/") t) -(setq savehist-file (concat my/var "history") - save-place-file (concat my/var "places.eld") - recentf-save-file (concat my/var "recentf.eld") - project-list-file (concat my/var "projects.eld") - transient-history-file (concat my/var "transient/history.el") - transient-levels-file (concat my/var "transient/levels.el") - transient-values-file (concat my/var "transient/values.el")) +(setq savehist-file (concat my/var "history") + save-place-file (concat my/var "places.eld") + project-list-file (concat my/var "projects.eld") + transient-history-file (concat my/var "transient/history.el") + transient-levels-file (concat my/var "transient/levels.el") + transient-values-file (concat my/var "transient/values.el")) -;; Custom output goes to its own file, not here. +;; Customize output goes to its own file. (setq custom-file (expand-file-name "var/custom.el" user-emacs-directory)) (load custom-file 'noerror 'nomessage) -;; No session manager save: stops the empty session.* files. -(add-hook 'emacs-save-session-functions #'always) - -;; Package GNU, NonGNU are built in melpa additional lowest priority. -(require 'package) -(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) -(setq package-archive-priorities '(("gnu" . 3) ("nongnu" . 2) ("melpa" . 1))) -(package-initialize) - +;; Only GNU and NonGNU ELPA (defaults). package-initialize runs automatically. (require 'use-package) (setq use-package-always-ensure t) -;;;; 2. Ui settings, theme setup and fonts +;;;; 2. UI, theme, fonts +;; Menu/tool/scroll bars are removed in early-init.el. (add-to-list 'default-frame-alist '(fullscreen . maximized)) -(menu-bar-mode -1) -(tool-bar-mode -1) -(scroll-bar-mode -1) (blink-cursor-mode -1) (setq inhibit-startup-screen t @@ -65,10 +50,9 @@ (electric-pair-mode 1) (which-key-mode 1) -;; Load the compline theme (load-theme 'minimal t) -;; set mode line at the top of each window +;; Mode line at the top of each window. (setq-default header-line-format mode-line-format mode-line-format nil) (set-face-attribute 'default nil :family "JetBrainsMono Nerd Font" :height 120) @@ -77,7 +61,10 @@ ;; Command launcher. (keymap-global-set "C-S-p" #'execute-extended-command) -;; Escape behaves like C-g +;; Full buffer list. +(keymap-global-set "C-l" #'ibuffer) + +;; Escape behaves like C-g. (keymap-global-set "" #'keyboard-quit) (keymap-set minibuffer-local-map "" #'abort-minibuffers) @@ -91,18 +78,15 @@ (save-place-mode 1) (savehist-mode 1) -(recentf-mode 1) (global-auto-revert-mode 1) ;;;; 4. Completion -;; C-n/C-p navigates up and down, section 5 stops evil from overrriding -(use-package vertico - :init - (vertico-mode 1) - :custom - (vertico-count 15)) +;; Built-in vertical minibuffer completion with flex matching. +;; RET picks the highlighted candidate, C-j submits the typed text as-is. +(fido-vertical-mode 1) -(setq completion-styles '(basic partial-completion flex) +(setq icomplete-prospects-height 15 + completion-styles '(basic partial-completion flex) completion-ignore-case t read-buffer-completion-ignore-case t read-file-name-completion-ignore-case t @@ -110,94 +94,8 @@ isearch-lazy-count t xref-search-program 'ripgrep) -(use-package vertico-posframe - :after vertico - :custom - (vertico-posframe-poshandler #'posframe-poshandler-frame-center) - :config - (vertico-posframe-mode 1)) - -;;;; 5. Evil -(defvar evil-mode-buffers nil) - -(defun my/insert-tab () - "Insert a literal tab character." - (interactive) - (insert "\t")) - -(use-package evil - :init - (setq evil-want-C-u-scroll t - evil-undo-system 'undo-redo - evil-want-keybinding nil) - :config - (evil-mode 1) - - (evil-define-key 'insert 'global - (kbd "TAB") #'my/insert-tab - (kbd "C-SPC") #'completion-at-point) - - ;; C-p and C-f are assigned to Consult below, C-m to ibuffer. - (evil-define-key '(normal motion) 'global - (kbd "C-e") #'dired-jump)) - -(use-package evil-collection - :after evil - :custom - ;; Don't add its global [b ]b [e ]e ... bindings. - (evil-collection-want-unimpaired-p nil) - :config - (evil-collection-init '(info ibuffer))) - -;; Minibuffer. Vertico -(with-eval-after-load 'vertico - (evil-define-key '(insert normal) vertico-map - (kbd "C-n") #'vertico-next - (kbd "C-p") #'vertico-previous - (kbd "TAB") #'vertico-insert - (kbd "") #'vertico-insert)) - -(evil-define-key '(insert normal) minibuffer-local-map - (kbd "") #'abort-minibuffers) - -;; Result buffers: hjkl motions and RET to jump to a result. -(dolist (m '(occur-mode grep-mode xref--xref-buffer-mode)) - (evil-set-initial-state m 'motion)) - -(with-eval-after-load 'compile - (evil-define-key 'motion compilation-mode-map - (kbd "RET") #'compile-goto-error)) - -(with-eval-after-load 'grep - (evil-define-key 'motion grep-mode-map - (kbd "RET") #'compile-goto-error)) - -(with-eval-after-load 'replace - (evil-define-key 'motion occur-mode-map - (kbd "RET") #'occur-mode-goto-occurrence)) - -(with-eval-after-load 'xref - (evil-define-key 'motion xref--xref-buffer-mode-map - (kbd "RET") #'xref-goto-xref)) - -;;;; 6. Consult -;; Requires the external `fd` and `rg` executables. Both honour .ignore files, -;; so keep excludes (node_modules, elpa, ...) in ~/.ignore or per-project .ignore. -;; Searches start at the project root when there is one, else the current directory. -(use-package consult - :config - ;; Don't re-run the preview on every keystroke while typing a search. - (consult-customize consult-ripgrep - :preview-key '(:debounce 0.4 any))) - -;; Bind immediately, without waiting for consult to load. -;; C-m opens the full ibuffer list (evil-collection provides its navigation). -(evil-define-key '(normal motion) 'global - (kbd "C-p") #'consult-fd - (kbd "C-f") #'consult-ripgrep - (kbd "C-m") #'ibuffer) - -;;;; 7. Dired +;;;; 5. Dired +;; Evil keys for dired live in modules/evil.el. (setq dired-dwim-target t dired-kill-when-opening-new-dired-buffer t dired-listing-switches "-agho --group-directories-first" @@ -207,29 +105,15 @@ (with-eval-after-load 'dired (require 'dired-x) (setq dired-omit-files "\\`\\.") - (add-hook 'dired-mode-hook #'dired-omit-mode) - (evil-set-initial-state 'dired-mode 'motion) - - (evil-define-key 'motion dired-mode-map - "h" #'dired-up-directory - "l" #'dired-find-file - "." #'dired-omit-mode - (kbd "RET") #'dired-find-file)) + (add-hook 'dired-mode-hook #'dired-omit-mode)) ;;;; Core config ends here. ;;;; ----------------------------------------------------------------- -;;;; 8. Modules - additional functionality outside of the core init.el - -;; Setup for orgmode -(load (locate-user-emacs-file "modules/org.el") nil 'nomessage) - -;; Magit and the :git command live in modules/git.el. -(load (locate-user-emacs-file "modules/git.el") nil 'nomessage) - -;; Setup for personal build commands and system. +;;;; 6. Modules. evil first: later modules may call evil-define-key. +(load (locate-user-emacs-file "modules/evil.el") nil 'nomessage) +(load (locate-user-emacs-file "modules/org.el") nil 'nomessage) +(load (locate-user-emacs-file "modules/git.el") nil 'nomessage) (load (locate-user-emacs-file "modules/build.el") nil 'nomessage) - -;; Setup for dev languages, modes, lsp and lsp keybinds. -(load (locate-user-emacs-file "modules/dev.el") nil 'nomessage) +(load (locate-user-emacs-file "modules/dev.el") nil 'nomessage) ;;; init.el ends here diff --git a/config/emacs/modules/dev.el b/config/emacs/modules/dev.el index fef8fa9..3be73b5 100644 --- a/config/emacs/modules/dev.el +++ b/config/emacs/modules/dev.el @@ -34,6 +34,9 @@ :mode "\\.odin\\'" :hook (odin-mode . eglot-ensure)) +;; OLS built-in definitions. +(setenv "OLS_BUILTIN_FOLDER" "/home/jason/ThirdParty/ols/builtin") + ;;;; Go ;; Emacs started from the desktop doesn't inherit fish env. (dolist (d '("/usr/local/go/bin" "/home/jason/.go/bin")) @@ -77,17 +80,6 @@ (:name "vendor" :path "/home/jason/.odin/vendor")]))))) -;; OLS built-in definitions. -(setenv "OLS_BUILTIN_FOLDER" "/home/jason/ThirdParty/ols/builtin") - -;;;; Code navigation -;; Vim-style code navigation. -(evil-define-key '(normal motion) 'global - "gd" #'xref-find-definitions - "gD" #'xref-find-references - "K" #'eldoc - (kbd "C-t") #'xref-go-back) - ;; ESC closes any open eldoc window. (defun my/eldoc-close (&rest _) "Quit every window showing an *eldoc* buffer." diff --git a/config/emacs/modules/git.el b/config/emacs/modules/git.el index c868ecf..b9e2fb0 100644 --- a/config/emacs/modules/git.el +++ b/config/emacs/modules/git.el @@ -1,19 +1,18 @@ -;;; git.el --- Magit, set up for Evil -*- lexical-binding: t; -*- +;;; git.el --- Magit, minimal Evil -*- lexical-binding: t; -*- ;;; Commentary: -;; Loaded from init.el, which must set `evil-want-keybinding' to nil before -;; Evil loads (Evil Collection needs it). +;; Loaded from init.el after evil.el. ;; ;; :git Magit status for the current repo, full frame. ;; q puts your previous window layout back. ;; :git ARGS Run `git ARGS' from the repo root, e.g. :git log --oneline ;; -;; In Magit (Evil Collection layout): -;; j/k move, TAB folds, s stage, u unstage, x discard, c c commit, -;; p push, F pull, l log, d diff, b branch, z stash, gr refresh, q quit, -;; ? lists every command. -;; Commit message: opens in insert state; ZZ or C-c C-c commits, -;; ZQ or C-c C-k cancels. -;; Ctrl+hjkl, C-f and C-b keep their global meaning in Magit buffers. +;; Magit buffers use Evil's emacs state, so every Magit key is native +;; (s stage, u unstage, c c commit, P push, F pull, l log, d diff, b branch, +;; z stash, g refresh, n/p sections, TAB folds, ? lists every command), +;; except j/k, which move by line. That shadows Magit's own j (jump to +;; section) and k (discard): use M-x magit-status-jump / magit-discard. +;; If ESC drops you into normal state, C-z toggles emacs state back. +;; Commit message: opens in insert state; C-c C-c commits, C-c C-k cancels. ;;; Code: (use-package magit @@ -23,22 +22,13 @@ (magit-display-buffer-function #'magit-display-buffer-fullframe-status-v1) (magit-bury-buffer-function #'magit-restore-window-configuration)) -;; Vim-style keys for Magit, its section folding, and the commit message buffer. -;; (magit magit-submodule) is the form Evil Collection's own default list uses. -(with-eval-after-load 'evil-collection - ;; Evil Collection puts section jumps on C-j/C-k and page scrolling on C-f/C-b. - ;; Unbind them so your window and Consult keys show through. Sibling sections - ;; are still on ] and [, and scrolling on C-d/C-u. - (add-hook 'evil-collection-setup-hook - (lambda (mode &rest _) - (when (eq mode 'magit) - (evil-define-key 'normal magit-mode-map - (kbd "C-j") nil - (kbd "C-k") nil - (kbd "C-f") nil - (kbd "C-b") nil)))) +;; All Magit buffers derive from magit-mode. +(evil-set-initial-state 'magit-mode 'emacs) - (evil-collection-init '((magit magit-submodule) magit-section with-editor))) +(with-eval-after-load 'magit-mode + (evil-define-key 'emacs magit-mode-map + "j" #'next-line + "k" #'previous-line)) ;; Commit messages start in insert state. Added after git-commit loads so its ;; default hook functions are kept. diff --git a/config/emacs/modules/org.el b/config/emacs/modules/org.el index 04a0309..ea5beed 100644 --- a/config/emacs/modules/org.el +++ b/config/emacs/modules/org.el @@ -2,8 +2,8 @@ ;;; Code: ;; Styled stars, bullets, tags, tables and blocks. -(use-package org-modern - :hook (org-mode . org-modern-mode)) +;; (use-package org-modern +;; :hook (org-mode . org-modern-mode)) (setq org-directory "~/Projects/notebook") (setq org-startup-indented t ; visual indent per level, no real spaces @@ -29,17 +29,6 @@ (add-hook 'org-mode-hook #'visual-line-mode) ; wrap at window edge (add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1))) ; prose reads better without -;; doom-themes' own Org fontification fixes (blocks, headings). -(doom-themes-org-config) - -;; Heading sizes; 'user survives theme reloads, same as in init.el. -(doom-themes-set-faces 'user - '(org-document-title :height 1.3 :weight 'bold) - '(org-level-1 :height 1.2 :weight 'bold) - '(org-level-2 :height 1.15 :weight 'bold) - '(org-level-3 :height 1.1 :weight 'bold) - '(org-level-4 :height 1.0 :weight 'bold)) - (defun my/notes-index () "Open the notes index." (interactive)