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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
|
;;; -*- lexical-binding: t -*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; .⌒. ▗▄▄▖▗ ▖ ▗▖ ▗▄ ▄▄ ▄▄ ▗ ▖▗▄▄ ▄▄ ▄▄▄▖▗▄▄ ▗▖ ▄▄▄▖▗▄▄▖ ;;;
;;; .# #. ▐ ▐▌▐▌ ▐▌ ▗▘ ▘▐▘ ▘ ▐▘ ▘▐ ▌▐ ▌▐▘ ▘ ▐ ▐ ▝▌ ▐▌ ▐ ▐ ;;;
;;; / \ ▐▄▄▖▐▐▌▌ ▌▐ ▐ ▝▙▄ ▝▙▄ ▐ ▌▐▄▄▘▝▙▄ ▐ ▐▄▄▘ ▌▐ ▐ ▐▄▄▖ ;;;
;;; (,,,___,,,) ▐ ▐▝▘▌ ▙▟ ▐ ▝▌ ▝▌▐ ▌▐ ▌ ▝▌ ▐ ▐ ▝▖ ▙▟ ▐ ▐ ;;;
;;; ) ( ▐▄▄▖▐ ▌▐ ▌ ▚▄▘▝▄▟▘ ▝▄▟▘▝▄▄▘▐▄▄▘▝▄▟▘ ▐ ▐ ▘▐ ▌ ▐ ▐▄▄▖ ;;;
;;; (___) ;;;
;;; ;;;
;;; init.el ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Guardrail
(when (< emacs-major-version 29)
(error "Emacs Substrate only works with Emacs 29 and newer; you have version %s" emacs-major-version))
;;; Custom variables
(defgroup substrate nil "Custom options for substrate")
(defcustom substrate-enable-windmove t
"Enable windmove to hop around windows with ctrl+arrow"
:type 'boolean :group 'substrate)
(defcustom substrate-display-startup-help t
"Show a help window on startup"
:type 'boolean :group 'substrate)
(defcustom substrate-enable-which-key t
"Use which-key to list available key combos"
:type 'boolean :group 'substrate)
(defcustom substrate-display-line-numbers t
"Display line numbers on buffers"
:type 'boolean :group 'substrate)
(defcustom substrate-configure-theme t
"Configure the default theme (evangelion) as part of the substrate init"
:type 'boolean :group 'substrate)
(defcustom substrate-enable-evil nil
"Enable evil-mode and the Vi-like keyboard mapping"
:type 'boolean :group 'substrate)
(defun substrate-set-theme (theme)
(if (daemonp)
(add-hook 'after-make-frame-functions
(defun substrate--load-theme-daemon (frame)
(with-selected-frame frame
(load-theme theme t))
;; Run this hook only once.
(remove-hook 'after-make-frame-functions
#'substrate--load-theme-daemon)
(fmakunbound 'substrate--load-theme-daemon)))
(load-theme theme t)))
(defun substrate--insert-centered-line (text)
(let ((window-width (window-width))
(text-width (length text)))
(dotimes (num (/ (- window-width text-width) 2))
(insert " "))
(insert text)
(insert "\n")
))
(defvar substrate--splash-screen-lines
'(" .⌒. "
" .# #. "
" / \\ "
" (,,,___,,,) "
" ) ( "
" (___) \n"
"Welcome to Emacs Substrate!\n\n\n\n"
"Quickstart:\n\n"
"←↑↓→ move around "
"Ctrl+x Ctrl+c quit "
"Ctrl+h t start the tutorial"
))
(defun substrate-splash-screen ()
(unless inhibit-startup-screen
(setq inhibit-startup-screen t)
(let ((splash-buffer (get-buffer-create "*GNU Emacs*")))
(with-current-buffer splash-buffer
(let ((inhibit-read-only t))
(erase-buffer)
(mapc #'substrate--insert-centered-line substrate--splash-screen-lines)
(set-buffer-modified-p nil)
(view-mode-enter nil 'kill-buffer)
(goto-char (point-min))
(switch-to-buffer splash-buffer)
)))))
(add-hook 'emacs-startup-hook #'substrate-splash-screen)
(defun substrate-init ()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Basic settings
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Package initialization
;;
;; Set up package and enable melpa
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; Boostrap straight.el
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name
"straight/repos/straight.el/bootstrap.el"
(or (bound-and-true-p straight-base-dir)
user-emacs-directory)))
(bootstrap-version 7))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(setq straight-use-package-by-default t)
(setopt initial-major-mode 'fundamental-mode) ; default mode for the *scratch* buffer
(setopt display-time-default-load-average nil) ; this information is useless for most
;; Automatically reread from disk if the underlying file changes
(setopt auto-revert-avoid-polling t)
;; Some systems don't do file notifications well; see
;; https://todo.sr.ht/~ashton314/emacs-bedrock/11
(setopt auto-revert-interval 5)
(setopt auto-revert-check-vc-info t)
(global-auto-revert-mode t)
;; Save history of minibuffer
(savehist-mode)
;; Move through windows with Ctrl-<arrow keys>
(when substrate-enable-windmove
(windmove-default-keybindings 'control)) ; You can use other modifiers here
;; Fix archaic defaults
(setopt sentence-end-double-space nil)
;; Make right-click do something sensible
(when (display-graphic-p)
(context-menu-mode))
;; Don't litter file system with *~ backup files; put them all inside
;; ~/.emacs.d/backup or wherever
(defun substrate--backup-file-name (fpath)
"Return a new file path of a given file path.
If the new path's directories does not exist, create them."
(let* ((backupRootDir (concat user-emacs-directory "emacs-backup/"))
(filePath (replace-regexp-in-string "[A-Za-z]:" "" fpath )) ; remove Windows driver letter in path
(backupFilePath (replace-regexp-in-string "//" "/" (concat backupRootDir filePath "~") )))
(make-directory (file-name-directory backupFilePath) (file-name-directory backupFilePath))
backupFilePath))
(setopt make-backup-file-name-function 'substrate--backup-file-name)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Discovery aids
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Show the help buffer after startup
(when substrate-display-startup-help
(add-hook 'after-init-hook 'help-quick))
;; which-key: shows a popup of available keybindings when typing a long key
;; sequence (e.g. C-x ...)
(when substrate-enable-which-key
(straight-use-package 'which-key)
(which-key-mode))
(when substrate-enable-evil
(setq evil-respect-visual-line-mode t)
(setq evil-undo-system 'undo-redo)
(straight-use-package 'evil)
(evil-mode)
;; If you use Magit, start editing in insert state
(add-hook 'git-commit-setup-hook 'evil-insert-state)
;; Configuring initial major mode for some modes
(evil-set-initial-state 'eat-mode 'emacs)
(evil-set-initial-state 'vterm-mode 'emacs))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Minibuffer/completion settings
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; For help, see: https://www.masteringemacs.org/article/understanding-minibuffer-completion
(setopt enable-recursive-minibuffers t) ; Use the minibuffer whilst in the minibuffer
(setopt completion-cycle-threshold 1) ; TAB cycles candidates
(setopt completions-detailed t) ; Show annotations
(setopt tab-always-indent 'complete) ; When I hit TAB, try to complete, otherwise, indent
(setopt completion-styles '(basic initials substring)) ; Different styles to match input to candidates
(setopt completion-auto-help 'always) ; Open completion always; `lazy' another option
(setopt completions-max-height 20) ; This is arbitrary
(setopt completions-detailed t)
(setopt completions-format 'one-column)
(setopt completions-group t)
(setopt completion-auto-select 'second-tab) ; Much more eager
;(setopt completion-auto-select t) ; See `C-h v completion-auto-select' for more possible values
(keymap-set minibuffer-mode-map "TAB" 'minibuffer-complete) ; TAB acts more like how it does in the shell
;; For a fancier built-in completion option, try ido-mode,
;; icomplete-vertical, or fido-mode. See also the file extras/base.el
;(icomplete-vertical-mode)
;(fido-vertical-mode)
;(setopt icomplete-delay-completions-threshold 4000)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Interface enhancements/defaults
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Mode line information
(setopt line-number-mode t) ; Show current line in modeline
(setopt column-number-mode t) ; Show column as well
(setopt x-underline-at-descent-line nil) ; Prettier underlines
(setopt switch-to-buffer-obey-display-actions t) ; Make switching buffers more consistent
(setopt show-trailing-whitespace nil) ; By default, don't underline trailing spaces
(setopt indicate-buffer-boundaries 'left) ; Show buffer top and bottom in the margin
;; Enable horizontal scrolling
(setopt mouse-wheel-tilt-scroll t)
(setopt mouse-wheel-flip-direction t)
;; We won't set these, but they're good to know about
;;
;; (setopt indent-tabs-mode nil)
;; (setopt tab-width 4)
;; Misc. UI tweaks
(blink-cursor-mode -1) ; Steady cursor
(pixel-scroll-precision-mode) ; Smooth scrolling
;; Display line numbers in programming mode
(when substrate-display-line-numbers
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(setopt display-line-numbers-width 3)) ; Set a minimum width
;; Nice line wrapping when working with text
(add-hook 'text-mode-hook 'visual-line-mode)
;; Modes to highlight the current line with
(let ((hl-line-hooks '(text-mode-hook prog-mode-hook)))
(mapc (lambda (hook) (add-hook hook 'hl-line-mode)) hl-line-hooks))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Tab-bar configuration
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Show the tab-bar as soon as tab-bar functions are invoked
(setopt tab-bar-show 1)
;; Add the time to the tab-bar, if visible
(add-to-list 'tab-bar-format 'tab-bar-format-align-right 'append)
(add-to-list 'tab-bar-format 'tab-bar-format-global 'append)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Theme
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when substrate-configure-theme
(straight-use-package 'challenger-deep-theme)
(substrate-set-theme 'challenger-deep))
;;; Relegate automatic custom variables to their own file.
(setq custom-file (expand-file-name "custom-vars.el"))
) ;; End substrate-init
(provide 'substrate)
;;; End of substrate.el
|