summary refs log tree commit diff stats
path: root/early-init.el
blob: 615b417e97c94199ae0260c62e35541be8acda54 (plain)
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
;;; early-init.el -*- lexical-binding: t; coding: utf-8-unix -*-

;; Author: Case Duckworth <acdw@acdw.net>
;; Created: Sometime during Covid-19, 2020
;; Keywords: configuration
;; URL: https://tildegit.org/acdw/emacs

;;; License:

;; Everyone is permitted to do whatever they like with this software
;; without limitation.  This software comes without any warranty
;; whatsoever, but with two pieces of advice:
;; - Be kind to yourself.
;; - Make good choices.

;;; Commentary:

;; Starting with Emacs 27.1, early-init.el is sourced before
;; package.el and any graphical frames.  In this file, I set up frame
;; parameters and packaging infrastructure.

;;; Code:

;;; Speed up init

;; Restore things after init
(defvar +emacs--startup-restore-alist nil
  "Variables and values to restore after init.")

(add-hook 'emacs-startup-hook
          (defun emacs-startup@restore-values ()
            "Restore values set during init.
This applies values in `+emacs--startup-restore-alist'."
            (dolist (a +emacs--startup-restore-alist)
              (set (car a) (cdr a)))))

(defun +set-during-startup (variable value &optional restore)
  "Set VARIABLE to VALUE during startup, but restore to RESTORE.
If RESTORE is nil or not passed, save the original value and
restore that."
  (unless after-init-time
    (setf (alist-get variable +emacs--startup-restore-alist)
          (or restore (symbol-value variable)))
    (set-default variable value)))

;; Garbage collection
(+set-during-startup 'gc-cons-threshold most-positive-fixnum)

(add-hook 'minibuffer-setup-hook (defun garbage-collect@minibuffer-enter ()
                                   (setq gc-cons-threshold most-positive-fixnum)))
(add-hook 'minibuffer-exit-hook (defun garbage-collect@minibuffer-exit ()
                                  (setq gc-cons-threshold 800000)))

;; Don't prematurely re-display
(unless debug-on-error
  (+set-during-startup 'inhibit-redisplay t)
  (+set-during-startup 'inhibit-message t))

;; Debug during init
(unless (eq debug-on-error 'startup)
  (+set-during-startup 'debug-on-error 'init))

;;; Set up extra load paths and functionality

(push (locate-user-emacs-file "lisp") load-path)
(require 'acdw)
(require '+compat)

(+define-dir .etc (locate-user-emacs-file ".etc")
  "Directory for all of Emacs's various files.
See `no-littering' for examples.")

(+define-dir sync/ (expand-file-name "~/Sync")
  "My Syncthing directory.")

;;; Default frame settings

(setq default-frame-alist '((tool-bar-lines . 0)
                            (menu-bar-lines . 0)
                            (vertical-scroll-bars)
                            (horizontal-scroll-bars))
      frame-inhibit-implied-resize t
      frame-resize-pixelwise t
      window-resize-pixelwise t
      inhibit-x-resources t
      indicate-empty-lines nil
      indicate-buffer-boundaries nil
      ;; '((top . right)
      ;;   (bottom . right))
      )

;;; No littering!
;; We install `no-littering' package below, but we can set the variables now.

(setq no-littering-etc-directory .etc
      no-littering-var-directory .etc
      straight-base-dir .etc)

;; https://github.com/emacscollective/no-littering/wiki/Setting-gccemacs'-eln-cache

(when (boundp 'comp-eln-load-path)
  (setcar comp-eln-load-path (expand-file-name (.etc "eln-cache" t))))

;;; Packages

(setq package-enable-at-startup nil
      package-quickstart nil
      straight-host-usernames '((github . "duckwork")
                                (gitlab .  "acdw"))
      straight-check-for-modifications '(check-on-save
                                         find-when-checking))

;; Bootstrap straight.el
;; https://github.com/raxod502/straight.el

(+with-message "Bootstrapping straight"
  (defvar bootstrap-version)
  (let ((bootstrap-file
         (expand-file-name
          "straight/repos/straight.el/bootstrap.el"
          straight-base-dir))
        (bootstrap-version 5))
    (unless (file-exists-p bootstrap-file)
      (with-current-buffer
          (url-retrieve-synchronously
           (concat "https://raw.githubusercontent.com/"
                   "raxod502/straight.el/develop/install.el")
           'silent 'inhibit-cookies)
        (goto-char (point-max))
        (eval-print-last-sexp)))
    (load bootstrap-file nil 'nomessage)))

;; Early-loaded packages -- those that, for some reason or another,
;; need to be ensured to be loaded first.

(require 'straight-x)

(dolist (pkg '(el-patch
               no-littering
               setup
               straight                 ; already installed, but what the hell
               ))
  (straight-use-package pkg)
  (require pkg)
  (require (intern (format "+%s" pkg)) nil :noerror))

;; Setup `setup'

(add-to-list 'setup-modifier-list '+setup-wrap-to-demote-errors)
(unless (memq debug-on-error '(nil init))
  (define-advice setup (:around (fn head &rest args) +setup-report)
    (+with-progress ((format "[Setup] %S..." head))
      (apply fn head args))))

;;; Appendix

;; Get rid of a dumb alias.  straight-ಠ_ಠ-mode really slows down all
;; minibuffer completion functions.  Since it's a (rarely-used, even)
;; alias anyway, I just define it back to nil.  By the way, the alias
;; is `straight-package-neutering-mode'.
(defalias 'straight-ಠ_ಠ-mode nil)

(provide 'early-init)
;;; early-init.el ends here