;;; 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 (* 128 1024 1024))

;; Don't prematurely re-display
(+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
