This commit is contained in:
2026-03-05 00:17:32 +01:00
commit 2234090b44
5 changed files with 4067 additions and 0 deletions

2802
README.md Normal file

File diff suppressed because it is too large Load Diff

463
early-init.el Normal file
View File

@@ -0,0 +1,463 @@
;;; early-init.el --- Early Init -*- lexical-binding: t; -*-
;; Author: James Cherti <https://www.jamescherti.com/contact/>
;; URL: https://github.com/jamescherti/minimal-emacs.d
;; Package-Requires: ((emacs "29.1"))
;; Keywords: maint
;; Version: 1.3.1
;; SPDX-License-Identifier: GPL-3.0-or-later
;;; Commentary:
;; The minimal-emacs.d project is a lightweight and optimized Emacs base
;; (init.el and early-init.el) that gives you full control over your
;; configuration. It provides better defaults, an optimized startup, and a clean
;; foundation for building your own vanilla Emacs setup.
;;
;; Building the minimal-emacs.d init.el and early-init.el was the result of
;; extensive research and testing to fine-tune the best parameters and
;; optimizations for an Emacs configuration.
;;
;; Do not modify this file; instead, modify pre-early-init.el or
;; post-early-init.el.
;;; Code:
;;; Internal variables
;; Backup of `gc-cons-threshold' and `gc-cons-percentage' before startup.
(defvar minimal-emacs--backup-gc-cons-threshold gc-cons-threshold)
(defvar minimal-emacs--backup-gc-cons-percentage gc-cons-percentage)
;; Temporarily raise the garbage collection threshold to its maximum value.
;; It will be restored later to controlled values.
(setq gc-cons-threshold most-positive-fixnum)
(setq gc-cons-percentage 1.0)
;;; Variables
(defvar minimal-emacs-ui-features '()
"List of user interface features to enable in minimal Emacs setup.
This variable holds a list of Emacs UI features that can be enabled:
- context-menu (Enables the context menu in graphical environments.)
- tool-bar (Enables the tool bar in graphical environments.)
- menu-bar (Enables the menu bar in graphical environments.)
- dialogs (Enables both file dialogs and dialog boxes.)
- tooltips (Enables tooltips.)")
(defvar minimal-emacs-frame-title-format "%b Emacs"
"Template for displaying the title bar of visible and iconified frame.")
(defvar minimal-emacs-debug (bound-and-true-p init-file-debug)
"Non-nil to enable debug.")
(defvar minimal-emacs-optimize-startup-gc t
"If non-nil, increase `gc-cons-threshold' during startup to reduce pauses.
After Emacs finishes loading, `gc-cons-threshold' is restored to the value
stored in `minimal-emacs-gc-cons-threshold'.")
(defvar minimal-emacs-gc-cons-threshold (* 32 1024 1024)
"Value to which `gc-cons-threshold' is set after Emacs startup.
Ignored if `minimal-emacs-optimize-startup-gc' is nil.")
(defvar minimal-emacs-gc-cons-percentage gc-cons-percentage
"Value to which `gc-cons-percentage' is set after Emacs startup.
Ignored if `minimal-emacs-optimize-startup-gc' is nil.")
(defvar minimal-emacs-gc-cons-threshold-restore-delay nil
"Number of seconds to wait before restoring `gc-cons-threshold'.")
(defvar minimal-emacs-optimize-file-name-handler-alist t
"Enable optimization of `file-name-handler-alist'.
When non-nil, this variable activates optimizations to reduce file name handler
lookups during Emacs startup.")
(defvar minimal-emacs-disable-mode-line-during-startup t
"Disable the mode line during startup.
This reduces visual clutter and slightly enhances startup performance. The
tradeoff is that the mode line is hidden during the startup phase.")
(defvar minimal-emacs-package-initialize-and-refresh t
"Whether to automatically initialize and refresh packages.
When set to non-nil, Emacs will automatically call `package-initialize' and
`package-refresh-contents' to set up and update the package system.")
(defvar minimal-emacs-inhibit-redisplay-during-startup nil
"Suppress redisplay during startup to improve performance.
This prevents visual updates while Emacs initializes. The tradeoff is that you
won't see the progress or activities during the startup process.")
(defvar minimal-emacs-inhibit-message-during-startup nil
"Suppress startup messages for a cleaner experience.
This slightly enhances performance. The tradeoff is that you won't be informed
of the progress or any relevant activities during startup.")
(defvar minimal-emacs-user-directory user-emacs-directory
"Directory beneath minimal-emacs.d files are placed.
Note that this should end with a directory separator.")
;;; Load pre-early-init.el
;; Prefer loading newer compiled files
(setq load-prefer-newer t)
(when minimal-emacs-debug
(setq debug-on-error minimal-emacs-debug))
(defvar minimal-emacs--success nil)
(defun minimal-emacs--check-success ()
"Verify that the Emacs configuration has loaded successfully."
(unless minimal-emacs--success
(cond
((or (file-exists-p (expand-file-name "~/.emacs.el"))
(file-exists-p (expand-file-name "~/.emacs")))
(error "Emacs ignored loading 'init.el'. Please ensure that files such as ~/.emacs or ~/.emacs.el do not exist, as they may be preventing Emacs from loading the 'init.el' file"))
(t
(error "Configuration error. Debug by starting Emacs with: emacs --debug-init")))))
(add-hook 'emacs-startup-hook #'minimal-emacs--check-success 102)
(defvar minimal-emacs-load-compiled-init-files nil
"If non-nil, attempt to load byte-compiled .elc for init files.
This will enable minimal-emacs to load byte-compiled or possibly native-compiled
init files for the following initialization files: pre-init.el, post-init.el,
pre-early-init.el, and post-early-init.el.")
(defun minimal-emacs--remove-el-file-suffix (filename)
"Remove the Elisp file suffix from FILENAME and return it (.el, .el.gz...)."
(let ((suffixes (mapcar (lambda (ext) (concat ".el" ext))
load-file-rep-suffixes)))
(catch 'done
(dolist (suffix suffixes filename)
(when (string-suffix-p suffix filename)
(setq filename (substring filename 0 (- (length suffix))))
(throw 'done t))))
filename))
(defun minimal-emacs-load-user-init (filename)
"Execute a file of Lisp code named FILENAME."
(let ((init-file (expand-file-name filename
minimal-emacs-user-directory)))
(if (not minimal-emacs-load-compiled-init-files)
(load init-file :no-error (not minimal-emacs-debug) :nosuffix)
;; Remove the file suffix (.el, .el.gz, etc.) to let the `load' function
;; select between .el and .elc files.
(setq init-file (minimal-emacs--remove-el-file-suffix init-file))
(load init-file :no-error (not minimal-emacs-debug)))))
(minimal-emacs-load-user-init "pre-early-init.el")
(setq custom-theme-directory
(expand-file-name "themes/" minimal-emacs-user-directory))
(setq custom-file (expand-file-name "custom.el" minimal-emacs-user-directory))
;;; Garbage collection
;; Garbage collection significantly affects startup times. This setting delays
;; garbage collection during startup but will be reset later.
(defun minimal-emacs--restore-gc-values ()
"Restore garbage collection values to minimal-emacs.d values."
(setq gc-cons-threshold minimal-emacs-gc-cons-threshold)
(setq gc-cons-percentage minimal-emacs-gc-cons-percentage))
(defun minimal-emacs--restore-gc ()
"Restore garbage collection settings."
(if (bound-and-true-p minimal-emacs-gc-cons-threshold-restore-delay)
;; Defer garbage collection during initialization to avoid 2 collections.
(run-with-timer minimal-emacs-gc-cons-threshold-restore-delay nil
#'minimal-emacs--restore-gc-values)
(minimal-emacs--restore-gc-values)))
(if minimal-emacs-optimize-startup-gc
;; `gc-cons-threshold' is managed by minimal-emacs.d
(add-hook 'emacs-startup-hook #'minimal-emacs--restore-gc 105)
;; gc-cons-threshold is not managed by minimal-emacs.d.
(when (= gc-cons-threshold most-positive-fixnum)
(setq gc-cons-threshold minimal-emacs--backup-gc-cons-threshold)
(setq gc-cons-percentage minimal-emacs--backup-gc-cons-percentage)))
;;; Native compilation and Byte compilation
(unless (and (featurep 'native-compile)
(fboundp 'native-comp-available-p)
(native-comp-available-p))
;; Deactivate the `native-compile' feature if it is not available
(setq features (delq 'native-compile features)))
(setq native-comp-warning-on-missing-source minimal-emacs-debug
native-comp-async-report-warnings-errors (or minimal-emacs-debug 'silent))
(setq jka-compr-verbose minimal-emacs-debug)
(setq byte-compile-warnings minimal-emacs-debug
byte-compile-verbose minimal-emacs-debug)
;;; Miscellaneous
(set-language-environment "UTF-8")
;; Increase how much is read from processes in a single chunk
(setq read-process-output-max (* 2 1024 1024)) ; 1024kb
(setq process-adaptive-read-buffering nil)
;; Don't ping things that look like domain names.
(setq ffap-machine-p-known 'reject)
(setq warning-minimum-level (if minimal-emacs-debug :warning :error))
(setq warning-suppress-types '((lexical-binding)))
(when minimal-emacs-debug
(setq message-log-max 16384))
;; In PGTK, this timeout introduces latency. Reducing it from the default 0.1
;; improves responsiveness of childframes and related packages.
(when (boundp 'pgtk-wait-for-event-timeout)
(setq pgtk-wait-for-event-timeout 0.001))
;; Disable warnings from the legacy advice API. They aren't useful.
(setq ad-redefinition-action 'accept)
;;; Performance: Miscellaneous options
;; Font compacting can be very resource-intensive, especially when rendering
;; icon fonts on Windows. This will increase memory usage.
(setq inhibit-compacting-font-caches t)
(when (not noninteractive)
;; Resizing the Emacs frame can be costly when changing the font. Disable this
;; to improve startup times with fonts larger than the system default.
(setq frame-resize-pixelwise t)
;; Without this, Emacs will try to resize itself to a specific column size
(setq frame-inhibit-implied-resize t)
;; A second, case-insensitive pass over `auto-mode-alist' is time wasted.
;; No second pass of case-insensitive search over auto-mode-alist.
(setq auto-mode-case-fold nil)
;; Reduce *Message* noise at startup. An empty scratch buffer (or the
;; dashboard) is more than enough, and faster to display.
(setq inhibit-startup-screen t
inhibit-startup-echo-area-message user-login-name)
(setq initial-buffer-choice nil
inhibit-startup-buffer-menu t
inhibit-x-resources t)
;; Disable bidirectional text scanning for a modest performance boost.
(setq-default bidi-display-reordering 'left-to-right
bidi-paragraph-direction 'left-to-right)
;; Give up some bidirectional functionality for slightly faster re-display.
(setq bidi-inhibit-bpa t)
;; Remove "For information about GNU Emacs..." message at startup
(advice-add 'display-startup-echo-area-message :override #'ignore)
;; Suppress the vanilla startup screen completely. We've disabled it with
;; `inhibit-startup-screen', but it would still initialize anyway.
(advice-add 'display-startup-screen :override #'ignore)
(unless minimal-emacs-debug
;; Unset command line options irrelevant to the current OS. These options
;; are still processed by `command-line-1` but have no effect.
(unless (eq system-type 'darwin)
(setq command-line-ns-option-alist nil))
(unless (memq initial-window-system '(x pgtk))
(setq command-line-x-option-alist nil))))
;;; Performance: File-name-handler-alist
(defvar minimal-emacs--old-file-name-handler-alist (default-toplevel-value
'file-name-handler-alist))
(defun minimal-emacs--respect-file-handlers (fn args-left)
"Respect file handlers.
FN is the function and ARGS-LEFT is the same argument as `command-line-1'.
Emacs processes command-line files very early in startup. These files may
include special paths like TRAMP paths, so restore `file-name-handler-alist' for
this stage of initialization."
(let ((file-name-handler-alist (if args-left
minimal-emacs--old-file-name-handler-alist
file-name-handler-alist)))
(funcall fn args-left)))
(defun minimal-emacs--restore-file-name-handler-alist ()
"Restore `file-name-handler-alist'."
(set-default-toplevel-value
'file-name-handler-alist
;; Merge instead of overwrite to preserve any changes made since startup.
(delete-dups (append file-name-handler-alist
minimal-emacs--old-file-name-handler-alist))))
(when (and minimal-emacs-optimize-file-name-handler-alist
(not minimal-emacs-debug))
;; Determine the state of bundled libraries using calc-loaddefs.el. If
;; compressed, retain the gzip handler in `file-name-handler-alist`. If
;; compiled or neither, omit the gzip handler during startup for improved
;; startup and package load time.
(set-default-toplevel-value
'file-name-handler-alist
(if (locate-file-internal "calc-loaddefs.el" load-path)
nil
(list (rassq 'jka-compr-handler
minimal-emacs--old-file-name-handler-alist))))
;; Ensure the new value persists through any current let-binding.
(put 'file-name-handler-alist 'initial-value
minimal-emacs--old-file-name-handler-alist)
;; Emacs processes command-line files very early in startup. These files may
;; include special paths TRAMP. Restore `file-name-handler-alist'.
(advice-add 'command-line-1 :around #'minimal-emacs--respect-file-handlers)
(add-hook 'emacs-startup-hook #'minimal-emacs--restore-file-name-handler-alist
101))
;;; Performance: Inhibit redisplay
(defun minimal-emacs--reset-inhibit-redisplay ()
"Reset inhibit redisplay."
(setq-default inhibit-redisplay nil)
(remove-hook 'post-command-hook #'minimal-emacs--reset-inhibit-redisplay))
(when (and minimal-emacs-inhibit-redisplay-during-startup
(not noninteractive)
(not minimal-emacs-debug))
;; Suppress redisplay and redraw during startup to avoid delays and
;; prevent flashing an unstyled Emacs frame.
(setq-default inhibit-redisplay t)
(add-hook 'post-command-hook #'minimal-emacs--reset-inhibit-redisplay -100))
;;; Performance: Inhibit message
(defun minimal-emacs--reset-inhibit-message ()
"Reset inhibit message."
(setq-default inhibit-message nil)
(remove-hook 'post-command-hook #'minimal-emacs--reset-inhibit-message))
(when (and minimal-emacs-inhibit-message-during-startup
(not noninteractive)
(not minimal-emacs-debug))
(setq-default inhibit-message t)
(add-hook 'post-command-hook #'minimal-emacs--reset-inhibit-message -100))
;;; Performance: Disable mode-line during startup
(when (and minimal-emacs-disable-mode-line-during-startup
(not noninteractive)
(not minimal-emacs-debug))
(put 'mode-line-format
'initial-value (default-toplevel-value 'mode-line-format))
(setq-default mode-line-format nil)
(dolist (buf (buffer-list))
(with-current-buffer buf
(setq mode-line-format nil))))
;;; Restore values
(defun minimal-emacs--startup-load-user-init-file (fn &rest args)
"Advice to reset `mode-line-format'. FN and ARGS are the function and args."
(unwind-protect
;; Start up as normal
(apply fn args)
;; If we don't undo inhibit-{message, redisplay} and there's an error, we'll
;; see nothing but a blank Emacs frame.
(when minimal-emacs-inhibit-message-during-startup
(setq-default inhibit-message nil))
(when minimal-emacs-inhibit-redisplay-during-startup
(setq-default inhibit-redisplay nil))
;; Restore the mode-line
(when minimal-emacs-disable-mode-line-during-startup
(unless (default-toplevel-value 'mode-line-format)
(setq-default mode-line-format (get 'mode-line-format
'initial-value))))))
(advice-add 'startup--load-user-init-file :around
#'minimal-emacs--startup-load-user-init-file)
;;; UI elements
(setq frame-title-format minimal-emacs-frame-title-format
icon-title-format minimal-emacs-frame-title-format)
;; Disable startup screens and messages
(setq inhibit-splash-screen t)
;; I intentionally avoid calling `menu-bar-mode', `tool-bar-mode', and
;; `scroll-bar-mode' because manipulating frame parameters can trigger or queue
;; a superfluous and potentially expensive frame redraw at startup, depending
;; on the window system. The variables must also be set to `nil' so users don't
;; have to call the functions twice to re-enable them.
(unless (memq 'menu-bar minimal-emacs-ui-features)
(push '(menu-bar-lines . 0) default-frame-alist)
(unless (memq window-system '(mac ns))
(setq menu-bar-mode nil)))
(defun minimal-emacs--setup-toolbar (&rest _)
"Setup the toolbar."
(when (fboundp 'tool-bar-setup)
(advice-remove 'tool-bar-setup #'ignore)
(when (bound-and-true-p tool-bar-mode)
(funcall 'tool-bar-setup))))
(unless noninteractive
(when (fboundp 'tool-bar-setup)
;; Temporarily override the tool-bar-setup function to prevent it from
;; running during the initial stages of startup
(advice-add 'tool-bar-setup :override #'ignore)
(advice-add 'startup--load-user-init-file :after
#'minimal-emacs--setup-toolbar)))
(unless (memq 'tool-bar minimal-emacs-ui-features)
(push '(tool-bar-lines . 0) default-frame-alist)
(setq tool-bar-mode nil))
(setq default-frame-scroll-bars 'right)
(push '(vertical-scroll-bars) default-frame-alist)
(push '(horizontal-scroll-bars) default-frame-alist)
(setq scroll-bar-mode nil)
(unless (memq 'tooltips minimal-emacs-ui-features)
(when (bound-and-true-p tooltip-mode)
(tooltip-mode -1)))
;; Disable GUIs because they are inconsistent across systems, desktop
;; environments, and themes, and they don't match the look of Emacs.
(unless (memq 'dialogs minimal-emacs-ui-features)
(setq use-file-dialog nil)
(setq use-dialog-box nil))
;;; Security
(setq gnutls-verify-error t) ; Prompts user if there are certificate issues
(setq tls-checktrust t) ; Ensure SSL/TLS connections undergo trust verification
(setq gnutls-min-prime-bits 3072) ; Stronger GnuTLS encryption
;; This results in a more compact output that emphasizes performance
(setq use-package-expand-minimally t)
(setq use-package-minimum-reported-time (if minimal-emacs-debug 0 0.1))
(setq use-package-verbose minimal-emacs-debug)
(setq use-package-always-ensure (not noninteractive))
(setq use-package-enable-imenu-support t)
;; package.el
(setq package-enable-at-startup nil) ; Let the init.el file handle this
(setq package-quickstart-file
(expand-file-name "package-quickstart.el" user-emacs-directory))
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa-stable" . "https://stable.melpa.org/packages/")))
(setq package-archive-priorities '(("gnu" . 99)
("nongnu" . 80)
("melpa" . 70)
("melpa-stable" . 50)))
;;; Load post-early-init.el
(minimal-emacs-load-user-init "post-early-init.el")
;; Local variables:
;; byte-compile-warnings: (not obsolete free-vars)
;; End:
;;; early-init.el ends here

573
init.el Normal file
View File

@@ -0,0 +1,573 @@
;;; init.el --- Init -*- lexical-binding: t; -*-
;; Author: James Cherti <https://www.jamescherti.com/contact/>
;; URL: https://github.com/jamescherti/minimal-emacs.d
;; Package-Requires: ((emacs "29.1"))
;; Keywords: maint
;; Version: 1.3.1
;; SPDX-License-Identifier: GPL-3.0-or-later
;;; Commentary:
;; The minimal-emacs.d project is a lightweight and optimized Emacs base
;; (init.el and early-init.el) that gives you full control over your
;; configuration. It provides better defaults, an optimized startup, and a clean
;; foundation for building your own vanilla Emacs setup.
;;
;; Building the minimal-emacs.d init.el and early-init.el was the result of
;; extensive research and testing to fine-tune the best parameters and
;; optimizations for an Emacs configuration.
;;
;; Do not modify this file; instead, modify pre-init.el or post-init.el.
;;; Code:
;;; Load pre-init.el
(if (fboundp 'minimal-emacs-load-user-init)
(minimal-emacs-load-user-init "pre-init.el")
(error "The early-init.el file failed to loaded"))
;;; Before package
;; The initial buffer is created during startup even in non-interactive
;; sessions, and its major mode is fully initialized. Modes like `text-mode',
;; `org-mode', or even the default `lisp-interaction-mode' load extra packages
;; and run hooks, which can slow down startup.
;;
;; Using `fundamental-mode' for the initial buffer to avoid unnecessary
;; startup overhead.
(setq initial-major-mode 'fundamental-mode
initial-scratch-message nil)
;; Set-language-environment sets default-input-method, which is unwanted.
(setq default-input-method nil)
;; Ask the user whether to terminate asynchronous compilations on exit.
;; This prevents native compilation from leaving temporary files in /tmp.
(setq native-comp-async-query-on-exit t)
;; Allow for shorter responses: "y" for yes and "n" for no.
(setq read-answer-short t)
(if (boundp 'use-short-answers)
(setq use-short-answers t)
(advice-add 'yes-or-no-p :override #'y-or-n-p))
;;; Undo/redo
(setq undo-limit (* 13 160000)
undo-strong-limit (* 13 240000)
undo-outer-limit (* 13 24000000))
;;; package.el
(when (and (bound-and-true-p minimal-emacs-package-initialize-and-refresh)
(not (bound-and-true-p byte-compile-current-file))
(not (or (fboundp 'straight-use-package)
(fboundp 'elpaca))))
;; Initialize and refresh package contents again if needed
(package-initialize)
(when (version< emacs-version "29.1")
(unless (package-installed-p 'use-package)
(unless package-archive-contents
(package-refresh-contents))
(package-install 'use-package)))
(require 'use-package))
;;; Minibuffer
(setq enable-recursive-minibuffers t) ; Allow nested minibuffers
;; Keep the cursor out of the read-only portions of the.minibuffer
(setq minibuffer-prompt-properties
'(read-only t intangible t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;;; Display and user interface
;; By default, Emacs "updates" its ui more often than it needs to
(setq which-func-update-delay 1.0)
(setq idle-update-delay which-func-update-delay) ;; Obsolete in >= 30.1
(defalias #'view-hello-file #'ignore) ; Never show the hello file
;; No beeping or blinking
(setq visible-bell nil)
(setq ring-bell-function #'ignore)
;; Position underlines at the descent line instead of the baseline.
(setq x-underline-at-descent-line t)
(setq truncate-string-ellipsis "")
(setq display-time-default-load-average nil) ; Omit load average
;;; Show-paren
(setq show-paren-delay 0.1
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t
show-paren-when-point-in-periphery t)
;;; Buffer management
(setq custom-buffer-done-kill t)
;; Disable auto-adding a new line at the bottom when scrolling.
(setq next-line-add-newlines nil)
;; This setting forces Emacs to save bookmarks immediately after each change.
;; Benefit: you never lose bookmarks if Emacs crashes.
(setq bookmark-save-flag 1)
(setq uniquify-buffer-name-style 'forward)
(setq remote-file-name-inhibit-cache 50)
;; Disable fontification during user input to reduce lag in large buffers.
;; Also helps marginally with scrolling performance.
(setq redisplay-skip-fontification-on-input t)
;;; Misc
(setq whitespace-line-column nil) ; Use the value of `fill-column'.
;; Disable truncation of printed s-expressions in the message buffer
(setq eval-expression-print-length nil
eval-expression-print-level nil)
;; This directs gpg-agent to use the minibuffer for passphrase entry
(setq epg-pinentry-mode 'loopback)
;; By default, Emacs stores sensitive authinfo credentials as unencrypted text
;; in your home directory. Use GPG to encrypt the authinfo file for enhanced
;; security.
(setq auth-sources (list "~/.authinfo.gpg"))
;;; `display-line-numbers-mode'
(setq-default display-line-numbers-width 3)
(setq-default display-line-numbers-widen t)
;;; imenu
;; Automatically rescan the buffer for Imenu entries when `imenu' is invoked
;; This ensures the index reflects recent edits.
(setq imenu-auto-rescan t)
;; Prevent truncation of long function names in `imenu' listings
(setq imenu-max-item-length 160)
;;; Tramp
(setq tramp-verbose 1)
(setq tramp-completion-reread-directory-timeout 50)
;;; Files
;; Delete by moving to trash in interactive mode
(setq delete-by-moving-to-trash (not noninteractive))
(setq remote-file-name-inhibit-delete-by-moving-to-trash t)
;; Ignoring this is acceptable since it will redirect to the buffer regardless.
(setq find-file-suppress-same-file-warnings t)
;; Resolve symlinks so that operations are conducted from the file's directory
(setq find-file-visit-truename t
vc-follow-symlinks t)
;; Prefer vertical splits over horizontal ones
(setq split-width-threshold 170
split-height-threshold nil)
;;; comint (general command interpreter in a window)
(setq ansi-color-for-comint-mode t
comint-prompt-read-only t
comint-buffer-maximum-size 4096)
;;; Compilation
(setq compilation-ask-about-save nil
compilation-always-kill t
compilation-scroll-output 'first-error)
;; Skip confirmation prompts when creating a new file or buffer
(setq confirm-nonexistent-file-or-buffer nil)
;;; Backup files
;; Avoid backups or lockfiles to prevent creating world-readable copies of files
(setq create-lockfiles nil)
(setq make-backup-files nil)
(setq backup-directory-alist
`(("." . ,(expand-file-name "backup" user-emacs-directory))))
(setq tramp-backup-directory-alist backup-directory-alist)
(setq backup-by-copying-when-linked t)
(setq backup-by-copying t) ; Backup by copying rather renaming
(setq delete-old-versions t) ; Delete excess backup versions silently
(setq version-control t) ; Use version numbers for backup files
(setq kept-new-versions 5)
(setq kept-old-versions 5)
;;; VC
(setq vc-git-print-log-follow t)
(setq vc-make-backup-files nil) ; Do not backup version controlled files
(setq vc-git-diff-switches '("--histogram")) ; Faster algorithm for diffing.
;;; Auto save
;; Enable auto-save to safeguard against crashes or data loss. The
;; `recover-file' or `recover-session' functions can be used to restore
;; auto-saved data.
(setq auto-save-default nil)
(setq auto-save-no-message t)
;; Do not auto-disable auto-save after deleting large chunks of
;; text.
(setq auto-save-include-big-deletions t)
(setq auto-save-list-file-prefix
(expand-file-name "autosave/" user-emacs-directory))
(setq tramp-auto-save-directory
(expand-file-name "tramp-autosave/" user-emacs-directory))
;; Auto save options
(setq kill-buffer-delete-auto-save-files t)
;; Remove duplicates from the kill ring to reduce clutter
(setq kill-do-not-save-duplicates t)
;;; Auto revert
;; Auto-revert in Emacs is a feature that automatically updates the contents of
;; a buffer to reflect changes made to the underlying file.
(setq revert-without-query (list ".") ; Do not prompt
auto-revert-stop-on-user-input nil
auto-revert-verbose t)
;; Revert other buffers (e.g, Dired)
(setq global-auto-revert-non-file-buffers t)
(setq global-auto-revert-ignore-modes '(Buffer-menu-mode)) ; Resolve issue #29
;;; recentf
;; `recentf' is an that maintains a list of recently accessed files.
(setq recentf-max-saved-items 300) ; default is 20
(setq recentf-max-menu-items 15)
(setq recentf-auto-cleanup 'mode)
(setq recentf-exclude nil)
;;; saveplace
;; Enables Emacs to remember the last location within a file upon reopening.
(setq save-place-file (expand-file-name "saveplace" user-emacs-directory))
(setq save-place-limit 600)
;;; savehist
;; `savehist-mode' is an Emacs feature that preserves the minibuffer history
;; between sessions.
(setq history-length 300)
(setq savehist-save-minibuffer-history t) ;; Default
(setq savehist-additional-variables
'(register-alist ; macros
mark-ring global-mark-ring ; marks
search-ring regexp-search-ring)) ; searches
;;; Frames and windows
;; However, do not resize windows pixelwise, as this can cause crashes in some
;; cases when resizing too many windows at once or rapidly.
(setq window-resize-pixelwise nil)
(setq resize-mini-windows 'grow-only)
;; The native border "uses" a pixel of the fringe on the rightmost
;; splits, whereas `window-divider-mode' does not.
(setq window-divider-default-bottom-width 1
window-divider-default-places t
window-divider-default-right-width 1)
;;; Scrolling
;; Enables faster scrolling. This may result in brief periods of inaccurate
;; syntax highlighting, which should quickly self-correct.
(setq fast-but-imprecise-scrolling t)
;; Move point to top/bottom of buffer before signaling a scrolling error.
(setq scroll-error-top-bottom t)
;; Keep screen position if scroll command moved it vertically out of the window.
(setq scroll-preserve-screen-position t)
;; Emacs recenters the window when the cursor moves past `scroll-conservatively'
;; lines beyond the window edge. A value over 101 disables recentering; the
;; default (0) is too eager. Here it is set to 20 for a balanced behavior.
(setq scroll-conservatively 20)
;; 1. Preventing automatic adjustments to `window-vscroll' for long lines.
;; 2. Resolving the issue of random half-screen jumps during scrolling.
(setq auto-window-vscroll nil)
;; Number of lines of margin at the top and bottom of a window.
(setq scroll-margin 0)
;; Number of lines of continuity when scrolling by screenfuls.
(setq next-screen-context-lines 0)
;; Horizontal scrolling
(setq hscroll-margin 2
hscroll-step 1)
;;; Mouse
(setq mouse-yank-at-point nil)
;; Emacs 29
(when (memq 'context-menu minimal-emacs-ui-features)
(when (and (display-graphic-p) (fboundp 'context-menu-mode))
(add-hook 'after-init-hook #'context-menu-mode)))
;;; Cursor
;; The blinking cursor is distracting and interferes with cursor settings in
;; some minor modes that try to change it buffer-locally (e.g., Treemacs).
(when (bound-and-true-p blink-cursor-mode)
(blink-cursor-mode -1))
;; Don't blink the paren matching the one at point, it's too distracting.
(setq blink-matching-paren nil)
;; Do not extend the cursor to fit wide characters
(setq x-stretch-cursor nil)
;; Reduce rendering/line scan work by not rendering cursors or regions in
;; non-focused windows.
(setq highlight-nonselected-windows nil)
;;; Text editing, indent, font, and formatting
;; Avoid automatic frame resizing when adjusting settings.
(setq global-text-scale-adjust-resizes-frames nil)
;; A longer delay can be annoying as it causes a noticeable pause after each
;; deletion, disrupting the flow of editing.
(setq delete-pair-blink-delay 0.03)
;; Disable visual indicators in the fringe for buffer boundaries and empty lines
(setq-default indicate-buffer-boundaries nil)
(setq-default indicate-empty-lines nil)
;; Continue wrapped lines at whitespace rather than breaking in the
;; middle of a word.
(setq-default word-wrap t)
;; Disable wrapping by default due to its performance cost.
(setq-default truncate-lines t)
;; If enabled and `truncate-lines' is disabled, soft wrapping will not occur
;; when the window is narrower than `truncate-partial-width-windows' characters.
(setq truncate-partial-width-windows nil)
;; Configure automatic indentation to be triggered exclusively by newline and
;; DEL (backspace) characters.
(setq-default electric-indent-chars '(?\n ?\^?))
;; Prefer spaces over tabs. Spaces offer a more consistent default compared to
;; 8-space tabs. This setting can be adjusted on a per-mode basis as needed.
(setq-default indent-tabs-mode nil
tab-width 4)
;; Enable indentation and completion using the TAB key
(setq tab-always-indent 'complete)
(setq tab-first-completion 'word-or-paren-or-punct)
;; Perf: Reduce command completion overhead.
(setq read-extended-command-predicate #'command-completion-default-include-p)
;; Enable multi-line commenting which ensures that `comment-indent-new-line'
;; properly continues comments onto new lines.
(setq comment-multi-line t)
;; Ensures that empty lines within the commented region are also commented out.
;; This prevents unintended visual gaps and maintains a consistent appearance.
(setq comment-empty-lines t)
;; We often split terminals and editor windows or place them side-by-side,
;; making use of the additional horizontal space.
(setq-default fill-column 80)
;; Disable the obsolete practice of end-of-line spacing from the typewriter era.
(setq sentence-end-double-space nil)
;; According to the POSIX, a line is defined as "a sequence of zero or more
;; non-newline characters followed by a terminating newline".
(setq require-final-newline t)
;; Eliminate delay before highlighting search matches
(setq lazy-highlight-initial-delay 0)
;;; Filetype
;; Do not notify the user each time Python tries to guess the indentation offset
(setq python-indent-guess-indent-offset-verbose nil)
(setq sh-indent-after-continuation 'always)
;;; Dired and ls-lisp
(setq dired-free-space nil
dired-dwim-target t ; Propose a target for intelligent moving/copying
dired-deletion-confirmer 'y-or-n-p
dired-filter-verbose nil
dired-recursive-deletes 'top
dired-recursive-copies 'always
dired-vc-rename-file t
dired-create-destination-dirs 'ask
;; Suppress Dired buffer kill prompt for deleted dirs
dired-clean-confirm-killing-deleted-buffers nil)
;; This is a higher-level predicate that wraps `dired-directory-changed-p'
;; with additional logic. This `dired-buffer-stale-p' predicate handles remote
;; files, wdired, unreadable dirs, and delegates to dired-directory-changed-p
;; for modification checks.
(setq auto-revert-remote-files nil)
(setq dired-auto-revert-buffer 'dired-buffer-stale-p)
;; dired-omit-mode
(setq dired-omit-verbose nil
dired-omit-files (concat "\\`[.]\\'"))
(setq ls-lisp-verbosity nil)
(setq ls-lisp-dirs-first t)
;;; Ediff
;; Configure Ediff to use a single frame and split windows horizontally
(setq ediff-window-setup-function 'ediff-setup-windows-plain
ediff-split-window-function 'split-window-horizontally)
;;; Help
;; Enhance `apropos' and related functions to perform more extensive searches
(setq apropos-do-all t)
;; Fixes #11: Prevents help command completion from triggering autoload.
;; Loading additional files for completion can slow down help commands and may
;; unintentionally execute initialization code from some libraries.
(setq help-enable-completion-autoload nil)
(setq help-enable-autoload nil)
(setq help-enable-symbol-autoload nil)
(setq help-window-select t) ;; Focus new help windows when opened
;;; Eglot
(setq eglot-report-progress minimal-emacs-debug) ; Prevent minibuffer spam
(setq eglot-autoshutdown t) ; Shut down after killing last managed buffer
;; A setting of nil or 0 means Eglot will not block the UI at all, allowing
;; Emacs to remain fully responsive, although LSP features will only become
;; available once the connection is established in the background.
(setq eglot-sync-connect 0)
;; Activate Eglot in cross-referenced non-project files
(setq eglot-extend-to-xref t)
;; Eglot optimization
(if minimal-emacs-debug
(setq eglot-events-buffer-config '(:size 2000000 :format full))
;; This reduces log clutter to improves performance.
(setq jsonrpc-event-hook nil)
;; Reduce memory usage and avoid cluttering *EGLOT events* buffer
(setq eglot-events-buffer-size 0) ; Deprecated
(setq eglot-events-buffer-config '(:size 0 :format short)))
;;; Flymake
(setq flymake-show-diagnostics-at-end-of-line nil)
(setq flymake-wrap-around nil)
;;; hl-line-mode
;; Highlighting the current window, reducing clutter and improving performance
(setq hl-line-sticky-flag nil)
(setq global-hl-line-sticky-flag nil)
;;; icomplete
;; Do not delay displaying completion candidates in `fido-mode' or
;; `fido-vertical-mode'
(setq icomplete-compute-delay 0.01)
;;; flyspell
;; Improves flyspell performance by preventing messages from being displayed for
;; each word when checking the entire buffer.
(setq flyspell-issue-message-flag nil)
(setq flyspell-issue-welcome-flag nil)
;;; ispell
;; In Emacs 30 and newer, disable Ispell completion to avoid annotation errors
;; when no `ispell' dictionary is set.
(setq text-mode-ispell-word-completion nil)
(setq ispell-silently-savep t)
;;; ibuffer
(setq ibuffer-formats
'((mark modified read-only locked
" " (name 55 55 :left :elide)
" " (size 8 -1 :right)
" " (mode 18 18 :left :elide) " " filename-and-process)
(mark " " (name 16 -1) " " filename)))
;;; xref
;; Enable completion in the minibuffer instead of the definitions buffer
(setq xref-show-definitions-function 'xref-show-definitions-completing-read
xref-show-xrefs-function 'xref-show-definitions-completing-read)
;;; abbrev
;; Ensure the abbrev_defs file is stored in the correct location when
;; `user-emacs-directory' is modified, as it defaults to ~/.emacs.d/abbrev_defs
;; regardless of the change.
(setq abbrev-file-name (expand-file-name "abbrev_defs" user-emacs-directory))
(setq save-abbrevs 'silently)
;;; dabbrev
(setq dabbrev-upcase-means-case-search t)
(setq dabbrev-ignored-buffer-modes
'(archive-mode image-mode docview-mode tags-table-mode
pdf-view-mode tags-table-mode))
(setq dabbrev-ignored-buffer-regexps
'(;; - Buffers starting with a space (internal or temporary buffers)
"\\` "
;; Tags files such as ETAGS, GTAGS, RTAGS, TAGS, e?tags, and GPATH,
;; including versions with numeric extensions like <123>
"\\(?:\\(?:[EG]?\\|GR\\)TAGS\\|e?tags\\|GPATH\\)\\(<[0-9]+>\\)?"))
;;; Remove warnings from narrow-to-region, upcase-region...
(dolist (cmd '(list-timers narrow-to-region narrow-to-page
upcase-region downcase-region
list-threads erase-buffer scroll-left
dired-find-alternate-file set-goal-column))
(put cmd 'disabled nil))
;;; Load post init
(when (fboundp 'minimal-emacs-load-user-init)
(minimal-emacs-load-user-init "post-init.el"))
(setq minimal-emacs--success t)
;; Local variables:
;; byte-compile-warnings: (not obsolete free-vars)
;; End:
;;; init.el ends here

214
post-init.el Normal file
View File

@@ -0,0 +1,214 @@
;;When installing a package used in the init file itself,
;;e.g. a package which adds a use-package key word,
;;use the :wait recipe keyword to block until that package is installed/configured.
;;For example:
;;(use-package general :ensure (:wait t) :demand t)
;; Expands to: (elpaca evil (use-package evil :demand t))
(use-package evil :ensure t
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-want-C-u-scroll t)
:config
(evil-mode))
(use-package evil-collection :ensure t
:after evil
:custom
(evil-collection-outline-bind-tab-p t)
(evil-collection-setup-minibuffer t)
:init
(evil-collection-init))
(use-package evil-goggles
:ensure t
:config
(evil-goggles-mode))
(use-package evil-surround
:ensure t
:config
(global-evil-surround-mode))
(use-package evil-commentary
:ensure t
:config
(evil-commentary-mode)
;; optionally use diff-mode's faces; as a result, deleted text
;; will be highlighed with `diff-removed` face which is typically
;; some red color (as defined by the color theme)
;; other faces such as `diff-added` will be used for other actions
(evil-goggles-use-diff-faces))
(use-package evil-org
:ensure t
:after org
:hook (org-mode . (lambda () evil-org-mode))
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))
(use-package general
:ensure t
:config
;; Create a leader-key definer (SPC in normal/visual, M-SPC elsewhere)
(general-create-definer leader!
:keymaps '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "M-SPC")
(general-define-key
"C-s" #'write-file)
(general-define-key
:states 'normal
:keymaps 'lsp-mode-map
"K" #'lsp-ui-doc-glance)
;; Named prefix groups
(leader!
"SPC" '(project-find-file :which-key "find project files")
"f" '(:ignore t :which-key "files")
"ff" '(find-file :which-key "find file")
"fs" '(save-buffer :which-key "save")
"fr" '(recentf-open :which-key "recent files")
"e" '(dired-jump :which-key "dired")
"b" '(:ignore t :which-key "buffers")
"bb" '(switch-to-buffer :which-key "switch buffer")
"bd" '(evil-delete-buffer :which-key "delete buffer")
"c" '(:ignore t :which-key "code")
"ca" '(lsp-execute-code-action :which-key "code action")
"cd" '(lsp-find-definition :which-key "definition")
"cr" '(lsp-rename :which-key "rename")
"cf" '(apheleia-format-buffer :which-key "format")
;; useful extras while you're at it
"p" '(:ignore t :which-key "project")
"pp" '(project-switch-project :which-key "switch project")
"pb" '(project-switch-to-buffer :which-key "project buffers")
"pk" '(project-kill-buffers :which-key "kill project buffers")))
;; Theming
(use-package catppuccin-theme :ensure t
:config
(load-theme 'catppuccin :no-confirm))
(set-frame-font "JetBrainsMono NFM 16" nil t)
;; Minibuffer
(use-package vertico
:custom
(vertico-scroll-margin 0) ;; Different scroll margin
(vertico-count 20) ;; Show more candidates
(vertico-resize t) ;; Grow and shrink the Vertico minibuffer
(vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
:init
(vertico-mode))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist :ensure nil
:init
(savehist-mode))
;; Emacs minibuffer configurations.
(use-package emacs :ensure nil
:custom
;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer
;; to switch display modes.
(context-menu-mode t)
;; Support opening new minibuffers from inside existing minibuffers.
(enable-recursive-minibuffers t)
;; Hide commands in M-x which do not work in the current mode. Vertico
;; commands are hidden in normal buffers. This setting is useful beyond
;; Vertico.
(read-extended-command-predicate #'command-completion-default-include-p)
;; Do not allow the cursor in the minibuffer prompt
(minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt)))
;; `orderless' completion style.
(use-package orderless
:custom
;; Configure a custom style dispatcher (see the Consult wiki)
;; (orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch))
;; (orderless-component-separator #'orderless-escapable-split-on-space)
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles partial-completion))))
(completion-category-defaults nil) ;; Disable defaults, use our settings
(completion-pcm-leading-wildcard t)) ;; Emacs 31: partial-completion behaves like substring;; LSP & Treesitter
;; #########
;; LSP Stuff
;; #########
(use-package treesit-auto :ensure t
:custom
(treesit-auto-install 'prompt)
:config
(global-treesit-auto-mode))
(use-package lsp-mode :ensure t
:init
(setq lsp-keymap-prefix "C-c l")
:hook ((c-mode . lsp-deferred )
(lsp-mode . lsp-enable-which-key-integration))
:commands (lsp lsp-deferred))
(use-package lsp-ui :ensure t
:custom
(lsp-ui-doc-enable t)
(lsp-ui-doc-position 'at-point)
(lsp-ui-sideline-show-diagnostics t)
:hook (lsp-mode . lsp-ui-mode))
;; Completion via corfu (modern, lighter than company)
(use-package corfu
:ensure t
:custom
(corfu-auto t)
(corfu-auto-delay 0.1)
:init (global-corfu-mode))
;; Diagnostics via flymake (built-in) or flycheck
(use-package flycheck
:ensure t
:hook (lsp-mode . flycheck-mode))
(use-package apheleia
:ensure t
:config
(apheleia-global-mode))
;; #########
;; Which-Key
;; #########
(use-package which-key :ensure t
:config
(which-key-mode))
(use-package smartparens
:ensure t
:hook (prog-mode . smartparens-mode)
:config
(require 'smartparens-config)) ; loads language-specific rules
(use-package rainbow-delimiters
:ensure t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package dashboard
:ensure t
:config
(setq dashboard-items '((recents . 5)
(bookmarks . 5)
(projects . 5)
(agenda . 5)
(registers . 5)))
(add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists)
(add-hook 'elpaca-after-init-hook #'dashboard-initialize)
(dashboard-setup-startup-hook))

15
pre-early-init.el Normal file
View File

@@ -0,0 +1,15 @@
;; By default, minimal-emacs-package-initialize-and-refresh is set to t, which
;; makes minimal-emacs.d call the built-in package manager. Since Elpaca will
;; replace the package manager, there is no need to call it.
(setq minimal-emacs-package-initialize-and-refresh nil)
(setq debug-on-error t)
(defun display-startup-time ()
"Display the startup time and number of garbage collections."
(message "Emacs init loaded in %.2f seconds (Full emacs-startup: %.2fs) with %d garbage collections."
(float-time (time-subtract after-init-time before-init-time))
(time-to-seconds (time-since before-init-time))
gcs-done))
(add-hook 'emacs-startup-hook #'display-startup-time 100)