-
Notifications
You must be signed in to change notification settings - Fork 17
/
init.el
217 lines (180 loc) · 10.2 KB
/
init.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
;; init.el --- MinEmacs core initialization file -*- lexical-binding: t; -*-
;; Copyright (C) 2022-2024 Abdelhak Bougouffa
;; Author: Abdelhak Bougouffa (rot13 "[email protected]")
;; __ __ _ ______
;; | \/ (_) | ____|
;; | \ / |_ _ __ | |__ _ __ ___ __ _ ___ ___
;; | |\/| | | '_ \ | __| | '_ ` _ \ / _` |/ __/ __|
;; | | | | | | | | | |____| | | | | | (_| | (__\__ \
;; |_| |_|_|_| |_| |______|_| |_| |_|\__,_|\___|___/
;;
;; MINIMALIST & LIGHTWEIGHT EMACS CONFIGURATION FRAMEWORK
;; abougouffa.github.io/minemacs
;;; Commentary:
;; # MinEmacs - a minimalist & lightweight Emacs configuration framework
;; Load and hooks order:
;; - `~/.emacs.d/early-init.el`
;; * `~/.emacs.d/core/me-vars.el`
;; * `~/.emacs.d/core/me-lib.el`
;; - `$MINEMACSDIR/early-config.el` (unless disabled in `$MINEMACS_IGNORE_USER_CONFIG`)
;; - `$MINEMACSDIR/local/early-config.el` (unless disabled)
;; - `~/.emacs.d/init.el`
;; * `before-init-hook'
;; * `~/.emacs.d/core/me-vars.el` (unless already loaded by "early-init.el")
;; * `$MINEMACSDIR/custom-vars.el`
;; * `~/.emacs.d/core/me-lib.el` (unless already loaded by "early-init.el")
;; * `~/.emacs.d/core/me-loaddefs.el`
;; * `$MINEMACSDIR/init-tweaks.el` (unless disabled)
;; * `$MINEMACSDIR/local/init-tweaks.el` (unless disabled)
;; * `$MINEMACSDIR/modules.el` (unless disabled)
;; * `$MINEMACSDIR/local/modules.el` (unless disabled)
;; * `~/.emacs.d/core/<module>.el`
;; * `~/.emacs.d/modules/<module>.el` (for module in `minemacs-modules')
;; * `minemacs-after-loading-modules-hook'
;; * `$MINEMACSDIR/config.el` (unless disabled)
;; * `$MINEMACSDIR/local/config.el` (unless disabled)
;; * `after-init-hook'
;; * `emacs-startup-hook'
;; * `minemacs-after-startup-hook'
;; + `minemacs-lazy-hook' (hooks are incrementally loaded via a timer)
;; Special hooks defined with `+make-first-file-hook!'
;; - `minemacs-first-file-hook'
;; - `minemacs-first-elisp-file-hook'
;; - `minemacs-first-python-file-hook'
;; - `minemacs-first-org-file-hook'
;; - `minemacs-first-c/c++-file-hook'
;;; Code:
;; Run a profiling session if `$MINEMACS_BENCHMARK' is defined.
(when (getenv "MINEMACS_BENCHMARK")
(let ((dir (concat (file-name-directory load-file-name) "elisp/benchmark-init/")))
(if (not (file-exists-p (concat dir "benchmark-init.el")))
(error "[MinEmacs:Error] `benchmark-init' is not available, make sure you've run \"git submodule update --init\" inside MinEmacs' directory")
(add-to-list 'load-path dir)
(require 'benchmark-init)
(benchmark-init/activate)
(add-hook 'minemacs-lazy-hook (lambda () (benchmark-init/deactivate) (require 'benchmark-init-modes) (benchmark-init/show-durations-tree)) 99))))
;; Check if Emacs version is supported.
(let ((min-ver 29)
(recommended-ver 29))
(when (< emacs-major-version min-ver)
(error "Emacs v%s is not supported, MinEmacs requires v%d or higher" emacs-version min-ver))
(when (< emacs-major-version recommended-ver)
(message "Recommended Emacs version for MinEmacs is %d or higher, you have v%s" recommended-ver emacs-version)))
;; PERF: Setting `file-name-handler-alist' to nil should boost startup time.
;; https://reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start
;; Store the current value so we can reset it after Emacs startup.
(put 'file-name-handler-alist 'original-value (default-toplevel-value 'file-name-handler-alist))
(set-default-toplevel-value 'file-name-handler-alist nil) ; Make sure the new value survives any current let-binding.
;; After Emacs startup, we restore `file-name-handler-alist' while conserving
;; the potential new elements made during startup.
(add-hook 'emacs-startup-hook (lambda () (setq file-name-handler-alist (delete-dups (append file-name-handler-alist (get 'file-name-handler-alist 'original-value))))) 99)
(dolist (dir '("core" "modules" "modules/extras" "elisp")) ; Add some of MinEmacs' directories to `load-path'
(add-to-list 'load-path (expand-file-name dir (file-name-directory (file-truename load-file-name)))))
;; NOTE: At this point, MinEmacs variables defined in `me-vars' should be
;; already loaded (in "early-init.el"). However, we load it here if necessary in
;; case Emacs has been loaded directly from "init.el" without passing by
;; "early-init.el". This can happen when we use some bootstrapping mechanism
;; like Chemacs2.
(require 'me-vars)
;; NOTE: It is important to set this here and not in `me-vars' nor in
;; "early-init.el", otherwise, it won't work with Chemacs2-based installations.
(setq user-emacs-directory minemacs-local-dir
custom-file (concat minemacs-config-dir "custom-vars.el"))
(when (file-exists-p custom-file) (load custom-file))
(require 'me-lib) ; Load MinEmacs' core library
(setq
;; Enable debugging on error when Emacs if needed
debug-on-error minemacs-debug-p
;; Decrease the warning type to `:error', unless we are running in verbose mode
warning-minimum-level (if minemacs-verbose-p :warning :error)
warning-minimum-log-level warning-minimum-level
;; Make byte compilation less noisy
byte-compile-warnings minemacs-verbose-p
byte-compile-verbose minemacs-verbose-p)
;; Native compilation settings
(when (featurep 'native-compile)
(setq
;; Silence compiler warnings unless we are running in `minemacs-verbose-p' mode
native-comp-async-report-warnings-errors (when minemacs-verbose-p 'silent)
;; Do not be too verbose
native-comp-verbose (if minemacs-verbose-p 1 0)
native-comp-debug (if minemacs-debug-p 1 0)
;; Make native compilation happens asynchronously
native-comp-jit-compilation t)
;; Set the directory for storing the native compilation cache
(startup-redirect-eln-cache (concat minemacs-cache-dir "eln/")))
(defun minemacs-generate-loaddefs ()
"Generate MinEmacs' loaddefs file."
(interactive)
(when (file-exists-p minemacs-loaddefs-file) (delete-file minemacs-loaddefs-file))
(loaddefs-generate
(list minemacs-core-dir minemacs-elisp-dir minemacs-extras-dir minemacs-on-demand-modules-dir)
minemacs-loaddefs-file))
;; Generate the loaddefs file if needed
(unless (file-exists-p minemacs-loaddefs-file) (minemacs-generate-loaddefs))
;; Then we load the loaddefs file
(+load minemacs-loaddefs-file)
;; Load user init tweaks when available
(+load-user-configs 'init-tweaks 'local/init-tweaks)
;; When `minemacs-proxies' is set in "early-init.el" or in "init-tweaks.el",
;; `minemacs-enable-proxy' will set the environment variables accordingly.
(unless minemacs-no-proxies-p (minemacs-enable-proxy minemacs-proxies))
;; HACK: Load the environment variables saved from shell using `+env-save' to
;; `+env-file'. `+env-save' saves all environment variables except these matched
;; by `+env-deny-vars'.
(+env-load) ; Load environment variables when available.
;; HACK: The `gc-cons-threshold' has been set in "early-init.el" to
;; `most-positive-fixnum' to avoid garbage collection during startup. We will
;; overwrite it at the end of `minemacs-lazy-hook' to maximize the benefit.
(defun +minemacs--gc-tweaks-h ()
"Better garbage collection settings, no GCMH required.
See: https://zenodo.org/records/10213384."
(setq gc-cons-threshold (* 128 1024 1024)
gc-cons-percentage 0.25))
(add-hook 'minemacs-lazy-hook #'+minemacs--gc-tweaks-h 90)
(defun +minemacs--loaded-h ()
"This is MinEmacs' synchronization point.
To achieve fast startup, we try to defer loading most of the packages
until this hook is executed. This is managed by the `minemacs-loaded'
and `minemacs-lazy' features.
After loading Emacs, the `emacs-startup-hook' gets executed, we use this
hook to profile the startup time, and load the theme. Lastly we require
the `minemacs-loaded' synchronization module, which runs the
`minemacs-after-startup-hook' hooks and provide `minemacs-loaded' so the
packages loaded with `:after minemacs-loaded' can be loaded.
The `minemacs-loaded' will require `minemacs-lazy', which incrementally
run the hooks in `minemacs-lazy-hook' after startup, and at the end,
provide the `minemacs-lazy' feature so the packages loaded with `:after
minemacs-lazy' can be loaded."
(+info! "Loaded Emacs%s in %s, including %.3fs for %d GCs." (if (daemonp) " (in daemon mode)" "") (emacs-init-time) gc-elapsed gcs-done)
(unless (featurep 'me-org-export-async-init) (+load-theme))
(require 'minemacs-loaded))
;; Add it to the very beginning of `emacs-startup-hook'
(add-hook 'emacs-startup-hook #'+minemacs--loaded-h -91)
;; ========= Make some special hooks =========
(+make-first-file-hook! 'org "\\.org$")
(+make-first-file-hook! 'elisp "\\.elc?$")
(+make-first-file-hook! 'python (rx "." (or "py" "pyw" "pyx" "pyz" "pyzw") eol))
(+make-first-file-hook! 'c/c++ (rx "." (or "c" "cpp" "cxx" "cc" "c++" "h" "hpp" "hxx" "hh" "h++" "ixx" "cppm" "cxxm" "c++m" "ccm") eol))
(+make-first-file-hook! nil ".")
;; ========= Load MinEmacs packages and user customization =========
;; When running in an async Org export context, the used modules are set in
;; "modules/extras/me-org-export-async-init.el", so we must not override them
;; with the user's enabled modules.
(if (featurep 'me-org-export-async-init)
(progn (message "Loading \"init.el\" in an org-export-async context.")
;; No need to load all modules, load only these related to Org
(setq minemacs-modules '(me-org me-project me-prog me-emacs-lisp on-demand/me-latex)
minemacs-not-lazy-p t)) ; Don't be lazy
;; Load the default list of enabled modules `minemacs-modules'
(+load-user-configs 'modules 'local/modules))
;; When the MINEMACS_LOAD_ALL_MODULES environment variable is set, we force
;; loading all modules.
(when minemacs-load-all-modules-p (setq minemacs-modules (minemacs-modules t)))
;; Load modules
(mapc #'+load (mapcar (apply-partially #'format "%s%s.el" minemacs-core-dir) '(me-bootstrap me-builtin)))
(mapc #'+load (mapcar (apply-partially #'format "%s%s.el" minemacs-modules-dir) minemacs-modules))
(run-hooks 'minemacs-after-loading-modules-hook)
(+load-user-configs 'config 'local/config) ; Load user configuration
(+log! "Loaded init.el")
;;; init.el ends here