dev: updating from latest pr7002

This commit is contained in:
Matt Nish-Lapidus 2024-02-06 14:05:25 -05:00
commit 7cef14960a
163 changed files with 1143 additions and 1224 deletions

View file

@ -199,7 +199,7 @@ module. This does not include your byte-compiled, third party packages.'"
in (append (doom-glob doom-emacs-dir "*.elc")
(doom-files-in doom-user-dir :match "\\.elc$" :depth 1)
(doom-files-in doom-core-dir :match "\\.elc$")
(doom-files-in doom-modules-dirs :match "\\.elc$" :depth 4))
(doom-files-in doom-module-load-path :match "\\.elc$" :depth 4))
if (file-exists-p path)
do (delete-file path)
and do (print! (success "\033[KDeleted %s%s") (relpath path) esc)

View file

@ -297,7 +297,7 @@ declaration) or dependency thereof that hasn't already been."
;; variables entry is missing the suffix" errors when
;; installing them (see hlissner/doom-emacs#2637), so
;; have git handle conversion by force.
(when (and IS-WINDOWS (stringp local-repo))
(when (and doom--system-windows-p (stringp local-repo))
(let ((default-directory (straight--repos-dir local-repo)))
(when (file-in-directory-p default-directory straight-base-dir)
(straight--process-run "git" "config" "core.autocrlf" "true")))))

654
lisp/demos.org Normal file
View file

@ -0,0 +1,654 @@
#+title: Doom Emacs API Demos
#+property: header-args:elisp :results pp :exports both :eval never-export
This module installs the elisp-demos package, which adds code examples to
documentation buffers (the ones help.el or helpful produces). The built-in demos
are great, but this file exists to add demos for Doom's API and beyond.
#+begin_quote
󰐃 Please make sure new additions to this file are arranged alphabetically and
has a :PROPERTIES: drawer that includes in what version of Doom that the
symbol/function was added.
#+end_quote
#+begin_quote
󰐃 Please don't add demos for code outside of Doom Emacs. PR those to the parent
project: https://github.com/xuchunyang/elisp-demos. And please don't add
functions from modules, put those in that module's demo.org file, or your
own in $DOOMDIR/demos.org.
#+end_quote
* add-hook!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
;; With only one hook and one function, this is identical to `add-hook'. In that
;; case, use that instead.
(add-hook! 'some-mode-hook #'enable-something)
;; Adding many-to-many functions to hooks
(add-hook! some-mode #'enable-something #'and-another)
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) #'enable-something)
(add-hook! (one-mode second-mode) #'enable-something)
;; Appending and local hooks
(add-hook! (one-mode second-mode) :append #'enable-something)
(add-hook! (one-mode second-mode) :local #'enable-something)
;; With arbitrary forms
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))
(add-hook! (one-mode second-mode) :append :local (setq v 5) (setq a 2))
;; Inline named hook functions
(add-hook! '(one-mode-hook second-mode-hook)
(defun do-something ()
...)
(defun do-another-thing ()
...))
#+end_src
* TODO add-transient-hook!
:PROPERTIES:
:added: 3.0.0-pre
:END:
* after!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;;; `after!' will take:
;; An unquoted package symbol (the name of a package)
(after! helm ...)
;; An unquoted list of package symbols (i.e. BODY is evaluated once both magit
;; and git-gutter have loaded)
(after! (magit git-gutter) ...)
;; An unquoted, nested list of compound package lists, using any combination of
;; :or/:any and :and/:all
(after! (:or package-a package-b ...) ...)
(after! (:and package-a package-b ...) ...)
(after! (:and package-a (:or package-b package-c) ...) ...)
;; (Without :or/:any/:and/:all, :and/:all are implied.)
;; A common mistake is to pass it the names of major or minor modes, e.g.
(after! rustic-mode ...)
(after! python-mode ...)
;; But the code in them will never run! rustic-mode is in the `rustic' package
;; and python-mode is in the `python' package. This is what you want:
(after! rustic ...)
(after! python ...)
#+end_src
* appendq!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(let ((x '(a b c)))
(appendq! x '(c d e))
x)
#+end_src
#+RESULTS:
: (a b c c d e)
#+begin_src emacs-lisp
(let ((x '(a b c))
(y '(c d e))
(z '(f g)))
(appendq! x y z '(h))
x)
#+end_src
#+RESULTS:
: (a b c c d e f g h)
* cmd!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(map! "C-j" (cmd! (newline) (indent-according-to-mode)))
#+end_src
* cmd!!
:PROPERTIES:
:added: 3.0.0-pre
:END:
When ~newline~ is passed a numerical prefix argument (=C-u 5 M-x newline=), it
inserts N newlines. We can use ~cmd!!~ to easily create a keybinds that bakes in
the prefix arg into the command call:
#+begin_src emacs-lisp :eval no
(map! "C-j" (cmd!! #'newline 5))
#+end_src
Or to create aliases for functions that behave differently:
#+begin_src emacs-lisp :eval no
(fset 'insert-5-newlines (cmd!! #'newline 5))
;; The equivalent of C-u M-x org-global-cycle, which resets the org document to
;; its startup visibility settings.
(fset 'org-reset-global-visibility (cmd!! #'org-global-cycle '(4))
#+end_src
* cmds!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(map! :i [tab] (cmds! (and (modulep! :editor snippets)
(bound-and-true-p yas-minor-mode)
(yas-maybe-expand-abbrev-key-filter 'yas-expand))
#'yas-expand
(modulep! :completion company +tng)
#'company-indent-or-complete-common)
:m [tab] (cmds! (and (bound-and-true-p yas-minor-mode)
(evil-visual-state-p)
(or (eq evil-visual-selection 'line)
(not (memq (char-after) (list ?\( ?\[ ?\{ ?\} ?\] ?\))))))
#'yas-insert-snippet
(and (modulep! :editor fold)
(save-excursion (end-of-line) (invisible-p (point))))
#'+fold/toggle
(fboundp 'evil-jump-item)
#'evil-jump-item))
#+end_src
* custom-set-faces!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(custom-set-faces!
'(outline-1 :weight normal)
'(outline-2 :weight normal)
'(outline-3 :weight normal)
'(outline-4 :weight normal)
'(outline-5 :weight normal)
'(outline-6 :weight normal)
'(default :background "red" :weight bold)
'(region :background "red" :weight bold))
(custom-set-faces!
'((outline-1 outline-2 outline-3 outline-4 outline-5 outline-6)
:weight normal)
'((default region)
:background "red" :weight bold))
(let ((red-bg-faces '(default region)))
(custom-set-faces!
`(,(cl-loop for i from 0 to 6 collect (intern (format "outline-%d" i)))
:weight normal)
`(,red-bg-faces
:background "red" :weight bold)))
;; You may utilise `doom-themes's theme API to fetch or tweak colors from their
;; palettes. No need to wait until the theme or package is loaded. e.g.
(custom-set-faces!
`(outline-1 :foreground ,(doom-color 'red))
`(outline-2 :background ,(doom-color 'blue)))
#+end_src
* custom-theme-set-faces!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(custom-theme-set-faces! 'doom-one
'(outline-1 :weight normal)
'(outline-2 :weight normal)
'(outline-3 :weight normal)
'(outline-4 :weight normal)
'(outline-5 :weight normal)
'(outline-6 :weight normal)
'(default :background "red" :weight bold)
'(region :background "red" :weight bold))
(custom-theme-set-faces! '(doom-one-theme doom-one-light-theme)
'((outline-1 outline-2 outline-3 outline-4 outline-5 outline-6)
:weight normal)
'((default region)
:background "red" :weight bold))
(let ((red-bg-faces '(default region)))
(custom-theme-set-faces! '(doom-one-theme doom-one-light-theme)
`(,(cl-loop for i from 0 to 6 collect (intern (format "outline-%d" i)))
:weight normal)
`(,red-bg-faces
:background "red" :weight bold)))
;; You may utilise `doom-themes's theme API to fetch or tweak colors from their
;; palettes. No need to wait until the theme or package is loaded. e.g.
(custom-theme-set-faces! 'doom-one
`(outline-1 :foreground ,(doom-color 'red))
`(outline-2 :background ,(doom-color 'blue)))
#+end_src
* TODO defer-feature!
:PROPERTIES:
:added: 3.0.0-pre
:END:
* TODO defer-until!
:PROPERTIES:
:added: 3.0.0-pre
:END:
* disable-packages!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; Disable packages enabled by DOOM
(disable-packages! some-package second-package)
#+end_src
* doom!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(doom! :completion
company
ivy
;;helm
:tools
(:if (featurep :system 'macos) macos)
docker
lsp
:lang
(cc +lsp)
(:cond ((string= system-name "work-pc")
python
rust
web)
((string= system-name "writing-pc")
(org +dragndrop)
ruby))
(:if (featurep :system 'linux)
(web +lsp)
web)
:config
literate
(default +bindings +smartparens))
(doom!
(pin "v3.0.0")
(source "modules/") ; Modules in $DOOMDIR/modules/*/*
(source :name doom :repo "doomemacs/modules" :pin "v21.12.0") ; Doom's default modules
(source :name contrib :repo "doomemacs/contrib-modules" :pin "v21.12.0") ; Community-contributed
;; Examples:
(source :name my :repo "my/modules" :root "unorthodox/path/to/modules/")
(source :name more :host gitlab :repo "more/modules")
;;; To enable (or disable) flags globally, they can be given at top-level:
+lsp -tree-sitter
;;;; Examples of explicit and/or remote modules:
:lang
(rust :repo "doomemacs/modules" :branch "somePR" :pin "1a2b3c4d"
:path "lang/rust"
:flags '(-lsp))
;; A local, out-of-tree module
(python :path "/nonstandard/location/for/modules/python"
:flags '(+pyenv +conda))
(cc :source 'doom) ; explicit source
(agda :source '(doom more)) ; multiple sources
:lang
(clojure +lsp) ; shorthand format still works for flags
nix
;; Conditional modules
(:os :if (featurep :system 'macos)) ; category-wide
macos
(tty :if (equal (system-name) "headless-machine")) ; per-module
...)
#+end_src
* file-exists-p!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(file-exists-p! "init.el" doom-emacs-dir)
#+end_src
#+begin_src emacs-lisp
(file-exists-p! (and (or "doesnotexist" "init.el")
"LICENSE")
doom-emacs-dir)
#+end_src
* fn!
#+begin_src emacs-lisp
(mapcar (fn! (symbol-name %)) '(hello world))
#+end_src
#+begin_src emacs-lisp
(seq-sort (fn! (string-lessp (symbol-name %1)
(symbol-name %2)))
'(bonzo foo bar buddy doomguy baz zombies))
#+end_src
#+begin_src emacs-lisp
(format "You passed %d arguments to this function"
(funcall (fn! (length %*)) :foo :bar :baz "hello" 123 t))
#+end_src
* kbd!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(map! "," (kbd! "SPC")
";" (kbd! ":"))
#+end_src
* lambda!
#+begin_src emacs-lisp
(mapcar (lambda! ((&key foo bar baz))
(list foo bar baz))
'((:foo 10 :bar 25)
(:baz hello :boop nil)
(:bar 42)))
#+end_src
* load!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;;; Lets say we're in ~/.doom.d/config.el
(load! "lisp/module") ; loads ~/.doom.d/lisp/module.el
(load! "somefile" doom-emacs-dir) ; loads ~/.emacs.d/somefile.el
(load! "anotherfile" doom-user-dir) ; loads ~/.doom.d/anotherfile.el
;; If you don't want a `load!' call to throw an error if the file doesn't exist:
(load! "~/.maynotexist" nil t)
#+end_src
* map!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(map! :map magit-mode-map
:m "C-r" 'do-something ; C-r in motion state
:nv "q" 'magit-mode-quit-window ; q in normal+visual states
"C-x C-r" 'a-global-keybind
:g "C-x C-r" 'another-global-keybind ; same as above
(:when (featurep :system 'macos)
:n "M-s" 'some-fn
:i "M-o" (cmd! (message "Hi"))))
(map! (:when (modulep! :completion company) ; Conditional loading
:i "C-@" #'+company/complete
(:prefix "C-x" ; Use a prefix key
:i "C-l" #'+company/whole-lines)))
(map! (:when (modulep! :lang latex) ; local conditional
(:map LaTeX-mode-map
:localleader ; Use local leader
:desc "View" "v" #'TeX-view)) ; Add which-key description
:leader ; Use leader key from now on
:desc "Eval expression" ";" #'eval-expression)
#+end_src
These are side-by-side comparisons, showing how to bind keys with and without
~map!~:
#+begin_src emacs-lisp :eval no
;; bind a global key
(global-set-key (kbd "C-x y") #'do-something)
(map! "C-x y" #'do-something)
;; bind a key on a keymap
(define-key emacs-lisp-mode-map (kbd "C-c p") #'do-something)
(map! :map emacs-lisp-mode-map "C-c p" #'do-something)
;; unbind a key defined elsewhere
(define-key lua-mode-map (kbd "SPC m b") nil)
(map! :map lua-mode-map "SPC m b" nil)
;; bind multiple keys
(global-set-key (kbd "C-x x") #'do-something)
(global-set-key (kbd "C-x y") #'do-something-else)
(global-set-key (kbd "C-x z") #'do-another-thing)
(map! "C-x x" #'do-something
"C-x y" #'do-something-else
"C-x z" #'do-another-thing)
;; bind global keys in normal mode
(evil-define-key* 'normal 'global
(kbd "C-x x") #'do-something
(kbd "C-x y") #'do-something-else
(kbd "C-x z") #'do-another-thing)
(map! :n "C-x x" #'do-something
:n "C-x y" #'do-something-else
:n "C-x z" #'do-another-thing)
;; or on a deferred keymap
(evil-define-key 'normal emacs-lisp-mode-map
(kbd "C-x x") #'do-something
(kbd "C-x y") #'do-something-else
(kbd "C-x z") #'do-another-thing)
(map! :map emacs-lisp-mode-map
:n "C-x x" #'do-something
:n "C-x y" #'do-something-else
:n "C-x z" #'do-another-thing)
;; or multiple maps
(dolist (map (list emacs-lisp-mode go-mode-map ivy-minibuffer-map))
(evil-define-key '(normal insert) map
"a" #'a
"b" #'b
"c" #'c))
(map! :map (emacs-lisp-mode go-mode-map ivy-minibuffer-map)
:ni "a" #'a
:ni "b" #'b
:ni "c" #'c)
;; or in multiple states (order of states doesn't matter)
(evil-define-key* '(normal visual) emacs-lisp-mode-map (kbd "C-x x") #'do-something)
(evil-define-key* 'insert emacs-lisp-mode-map (kbd "C-x x") #'do-something-else)
(evil-define-key* '(visual normal insert emacs) emacs-lisp-mode-map (kbd "C-x z") #'do-another-thing)
(map! :map emacs-lisp-mode
:nv "C-x x" #'do-something ; normal+visual
:i "C-x y" #'do-something-else ; insert
:vnie "C-x z" #'do-another-thing) ; visual+normal+insert+emacs
;; You can nest map! calls:
(evil-define-key* '(normal visual) emacs-lisp-mode-map (kbd "C-x x") #'do-something)
(evil-define-key* 'normal go-lisp-mode-map (kbd "C-x x") #'do-something-else)
(map! (:map emacs-lisp-mode :nv "C-x x" #'do-something)
(:map go-lisp-mode :n "C-x x" #'do-something-else))
#+end_src
* package!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; To install a package that can be found on ELPA or any of the sources
;; specified in `straight-recipe-repositories':
(package! evil)
(package! js2-mode)
(package! rainbow-delimiters)
;; To disable a package included with Doom (which will no-op all its `after!'
;; and `use-package!' blocks):
(package! evil :disable t)
(package! rainbow-delimiters :disable t)
;; To install a package from a github repo
(package! so-long :host 'github :repo "hlissner/emacs-so-long")
;; If a package is particularly big and comes with submodules you don't need,
;; you can tell the package manager not to clone the repo recursively:
(package! ansible :nonrecursive t)
;; To pin a package to a specific commit:
(package! evil :pin "e7bc39de2f9")
;; ...or branch:
(package! evil :branch "stable")
;; To unpin a pinned package:
(package! evil :pin nil)
;; If you share your config between two computers, and don't want bin/doom
;; refresh to delete packages used only on one system, use :ignore
(package! evil :ignore (not (equal system-name "my-desktop")))
#+end_src
* prependq!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(let ((x '(a b c)))
(prependq! x '(c d e))
x)
#+end_src
#+RESULTS:
: (c d e a b c)
#+begin_src emacs-lisp
(let ((x '(a b c))
(y '(c d e))
(z '(f g)))
(prependq! x y z '(h))
x)
#+end_src
#+RESULTS:
: (c d e f g h a b c)
* pushnew!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(let ((list '(a b c)))
(pushnew! list 'c 'd 'e)
list)
#+end_src
#+RESULTS:
: (e d a b c)
* quiet!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; Enters recentf-mode without extra output
(quiet! (recentf-mode +1))
#+end_src
* remove-hook!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; With only one hook and one function, this is identical to `remove-hook'. In
;; that case, use that instead.
(remove-hook! 'some-mode-hook #'enable-something)
;; Removing N functions from M hooks
(remove-hook! some-mode #'enable-something #'and-another)
(remove-hook! some-mode #'(enable-something and-another))
(remove-hook! '(one-mode-hook second-mode-hook) #'enable-something)
(remove-hook! (one-mode second-mode) #'enable-something)
;; Removing buffer-local hooks
(remove-hook! (one-mode second-mode) :local #'enable-something)
;; Removing arbitrary forms (must be exactly the same as the definition)
(remove-hook! (one-mode second-mode) (setq v 5) (setq a 2))
#+end_src
* setq!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
;; Each of these have a setter associated with them, which must be triggered in
;; order for their new values to have an effect.
(setq! evil-want-Y-yank-to-eol nil
evil-want-C-u-scroll nil
evil-want-C-d-scroll nil)
#+end_src
* setq-hook!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; Set multiple variables after a hook
(setq-hook! 'markdown-mode-hook
line-spacing 2
fill-column 80)
;; Set variables after multiple hooks
(setq-hook! '(eshell-mode-hook term-mode-hook)
hscroll-margin 0)
#+end_src
* unsetq-hook!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(unsetq-hook! 'markdown-mode-hook line-spacing)
;; Removes the following variable hook
(setq-hook! 'markdown-mode-hook line-spacing 2)
;; Removing N variables from M hooks
(unsetq-hook! some-mode enable-something and-another)
(unsetq-hook! some-mode (enable-something and-another))
(unsetq-hook! '(one-mode-hook second-mode-hook) enable-something)
(unsetq-hook! (one-mode second-mode) enable-something)
#+end_src
* use-package!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
;; Use after-call to load package before hook
(use-package! projectile
:after-call (pre-command-hook after-find-file dired-before-readin-hook))
;; defer recentf packages one by one
(use-package! recentf
:defer-incrementally easymenu tree-widget timer
:after-call after-find-file)
;; This is equivalent to :defer-incrementally (abc)
(use-package! abc
:defer-incrementally t)
#+end_src
* versionp!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(versionp! "25.3" > "27.1")
#+end_src
#+RESULTS:
: nil
#+begin_src emacs-lisp
(versionp! "28.0" <= emacs-version <= "28.1")
#+end_src
#+RESULTS:
: t

View file

@ -35,7 +35,7 @@ and Emacs states, and for non-evil users.")
;;; Global keybind settings
(cond
(IS-MAC
(doom--system-macos-p
;; mac-* variables are used by the special emacs-mac build of Emacs by
;; Yamamoto Mitsuharu, while other builds use ns-*.
(setq mac-command-modifier 'super
@ -45,7 +45,7 @@ and Emacs states, and for non-evil users.")
;; Free up the right option for character composition
mac-right-option-modifier 'none
ns-right-option-modifier 'none))
(IS-WINDOWS
(doom--system-windows-p
(setq w32-lwindow-modifier 'super
w32-rwindow-modifier 'super)))

View file

@ -8,10 +8,19 @@
(defvar doom-modules (make-hash-table :test 'equal)
"A hash table of enabled modules. Set by `doom-initialize-modules'.")
(defvar doom-modules-dirs
(list (expand-file-name "modules/" doom-user-dir)
doom-modules-dir)
"A list of module root directories. Order determines priority.")
(define-obsolete-variable-alias 'doom-modules-dirs 'doom-module-load-path "3.0.0")
(defvar doom-module-load-path
(list (file-name-concat doom-user-dir "modules")
(file-name-concat doom-emacs-dir "modules"))
"A list of paths where Doom should search for modules.
Order determines priority (from highest to lowest).
Each entry is a string; an absolute path to the root directory of a module tree.
In other words, they should contain a two-level nested directory structure,
where the module's group and name was deduced from the first and second level of
directories. For example: if $DOOMDIR/modules/ is an entry, a
$DOOMDIR/modules/lang/ruby/ directory represents a ':lang ruby' module.")
;;; Module file variables
(defvar doom-module-init-file "init.el"
@ -41,6 +50,8 @@ NOT IMPLEMENTED YET. This file contains a module's metadata: their version,
maintainers, checks, features, submodules, debug information, etc. And are used
to locate modules in the user's file tree.")
;; DEPRECATED: Module warnings will be rewritten in v3, and this variable will no longer be needed.
(make-obsolete-variable 'doom-obsolete-modules nil "3.0.0")
(defconst doom-obsolete-modules
'((:feature (version-control (:emacs vc) (:ui vc-gutter))
(spellcheck (:checkers spell))
@ -83,6 +94,7 @@ syntax-checker modules obsolete. e.g. If :feature version-control is found in
your `doom!' block, a warning is emitted before replacing it with :emacs vc and
:ui vc-gutter.")
(make-obsolete-variable 'doom-inhibit-module-warnings nil "3.0.0")
(defvar doom-inhibit-module-warnings (not noninteractive)
"If non-nil, don't emit deprecated or missing module warnings at startup.")
@ -111,12 +123,12 @@ your `doom!' block, a warning is emitted before replacing it with :emacs vc and
;;
;;; `doom-module-context'
(defvar doom--empty-module-context [nil nil nil nil nil nil nil])
(defvar doom-module--empty-context [nil nil nil nil nil nil nil])
(eval-and-compile
(setplist 'doom-module-context '(index 0 initdepth 1 configdepth 2
group 3 name 4 flags 5 features 6)))
(defvar doom-module-context doom--empty-module-context
(put 'doom-module-context 'keys '(:index 0 :initdepth 1 :configdepth 2
:group 3 :name 4 :flags 5 :features 6)))
(defvar doom-module-context doom-module--empty-context
"A vector describing the module associated it with the active context.
Contains the following: [INDEX INITDEPTH CONFIGDEPTH :GROUP MODULE FLAGS FEATURES]
@ -124,7 +136,8 @@ Contains the following: [INDEX INITDEPTH CONFIGDEPTH :GROUP MODULE FLAGS FEATURE
Do not directly set this variable, only let-bind it.")
;; DEPRECATED: Remove this when byte-compilation is introduced to Doom core.
(defmacro doom-module--context-field (field) (get 'doom-module-context field))
(defmacro doom-module--context-field (field)
(plist-get (get 'doom-module-context 'keys) field))
(defun doom-module-context-get (field &optional context)
"Return the FIELD of CONTEXT.
@ -132,7 +145,9 @@ Do not directly set this variable, only let-bind it.")
FIELD should be one of `index', `initdepth', `configdepth', `group', `name',
`flags', or `features'. CONTEXT should be a `doom-module-context' vector. If
omitted, defaults to `doom-module-context'."
(aref (or context doom-module-context) (get 'doom-module-context field)))
(aref (or context doom-module-context)
(plist-get (get 'doom-module-context 'keys)
field)))
(defun doom-module-context (group &optional name)
"Create a `doom-module-context' from a module by GROUP and NAME.
@ -142,14 +157,14 @@ If NAME is omitted, GROUP is treated as a module key cons cell: (GROUP . NAME)."
(let ((key (if name (cons group name) group)))
(or (get (or (car-safe key) key)
(cdr-safe key))
doom--empty-module-context)))
doom-module--empty-context)))
(defun doom-module-context-key (&optional context)
"Return the module of the active `doom-module-context' as a module key."
(declare (side-effect-free t))
(let ((context (or context doom-module-context)))
(cons (aref context (doom-module--context-field group))
(aref context (doom-module--context-field name)))))
(cons (aref context (doom-module--context-field :group))
(aref context (doom-module--context-field :name)))))
(defmacro doom-module-context-with (module-key &rest body)
"Evaluate BODY with `doom-module-context' informed by MODULE-KEY."
@ -252,7 +267,7 @@ If PLIST consists of a single nil, the module is purged from memory instead."
PATHS-OR-ALL can either be a non-nil value or a list of directories. If given a
list of directories, return a list of module keys for all modules present
underneath it. If non-nil, return the same, but search `doom-modules-dirs'
underneath it. If non-nil, return the same, but search `doom-module-load-path'
(includes :core and :user). Modules that are enabled are sorted first by their
:depth, followed by disabled modules in lexicographical order (unless a :depth
is specified in their .doommodule).
@ -264,7 +279,7 @@ configdepth. See `doom-module-set' for details."
(append (seq-remove #'cdr (doom-module-list nil initorder?))
(doom-files-in (if (listp paths-or-all)
paths-or-all
doom-modules-dirs)
doom-modules-load-path)
:map #'doom-module-from-path
:type 'dirs
:mindepth 1
@ -294,7 +309,7 @@ If the category isn't enabled this returns nil. For finding disabled modules use
path)))
(defun doom-module-locate-path (category &optional module file)
"Searches `doom-modules-dirs' to find the path to a module.
"Searches `doom-module-load-path' to find the path to a module.
CATEGORY is a keyword (e.g. :lang) and MODULE is a symbol (e.g. 'python). FILE
is a string that will be appended to the resulting path. If no path exists, this
@ -310,8 +325,8 @@ returns nil, otherwise an absolute path."
(if file
;; PERF: locate-file-internal is a little faster for finding files,
;; but its interface for finding directories is clumsy.
(locate-file-internal path doom-modules-dirs '("" ".elc" ".el"))
(cl-loop for default-directory in doom-modules-dirs
(locate-file-internal path doom-module-load-path '("" ".elc" ".el"))
(cl-loop for default-directory in doom-module-load-path
if (file-exists-p path)
return (expand-file-name path)))))))
@ -320,8 +335,7 @@ returns nil, otherwise an absolute path."
MODULE-LIST is a list of cons cells (GROUP . NAME). See `doom-module-list' for
an example."
(cl-loop with file = (file-name-sans-extension file)
for (group . name) in module-list
(cl-loop for (group . name) in (or module-list (doom-module-list))
if (doom-module-locate-path group name file)
collect it))
@ -342,14 +356,15 @@ If ENABLED-ONLY, return nil if the containing module isn't enabled."
((file-in-directory-p path doom-user-dir)
(cons :user nil))))))
(defun doom-module-load-path (&optional module-dirs)
(defun doom-module-load-path (&optional module-load-path)
"Return a list of file paths to activated modules.
The list is in no particular order and its file paths are absolute. If
MODULE-DIRS is non-nil, include all modules (even disabled ones) available in
those directories."
(declare (pure t) (side-effect-free t))
(cl-loop for (cat . mod) in (doom-module-list module-dirs)
(cl-loop with module-load-path = (or module-load-path doom-module-load-path)
for (cat . mod) in (doom-module-list module-load-path)
collect (doom-module-locate-path cat mod)))
(defun doom-module-mplist-map (fn mplist)
@ -462,20 +477,20 @@ For more about modules and flags, see `doom!'."
;; PERF: This macro bypasses the module API to spare startup their runtime
;; cost, as `modulep!' gets called *a lot* during startup. In the future,
;; Doom will byte-compile its core files. At that time, we can use it again.
(and (cond (flag (memq flag (aref (or (get category module) doom--empty-module-context)
(doom-module--context-field flags))))
(and (cond (flag (memq flag (aref (or (get category module) doom-module--empty-context)
(doom-module--context-field :flags))))
(module (get category module))
((aref doom-module-context 0)
(memq category (aref doom-module-context
(doom-module--context-field flags))))
(doom-module--context-field :flags))))
((let ((file
;; This must be expanded at the call site, not in
;; `modulep!'s definition, to get the file we want.
(macroexpand '(file!))))
(if-let (module (doom-module-from-path file))
(memq category (aref (or (get (car module) (cdr module))
doom--empty-module-context)
(doom-module--context-field flags)))
doom-module--empty-context)
(doom-module--context-field :flags)))
(error "(modulep! %s %s %s) couldn't figure out what module it was called from (in %s)"
category module flag file)))))
t))

View file

@ -343,7 +343,7 @@ Defaults to the profile at `doom-profile-default'."
";; This file was autogenerated; do not edit it by hand!\n")
;; 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
;; compatible, and many packages (including Doom), bake in absolute
;; paths into their caches that need to be refreshed.
(prin1 `(unless (equal doom-version ,doom-version)
(error ,(concat
@ -439,7 +439,7 @@ Defaults to the profile at `doom-profile-default'."
(doom-autoloads--scan
(append (doom-glob doom-core-dir "lib/*.el")
(cl-loop for dir
in (append (doom-module-load-path doom-modules-dirs)
in (append (doom-module-load-path)
(list doom-user-dir))
if (doom-glob dir "autoload.el") collect (car it)
if (doom-glob dir "autoload/*.el") append it)

View file

@ -147,7 +147,7 @@ c) are not valid projectile projects."
(projectile-serialize-cache))))
;; Some MSYS utilities auto expanded the `/' path separator, so we need to prevent it.
(when IS-WINDOWS
(when doom--system-windows-p
(setenv "MSYS_NO_PATHCONV" "1") ; Fix path in Git Bash
(setenv "MSYS2_ARG_CONV_EXCL" "--path-separator")) ; Fix path in MSYS2
@ -192,11 +192,11 @@ And if it's a function, evaluate it."
(concat (format "%s . -0 -H --color=never --type file --type symlink --follow --exclude .git %s"
bin (if (version< version "8.3.0")
"" "--strip-cwd-prefix"))
(if IS-WINDOWS " --path-separator=/"))))
(if doom--system-windows-p " --path-separator=/"))))
;; Otherwise, resort to ripgrep, which is also faster than find
((executable-find "rg" t)
(concat "rg -0 --files --follow --color=never --hidden -g!.git"
(if IS-WINDOWS " --path-separator=/")))
(if doom--system-windows-p " --path-separator=/")))
("find . -type f -print0"))))
(defadvice! doom--projectile-default-generic-command-a (fn &rest args)

View file

@ -120,7 +120,7 @@
;; focus when it is started, among other things, so enable the menu-bar for
;; GUI frames, but keep it disabled in terminal frames because there it
;; activates an ugly, in-frame menu bar.
(eval-when! IS-MAC
(eval-when! doom--system-macos-p
(add-hook! '(window-setup-hook after-make-frame-functions)
(defun doom-restore-menu-bar-in-gui-frames-h (&optional frame)
(when-let (frame (or frame (selected-frame)))
@ -137,7 +137,7 @@
(setq default-input-method nil)
;; ...And the clipboard on Windows could be in a wider encoding (UTF-16), so
;; leave Emacs to its own devices.
(eval-when! IS-WINDOWS
(eval-when! (not doom--system-windows-p)
(setq selection-coding-system 'utf-8))

View file

@ -99,7 +99,7 @@
;; 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
;; packages (including Doom), bake 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)
@ -107,7 +107,30 @@
"recompile it.")
emacs-version old-version)))
;;; Custom features
;;; Custom features & global constants
;; Doom has its own features that its modules, CLI, and user extensions can
;; announce, and don't belong in `features', so they are stored here, which can
;; include information about the external system environment.
(defconst doom-features
(pcase system-type
('darwin '(macos bsd))
((or 'cygwin 'windows-nt 'ms-dos) '(windows))
((or 'gnu 'gnu/linux) '(linux))
((or 'gnu/kfreebsd 'berkeley-unix) '(linux bsd)))
"A list of symbols denoting available features in the active Doom profile.")
;; Convenience aliases for internal use only (may be removed later).
(defconst doom-system (car doom-features))
(defconst doom--system-windows-p (eq 'windows doom-system))
(defconst doom--system-macos-p (eq 'macos doom-system))
(defconst doom--system-linux-p (eq 'linux doom-system))
;; `system-type' is esoteric, so I create a pseudo feature as a stable and
;; consistent alternative, and all while using the same `featurep' interface
;; we're already familiar with.
(push :system features)
(put :system 'subfeatures doom-features)
;; Emacs needs a more consistent way to detect build features, and the docs
;; claim `system-configuration-features' is not da way. Some features (that
;; don't represent packages) can be found in `features' (which `featurep'
@ -126,25 +149,30 @@
(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))
(with-no-warnings
(defconst IS-MAC doom--system-macos-p)
(defconst IS-LINUX doom--system-linux-p)
(defconst IS-WINDOWS doom--system-windows-p)
(defconst IS-BSD (memq 'bsd doom-features))
(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 'IS-MAC "Use (featurep :system 'macos) instead" "3.0.0")
(make-obsolete-variable 'IS-LINUX "Use (featurep :system 'linux) instead" "3.0.0")
(make-obsolete-variable 'IS-WINDOWS "Use (featurep :system 'windows) instead" "3.0.0")
(make-obsolete-variable 'IS-BSD "Use (featurep :system 'bsd) instead" "3.0.0")
(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"))
(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 doom--system-windows-p
(when-let (realhome
(and (null (getenv-internal "HOME"))
(getenv "USERPROFILE")))
@ -228,7 +256,7 @@ These files should not be shared across systems. By default, it is used by
(define-obsolete-variable-alias 'doom-etc-dir 'doom-data-dir "3.0.0")
(defvar doom-data-dir
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(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
@ -247,7 +275,7 @@ For profile-local data files, use `doom-profile-data-dir' instead.")
(defvar doom-cache-dir
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(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
@ -266,7 +294,7 @@ For profile-local cache files, use `doom-profile-cache-dir' instead.")
(defvar doom-state-dir
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(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
@ -470,8 +498,8 @@ users).")
(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
;; relevant to this session, but `command-line-1' still processes.
(unless doom--system-macos-p
(setq command-line-ns-option-alist nil))
(unless (memq initial-window-system '(x pgtk))
(setq command-line-x-option-alist nil)))))
@ -649,7 +677,7 @@ of 'doom sync' or 'doom gc'."
gnutls-algorithm-priority
(when (boundp 'libgnutls-version)
(concat "SECURE128:+SECURE192:-VERS-ALL"
(if (and (not IS-WINDOWS)
(if (and (not doom--system-windows-p)
(>= libgnutls-version 30605))
":+VERS-TLS1.3")
":+VERS-TLS1.2"))
@ -713,6 +741,8 @@ appropriately against `noninteractive' or the `cli' context."
(defun doom--begin-init-h ()
"Begin the startup process."
(when (doom-context-push 'init)
;; HACK: Ensure OS checks are as fast as possible (given their ubiquity).
(setq features (cons :system (delq :system features)))
;; 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))

View file

@ -186,7 +186,7 @@ non-nil, treat FILES as pre-generated autoload files instead."
(let ((load-file-name file)
(load-path
(append (list doom-user-dir)
doom-modules-dirs
doom-module-load-path
load-path)))
(condition-case _
(while t

View file

@ -260,7 +260,8 @@ ready to be pasted in a bug report on github."
(bound-and-true-p emacs-repository-branch)
(and (stringp emacs-repository-version)
(substring emacs-repository-version 0 9))
(symlink-path doom-emacs-dir))))
(format "EMACSDIR=%s" (symlink-path doom-emacs-dir))
(format "EMACS=%s" (expand-file-name invocation-name invocation-directory)))))
(doom . ,(list doom-version
(if doom-profile
(format "PROFILE=%s@%s"
@ -300,7 +301,7 @@ ready to be pasted in a bug report on github."
'compiled-user-config)
(if (doom-files-in doom-core-dir :type 'files :match "\\.elc$")
'compiled-core)
(if (doom-files-in doom-modules-dirs :type 'files :match "\\.elc$")
(if (doom-files-in doom-module-load-path :type 'files :match "\\.elc$")
'compiled-modules)))))
(custom
,@(when (and (stringp custom-file)

View file

@ -4,8 +4,8 @@
(defun doom-system-distro ()
"Return a symbol representing the installed distro."
(with-memoization (get 'doom-system-distro 'cached-value)
(cond (IS-WINDOWS 'windows)
(IS-MAC 'macos)
(cond (doom--system-windows-p 'windows)
(doom--system-macos-p 'macos)
((ignore-errors
(with-file-contents! "/etc/os-release"
(when (re-search-forward "^ID=\"?\\([^\"\n]+\\)\"?" nil t)

View file

@ -20,8 +20,8 @@
:pin "b3760f5829dba37e855add7323304561eb57a3d4")
;; doom-ui.el
(package! all-the-icons :pin "be9d5dcda9c892e8ca1535e288620eec075eb0be")
(package! nerd-icons :pin "e109d09b95706bb93c821b1229ca09cf00195690")
(package! all-the-icons :pin "ee414384938ccf2ce93c77d717b85dc5538a257d")
(package! nerd-icons :pin "c6a4acf19454b415cba1c43daf4bfca8fccdd9ba")
(package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942")
(package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307")
(package! rainbow-delimiters :pin "f40ece58df8b2f0fb6c8576b527755a552a5e763")
@ -29,7 +29,7 @@
;; doom-editor.el
(package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319")
(package! dtrt-indent :pin "e0630f74f915c6cded05f76f66d66e540fcc37c3")
(package! dtrt-indent :pin "0230ec503283b895bd3df6c1e30b35a01aa0b9af")
(package! helpful :pin "a32a5b3d959a7fccf09a71d97b3d7c888ac31c69")
(package! pcre2el :pin "018531ba0cf8e2b28d1108136a0e031b6a45f1c1")
(package! smartparens :pin "0778a8a84064cf2bc3a9857bd0e7a4619cc1e5c3")
@ -40,13 +40,13 @@
:pin "572a10c11b6cb88293de48acbb59a059d36f9ba5")
;; doom-projects.el
(package! projectile :pin "9446ea92d28462aeb37846a8be0a0c97a7bc0cee")
(package! project :pin "f64bcf065c0731caecbdcff5ca1c7f2d711b5b1e")
(package! projectile :pin "e45f0b0cc43fdc066e7971ff3ed3bf4c78015ed0")
(package! project :pin "10a6b691e36ff897fb2a4b48896e08818afa77b0")
;; doom-keybinds.el
(package! general :pin "833dea2c4a60e06fcd552b653dfc8960935c9fb4")
(package! general :pin "bda777cd303db217fd2fbf2087eff40ec4aafda1")
(package! which-key :pin "4d20bc852545a2e602f59084a630f888542052b1")
(package! compat
:recipe (:host github :repo "emacs-compat/compat")
:pin "ea8de2ea18cf7c348aadb6eb2aeb2a9d840bd064")
:pin "eb8fbfa5582a8e5880e2eaa66d15d498bca6a45a")