doomemacs/lisp/doom.el
2022-09-17 11:00:08 +02:00

601 lines
28 KiB
EmacsLisp

;;; doom.el --- the heart of the beast -*- lexical-binding: t; -*-
;;
;; Author: Henrik Lissner <contact@henrik.io>
;; URL: https://github.com/doomemacs/doomemacs
;;
;; ================= =============== =============== ======== ========
;; \\ . . . . . . .\\ //. . . . . . .\\ //. . . . . . .\\ \\. . .\\// . . //
;; ||. . ._____. . .|| ||. . ._____. . .|| ||. . ._____. . .|| || . . .\/ . . .||
;; || . .|| ||. . || || . .|| ||. . || || . .|| ||. . || ||. . . . . . . ||
;; ||. . || || . .|| ||. . || || . .|| ||. . || || . .|| || . | . . . . .||
;; || . .|| ||. _-|| ||-_ .|| ||. . || || . .|| ||. _-|| ||-_.|\ . . . . ||
;; ||. . || ||-' || || `-|| || . .|| ||. . || ||-' || || `|\_ . .|. .||
;; || . _|| || || || || ||_ . || || . _|| || || || |\ `-_/| . ||
;; ||_-' || .|/ || || \|. || `-_|| ||_-' || .|/ || || | \ / |-_.||
;; || ||_-' || || `-_|| || || ||_-' || || | \ / | `||
;; || `' || || `' || || `' || || | \ / | ||
;; || .===' `===. .==='.`===. .===' /==. | \/ | ||
;; || .==' \_|-_ `===. .===' _|_ `===. .===' _-|/ `== \/ | ||
;; || .==' _-' `-_ `=' _-' `-_ `=' _-' `-_ /| \/ | ||
;; || .==' _-' '-__\._-' '-_./__-' `' |. /| | ||
;; ||.==' _-' `' | /==.||
;; ==' _-' \/ `==
;; \ _-' `-_ /
;; `'' ``'
;;
;; These demons are not part of GNU Emacs.
;;
;;; Commentary:
;;
;; This is Doom's heart, where I define all its major constants and variables,
;; set its saner global defaults, then prepare Emacs to bootstrap Doom.
;;
;; The overall load order of Doom is as follows:
;;
;; > $EMACSDIR/early-init.el
;; > $EMACSDIR/lisp/doom.el
;; - $EMACSDIR/lisp/doom-lib.el
;; > $EMACSDIR/lisp/doom-start.el
;; - $EMACSDIR/doom-{keybinds,ui,projects,editor}.el
;; - hook: `doom-before-init-hook'
;; - $DOOMDIR/init.el
;; > $XDG_DATA_HOME/doom/$PROFILE/@/curr/init.el (replaces $EMACSDIR/init.el)
;; - hook: `doom-before-modules-init-hook'
;; - {$DOOMDIR,$EMACSDIR}/modules/*/*/init.el
;; - hook: `doom-after-modules-init-hook'
;; - hook: `doom-before-modules-config-hook'
;; - {$DOOMDIR,$EMACSDIR}/modules/*/*/config.el
;; - hook: `doom-after-modules-config-hook'
;; - $DOOMDIR/config.el
;; - `custom-file' or $DOOMDIR/custom.el
;; > The rest of `command-line' (Emacs startup)
;; - hook: `after-init-hook'
;; - hook: `emacs-startup-hook'
;; - hook: `window-setup-hook'
;; - hook: `doom-init-ui-hook'
;; - hook: `doom-after-init-hook'
;; > After startup is complete:
;; - On first input: `doom-first-input-hook'
;; - On first switched-to buffer: `doom-first-buffer-hook'
;; - On first opened file: `doom-first-file-hook'
;;
;; This is Doom's heart, where I define all its major constants and variables,
;; set only its sanest global defaults, employ its hackiest (and least
;; offensive) optimizations, and load the minimum for all Doom sessions.
;;
;;; Code:
(eval-when-compile (require 'subr-x))
;;; Version checks
(eval-and-compile ; Check version at both compile and runtime.
;; Doom's minimum supported version of Emacs is 27.1. Its my goal to support
;; one major version below the stable release, for about a year or until
;; stable is ubiquitous (or at least easily accessible) across Linux distros.
(when (< emacs-major-version 27)
(user-error
(concat
"Detected Emacs " emacs-version ", but Doom requires 27.1 or newer (28.1 is\n\n"
"recommended). The current Emacs executable in use is:\n\n " (car command-line-args)
"\n\nA guide for installing a newer version of Emacs can be found at:\n\n "
(format "https://docs.doomemacs.org/-/install/%s"
(cond ((eq system-type 'darwin) "on-macos")
((memq system-type '(cygwin windows-nt ms-dos)) "on-windows")
("on-linux")))
"\n\n"
(if noninteractive
(concat "Alternatively, either update your $PATH environment variable to include the\n"
"path of the desired Emacs executable OR alter the $EMACS environment variable\n"
"to specify the exact path or command needed to invoke Emacs."
(when-let (command (ignore-errors (file-name-nondirectory (cadr (member "--load" command-line-args)))))
(concat " For example:\n\n"
" $ EMACS=/path/to/valid/emacs " command " ...\n"
" $ EMACS=\"/Applications/Emacs.app/Contents/MacOS/Emacs\" " command " ...\n"
" $ EMACS=\"snap run emacs\" " command " ..."))
"\n\nAborting...")
(concat "If you believe this error is a mistake, run 'doom doctor' on the command line\n"
"to diagnose common issues with your config and system."))))))
;; Doom needs to be synced/rebuilt if either Doom or Emacs has been
;; up/downgraded. This is because byte-code isn't backwards compatible, and many
;; packages (including Doom), make in absolute paths into their caches that need
;; to be refreshed.
(let ((old-version (eval-when-compile emacs-version)))
(unless (equal emacs-version old-version)
(user-error (concat "Doom was compiled with Emacs %s, but was loaded with %s. Run 'doom sync' to"
"recompile it.")
emacs-version old-version)))
;;; Custom features
;; Since `system-configuration-features's docs state not to rely on it to test
;; for features, let's give users an easier way to detect them.
(if (bound-and-true-p module-file-suffix)
(push 'dynamic-modules features))
(if (fboundp #'json-parse-string)
(push 'jansson features))
;; `native-compile' exists whether or not it is functional (e.g. libgcc is
;; available or not). This seems silly, so pretend it doesn't exist if it
;; isn't available.
(if (featurep 'native-compile)
(if (not (native-comp-available-p))
(delq 'native-compile features)))
;;; Global constants
;; DEPRECATED remove in v3
(defconst IS-MAC (eq system-type 'darwin))
(defconst IS-LINUX (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix)))
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))
(defconst IS-BSD (memq system-type '(darwin berkeley-unix gnu/kfreebsd)))
(defconst EMACS28+ (> emacs-major-version 27))
(defconst EMACS29+ (> emacs-major-version 28))
(defconst MODULES (featurep 'dynamic-modules))
(defconst NATIVECOMP (featurep 'native-compile))
(make-obsolete-variable 'EMACS28+ "Use (>= emacs-major-version 28) instead" "3.0.0")
(make-obsolete-variable 'EMACS29+ "Use (>= emacs-major-version 29) instead" "3.0.0")
(make-obsolete-variable 'MODULES "Use (featurep 'dynamic-modules) instead" "3.0.0")
(make-obsolete-variable 'NATIVECOMP "Use (featurep 'native-compile) instead" "3.0.0")
;;; Fix $HOME on Windows
;; $HOME isn't normally defined on Windows, but many unix tools expect it.
(when IS-WINDOWS
(when-let (realhome
(and (null (getenv-internal "HOME"))
(getenv "USERPROFILE")))
(setenv "HOME" realhome)
(setq abbreviated-home-dir nil)))
;;; Load Doom's stdlib
(add-to-list 'load-path (file-name-directory load-file-name))
(require 'doom-lib)
;;
;;; Core globals
(defgroup doom nil
"An Emacs framework for the stubborn martian hacker."
:link '(url-link "https://doomemacs.org"))
(defconst doom-version "3.0.0-pre"
"Current version of Doom Emacs core.")
;; DEPRECATED: Remove these when the modules are moved out of core.
(defconst doom-modules-version "22.09.0-pre"
"Current version of Doom Emacs.")
(defconst doom-profile
(if-let (profile (getenv-internal "DOOMPROFILE"))
(save-match-data
(if (string-match "^\\([^@]+\\)@\\(.+\\)$" profile)
(cons (match-string 1 profile)
(match-string 2 profile))
(cons profile "0")))
;; TODO Restore this in 3.0
;; (cons "_" "0")
)
"The active profile as a cons cell (NAME . VERSION).")
;;; Data directory variables
(defconst doom-emacs-dir user-emacs-directory
"The path to the currently loaded .emacs.d directory. Must end with a slash.")
(defconst doom-core-dir (file-name-directory load-file-name)
"The root directory of Doom's core files. Must end with a slash.")
(defconst doom-modules-dir (expand-file-name "modules/" doom-emacs-dir)
"The root directory for Doom's modules. Must end with a slash.")
(define-obsolete-variable-alias 'doom-private-dir 'doom-user-dir "3.0.0")
(defconst doom-user-dir
(expand-file-name
(if-let (doomdir (getenv-internal "DOOMDIR"))
(file-name-as-directory doomdir)
(or (let ((xdgdir
(file-name-concat
(or (getenv-internal "XDG_CONFIG_HOME")
"~/.config")
"doom/")))
(if (file-directory-p xdgdir) xdgdir))
"~/.doom.d/")))
"Where your private configuration is placed.
Defaults to ~/.config/doom, ~/.doom.d or the value of the DOOMDIR envvar;
whichever is found first. Must end in a slash.")
;; DEPRECATED: .local will be removed entirely in 3.0
(defvar doom-local-dir
(if-let (localdir (getenv-internal "DOOMLOCALDIR"))
(expand-file-name (file-name-as-directory localdir))
(expand-file-name ".local/" doom-emacs-dir))
"Root directory for local storage.
Use this as a storage location for this system's installation of Doom Emacs.
These files should not be shared across systems. By default, it is used by
`doom-data-dir' and `doom-cache-dir'. Must end with a slash.")
(define-obsolete-variable-alias 'doom-etc-dir 'doom-data-dir "3.0.0")
(defvar doom-data-dir
(if doom-profile
(if IS-WINDOWS
(expand-file-name "doomemacs/data/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_DATA_HOME") "~/.local/share")))
;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "etc/"))
"Where Doom stores its global data files.
Data files contain shared and long-lived data that Doom, Emacs, and their
packages require to function correctly or at all. Deleting them by hand will
cause breakage, and require user intervention (e.g. a 'doom sync' or 'doom env')
to restore.
Use this for: server binaries, package source, pulled module libraries,
generated files for profiles, profiles themselves, autoloads/loaddefs, etc.
For profile-local data files, use `doom-profile-data-dir' instead.")
(defvar doom-cache-dir
(if doom-profile
(if IS-WINDOWS
(expand-file-name "doomemacs/cache/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_CACHE_HOME") "~/.cache")))
;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "cache/"))
"Where Doom stores its global cache files.
Cache files represent non-essential data that shouldn't be problematic when
deleted (besides, perhaps, a one-time performance hit), lack portability (and so
shouldn't be copied to other systems/configs), and are regenerated when needed,
without user input (e.g. a 'doom sync').
Some examples: images/data caches, elisp bytecode, natively compiled elisp,
session files, ELPA archives, authinfo files, org-persist, etc.
For profile-local cache files, use `doom-profile-cache-dir' instead.")
(defvar doom-state-dir
(if doom-profile
(if IS-WINDOWS
(expand-file-name "doomemacs/state/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_STATE_HOME") "~/.local/state")))
;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "state/"))
"Where Doom stores its global state files.
State files contain non-essential, unportable, but persistent data which, if
lost won't cause breakage, but may be inconvenient as they cannot be
automatically regenerated or restored. For example, a recently-opened file list
is not essential, but losing it means losing this record, and restoring it
requires revisiting all those files.
Use this for: history, logs, user-saved data, autosaves/backup files, known
projects, recent files, bookmarks.
For profile-local state files, use `doom-profile-state-dir' instead.")
;;; Profile file/directory variables
(defvar doom-profile-cache-dir
(file-name-concat doom-cache-dir (car doom-profile))
"For profile-local cache files under `doom-cache-dir'.")
(defvar doom-profile-data-dir
(file-name-concat doom-data-dir (car doom-profile))
"For profile-local data files under `doom-data-dir'.")
(defvar doom-profile-state-dir
(file-name-concat doom-state-dir (car doom-profile))
"For profile-local state files under `doom-state-dir'.")
(defconst doom-profile-dir
(file-name-concat doom-profile-data-dir "@" (cdr doom-profile))
"Where generated files for the active profile are kept.")
;; DEPRECATED: Will be moved to cli/env
(defconst doom-env-file
(file-name-concat (if doom-profile
doom-profile-dir
doom-local-dir)
"env")
"The location of your envvar file, generated by `doom env`.
This file contains environment variables scraped from your shell environment,
which is loaded at startup (if it exists). This is helpful if Emacs can't
\(easily) be launched from the correct shell session (particularly for MacOS
users).")
;;
;;; Startup optimizations
;; Here are Doom's hackiest (and least offensive) startup optimizations. They
;; exploit implementation details and unintended side-effects, and will change
;; often between major Emacs releases. However, I disable them if this is a
;; daemon session (where startup time matters less) or in debug-mode (to
;; mitigate interference with our debugging).
(unless (or (daemonp) init-file-debug)
;; PERF: `file-name-handler-alist' is consulted on each call to `require',
;; `load', or various file/io functions (like `expand-file-name' or
;; `file-remote-p'). You get a noteable boost to startup time by unsetting
;; or simplifying its value.
(let ((old-value (default-toplevel-value 'file-name-handler-alist)))
(setq file-name-handler-alist
;; HACK: If the bundled elisp for this Emacs install isn't
;; byte-compiled (but is compressed), then leave the gzip file
;; handler there so Emacs won't forget how to read read them.
;;
;; calc-loaddefs.el is our heuristic for this because it is built-in
;; to all supported versions of Emacs, and calc.el explicitly loads
;; it uncompiled. This ensures that the only other, possible
;; fallback would be calc-loaddefs.el.gz.
(if (eval-when-compile
(locate-file-internal "calc-loaddefs.el" load-path))
nil
(list (rassq 'jka-compr-handler old-value))))
;; Make sure the new value survives any current let-binding.
(set-default-toplevel-value 'file-name-handler-alist file-name-handler-alist)
;; COMPAT: ...but restore `file-name-handler-alist' later, because it is
;; needed for handling encrypted or compressed files, among other things.
(add-hook! 'emacs-startup-hook :depth 101
(defun doom--reset-file-handler-alist-h ()
(setq file-name-handler-alist
;; Merge instead of overwrite because there may have been changes to
;; `file-name-handler-alist' since startup we want to preserve.
(delete-dups (append file-name-handler-alist old-value))))))
(unless noninteractive
;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or
;; larger than the system font) appears to impact startup time
;; dramatically. The larger the delta in font size, the greater the delay.
;; Even trivial deltas can yield a ~1000ms loss, though it varies wildly
;; depending on font size.
(setq frame-inhibit-implied-resize t)
;; PERF,UX: 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)
;; PERF,UX: Remove "For information about GNU Emacs..." message at startup.
;; It's redundant with our dashboard and incurs a premature redraw.
(advice-add #'display-startup-echo-area-message :override #'ignore)
;; PERF: Shave seconds off startup time by starting the scratch buffer in
;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which
;; pull in a ton of packages. `doom/open-scratch-buffer' provides a better
;; scratch buffer anyway.
(setq initial-major-mode 'fundamental-mode
initial-scratch-message nil)
;; PERF: Inexplicably, `tty-run-terminal-initialization' can sometimes take
;; 2-3s when starting up Emacs in the terminal. Whatever slows it down at
;; startup doesn't appear to affect it if it's called a little later in
;; the startup process, so that's what I do.
;; REVIEW: This optimization is not well understood. Investigate it!
(unless initial-window-system
(advice-add #'tty-run-terminal-initialization :override #'ignore)
(add-hook! 'window-setup-hook
(defun doom--reset-tty-run-terminal-initialization-h ()
(advice-remove #'tty-run-terminal-initialization #'ignore)
(tty-run-terminal-initialization (selected-frame) nil t))))
;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..."
;; messages in the echo area. Writing to the echo-area triggers a
;; redisplay, which can be expensive during startup. This may also cause
;; an flash of white when creating the first frame.
(define-advice load-file (:override (file) silence)
(load file nil 'nomessage))
;; COMPAT: But undo our `load-file' advice later, as to limit the scope of
;; any edge cases it could induce.
(define-advice startup--load-user-init-file (:before (&rest _) undo-silence)
(advice-remove #'load-file #'load-file@silence))
;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on each
;; `require' and `load'. Doom won't load any dmodules this early, so omit
;; .so for a small startup boost. This is later restored in doom-start.
(put 'load-suffixes 'initial-value (default-toplevel-value 'load-suffixes))
(put 'load-file-rep-suffixes 'initial-value (default-toplevel-value 'load-file-rep-suffixes))
(set-default-toplevel-value 'load-suffixes '(".elc" ".el"))
(set-default-toplevel-value 'load-file-rep-suffixes '(""))
;; COMPAT: Undo any problematic startup optimizations; from this point, I make
;; no assumptions about what might be loaded in userland.
(add-hook! 'doom-before-init-hook
(defun doom--reset-load-suffixes-h ()
(setq load-suffixes (get 'load-suffixes 'initial-value)
load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value))))
;; PERF: The mode-line procs a couple dozen times during startup. This is
;; normally quite fast, but disabling the default mode-line and reducing the
;; update delay timer seems to stave off ~30-50ms.
(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)))
;; PERF,UX: Premature redisplays can substantially affect startup times and
;; produce ugly flashes of unstyled Emacs.
(setq-default inhibit-redisplay t
inhibit-message t)
;; COMPAT: Then reset it with advice, because `startup--load-user-init-file'
;; will never be interrupted by errors. And if these settings are left
;; set, Emacs could appear frozen or garbled.
(define-advice startup--load-user-init-file (:after (&rest _) undo-inhibit-vars)
(setq-default inhibit-redisplay nil
inhibit-message nil)
(unless (default-toplevel-value 'mode-line-format)
(setq-default mode-line-format (get 'mode-line-format 'initial-value))))
;; PERF: Doom disables the UI elements by default, so that there's less for
;; the frame to initialize. However, the toolbar is still populated
;; regardless, so I lazy load it until tool-bar-mode is actually used.
(advice-add #'tool-bar-setup :override #'ignore)
(define-advice startup--load-user-init-file (:before (&rest _) defer-tool-bar-setup)
(advice-remove #'tool-bar-setup #'ignore)
(add-transient-hook! 'tool-bar-mode (tool-bar-setup)))
;; PERF: Unset a non-trivial list of command line options that aren't
;; relevant to our current OS, but `command-line-1' still processes.
(unless IS-MAC
(setq command-line-ns-option-alist nil))
(when (or IS-MAC IS-WINDOWS)
(setq command-line-x-option-alist nil))))
;;
;;; Reasonable, global defaults
;;; Don't litter `doom-emacs-dir'/$HOME
;; HACK: I change `user-emacs-directory' because many packages (even built-in
;; ones) abuse it to build paths for storage/cache files (instead of correctly
;; using `locate-user-emacs-file'). This change ensures that said data files
;; are never saved to the root of your emacs directory *and* saves us the
;; trouble of setting a million directory/file variables. But it may throw off
;; anyone (or any package) that uses it to search for your Emacs initfiles.
(setq user-emacs-directory doom-cache-dir)
;; ...However, this may surprise packages (and users) that read
;; `user-emacs-directory' expecting to find the location of your Emacs config,
;; such as server.el!
(setq server-auth-dir (file-name-concat doom-emacs-dir "server/"))
;; Packages with file/dir settings that don't use `user-emacs-directory' or
;; `locate-user-emacs-file' to initialize will need to set explicitly, to stop
;; them from littering in ~/.emacs.d/.
(setq desktop-dirname (file-name-concat doom-cache-dir "desktop")
pcache-directory (file-name-concat doom-cache-dir "pcache/"))
;; Allow the user to store custom.el-saved settings and themes in their Doom
;; config (e.g. ~/.doom.d/).
(setq custom-file (file-name-concat doom-user-dir "custom.el"))
;; By default, Emacs stores `authinfo' in $HOME and in plain-text. Let's not do
;; that, mkay? This file stores usernames, passwords, and other treasures for
;; the aspiring malicious third party. You'll need a GPG setup though.
(setq auth-sources (list (file-name-concat doom-data-dir "authinfo.gpg")
"~/.authinfo.gpg"))
(define-advice en/disable-command (:around (fn &rest args) write-to-data-dir)
"Save safe-local-variables to `custom-file' instead of `user-init-file'.
Otherwise, `en/disable-command' (in novice.el.gz) is hardcoded to write them to
`user-init-file')."
(let ((user-init-file custom-file))
(apply fn args)))
;;; Native compilation support (see http://akrl.sdf.org/gccemacs.html)
(when (boundp 'native-comp-eln-load-path)
;; Don't store eln files in ~/.emacs.d/eln-cache (where they can easily be
;; deleted by 'doom upgrade').
;; REVIEW Use `startup-redirect-eln-cache' when 28 support is dropped
(add-to-list 'native-comp-eln-load-path (expand-file-name "eln/" doom-cache-dir))
;; UX: Suppress compiler warnings and don't inundate users with their popups.
;; They are rarely more than warnings, so are safe to ignore.
(setq native-comp-async-report-warnings-errors init-file-debug
native-comp-warning-on-missing-source init-file-debug)
;; UX: By default, native-comp uses 100% of half your cores. If you're
;; expecting this this should be no issue, but the sudden (and silent) spike
;; of CPU and memory utilization can alarm folks, overheat laptops, or
;; overwhelm less performant systems.
(define-advice comp-effective-async-max-jobs (:before (&rest _) set-default-cpus)
"Default to 1/4 of cores in interactive sessions and all of them otherwise."
(and (null comp-num-cpus)
(zerop native-comp-async-jobs-number)
(setq comp-num-cpus
(max 1 (/ (num-processors) (if noninteractive 1 4)))))))
;;; Suppress package.el
;; Since Emacs 27, package initialization occurs before `user-init-file' is
;; loaded, but after `early-init-file'. Doom handles package initialization, so
;; we must prevent Emacs from doing it again.
(setq package-enable-at-startup nil)
;;; Reduce unnecessary/unactionable warnings/logs
;; Disable warnings from the legacy advice API. They aren't actionable or
;; useful, and often come from third party packages.
(setq ad-redefinition-action 'accept)
;; Ignore warnings about "existing variables being aliased". Otherwise the user
;; gets very intrusive popup warnings about our (intentional) uses of
;; defvaralias, which are done because ensuring aliases are created before
;; packages are loaded is an unneeded and unhelpful maintenance burden. Emacs
;; still aliases them fine regardless.
(with-eval-after-load 'warnings
(add-to-list 'warning-suppress-types '(defvaralias)))
;; Reduce debug output unless we've asked for it.
(setq debug-on-error init-file-debug
jka-compr-verbose init-file-debug)
;;; Stricter security defaults
;; Emacs is essentially one huge security vulnerability, what with all the
;; dependencies it pulls in from all corners of the globe. Let's try to be a
;; *little* more discerning.
(setq gnutls-verify-error noninteractive
gnutls-algorithm-priority
(when (boundp 'libgnutls-version)
(concat "SECURE128:+SECURE192:-VERS-ALL"
(if (and (not IS-WINDOWS)
(>= libgnutls-version 30605))
":+VERS-TLS1.3")
":+VERS-TLS1.2"))
;; `gnutls-min-prime-bits' is set based on recommendations from
;; https://www.keylength.com/en/4/
gnutls-min-prime-bits 3072
tls-checktrust gnutls-verify-error
;; Emacs is built with gnutls.el by default, so `tls-program' won't
;; typically be used, but in the odd case that it does, we ensure a more
;; secure default for it (falling back to `openssl' if absolutely
;; necessary). See https://redd.it/8sykl1 for details.
tls-program '("openssl s_client -connect %h:%p -CAfile %t -nbio -no_ssl3 -no_tls1 -no_tls1_1 -ign_eof"
"gnutls-cli -p %p --dh-bits=3072 --ocsp --x509cafile=%t \
--strict-tofu --priority='SECURE192:+SECURE128:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3' %h"
;; compatibility fallbacks
"gnutls-cli -p %p %h"))
;;
;;; Custom hooks
(defcustom doom-before-init-hook ()
"A hook run before Doom has been initialized and before $DOOMDIR/init.el.
This occurs in the context of early-init.el. Much of Emacs and Doom isn't
initialized at this point, only loaded. Use this for configuration at the latest
opportunity before the session becomes unpredictably complicated by user config,
packages, etc.
Do not use this for interactive functionality, as it's triggered in
noninteractive sessions as well, after Doom core has been loaded, but not
initialized.
In contrast, `before-init-hook' is run just after $DOOMDIR/init.el is loaded,
but before the rest of Doom is loaded."
:group 'doom
:type 'hook)
(defcustom doom-after-init-hook ()
"A hook run at the (true) end of Emacs startup.
When this runs, all modules, config files, and startup hooks have been
triggered. This is the absolute latest point in the startup process."
:group 'doom
:type 'hook)
;;
;;; Last minute initialization
(add-hook! 'doom-before-init-hook
(defun doom--set-initial-values-h ()
;; Remember these variables' initial values, so we can safely reset them at
;; a later time, or consult them without fear of contamination.
(dolist (var '(exec-path load-path process-environment))
(put var 'initial-value (default-toplevel-value var)))))
;; This is the absolute latest a hook can run in Emacs' startup process.
(define-advice command-line-1 (:after (&rest _) run-after-init-hook)
(doom-run-hooks 'doom-after-init-hook))
(provide 'doom)
;;; doom.el ends here