dev: merging from main

This commit is contained in:
Matt Nish-Lapidus 2024-03-29 10:45:55 -04:00
commit f94083403d
496 changed files with 5618 additions and 6088 deletions

View file

@ -2,6 +2,7 @@
name: 📝 Bug Report name: 📝 Bug Report
description: Report something that isn't working as intended description: Report something that isn't working as intended
labels: ["is:bug", "needs-triage"] labels: ["is:bug", "needs-triage"]
projects: ["doomemacs/2"]
body: body:
- type: markdown - type: markdown
attributes: attributes:
@ -32,9 +33,8 @@ body:
Doom. Doom.
required: true required: true
- label: > - label: >
The issue can be reproduced on a stable release of Emacs, such as 27 The issue can be reproduced on a stable release of Emacs, such as 27,
or 28. *(Doom does not support development builds like 29+ or any 28, or 29. *(Unstable versions end in .50, .60, or .9x)*
version ending in .50 or .9x)*
required: true required: true
- type: markdown - type: markdown
attributes: attributes:

View file

@ -1,8 +0,0 @@
name: Add issues to project
on:
issues:
types: [opened]
jobs:
add-to-project:
uses: doomemacs/ci/.github/workflows/add-to-project.yml@legacy
secrets: inherit

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
# generated by macOS
.DS_Store
# machine generated doom profiles or metadata # machine generated doom profiles or metadata
/profiles/*.el /profiles/*.el
/.local*/ /.local*/

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014-2022 Henrik Lissner. Copyright (c) 2014-2024 Henrik Lissner.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View file

@ -5,7 +5,7 @@
[Install](#install) • [Documentation] • [FAQ] • [Screenshots] • [Contribute](#contribute) [Install](#install) • [Documentation] • [FAQ] • [Screenshots] • [Contribute](#contribute)
![Made with Doom Emacs](https://img.shields.io/github/tag/doomemacs/doomemacs.svg?style=flat-square&label=release&color=58839b) ![Made with Doom Emacs](https://img.shields.io/github/tag/doomemacs/doomemacs.svg?style=flat-square&label=release&color=58839b)
![Supports Emacs 27.129.1](https://img.shields.io/badge/Supports-Emacs_27.129.1-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white) ![Supports Emacs 27.129.2](https://img.shields.io/badge/Supports-Emacs_27.129.2-blueviolet.svg?style=flat-square&logo=GNU%20Emacs&logoColor=white)
![Latest commit](https://img.shields.io/github/last-commit/doomemacs/doomemacs/master?style=flat-square) ![Latest commit](https://img.shields.io/github/last-commit/doomemacs/doomemacs/master?style=flat-square)
![Build status: master](https://img.shields.io/github/workflow/status/doomemacs/doomemacs/CI/master?style=flat-square) ![Build status: master](https://img.shields.io/github/workflow/status/doomemacs/doomemacs/CI/master?style=flat-square)
[![Discord Server](https://img.shields.io/discord/406534637242810369?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)][Discord] [![Discord Server](https://img.shields.io/discord/406534637242810369?color=738adb&label=Discord&logo=discord&logoColor=white&style=flat-square)][Discord]
@ -98,20 +98,23 @@ Check out [the FAQ][FAQ] for answers to common questions about the project.
# Prerequisites # Prerequisites
+ Git 2.23+ - Git 2.23+
+ Emacs 27.129.1 (**Recommended: 29.1 + - Emacs 27.129.2 (**Recommended: 29.2 +
[native-comp](https://www.emacswiki.org/emacs/GccEmacs)**) [native-comp](https://www.emacswiki.org/emacs/GccEmacs)**)
> :warning: Unstable and pre-release builds of Emacs -- which end in `.50`, - [ripgrep] 11.0+
> `.60`, or `.9X` (e.g. `28.1.91`) -- **are not officially supported**. There - GNU `find`
> *is* some effort to support Emacs HEAD, however. [Follow this Discourse - *OPTIONAL:* [fd] 7.3.0+ (improves file indexing performance for some commands)
> post](https://discourse.doomemacs.org/t/3241) for details.
+ [ripgrep] 11.0+ > [!WARNING]
+ GNU `find` > Unstable and pre-release builds of Emacs -- which end in `.50`, `.60`, or
+ *OPTIONAL:* [fd] 7.3.0+ (improves file indexing performance for some commands) > `.9X` (e.g. `28.1.91`) -- **are not officially supported**. There *is* some
> effort to support Emacs HEAD, however. [Follow this Discourse
Doom is comprised of [~150 optional modules][Modules], some of which may have > post](https://discourse.doomemacs.org/t/3241) for details.
additional dependencies. [Visit their documentation][Modules] or run `bin/doom
doctor` to check for any that you may have missed. > [!IMPORTANT]
> Doom is comprised of [~150 optional modules][Modules], some of which may have
> additional dependencies. [Visit their documentation][Modules] or run `bin/doom
> doctor` to check for any that you may have missed.
# Install # Install
@ -135,8 +138,6 @@ commands you should know about:
+ `doom env` to dump a snapshot of your shell environment to a file that Doom + `doom env` to dump a snapshot of your shell environment to a file that Doom
will load at startup. This allows Emacs to inherit your `PATH`, among other will load at startup. This allows Emacs to inherit your `PATH`, among other
things. things.
+ `doom build` to recompile all installed packages (use this if you up/downgrade
Emacs).
# Roadmap # Roadmap

View file

@ -89,9 +89,9 @@
(user-error (message "Error: %s" (cadr e)) (user-error (message "Error: %s" (cadr e))
(kill-emacs 2))) (kill-emacs 2)))
;; UX: Abort if the user is using 'doom' as root, unless ~/.config/emacs is ;; UX: Abort if the user is using 'doom' as root, unless $EMACSDIR is owned by
;; owned by root, in which case we assume the user genuinely wants root to be ;; root, in which case we can safely assume the user genuinely wants root to
;; their primary user account for Emacs. ;; be their primary user account for this session.
(when (equal 0 (user-real-uid)) (when (equal 0 (user-real-uid))
(unless (equal 0 (file-attribute-user-id (file-attributes doom-emacs-dir))) (unless (equal 0 (file-attribute-user-id (file-attributes doom-emacs-dir)))
(message (message
@ -271,10 +271,8 @@ SEE ALSO:
(defcli-autoload! ((profiles profile))) (defcli-autoload! ((profiles profile)))
(defcli-autoload! ((upgrade up))) (defcli-autoload! ((upgrade up)))
(defcli-autoload! (env)) (defcli-autoload! (env))
(defcli-autoload! ((build b purge p rollback)) "packages") (defcli-autoload! ((build b purge p gc rollback)) "packages")
(defcli-autoload! ((install i))) (defcli-autoload! ((install i)))
(defcli-autoload! ((compile c)))
(defcli-autoload! (clean) "compile")
;; TODO Post-3.0 commands ;; TODO Post-3.0 commands
;; (load! "gc" dir) ;; (load! "gc" dir)
@ -282,8 +280,6 @@ SEE ALSO:
;; (load! "nuke" dir) ;; (load! "nuke" dir)
;; (load! "package" dir) ;; (load! "package" dir)
;; (load! "profile" dir) ;; (load! "profile" dir)
;; (defcli-obsolete! ((compile c)) (sync "--compile") "v3.0.0")
;; (defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0")
) )
(defcli-group! "Diagnostics" (defcli-group! "Diagnostics"

View file

@ -173,7 +173,7 @@
behaviour for known commands. behaviour for known commands.
#+begin_quote #+begin_quote
📌 Doom users with evil enabled will find the universal argument on [[kbd:][SPC u]] 󰐃 Doom users with evil enabled will find the universal argument on [[kbd:][SPC u]]
instead than [[kbd:][C-u]]. instead than [[kbd:][C-u]].
#+end_quote #+end_quote

View file

@ -5,6 +5,12 @@
#+subtitle: Samples of Emacs/Doom dotfiles, concepts, and sub-projects #+subtitle: Samples of Emacs/Doom dotfiles, concepts, and sub-projects
#+property: header-args:elisp :results pp #+property: header-args:elisp :results pp
#+begin_quote
󰐃 Our documentation was designed to be read in Doom Emacs ([[kbd:][M-x doom/help]]) or
online at https://docs.doomemacs.org. Avoid reading it elsewhere (like
Github), where it will be rendered incorrectly.
#+end_quote
* Introduction * Introduction
Examples speak louder than technical explanations, so this file exists to house Examples speak louder than technical explanations, so this file exists to house
examples of Doom's (and Emacs') concepts, libraries, dotfiles, and more, for examples of Doom's (and Emacs') concepts, libraries, dotfiles, and more, for
@ -28,33 +34,6 @@ of our contributing guide first.
This section is dedicated to examples of concepts and libraries that can benefit This section is dedicated to examples of concepts and libraries that can benefit
all Emacs users, whether or not they use Doom. all Emacs users, whether or not they use Doom.
** TODO Emacs Lisp :demos:
**** file-name-with-extension
:PROPERTIES:
:added: 28.1
:END:
#+begin_src emacs-lisp
(file-name-with-extension "some/file.cpp" "h")
#+end_src
#+RESULTS:
: some/file.h
**** file-name-concat
:PROPERTIES:
:added: 28.1
:END:
#+begin_src emacs-lisp
(file-name-concat user-emacs-directory "lisp" "file.el")
#+end_src
#+begin_src emacs-lisp
(file-name-concat "foo" "bar" "baz")
#+end_src
#+RESULTS:
: foo/bar/baz
** TODO Templates ** TODO Templates
*** TODO Emacs package *** TODO Emacs package
*** TODO Dynamic module *** TODO Dynamic module
@ -64,655 +43,6 @@ This section is dedicated to examples of concepts and libraries only relevant to
Doom and its users. These are intended to be demonstrations, not substitutes for Doom and its users. These are intended to be demonstrations, not substitutes for
documentation. documentation.
** TODO Emacs Lisp :demos:
*** doom-lib
**** 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)
**** 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
**** file-exists-p!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp
(file-exists-p! "init.el" doom-emacs-dir)
#+end_src
#+RESULTS:
: /home/hlissner/.emacs.d/init.el
#+begin_src emacs-lisp
(file-exists-p! (and (or "doesnotexist" "init.el")
"LICENSE")
doom-emacs-dir)
#+end_src
#+RESULTS:
: /home/hlissner/.emacs.d/LICENSE
**** 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
**** 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
**** 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
**** 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 IS-MAC
: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
**** 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)
**** 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)
**** 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
**** 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
*** doom-modules
**** doom!
:PROPERTIES:
:added: 3.0.0-pre
:END:
#+begin_src emacs-lisp :eval no
(doom! :completion
company
ivy
;;helm
:tools
(:if IS-MAC macos)
docker
lsp
:lang
(cc +lsp)
(:cond ((string= system-name "work-pc")
python
rust
web)
((string= system-name "writing-pc")
(org +dragndrop)
ruby))
(:if IS-LINUX
(web +lsp)
web)
:config
literate
(default +bindings +smartparens))
#+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
**** 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 :recipe (: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 :recipe (:nonrecursive t))
;; To pin a package to a specific commit:
(package! evil :pin "e7bc39de2f9")
;; ...or branch:
(package! evil :recipe (: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
*** doom-cli
**** TODO defcli!
**** TODO defcli-alias!
**** TODO defcli-obsolete!
**** TODO defcli-stub!
**** TODO defcli-autoload!
**** TODO defcli-group!
**** TODO exit!
**** TODO call!
**** TODO run!
**** TODO sh!
**** TODO sh!!
**** TODO git!
**** TODO def-cli-context-get
**** TODO def-cli-context-put
**** TODO def-cli-context-find-option
**** TODO def-cli-call
**** TODO def-cli-exit
**** TODO def-cli-load
**** TODO def-cli-load-all
**** TODO doom-cli-find
**** TODO doom-cli-get
**** TODO doom-cli-prop
**** TODO doom-cli-subcommands
**** TODO doom-cli-aliases
*** TODO lib/files.el
**** TODO doom-path
**** TODO doom-glob
**** TODO doom-dir
**** TODO doom-files-in
**** TODO doom-file-cookie-p
**** TODO file-exists-p!
**** TODO doom-file-size
**** TODO doom-file-line-count
**** TODO doom-directory-size
**** TODO doom-file-read
**** TODO doom-file-write
**** TODO with-file-contents!
** TODO Configuration files ** TODO Configuration files
*** =profiles.el= *** =profiles.el=
:PROPERTIES: :PROPERTIES:
@ -779,7 +109,7 @@ Here is an exhaustive example of all its syntax and capabilities:
(profile3 (profile3
...)) ...))
#+end_src #+end_src
*** =.doomprofile= *** =.doomprofile=
:PROPERTIES: :PROPERTIES:
:ID: ac37ac6f-6082-4c34-b98c-962bc1e528c9 :ID: ac37ac6f-6082-4c34-b98c-962bc1e528c9

View file

@ -5,6 +5,12 @@
#+subtitle: Answers to common issues and questions #+subtitle: Answers to common issues and questions
#+startup: nonum show2levels* #+startup: nonum show2levels*
#+begin_quote
󰐃 Our documentation was designed to be read in Doom Emacs ([[kbd:][M-x doom/help]]) or
online at https://docs.doomemacs.org. Avoid reading it elsewhere (like
Github) where it will be rendered incorrectly.
#+end_quote
* General * General
:PROPERTIES: :PROPERTIES:
:ID: 3c17177d-8ba9-4d1a-a279-b6dea21c8a9a :ID: 3c17177d-8ba9-4d1a-a279-b6dea21c8a9a
@ -242,8 +248,9 @@ Doom exposes a couple variables for setting fonts. They are:
- [[var:doom-variable-pitch-font]]: used for non-monospace fonts (e.g. when using - [[var:doom-variable-pitch-font]]: used for non-monospace fonts (e.g. when using
variable-pitch-mode or mixed-pitch-mode). Popular for text modes, like Org or variable-pitch-mode or mixed-pitch-mode). Popular for text modes, like Org or
Markdown. Markdown.
- [[var:doom-unicode-font]]: used for rendering unicode glyphs. This is ~Symbola~ by - [[var:doom-emoji-font]]: used for rendering emoji. Only needed if you want to use
default. It is ignored if the [[doom-module::ui unicode]] module is enabled. a font other than your operating systems default.
- [[var:doom-symbol-font]]: used for rendering symbols.
- [[var:doom-serif-font]]: the sans-serif font to use wherever the [[face:fixed-pitch-serif]] - [[var:doom-serif-font]]: the sans-serif font to use wherever the [[face:fixed-pitch-serif]]
face is used. face is used.
- [[var:doom-big-font]]: the large font to use when [[fn:doom-big-font-mode]] is active. - [[var:doom-big-font]]: the large font to use when [[fn:doom-big-font-mode]] is active.
@ -261,12 +268,12 @@ For example:
;; in $DOOMDIR/config.el ;; in $DOOMDIR/config.el
(setq doom-font (font-spec :family "JetBrainsMono" :size 12 :weight 'light) (setq doom-font (font-spec :family "JetBrainsMono" :size 12 :weight 'light)
doom-variable-pitch-font (font-spec :family "DejaVu Sans" :size 13) doom-variable-pitch-font (font-spec :family "DejaVu Sans" :size 13)
doom-unicode-font (font-spec :family "Symbola") doom-symbol-font (font-spec :family "JuliaMono")
doom-big-font (font-spec :family "JetBrainsMono" :size 24)) doom-big-font (font-spec :family "JetBrainsMono" :size 24))
#+end_src #+end_src
#+begin_quote #+begin_quote
🚧 If you or Emacs can't find your font, use ~M-x describe-font~ to look them 󰐃 If you or Emacs can't find your font, use ~M-x describe-font~ to look them
up, or run ~$ fc-list~ to see all the available fonts on your system. *Font up, or run ~$ fc-list~ to see all the available fonts on your system. *Font
issues are /rarely/ Doom issues!* issues are /rarely/ Doom issues!*
#+end_quote #+end_quote
@ -395,14 +402,13 @@ This command is never needed for changes to =$DOOMDIR/config.el=.
** Copy or sync my config to another system? ** Copy or sync my config to another system?
*Short answer:* it is safe to sync =$DOOMDIR= across systems, but not *Short answer:* it is safe to sync =$DOOMDIR= across systems, but not
=$EMACSDIR=. Once moved, use ~$ doom sync && doom build~ to ensure everything is =$EMACSDIR=. Once moved, use ~$ doom sync~ to ensure everything is set up
set up correctly. correctly.
*Long answer:* packages can contain baked-in absolute paths and non-portable *Long answer:* packages can contain baked-in absolute paths and non-portable
byte-code. It is never a good idea to mirror it across multiple systems, unless byte-code. It is never a good idea to mirror it across multiple systems, unless
they are all the same (same OS, same version of Emacs, same paths). Most issues they are all the same (same OS, same version of Emacs, same paths). Most issues
should be solved by running ~$ doom sync && doom build~ on the other end, once should be solved by running ~$ doom sync~ on the other end, once moved.
moved.
** Start over, in case something went terribly wrong? ** Start over, in case something went terribly wrong?
Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~. Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~.
@ -518,7 +524,7 @@ Here are a few common causes for random crashes:
- Some fonts cause Emacs to crash when they lack support for a particular glyph - Some fonts cause Emacs to crash when they lack support for a particular glyph
(typically symbols). Try changing your font by changing ~doom-font~ or (typically symbols). Try changing your font by changing ~doom-font~ or
~doom-unicode-font~. ~doom-symbol-font~.
- Ligatures can cause Emacs to crash. Try a different [[doom-module::ui ligatures +fira][ligature font]] or disable - Ligatures can cause Emacs to crash. Try a different [[doom-module::ui ligatures +fira][ligature font]] or disable
the [[doom-module::ui ligatures]] module altogether. the [[doom-module::ui ligatures]] module altogether.
@ -618,7 +624,7 @@ keybinds to work:
#+end_src #+end_src
#+begin_quote #+begin_quote
📌 I use [C-left] because it is easier to type than "<C-left>", but they are 󰐃 I use [C-left] because it is easier to type than "<C-left>", but they are
equivalent; two different ways to refer to the same key. equivalent; two different ways to refer to the same key.
#+end_quote #+end_quote
** Recursive load error on startup ** Recursive load error on startup
@ -638,7 +644,7 @@ Then these are the three most common explanations:
- *GNU* =tar= and/or =gzip= are not installed on your system. - *GNU* =tar= and/or =gzip= are not installed on your system.
#+begin_quote #+begin_quote
🚧 *Warning macOS and *BSD distro users:* you likely have BSD variants of *Warning macOS and *BSD distro users:* you likely have BSD variants of
=tar= and =gzip= installed by default. Emacs requires the GNU variants! =tar= and =gzip= installed by default. Emacs requires the GNU variants!
#+end_quote #+end_quote
@ -833,13 +839,13 @@ There's more about quoting [[https://emacsdocs.org/docs/elisp/Quoting][in the Em
** TODO How does Doom Emacs start up so quickly? ** TODO How does Doom Emacs start up so quickly?
#+begin_quote #+begin_quote
🔨 *This post is a work in progress!* However, there's a post on our Discourse 󱌣 *This post is a work in progress!* However, there's a post on our Discourse
that outlines [[https://discourse.doomemacs.org/t/how-does-doom-start-up-so-quickly/163/1][some of our older techniques]]. that outlines [[https://discourse.doomemacs.org/t/how-does-doom-start-up-so-quickly/163/1][some of our older techniques]].
#+end_quote #+end_quote
** TODO How does Doom Emacs improve runtime performance? ** TODO How does Doom Emacs improve runtime performance?
#+begin_quote #+begin_quote
🔨 *This post is a work in progress!* 󱌣 *This post is a work in progress!*
#+end_quote #+end_quote
** Why does Doom not use dash, f, s, or similar libraries? ** Why does Doom not use dash, f, s, or similar libraries?
@ -911,7 +917,7 @@ you, a combination of [[kbd:][o]] (swaps your cursor between the two ends of the
and motion keys can adjust the ends of your selection. and motion keys can adjust the ends of your selection.
#+begin_quote #+begin_quote
📌 There are also text objects for xml tags ([[kbd:][x]]), C-style function arguments 󰐃 There are also text objects for xml tags ([[kbd:][x]]), C-style function arguments
([[kbd:][a]]), angle brackets, and single/double quotes. ([[kbd:][a]]), angle brackets, and single/double quotes.
#+end_quote #+end_quote

View file

@ -551,9 +551,7 @@ doom sync
doom env doom env
# Lastly, install the icon fonts Doom uses: # Lastly, install the icon fonts Doom uses:
emacs --batch -f all-the-icons-install-fonts emacs --batch -f nerd-icons-install-fonts
# On Windows, `all-the-icons-install-fonts` will only download the fonts, you'll
# have to install them by hand afterwards!
#+END_SRC #+END_SRC
To understand the purpose of the =~/.doom.d= directory and =~/.doom.d/init.el= To understand the purpose of the =~/.doom.d= directory and =~/.doom.d/init.el=

View file

@ -27,16 +27,17 @@
;;; Code: ;;; Code:
;; PERF: Garbage collection is a big contributor to startup times. This fends it ;; PERF: Garbage collection is a big contributor to startup times. This fends it
;; off, but will be reset later by `gcmh-mode'. Not resetting it later will ;; off, but will be reset later by `gcmh-mode' (or in doom-cli.el, if in a
;; cause stuttering/freezes. ;; noninteractive session). Not resetting it later causes stuttering/freezes.
(setq gc-cons-threshold most-positive-fixnum) (setq gc-cons-threshold most-positive-fixnum)
;; PERF: Don't use precious startup time checking mtime on elisp bytecode. ;; PERF: Don't use precious startup time checking mtime on elisp bytecode.
;; Ensuring correctness is 'doom sync's job, not the interactive session's. ;; Ensuring correctness is 'doom sync's job, not the interactive session's.
;; Still, stale byte-code will cause *heavy* losses in startup efficiency. ;; Still, stale byte-code will cause *heavy* losses in startup efficiency, but
;; performance is unimportant when Emacs is in an error state.
(setq load-prefer-newer noninteractive) (setq load-prefer-newer noninteractive)
;; UX: Respect DEBUG envvar as an alternative to --debug-init, and to make are ;; UX: Respect DEBUG envvar as an alternative to --debug-init, and to make
;; startup sufficiently verbose from this point on. ;; startup sufficiently verbose from this point on.
(when (getenv-internal "DEBUG") (when (getenv-internal "DEBUG")
(setq init-file-debug t (setq init-file-debug t
@ -48,17 +49,17 @@
(or (or
;; PERF: `file-name-handler-alist' is consulted often. Unsetting it offers a ;; PERF: `file-name-handler-alist' is consulted often. Unsetting it offers a
;; notable saving in startup time. This let-binding is just a stopgap though, ;; notable saving in startup time. This is just a stopgap though; this
;; a more complete version of this optimization can be found in lisp/doom.el. ;; optimization is continued more comprehensively in lisp/doom.el.
(let (file-name-handler-alist) (let (file-name-handler-alist)
(let* (;; FIX: Unset `command-line-args' in noninteractive sessions, to (let (;; FIX: Unset `command-line-args' in noninteractive sessions, to
;; ensure upstream switches aren't misinterpreted. ;; ensure upstream switches aren't misinterpreted.
(command-line-args (unless noninteractive command-line-args)) (command-line-args (unless noninteractive command-line-args))
;; I avoid using `command-switch-alist' to process --profile (and ;; I avoid using `command-switch-alist' to process --profile (and
;; --init-directory) because it is processed too late to change ;; --init-directory) because it is processed too late to change
;; `user-emacs-directory' in time. ;; `user-emacs-directory' in time.
(profile (or (cadr (member "--profile" command-line-args)) (profile (or (cadr (member "--profile" command-line-args))
(getenv-internal "DOOMPROFILE")))) (getenv-internal "DOOMPROFILE"))))
(if (null profile) (if (null profile)
;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped. ;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped.
(let ((init-dir (or (cadr (member "--init-directory" command-line-args)) (let ((init-dir (or (cadr (member "--init-directory" command-line-args))
@ -84,7 +85,10 @@
(or (load (expand-file-name (or (load (expand-file-name
(format (let ((lfile (getenv-internal "DOOMPROFILELOADFILE"))) (format (let ((lfile (getenv-internal "DOOMPROFILELOADFILE")))
(if lfile (if lfile
(concat (string-remove-suffix ".el" lfile) (concat (let ((suffix ".el"))
(if (string-suffix-p suffix lfile)
(substring lfile 0 (- (length lfile) (length suffix)))
lfile))
".%d.elc") ".%d.elc")
"profiles/load.%d.elc")) "profiles/load.%d.elc"))
emacs-major-version) emacs-major-version)
@ -94,33 +98,33 @@
;; PERF: When `load'ing or `require'ing files, each permutation of ;; PERF: When `load'ing or `require'ing files, each permutation of
;; `load-suffixes' and `load-file-rep-suffixes' (then `load-suffixes' + ;; `load-suffixes' and `load-file-rep-suffixes' (then `load-suffixes' +
;; `load-file-rep-suffixes') is used to locate the file. Each permutation ;; `load-file-rep-suffixes') is used to locate the file. Each permutation
;; is a file op, which is normally very fast, but they can add up over the ;; amounts to at least one file op, which is normally very fast, but can
;; hundreds/thousands of files Emacs needs to load. ;; add up over the hundreds/thousands of files Emacs loads.
;; ;;
;; To reduce that burden -- and since Doom doesn't load any dynamic modules ;; To reduce that burden -- and since Doom doesn't load any dynamic modules
;; -- I remove `.so' from `load-suffixes' and pass the `must-suffix' arg to ;; this early -- I remove `.so' from `load-suffixes' and pass the
;; `load'. See the docs of `load' for details. ;; `must-suffix' arg to `load'. See the docs of `load' for details.
(if (let ((load-suffixes '(".elc" ".el"))) (if (let ((load-suffixes '(".elc" ".el")))
;; I avoid `load's NOERROR argument because other, legitimate errors ;; I avoid `load's NOERROR argument because it suppresses other,
;; (like permission or IO errors) should not be suppressed or ;; legitimate errors (like permission or IO errors), which gets
;; interpreted as "this is not a Doom config". ;; incorrectly interpreted as "this is not a Doom config".
(condition-case _ (condition-case-unless-debug _
;; Load the heart of Doom Emacs. ;; Load the heart of Doom Emacs.
(load (expand-file-name "lisp/doom" user-emacs-directory) (load (expand-file-name "lisp/doom" user-emacs-directory)
nil (not init-file-debug) nil 'must-suffix) nil (not init-file-debug) nil 'must-suffix)
;; Failing that, assume that we're loading a non-Doom config. ;; Failing that, assume that we're loading a non-Doom config.
(file-missing (file-missing
;; HACK: `startup--load-user-init-file' resolves $EMACSDIR from a ;; HACK: `startup--load-user-init-file' resolves $EMACSDIR from a
;; lexically bound `startup-init-directory', which means changes ;; lexical (and so, not-trivially-modifiable)
;; to `user-emacs-directory' won't be respected when loading ;; `startup-init-directory', so Emacs will fail to locate the
;; $EMACSDIR/init.el, so I force it to: ;; correct $EMACSDIR/init.el without help.
(define-advice startup--load-user-init-file (:filter-args (args) reroute-to-profile) (define-advice startup--load-user-init-file (:filter-args (args) reroute-to-profile)
(list (lambda () (expand-file-name "init.el" user-emacs-directory)) (list (lambda () (expand-file-name "init.el" user-emacs-directory))
nil (nth 2 args))) nil (nth 2 args)))
;; Set `user-init-file' for the `load' call further below, and do so ;; (Re)set `user-init-file' for the `load' call further below, and
;; here while our `file-name-handler-alist' optimization is still ;; do so here while our `file-name-handler-alist' optimization is
;; effective (benefits `expand-file-name'). BTW: Emacs resets ;; still effective (benefits `expand-file-name'). BTW: Emacs resets
;; `user-init-file' and `early-init-file' after this file is loaded. ;; `user-init-file' and `early-init-file' after this file is loaded.
(setq user-init-file (expand-file-name "early-init" user-emacs-directory)) (setq user-init-file (expand-file-name "early-init" user-emacs-directory))
;; COMPAT: I make no assumptions about the config we're going to ;; COMPAT: I make no assumptions about the config we're going to
@ -133,7 +137,7 @@
;; as a best fit guess. It's better than Emacs' 80kb default. ;; as a best fit guess. It's better than Emacs' 80kb default.
(setq gc-cons-threshold (* 16 1024 1024)) (setq gc-cons-threshold (* 16 1024 1024))
nil))) nil)))
;; ...But if Doom loaded then continue as normal. ;; ...Otherwise, we're loading a Doom config, so continue as normal.
(doom-require (if noninteractive 'doom-cli 'doom-start)))) (doom-require (if noninteractive 'doom-cli 'doom-start))))
;; Then continue on to the config/profile we want to load. ;; Then continue on to the config/profile we want to load.

View file

@ -1,214 +0,0 @@
;;; lisp/cli/commands/byte-compile.el -*- lexical-binding: t; -*-
;;
;;; Variables
;; None yet!
;;
;;; Commands
(defcli! ((compile c))
((recompile-p ("-r" "--recompile"))
(core-p ("-c" "--core"))
(private-p ("-p" "--private"))
(verbose-p ("-v" "--verbose")))
"Byte-compiles your config or selected modules.
compile [TARGETS...]
compile :core :user lang/python
compile feature lang
Accepts :core and :user as special arguments, which target Doom's core files
and your private config files, respectively. To recompile your packages, use
'doom build' instead."
(doom-cli-compile
(if (or core-p private-p)
(append (if core-p (doom-glob doom-emacs-dir "init.el"))
(if core-p (list doom-core-dir))
(if private-p (list doom-user-dir)))
(or (y-or-n-p
(concat "WARNING: Changes made to your config after compiling it won't take effect until\n"
"this command is rerun or you run 'doom clean'! It will also make error backtraces\n"
"much more difficult to decipher.\n\n"
"If you intend to use it anyway, remember this or it will come back to bite you!\n\n"
"Continue anyway?"))
(user-error "Aborted"))
(append (doom-glob doom-emacs-dir "init.el")
(list doom-core-dir)
(seq-filter
;; Only compile Doom's modules
(doom-rpartial #'file-in-directory-p doom-emacs-dir)
;; Omit `doom-user-dir', which is always first
(doom-module-load-path))))
recompile-p
verbose-p))
(defcli! clean ()
"Delete all *.elc files."
(doom-compile-clean))
;;
;;; Helpers
(cl-defun doom-cli-compile (&optional targets recompile-p verbose-p)
"Byte compiles your emacs configuration.
init.el is always byte-compiled by this.
If TARGETS is specified, as a list of direcotries
If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are
byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom
core. It always ignores unit tests and files with `no-byte-compile' enabled.
WARNING: byte-compilation yields marginal gains and makes debugging new issues
difficult. It is recommended you don't use it unless you understand the
reprecussions.
Use `doom-compile-clean' or `make clean' to reverse
byte-compilation.
If RECOMPILE-P is non-nil, only recompile out-of-date files."
(let* ((default-directory doom-emacs-dir)
(targets (nreverse (delete-dups targets)))
;; In case it is changed during compile-time
(auto-mode-alist auto-mode-alist)
kill-emacs-hook kill-buffer-query-functions)
(let ((after-load-functions
(if (null targets)
after-load-functions
;; Assemble el files we want to compile, and preserve in the order
;; they are loaded in, so we don't run into any scary catch-22s
;; while byte-compiling, like missing macros.
(cons (let ((target-dirs (seq-filter #'file-directory-p targets)))
(lambda (path)
(and (not (doom-compile--ignore-file-p path))
(seq-find (doom-partial #'file-in-directory-p path)
target-dirs)
(cl-pushnew path targets))))
after-load-functions))))
(doom-log "Reloading Doom in preparation for byte-compilation")
;; But first we must be sure that Doom and your private config have been
;; fully loaded. Which usually aren't so in an noninteractive session.
(let ((load-prefer-newer t))
(require 'doom-start)))
(if (null targets)
(print! (item "No targets to %scompile" (if recompile-p "re" "")))
(print! (start "%scompiling your config...")
(if recompile-p "Re" "Byte-"))
(dolist (dir
(cl-remove-if-not #'file-directory-p targets)
(setq targets (cl-remove-if #'file-directory-p targets)))
(prependq! targets
(doom-files-in
dir :match "\\.el" :filter #'doom-compile--ignore-file-p)))
(print-group!
(require 'use-package)
(condition-case-unless-debug e
(let* ((total-ok 0)
(total-fail 0)
(total-noop 0)
(byte-compile-verbose nil)
(byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local))
(byte-compile-dynamic-docstrings t)
(use-package-compute-statistics nil)
(use-package-defaults use-package-defaults)
(use-package-expand-minimally t)
(targets (delete-dups targets))
(modules (seq-group-by #'doom-module-from-path targets))
(total-files (length targets))
(total-modules (length modules))
(i 0)
last-module)
;; Prevent packages from being loaded at compile time if they
;; don't meet their own predicates.
(push (list :no-require t
(lambda (_name args)
(or (when-let (pred (or (plist-get args :if)
(plist-get args :when)))
(not (eval pred t)))
(when-let (pred (plist-get args :unless))
(eval pred t)))))
use-package-defaults)
(dolist (module-files modules)
(cl-incf i)
(dolist (target (cdr module-files))
(let ((elc-file (byte-compile-dest-file target)))
(cl-incf
(if (and recompile-p (not (file-newer-than-file-p target elc-file)))
total-noop
(pcase (if (not (doom-file-cookie-p target "if" t))
'no-byte-compile
(unless (equal last-module (car module-files))
(print! (success "(% 3d/%d) Compiling %s")
i total-modules
(if-let (m (caar module-files))
(format "%s %s module..." m (cdar module-files))
(format "%d stand alone elisp files..."
(length (cdr module-files))))
(caar module-files) (cdar module-files))
(setq last-module (car module-files)))
(if verbose-p
(byte-compile-file target)
(quiet! (byte-compile-file target))))
(`no-byte-compile
(doom-log "(% 3d/%d) Ignored %s" i total-modules target)
total-noop)
(`nil
(print! (error "(% 3d/%d) Failed to compile %s")
i total-modules (relpath target))
total-fail)
(_ total-ok)))))))
(print! (class (if (= total-fail 0) 'success 'warn)
"%s %d/%d file(s) (%d ignored)")
(if recompile-p "Recompiled" "Byte-compiled")
total-ok total-files
total-noop)
(= total-fail 0))
((debug error)
(print! (error "There were breaking errors.\n\n%s")
"Reverting changes...")
(signal 'doom-error (list 'byte-compile e))))))))
(defun doom-compile--ignore-file-p (path)
(let ((filename (file-name-nondirectory path)))
(or (not (equal (file-name-extension path) "el"))
(member filename (list doom-module-packages-file "doctor.el"))
(string-prefix-p "." filename)
(string-prefix-p "test-" filename)
(string-prefix-p "flycheck_" filename)
(string-suffix-p ".example.el" filename))))
(defun doom-compile-clean ()
"Delete all the compiled elc files in your Emacs configuration and private
module. This does not include your byte-compiled, third party packages.'"
(require 'doom-modules)
(print! (start "Cleaning .elc files"))
(print-group!
(cl-loop with default-directory = doom-emacs-dir
with success = 0
with esc = (if init-file-debug "" "\033[1A")
for path
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))
if (file-exists-p path)
do (delete-file path)
and do (print! (success "\033[KDeleted %s%s") (relpath path) esc)
and do (cl-incf success)
finally do
(print! (if (> success 0)
(success "\033[K%d elc files deleted" success)
(item "\033[KNo elc files to clean"))))
t))
(provide 'doom-cli-compile)
;;; compile.el ends here

View file

@ -96,48 +96,86 @@ in."
(error! "Couldn't find the `rg' binary; this a hard dependecy for Doom, file searches may not work at all"))) (error! "Couldn't find the `rg' binary; this a hard dependecy for Doom, file searches may not work at all")))
(print! (start "Checking for Emacs config conflicts...")) (print! (start "Checking for Emacs config conflicts..."))
(when (file-exists-p "~/.emacs") (print-group!
(warn! "Detected an ~/.emacs file, which may prevent Doom from loading") (unless (or (file-equal-p doom-emacs-dir "~/.emacs.d")
(explain! "If Emacs finds an ~/.emacs file, it will ignore ~/.emacs.d, where Doom is " (file-equal-p doom-emacs-dir "~/.config/emacs"))
"typically installed. If you're seeing a vanilla Emacs splash screen, this " (print! (warn "Doom is installed in a non-standard location"))
"may explain why. If you use Chemacs, you may ignore this warning.")) (explain! "The standard locations are ~/.config/emacs or ~/.emacs.d. Emacs will fail "
"to load Doom if it is not explicitly told where to look for it. In Emacs 29+, "
"this is possible with the --init-directory option:\n\n"
" $ emacs --init-directory '" (abbreviate-file-name doom-emacs-dir) "'\n\n"
"However, Emacs 27-28 users have no choice but to move Doom to a standard "
"location.\n\n"
"Chemacs users may ignore this warning, however."))
(let (found?)
(dolist (file '("~/_emacs" "~/.emacs" "~/.emacs.el" "~/.emacs.d" "~/.config/emacs"))
(when (and (file-exists-p file)
(not (file-equal-p file doom-emacs-dir)))
(setq found? t)
(print! (warn "Found another Emacs config: %s (%s)")
file (if (file-directory-p file) "directory" "file"))))
(when found?
(explain! "Having multiple Emacs configs may prevent Doom from loading properly. Emacs "
"will load the first it finds and ignore the rest. If Doom isn't starting up "
"correctly (e.g. you get a vanilla splash screen), make sure that only one of "
"these exist.\n\n"
"Chemacs users may ignore this warning."))))
(print! (start "Checking for great Emacs features...")) (print! (start "Checking for missing Emacs features..."))
(unless (functionp 'json-serialize) (print-group!
(warn! "Emacs was not built with native JSON support") (unless (functionp 'json-serialize)
(explain! "Users will see a substantial performance gain by building Emacs with " (warn! "Emacs was not built with native JSON support")
"jansson support (i.e. a native JSON library), particularly LSP users. " (explain! "Users will see a substantial performance gain by building Emacs with "
"You must install a prebuilt Emacs binary with this included, or compile " "jansson support (i.e. a native JSON library), particularly LSP users. "
"Emacs with the --with-json option.")) "You must install a prebuilt Emacs binary with this included, or compile "
(unless (featurep 'native-compile) "Emacs with the --with-json option."))
(warn! "Emacs was not built with native compilation support") (unless (featurep 'native-compile)
(explain! "Users will see a substantial performance gain by building Emacs with " (warn! "Emacs was not built with native compilation support")
"native compilation support, availible in emacs 28+." (explain! "Users will see a substantial performance gain by building Emacs with "
"You must install a prebuilt Emacs binary with this included, or compile " "native compilation support, availible in emacs 28+."
"Emacs with the --with-native-compilation option.")) "You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-native-compilation option.")))
(print! (start "Checking for private config conflicts...")) (print! (start "Checking for private config conflicts..."))
(let* ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME") (print-group!
"~/.config") (let* ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"/doom/")) "~/.config")
(doom-dir (or (getenv "DOOMDIR") "/doom/"))
"~/.doom.d/")) (doom-dir (or (getenv "DOOMDIR")
(dir (if (file-directory-p xdg-dir) "~/.doom.d/"))
xdg-dir (dir (if (file-directory-p xdg-dir)
doom-dir))) xdg-dir
(when (file-equal-p dir doom-emacs-dir) doom-dir)))
(print! (error "Doom was cloned to %S, not ~/.emacs.d or ~/.config/emacs" (when (file-equal-p dir doom-emacs-dir)
(path dir))) (print! (error "Doom was cloned to %S, not ~/.emacs.d or ~/.config/emacs"
(explain! "Doom's source and your private Doom config have to live in separate directories. " (path dir)))
"Putting them in the same directory (without changing the DOOMDIR environment " (explain! "Doom's source and your private Doom config have to live in separate directories. "
"variable) will cause errors on startup.")) "Putting them in the same directory (without changing the DOOMDIR environment "
(when (and (not (file-equal-p xdg-dir doom-dir)) "variable) will cause errors on startup."))
(file-directory-p xdg-dir) (when (and (not (file-equal-p xdg-dir doom-dir))
(file-directory-p doom-dir)) (file-directory-p xdg-dir)
(print! (warn "Detected two private configs, in %s and %s") (file-directory-p doom-dir))
(abbreviate-file-name xdg-dir) (print! (warn "Detected two private configs, in %s and %s")
doom-dir) (abbreviate-file-name xdg-dir)
(explain! "The second directory will be ignored, as it has lower precedence."))) doom-dir)
(explain! "The second directory will be ignored, as it has lower precedence."))))
(print! (start "Checking for common environmental issues..."))
(when (string-match-p "/fish$" shell-file-name)
(print! (warn "Detected Fish as your $SHELL"))
(explain! "Fish (and possibly other non-POSIX shells) is known to inject garbage "
"output into some of the child processes that Emacs spawns. Many Emacs "
"packages/utilities will choke on this output, causing unpredictable issues. "
"To get around this, either:\n\n"
" - Add the following to $DOOMDIR/config.el:\n\n"
" (setq shell-file-name (executable-find \"bash\"))\n\n"
" - Or change your default shell to a POSIX shell (like bash or zsh) "
" and explicitly configure your terminal apps to use the shell you "
" want.\n\n"
"If you opt for option 1 and use one of Emacs' terminal emulators, you "
"will also need to configure them to use Fish, e.g.\n\n"
" (setq-default vterm-shell (executable-find \"fish\"))\n\n"
" (setq-default explicit-shell-file-name (executable-find \"fish\"))\n"))
(print! (start "Checking for stale elc files...")) (print! (start "Checking for stale elc files..."))
(elc-check-dir doom-core-dir) (elc-check-dir doom-core-dir)
@ -205,13 +243,13 @@ in."
;; Check for fonts ;; Check for fonts
(if (not (executable-find "fc-list")) (if (not (executable-find "fc-list"))
(warn! "Warning: unable to detect fonts because fontconfig isn't installed") (warn! "Warning: unable to detect fonts because fontconfig isn't installed")
;; all-the-icons fonts ;; nerd-icons fonts
(when (and (pcase system-type (when (and (pcase system-type
(`gnu/linux (concat (or (getenv "XDG_DATA_HOME") (`gnu/linux (concat (or (getenv "XDG_DATA_HOME")
"~/.local/share") "~/.local/share")
"/fonts/")) "/fonts/"))
(`darwin "~/Library/Fonts/")) (`darwin "~/Library/Fonts/"))
(require 'all-the-icons nil t)) (require 'nerd-icons nil t))
(with-temp-buffer (with-temp-buffer
(let ((errors 0)) (let ((errors 0))
(cl-destructuring-bind (status . output) (cl-destructuring-bind (status . output)
@ -219,15 +257,16 @@ in."
(if (not (zerop status)) (if (not (zerop status))
(print! (error "There was an error running `fc-list'. Is fontconfig installed correctly?")) (print! (error "There was an error running `fc-list'. Is fontconfig installed correctly?"))
(insert (cdr (doom-call-process "fc-list" "" "file"))) (insert (cdr (doom-call-process "fc-list" "" "file")))
(dolist (font all-the-icons-font-names) (dolist (font nerd-icons-font-names)
(if (save-excursion (re-search-backward font nil t)) (if (save-excursion (re-search-backward font nil t))
(success! "Found font %s" font) (success! "Found font %s" font)
(print! (warn "Warning: couldn't find %S font") font))) (print! (warn "%S font is not installed on your system") font)
(cl-incf errors)))
(when (> errors 0) (when (> errors 0)
(explain! "Some all-the-icons fonts were missing.\n\n" (explain! "Some needed fonts are not properly installed on your system. To download and "
"You can install them by running `M-x all-the-icons-install-fonts' within Emacs.\n" "install them, run `M-x nerd-icons-install-fonts' from within Doom Emacs. "
"This could also mean you've installed them in non-standard locations, in which " "However, on Windows this command will only download them; the fonts must "
"case feel free to ignore this warning."))))))))) "be installed manually afterwards.")))))))))
(print! (start "Checking for stale elc files in your DOOMDIR...")) (print! (start "Checking for stale elc files in your DOOMDIR..."))
(when (file-directory-p doom-user-dir) (when (file-directory-p doom-user-dir)

View file

@ -33,7 +33,8 @@
"^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$" "^\\(SSH\\|GPG\\)_TTY$" "^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$" "^\\(SSH\\|GPG\\)_TTY$"
"^GPG_AGENT_INFO$" "^GPG_AGENT_INFO$"
;; Internal Doom envvars ;; Internal Doom envvars
"^DEBUG$" "^INSECURE$" "^\\(EMACS\\|DOOM\\)DIR$" "^DOOMPROFILE$" "^__") "^DEBUG$" "^INSECURE$" "^\\(EMACS\\|DOOM\\)DIR$"
"^DOOM\\(PATH\\|PROFILE\\)$" "^__")
"Environment variables to omit from envvar files. "Environment variables to omit from envvar files.
Each string is a regexp, matched against variable names to omit from Each string is a regexp, matched against variable names to omit from

View file

@ -1,466 +0,0 @@
;;; lisp/cli/help.el -*- lexical-binding: t; -*-
;;; Commentary:
;;
;; This file defines special commands that the Doom CLI will invoke when a
;; command is passed with -?, --help, or --version. They can also be aliased to
;; a sub-command to make more of its capabilities accessible to users, with:
;;
;; (defcli-alias! (myscript (help h)) (:help))
;;
;; You can define your own command-specific help handlers, e.g.
;;
;; (defcli! (:help myscript subcommand) () ...)
;;
;; And it will be invoked instead of the generic one.
;;
;;; Code:
;;
;;; Variables
(defvar doom-help-commands '("%p %c {-?,--help}")
"A list of help commands recognized for the running script.
Recognizes %p (for the prefix) and %c (for the active command).")
;;
;;; Commands
(defcli! (:root :help)
((localonly? ("-g" "--no-global") "Hide global options")
(manpage? ("--manpage") "Generate in manpage format")
(commands? ("--commands") "List all known commands")
&multiple
(sections ("--synopsis" "--subcommands" "--similar" "--envvars"
"--postamble")
"Show only the specified sections.")
&context context
&args command)
"Show documentation for a Doom CLI command.
OPTIONS:
--synopsis, --subcommands, --similar, --envvars, --postamble
TODO"
(doom-cli-load-all)
(when (doom-cli-context-error context)
(terpri))
(let* ((command (cons (doom-cli-context-prefix context) command))
(cli (doom-cli-get command t))
(rcli (doom-cli-get cli))
(fallbackcli (cl-loop with targets = (doom-cli--command-expand (butlast command) t)
for cmd in (cons command targets)
if (doom-cli-get cmd t)
return it)))
(cond (commands?
(let ((cli (or cli (doom-cli-get (doom-cli-context-prefix context)))))
(print! "Commands under '%s':\n%s"
(doom-cli-command-string cli)
(indent (doom-cli-help--render-commands
(or (doom-cli-subcommands cli)
(user-error "No commands found"))
:prefix (doom-cli-command cli)
:inline? t
:docs? t)))))
((null sections)
(if (null cli)
(signal 'doom-cli-command-not-found-error command)
(doom-cli-help--print cli context manpage? localonly?)
(exit! :pager?)))
((dolist (section sections)
(unless (equal section (car sections)) (terpri))
(pcase section
("--synopsis"
(print! "%s" (doom-cli-help--render-synopsis
(doom-cli-help--synopsis cli)
"Usage: ")))
("--subcommands"
(print! "%s\n%s" (bold "Available commands:")
(indent (doom-cli-help--render-commands
(doom-cli-subcommands rcli 1)
:prefix command
:grouped? t
:docs? t)
doom-print-indent-increment)))
("--similar"
(unless command
(user-error "No command specified"))
(let ((similar (doom-cli-help-similar-commands command 0.4)))
(print! "Similar commands:")
(if (not similar)
(print! (indent (warn "Can't find any!")))
(dolist (command (seq-take similar 10))
(print! (indent (item "(%d%%) %s"))
(* (car command) 100)
(doom-cli-command-string (cdr command)))))))
("--envvars"
(let* ((key "ENVIRONMENT VARIABLES")
(clis (if command (doom-cli-find command) (hash-table-values doom-cli--table)))
(clis (seq-remove #'doom-cli-alias clis))
(clis (seq-filter (fn! (cdr (assoc key (doom-cli-docs %)))) clis))
(clis (seq-group-by #'doom-cli-command clis)))
(print! "List of environment variables for %s:\n" command)
(if (null clis)
(print! (indent "None!"))
(dolist (group clis)
(print! (bold "%s%s:"
(doom-cli-command-string (car group))
(if (doom-cli-fn (doom-cli-get (car group)))
"" " *")))
(dolist (cli (cdr group))
(print! (indent "%s") (markup (cdr (assoc key (doom-cli-docs cli))))))))))
("--postamble"
(print! "See %s for documentation."
(join (cl-loop with spec =
`((?p . ,(doom-cli-context-prefix context))
(?c . ,(doom-cli-command-string (cdr (doom-cli-command (or cli fallbackcli))))))
for cmd in doom-help-commands
for formatted = (trim (format-spec cmd spec))
collect (replace-regexp-in-string
" +" " " (format "'%s'" formatted)))
" or ")))))))))
(defcli! (:root :version)
((simple? ("--simple"))
&context context)
"Show installed versions of Doom, Doom modules, and Emacs."
(doom/version)
(unless simple?
(terpri)
(with-temp-buffer
(insert-file-contents (doom-path doom-emacs-dir "LICENSE"))
(re-search-forward "^Copyright (c) ")
(print! "%s\n" (trim (thing-at-point 'line t)))
(print! (p "Doom Emacs uses the MIT license and is provided without warranty "
"of any kind. You may redistribute and modify copies if "
"given proper attribution. See the LICENSE file for details.")))))
;;
;;; Helpers
(defun doom-cli-help (cli)
"Return an alist of documentation summarizing CLI (a `doom-cli')."
(let* ((rcli (doom-cli-get cli))
(docs (doom-cli-docs rcli)))
`((command . ,(doom-cli-command-string cli))
(summary . ,(or (cdr (assoc "SUMMARY" docs)) "TODO"))
(description . ,(or (cdr (assoc "MAIN" docs)) "TODO"))
(synopsis . ,(doom-cli-help--synopsis cli))
(arguments . ,(doom-cli-help--arguments rcli))
(options . ,(doom-cli-help--options rcli))
(commands . ,(doom-cli-subcommands cli 1))
(sections . ,(seq-filter #'cdr (cddr docs))))))
(defun doom-cli-help-similar-commands (command &optional maxscore)
"Return N commands that are similar to COMMAND."
(seq-take-while
(fn! (>= (car %) (or maxscore 0.0)))
(seq-sort-by
#'car #'>
(cl-loop with prefix = (seq-find #'doom-cli-get (nreverse (doom-cli--command-expand command t)))
with input = (doom-cli-command-string (cdr (doom-cli--command command t)))
for command in (hash-table-keys doom-cli--table)
if (doom-cli-fn (doom-cli-get command))
if (equal prefix (seq-take command (length prefix)))
collect (cons (doom-cli-help--similarity
input (doom-cli-command-string (cdr command)))
command)))))
(defun doom-cli-help--similarity (s1 s2)
;; Ratcliff-Obershelp similarity
(let* ((s1 (downcase s1))
(s2 (downcase s2))
(s1len (length s1))
(s2len (length s2)))
(if (or (zerop s1len)
(zerop s2len))
0.0
(/ (let ((i 0) (j 0) (score 0) jlast)
(while (< i s1len)
(unless jlast (setq jlast j))
(if (and (< j s2len)
(= (aref s1 i) (aref s2 j)))
(progn (cl-incf score)
(cl-incf i)
(cl-incf j))
(setq m 0)
(cl-incf j)
(when (>= j s2len)
(setq j (or jlast j)
jlast nil)
(cl-incf i))))
(* 2.0 score))
(+ (length s1)
(length s2))))))
;;; Help: printers
;; TODO Parameterize optional args with `cl-defun'
(defun doom-cli-help--print (cli context &optional manpage? noglobal?)
"Write CLI's documentation in a manpage-esque format to stdout."
(let-alist (doom-cli-help cli)
(let* ((alist
`(,@(if manpage?
`((nil . ,(let* ((title (cadr (member "--load" command-line-args)))
(width (floor (/ (- (doom-cli-context-width context)
(length title))
2.0))))
;; FIXME Who am I fooling?
(format (format "%%-%ds%%s%%%ds" width width)
"DOOM(1)" title "DOOM(1)")))
("NAME" . ,(concat .command " - " .summary))
("SYNOPSIS" . ,(doom-cli-help--render-synopsis .synopsis nil t))
("DESCRIPTION" . ,.description))
`((nil . ,(doom-cli-help--render-synopsis .synopsis "Usage: "))
(nil . ,(string-join (seq-remove #'string-empty-p (list .summary .description))
"\n\n"))))
("ARGUMENTS" . ,(doom-cli-help--render-arguments .arguments))
("COMMANDS"
. ,(doom-cli-help--render-commands
.commands :prefix (doom-cli-command cli) :grouped? t :docs? t))
("OPTIONS"
. ,(doom-cli-help--render-options
(if (or (not (doom-cli-fn cli)) noglobal?)
`(,(assq 'local .options))
.options)
cli))))
(command (doom-cli-command cli)))
(letf! (defun printsection (section)
(print! "%s\n"
(if (null section)
(dark "TODO")
(markup
(format-spec
section `((?p . ,(car command))
(?c . ,(doom-cli-command-string (cdr command))))
'ignore)))))
(pcase-dolist (`(,label . ,contents) alist)
(when (and contents (not (string-blank-p contents)))
(when label
(print! (bold "%s%s") label (if manpage? "" ":")))
(print-group! :if label (printsection contents))))
(pcase-dolist (`(,label . ,contents) .sections)
(when (and contents (not (assoc label alist)))
(print! (bold "%s:") label)
(print-group! (printsection contents))))))))
;;; Help: synopsis
(defun doom-cli-help--synopsis (cli &optional all-options?)
(let* ((rcli (doom-cli-get cli))
(opts (doom-cli-help--options rcli))
(opts (mapcar #'car (if all-options? (mapcan #'cdr opts) (alist-get 'local opts))))
(opts (cl-loop for opt in opts
for args = (cdar opt)
for switches = (mapcar #'car opt)
for multi? = (member "..." args)
if args
collect (format (if multi? "[%s %s]..." "[%s %s]")
(string-join switches "|")
(string-join (remove "..." args) "|"))
else collect (format "[%s]" (string-join switches "|"))))
(args (doom-cli-arguments rcli))
(subcommands? (doom-cli-subcommands rcli 1 :predicate? t)))
`((command . ,(doom-cli-command cli))
(options ,@opts)
(required ,@(mapcar (fn! (upcase (format "`%s'" %))) (if subcommands? '(command) (alist-get '&required args))))
(optional ,@(mapcar (fn! (upcase (format "[`%s']" %)))(alist-get '&optional args)))
(rest ,@(mapcar (fn! (upcase (format "[`%s'...]" %))) (if subcommands? '(args) (alist-get '&args args)))))))
(defun doom-cli-help--render-synopsis (synopsis &optional prefix)
(let-alist synopsis
(let ((doom-print-indent 0)
(prefix (or prefix ""))
(command (doom-cli-command-string .command)))
(string-trim-right
(format! "%s\n\n"
(fill (concat (bold prefix)
(format "%s " command)
(markup
(join (append .options
(and .options
(or .required
.optional
.rest)
(list (dark "[--]")))
.required
.optional
.rest))))
80 (1+ (length (concat prefix command)))))))))
;;; Help: arguments
(defun doom-cli-help--arguments (cli &optional all?)
(doom-cli-help--parse-docs (doom-cli-find cli t) "ARGUMENTS"))
(defun doom-cli-help--render-arguments (arguments)
(mapconcat (lambda (arg)
(format! "%-20s\n%s"
(underscore (car arg))
(indent (if (equal (cdr arg) "TODO")
(dark (cdr arg))
(cdr arg))
doom-print-indent-increment)))
arguments
"\n"))
;;; Help: commands
(cl-defun doom-cli-help--render-commands (commands &key prefix grouped? docs? (inline? t))
(with-temp-buffer
(let* ((doom-print-indent 0)
(commands (seq-group-by (fn! (if grouped? (doom-cli-prop (doom-cli-get % t) :group)))
(nreverse commands)))
(toplevel (assq nil commands))
(rest (remove toplevel commands))
(drop (if prefix (length prefix) 0))
(minwidth
(apply
#'max (or (cl-loop for cmd in (apply #'append (mapcar #'cdr commands))
for cmd = (seq-drop cmd drop)
collect (length (doom-cli-command-string cmd)))
(list 15))))
(ellipsis (doom-print--style 'dark " […]"))
(ellipsislen (- (length ellipsis) (if (eq doom-print-backend 'ansi) 2 4))))
(dolist (group (cons toplevel rest))
(let ((label (if (car-safe group) (cdr commands))))
(when label
(insert! ((bold "%s:") (car group)) "\n"))
(print-group! :if label
(dolist (command (cdr group))
(let* ((cli (doom-cli-get command t))
(rcli (doom-cli-get command))
(summary (doom-cli-short-docs rcli))
(subcommands? (doom-cli-subcommands cli 1 :predicate? t)))
(insert! ((format "%%-%ds%%s%%s"
(+ (- minwidth doom-print-indent)
doom-print-indent-increment
(if subcommands? ellipsislen 0)))
(concat (doom-cli-command-string (seq-drop command drop))
(if subcommands? ellipsis))
(if inline? " " "\n")
(indent (if (and (doom-cli-alias cli)
(not (doom-cli-type rcli)))
(dark "-> %s" (doom-cli-command-string cli))
(when docs?
(if summary (markup summary) (dark "TODO"))))))
"\n")))
(when (cdr rest)
(insert "\n")))))
(string-trim-right (buffer-string)))))
;;; Help: options
(defun doom-cli-help--options (cli &optional noformatting?)
"Return an alist summarizing CLI's options.
The alist's CAR are lists of formatted switches plus their arguments, e.g.
'((\"`--foo'\" \"`BAR'\") ...). Their CDR is their formatted documentation."
(let* ((docs (doom-cli-help--parse-docs (doom-cli-find cli t) "OPTIONS"))
(docs (mapcar (fn! (cons (split-string (car %) ", ")
(cdr %)))
docs))
(strfmt (if noformatting? "%s" "`%s'"))
local-options
global-options
seen)
(dolist (neighbor (nreverse (doom-cli-find cli)))
(dolist (option (doom-cli-options neighbor))
(when-let* ((switches (cl-loop for sw in (doom-cli-option-switches option)
if (and (doom-cli-option-flag-p option)
(string-prefix-p "--" sw))
collect (format "--[no-]%s" (substring sw 2))
else collect sw))
(switches (seq-difference switches seen)))
(dolist (switch switches) (push switch seen))
(push (cons (cl-loop for switch in switches
if (doom-cli-option-arguments option)
collect (cons (format strfmt switch)
(append (doom-cli-help--parse-args it noformatting?)
(when (doom-cli-option-multiple-p option)
(list "..."))))
else collect (list (format strfmt switch)))
(string-join
(or (delq
nil (cons (when-let (docs (doom-cli-option-docs option))
(concat docs "."))
(cl-loop for (flags . docs) in docs
unless (equal (seq-difference flags switches) flags)
collect docs)))
'("TODO"))
"\n\n"))
(if (equal (doom-cli-command neighbor)
(doom-cli-command cli))
local-options
global-options)))))
`((local . ,(nreverse local-options))
(global . ,(nreverse global-options)))))
(defun doom-cli-help--render-options (options &optional cli)
(let ((doom-print-indent 0)
(local (assq 'local options))
(global (assq 'global options)))
(when (or (cdr local) (cdr global))
(letf! (defun printopts (opts)
(pcase-dolist (`(,switches . ,docs) (cdr opts))
(let (multiple?)
(insert!
("%s%s\n%s"
(mapconcat
(fn! (when (member "..." (cdr %))
(setq multiple? t))
(string-trim-right
(format "%s %s"
(doom-print--cli-markup (car %))
(doom-print--cli-markup
(string-join (remove "..." (cdr %)) "|")))))
switches
", ")
(if multiple? ", ..." "")
(indent (fill (markup docs)) doom-print-indent-increment))
"\n\n"))))
(with-temp-buffer
(if (null (cdr local))
(insert (if global "This command has no local options.\n" "") "\n")
(printopts local))
(when (cdr global)
(insert! ((bold "Global options:\n")))
(print-group! (printopts global)))
(string-trim-right (buffer-string)))))))
;;; Help: internal
(defun doom-cli-help--parse-args (args &optional noformatting?)
(cl-loop for arg in args
if (listp arg)
collect (string-join (doom-cli-help--parse-args arg noformatting?) "|")
else if (symbolp arg)
collect (format (if noformatting? "%s" "`%s'") (upcase (symbol-name arg)))
else collect arg))
(defun doom-cli-help--parse-docs (cli-list section-name)
(cl-check-type section-name string)
(let (alist)
(dolist (cli cli-list (nreverse alist))
(when-let (section (cdr (assoc section-name (doom-cli-docs cli))))
(with-temp-buffer
(save-excursion (insert section))
(let ((lead (current-indentation))
(buffer (current-buffer)))
(while (not (eobp))
(let ((heading (string-trim (buffer-substring (point-at-bol) (point-at-eol))))
(beg (point-at-bol 2))
end)
(forward-line 1)
(while (and (not (eobp))
(/= (current-indentation) lead)
(forward-line 1)))
(setf (alist-get heading alist nil nil #'equal)
(string-join
(delq
nil (list (alist-get heading alist nil nil #'equal)
(let ((end (point)))
(with-temp-buffer
(insert-buffer-substring buffer beg end)
(goto-char (point-min))
(indent-rigidly (point-min) (point-max) (- (current-indentation)))
(string-trim-right (buffer-string))))))
"\n\n"))))))))))
(provide 'doom-cli-help)
;;; help.el ends here

View file

@ -19,7 +19,7 @@
(config? ("--config" :yes) "Create `$DOOMDIR' or dummy files therein?") (config? ("--config" :yes) "Create `$DOOMDIR' or dummy files therein?")
(envfile? ("--env" :yes) "(Re)generate an envvars file? (see `$ doom help env`)") (envfile? ("--env" :yes) "(Re)generate an envvars file? (see `$ doom help env`)")
(install? ("--install" :yes) "Auto-install packages?") (install? ("--install" :yes) "Auto-install packages?")
(fonts? ("--fonts" :yes) "Install (or prompt to install) all-the-icons fonts?") (fonts? ("--fonts" :yes) "Install (or prompt to install) nerd-icons fonts?")
(hooks? ("--hooks" :yes) "Deploy Doom's git hooks to itself?") (hooks? ("--hooks" :yes) "Deploy Doom's git hooks to itself?")
&context context) &context context)
"Installs and sets up Doom Emacs for the first time. "Installs and sets up Doom Emacs for the first time.
@ -32,7 +32,7 @@ This command does the following:
3. Creates dummy files for `$DOOMDIR'/{config,packages}.el, 3. Creates dummy files for `$DOOMDIR'/{config,packages}.el,
4. Prompts you to generate an envvar file (same as `$ doom env`), 4. Prompts you to generate an envvar file (same as `$ doom env`),
5. Installs any dependencies of enabled modules (specified by `$DOOMDIR'/init.el), 5. Installs any dependencies of enabled modules (specified by `$DOOMDIR'/init.el),
6. And prompts to install all-the-icons' fonts 6. And prompts to install nerd-icons' fonts
This command is idempotent and safe to reuse. This command is idempotent and safe to reuse.
@ -55,20 +55,19 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
(setq doom-user-dir (expand-file-name "doom/" xdg-config-dir))))) (setq doom-user-dir (expand-file-name "doom/" xdg-config-dir)))))
(if (file-directory-p doom-user-dir) (if (file-directory-p doom-user-dir)
(print! (item "Skipping %s (already exists)") (relpath doom-user-dir)) (print! (item "Skipping %s (already exists)") (path doom-user-dir))
(make-directory doom-user-dir 'parents) (make-directory doom-user-dir 'parents)
(print! (success "Created %s") (relpath doom-user-dir))) (print! (success "Created %s") (path doom-user-dir)))
;; Create init.el, config.el & packages.el ;; Create init.el, config.el & packages.el
(print-group! (print-group!
(mapc (lambda (file) (mapc (lambda (file)
(cl-destructuring-bind (filename . template) file (cl-destructuring-bind (filename . template) file
(if (file-exists-p! filename doom-user-dir) (setq filename (doom-path doom-user-dir filename))
(print! (item "Skipping %s (already exists)") (if (file-exists-p filename)
(path filename)) (print! (item "Skipping %s (already exists)...") (path filename))
(print! (item "Creating %s%s") (relpath doom-user-dir) filename) (print! (item "Creating %s...") (path filename))
(with-temp-file (doom-path doom-user-dir filename) (with-temp-file filename (insert-file-contents template))
(insert-file-contents template))
(print! (success "Done!"))))) (print! (success "Done!")))))
(let ((template-dir (doom-path doom-emacs-dir "templates"))) (let ((template-dir (doom-path doom-emacs-dir "templates")))
`((,doom-module-init-file `((,doom-module-init-file
@ -96,7 +95,7 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
(if (eq install? :no) (if (eq install? :no)
(print! (warn "Not installing plugins, as requested")) (print! (warn "Not installing plugins, as requested"))
(print! "Installing plugins") (print! "Installing plugins")
(doom-packages-install)) (doom-packages-ensure))
(print! "Regenerating autoloads files") (print! "Regenerating autoloads files")
(doom-profile-generate) (doom-profile-generate)
@ -110,22 +109,6 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
('user-error ('user-error
(print! (warn "%s") (error-message-string e)))))) (print! (warn "%s") (error-message-string e))))))
(cond ((eq fonts? :no))
(IS-WINDOWS
(print! (warn "Doom cannot install all-the-icons' fonts on Windows!\n"))
(print-group!
(print!
(concat "You'll have to do so manually:\n\n"
" 1. Launch Doom Emacs\n"
" 2. Execute 'M-x all-the-icons-install-fonts' to download the fonts\n"
" 3. Open the download location in windows explorer\n"
" 4. Open each font file to install them"))))
((or yes? (y-or-n-p "Download and install all-the-icon's fonts?"))
(require 'all-the-icons)
(let ((window-system (cond (IS-MAC 'ns)
(IS-LINUX 'x))))
(all-the-icons-install-fonts 'yes))))
(when (file-exists-p "~/.emacs") (when (file-exists-p "~/.emacs")
(print! (warn "A ~/.emacs file was detected. This conflicts with Doom and should be deleted!"))) (print! (warn "A ~/.emacs file was detected. This conflicts with Doom and should be deleted!")))

View file

@ -183,32 +183,69 @@ OPTIONS:
input (doom-cli-command-string (cdr command))) input (doom-cli-command-string (cdr command)))
command))))) command)))))
(defun doom-cli-help--similarity (s1 s2) (defun doom-cli-help--similarity (a b)
;; Ratcliff-Obershelp similarity (- 1 (/ (float (doom-cli-help--string-distance a b))
(let* ((s1 (downcase s1)) (max (length a) (length b)))))
(s2 (downcase s2))
(s1len (length s1)) (defun doom-cli-help--string-distance (a b)
(s2len (length s2))) "Calculate the Restricted Damerau-Levenshtein distance between A and B.
(if (or (zerop s1len) This is also known as the Optimal String Alignment algorithm.
(zerop s2len))
0.0 It is assumed that A and B are both strings, and before processing both are
(/ (let ((i 0) (j 0) (score 0) jlast) converted to lowercase.
(while (< i s1len)
(unless jlast (setq jlast j)) This returns the minimum number of edits required to transform A
(if (and (< j s2len) to B, where each edit is a deletion, insertion, substitution, or
(= (aref s1 i) (aref s2 j))) transposition of a character, with the restriction that no
(progn (cl-incf score) substring is edited more than once."
(cl-incf i) (let ((a (downcase a))
(cl-incf j)) (b (downcase b))
(setq m 0) (alen (length a))
(cl-incf j) (blen (length b))
(when (>= j s2len) (start 0))
(setq j (or jlast j) (when (> alen blen)
jlast nil) (let ((c a)
(cl-incf i)))) (clen alen))
(* 2.0 score)) (setq a b alen blen
(+ (length s1) b c blen clen)))
(length s2)))))) (while (and (< start (min alen blen))
(= (aref a start) (aref b start)))
(cl-incf start))
(cl-decf start)
(if (= (1+ start) alen)
(- blen start)
(let ((v0 (make-vector (- blen start) 0))
(v1 (make-vector (- blen start) 0))
(a_i (aref a (max 0 start)))
(current 0)
a_i-1 b_j b_j-1
left transition-next
above this-transition)
(dotimes (vi (length v0))
(aset v0 vi (1+ vi)))
(dolist (i (number-sequence (1+ start) (1- alen)))
(setq a_i-1 a_i
a_i (aref a i)
b_j (aref b (max 0 start))
left (- i start 1)
current (- i start)
transition-next 0)
(dolist (j (number-sequence (1+ start) (1- blen)))
(setq b_j-1 b_j
b_j (aref b j)
above current
current left
this-transition transition-next
transition-next (aref v1 (- j start)))
(aset v1 (- j start) current)
(setq left (aref v0 (- j start)))
(unless (= a_i b_j)
;; Minimum between substitution, deletion, and insertion
(setq current (min (1+ current) (1+ above) (1+ left)))
(when (and (> i (1+ start)) (> j (1+ start)) (= a_i b_j-1) (= a_i-1 b_j))
(setq current (min current (cl-incf this-transition)))))
(aset v0 (- j start) current)))
current))))
;;; Help: printers ;;; Help: printers
;; TODO Parameterize optional args with `cl-defun' ;; TODO Parameterize optional args with `cl-defun'

View file

@ -13,28 +13,12 @@
;; ;;
;;; Commands ;;; Commands
(defcli! (:before (build b purge p)) (&context context) (defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0")
(require 'comp nil t)
(doom-initialize-core-packages))
;; DEPRECATED Replace with "doom sync --rebuild" (defcli-obsolete! ((purge p)) (gc) "v3.0.0")
(defcli! ((build b))
((rebuild-p ("-r") "Only rebuild packages that need rebuilding")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation"))
"Byte-compiles & symlinks installed packages.
This ensures that all needed files are symlinked from their package repo and
their elisp files are byte-compiled. This is especially necessary if you upgrade
Emacs (as byte-code is generally not forward-compatible)."
:benchmark t
(when jobs
(setq native-comp-async-jobs-number (truncate jobs)))
(when (doom-packages-build (not rebuild-p))
(doom-profile-generate))
t)
;; TODO Rename to "doom gc" and move to its own file ;; TODO Rename to "doom gc" and move to its own file
(defcli! ((purge p)) (defcli! (gc)
((nobuilds-p ("-b" "--no-builds") "Don't purge unneeded (built) packages") ((nobuilds-p ("-b" "--no-builds") "Don't purge unneeded (built) packages")
(noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages") (noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages")
(norepos-p ("-r" "--no-repos") "Don't purge unused straight repos") (norepos-p ("-r" "--no-repos") "Don't purge unused straight repos")
@ -50,6 +34,8 @@ possible.
It is a good idea to occasionally run this doom purge -g to ensure your package It is a good idea to occasionally run this doom purge -g to ensure your package
list remains lean." list remains lean."
:benchmark t :benchmark t
(require 'comp nil t)
(doom-initialize-core-packages)
(straight-check-all) (straight-check-all)
(when (doom-packages-purge (when (doom-packages-purge
(not noelpa-p) (not noelpa-p)
@ -242,154 +228,149 @@ list remains lean."
(defun doom-packages--write-missing-eln-errors () (defun doom-packages--write-missing-eln-errors ()
"Write .error files for any expected .eln files that are missing." "Write .error files for any expected .eln files that are missing."
(when (featurep 'native-compile) (cl-loop for file in doom-packages--eln-output-expected
(cl-loop for file in doom-packages--eln-output-expected for eln-name = (doom-packages--eln-file-name file)
for eln-name = (doom-packages--eln-file-name file) for eln-file = (doom-packages--eln-output-file eln-name)
for eln-file = (doom-packages--eln-output-file eln-name) for error-file = (doom-packages--eln-error-file eln-name)
for error-file = (doom-packages--eln-error-file eln-name) for error-dir = (file-name-directory error-file)
for error-dir = (file-name-directory error-file) unless (or (file-exists-p eln-file)
unless (or (file-exists-p eln-file) (file-newer-than-file-p error-file file)
(file-newer-than-file-p error-file file) (not (file-writable-p error-dir)))
(not (file-writable-p error-dir))) do (make-directory error-dir 'parents)
do (make-directory error-dir 'parents) (write-region "" nil error-file)
(write-region "" nil error-file) (doom-log "Wrote %s" error-file))
(doom-log "Wrote %s" error-file)) (setq doom-packages--eln-output-expected nil))
(setq doom-packages--eln-output-expected nil)))
(defun doom-packages--compile-site-files () (defun doom-packages--compile-site-files ()
"Queue async compilation for all non-doom Elisp files." "Queue async compilation for all non-doom Elisp files."
(when (featurep 'native-compile) (cl-loop with paths = (cl-loop for path in load-path
(cl-loop with paths = (cl-loop for path in load-path unless (file-in-directory-p path doom-local-dir)
unless (file-in-directory-p path doom-local-dir) collect path)
collect path) for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$")
for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$") if (and (file-exists-p (byte-compile-dest-file file))
if (and (file-exists-p (byte-compile-dest-file file)) (not (doom-packages--find-eln-file (doom-packages--eln-file-name file)))
(not (doom-packages--find-eln-file (doom-packages--eln-file-name file))) (not (cl-some (fn! (string-match-p % file))
(not (cl-some (fn! (string-match-p % file)) native-comp-deferred-compilation-deny-list))) do
native-comp-deferred-compilation-deny-list))) do (doom-log "Compiling %s" file)
(doom-log "Compiling %s" file) (native-compile-async file)))
(native-compile-async file))))
(defun doom-packages-install () (defun doom-packages-ensure (&optional force-p)
"Installs missing packages. "Ensure packages are installed, built"
This function will install any primary package (i.e. a package with a `package!'
declaration) or dependency thereof that hasn't already been."
(doom-initialize-packages) (doom-initialize-packages)
(print! (start "Installing packages...")) (if (not (file-directory-p (straight--repos-dir)))
(let ((pinned (doom-package-pinned-list))) (print! (start "Installing all packages for the first time (this may take a while)..."))
(print-group! (if force-p
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) (print! (start "Rebuilding all packages (this may take a while)..."))
(if-let (built (print! (start "Ensuring packages are installed and built..."))))
(doom-packages--with-recipes (doom-package-recipe-list)
(recipe package type local-repo)
(unless (file-directory-p (straight--repos-dir local-repo))
(doom-packages--cli-recipes-update))
(condition-case-unless-debug e
(let ((straight-use-package-pre-build-functions
(cons (lambda (pkg &rest _)
(when-let (commit (cdr (assoc pkg pinned)))
(print! (item "Checked out %s: %s") pkg commit)))
straight-use-package-pre-build-functions)))
(straight-use-package (intern package))
;; HACK Line encoding issues can plague repos with dirty
;; worktree prompts when updating packages or "Local
;; 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))
(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")))))
(error
(signal 'doom-package-error (list package e))))))
(progn
(when (featurep 'native-compile)
(doom-packages--compile-site-files)
(doom-packages--wait-for-native-compile-jobs)
(doom-packages--write-missing-eln-errors))
(print! (success "\033[KInstalled %d packages") (length built)))
(print! (item "No packages need to be installed"))
nil))))
(defun doom-packages-build (&optional force-p)
"(Re)build all packages."
(doom-initialize-packages)
(print! (start "(Re)building %spackages...") (if force-p "all " ""))
(print-group! (print-group!
(let ((straight-check-for-modifications (let ((straight-check-for-modifications
(when (file-directory-p (straight--modified-dir)) (when (file-directory-p (straight--modified-dir))
'(find-when-checking))) '(find-when-checking)))
(straight--allow-find (straight--allow-find
(and straight-check-for-modifications (and straight-check-for-modifications
(executable-find straight-find-executable) (executable-find straight-find-executable)
t)) t))
(straight--packages-not-to-rebuild (straight--packages-not-to-rebuild
(or straight--packages-not-to-rebuild (make-hash-table :test #'equal))) (or straight--packages-not-to-rebuild (make-hash-table :test #'equal)))
(straight--packages-to-rebuild (straight--packages-to-rebuild
(or (if force-p :all straight--packages-to-rebuild) (or (if force-p :all straight--packages-to-rebuild)
(make-hash-table :test #'equal))) (make-hash-table :test #'equal)))
(recipes (doom-package-recipe-list))) (recipes (doom-package-recipe-list))
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h) (pinned (doom-package-pinned-list)))
(unless force-p (add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h)
(straight--make-build-cache-available)) (straight--make-build-cache-available)
(if-let (built (if-let (built
(doom-packages--with-recipes recipes (package local-repo recipe) (doom-packages--with-recipes recipes (package local-repo recipe)
(unless force-p (let ((repo-dir (straight--repos-dir (or local-repo package)))
;; Ensure packages with outdated files/bytecode are rebuilt (build-dir (straight--build-dir package)))
(let* ((build-dir (straight--build-dir package)) (unless force-p
(repo-dir (straight--repos-dir local-repo)) ;; Ensure packages with outdated files/bytecode are rebuilt
(build (if (plist-member recipe :build) (let* ((build (if (plist-member recipe :build)
(plist-get recipe :build) (plist-get recipe :build)
t)) t))
(want-byte-compile (want-byte-compile
(or (eq build t) (or (eq build t)
(memq 'compile build))) (memq 'compile build)))
(want-native-compile (want-native-compile
(or (eq build t) (or (eq build t)
(memq 'native-compile build)))) (memq 'native-compile build))))
(and (eq (car-safe build) :not) (and (eq (car-safe build) :not)
(setq want-byte-compile (not want-byte-compile) (setq want-byte-compile (not want-byte-compile)
want-native-compile (not want-native-compile))) want-native-compile (not want-native-compile)))
(unless (featurep 'native-compile) (unless (featurep 'native-compile)
(setq want-native-compile nil)) (setq want-native-compile nil))
(and (or want-byte-compile want-native-compile) (and (or want-byte-compile want-native-compile)
(or (file-newer-than-file-p repo-dir build-dir) (or (file-newer-than-file-p repo-dir build-dir)
(file-exists-p (straight--modified-dir (or local-repo package))) (file-exists-p (straight--modified-dir (or local-repo package)))
(cl-loop with outdated = nil (cl-loop with outdated = nil
for file in (doom-files-in build-dir :match "\\.el$" :full t) for file in (doom-files-in build-dir :match "\\.el$" :full t)
if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file)) if (or (if want-byte-compile (doom-packages--elc-file-outdated-p file))
(if want-native-compile (doom-packages--eln-file-outdated-p file))) (if want-native-compile (doom-packages--eln-file-outdated-p file)))
do (setq outdated t) do (setq outdated t)
(when want-native-compile (when want-native-compile
(push file doom-packages--eln-output-expected)) (push file doom-packages--eln-output-expected))
finally return outdated)) finally return outdated))
(puthash package t straight--packages-to-rebuild)))) (puthash package t straight--packages-to-rebuild))))
(straight-use-package (intern package)))) (unless (file-directory-p repo-dir)
(progn (doom-packages--cli-recipes-update))
(when (featurep 'native-compile) (condition-case-unless-debug e
(doom-packages--compile-site-files) (let ((straight-vc-git-post-clone-hook
(doom-packages--wait-for-native-compile-jobs) (cons (lambda! (&key repo-dir commit)
(doom-packages--write-missing-eln-errors)) (print-group!
;; HACK Every time you save a file in a package that straight tracks, (if-let (pin (cdr (assoc package pinned)))
;; it is recorded in ~/.emacs.d/.local/straight/modified/. (print! (item "Pinned to %s") pin)
;; Typically, straight will clean these up after rebuilding, but (print! (item "Checked out %s") commit)))
;; Doom's use-case circumnavigates that, leaving these files ;; HACK: Line encoding issues can plague
;; there and causing a rebuild of those packages each time `doom ;; repos with dirty worktree prompts
;; sync' or similar is run, so we clean it up ourselves: ;; when updating packages or "Local
(delete-directory (straight--modified-dir) 'recursive) ;; variables entry is missing the
(print! (success "\033[KRebuilt %d package(s)") (length built))) ;; suffix" errors when installing them
(print! (item "No packages need rebuilding")) ;; (see #2637), so have git handle
nil)))) ;; conversion by force.
(when (and doom--system-windows-p (stringp repo-dir))
(let ((default-directory repo-dir))
(when (file-in-directory-p default-directory straight-base-dir)
(straight--process-run "git" "config" "core.autocrlf" "true")))))
straight-vc-git-post-clone-hook)))
(straight-use-package (intern package))
;; HACK: Straight can sometimes fail to clone a repo,
;; leaving behind an empty directory which, in future
;; invocations, it will assume indicates a successful
;; clone (causing load errors later).
(let ((try 0))
(while (or (not (file-directory-p repo-dir))
(directory-empty-p repo-dir))
(when (= try 3)
(error "Failed to clone package"))
(print! "Failed to clone %S, trying again (attempt #%d)..." package (1+ try))
(delete-directory repo-dir t)
(delete-directory build-dir t)
(straight-use-package (intern package))
(cl-incf try))))
(error
(signal 'doom-package-error (list package e)))))))
(progn
(when (featurep 'native-compile)
(doom-packages--compile-site-files)
(doom-packages--wait-for-native-compile-jobs)
(doom-packages--write-missing-eln-errors))
;; HACK: Every time you save a file in a package that straight
;; tracks, it is recorded in ~/.emacs.d/.local/straight/modified/.
;; Typically, straight will clean these up after rebuilding, but
;; Doom's use-case circumnavigates that, leaving these files there
;; and causing a rebuild of those packages each time `doom sync'
;; or similar is run, so we clean it up ourselves:
(delete-directory (straight--modified-dir) 'recursive)
(print! (success "\033[KBuilt %d package(s)") (length built)))
(print! (item "No packages need attention"))
nil))))
(defun doom-packages-update () (defun doom-packages-update (&optional pinned-only-p)
"Updates packages." "Updates packages."
(doom-initialize-packages) (doom-initialize-packages)
(doom-packages--barf-if-incomplete) (doom-packages--barf-if-incomplete)
(doom-packages--cli-recipes-update)
(let* ((repo-dir (straight--repos-dir)) (let* ((repo-dir (straight--repos-dir))
(pinned (doom-package-pinned-list)) (pinned (doom-package-pinned-list))
(recipes (doom-package-recipe-list)) (recipes (doom-package-recipe-list))
@ -397,9 +378,10 @@ declaration) or dependency thereof that hasn't already been."
(repos-to-rebuild (make-hash-table :test 'equal)) (repos-to-rebuild (make-hash-table :test 'equal))
(total (length recipes)) (total (length recipes))
(esc (unless init-file-debug "\033[1A")) (esc (unless init-file-debug "\033[1A"))
(i 0) (i 0))
errors) (if pinned-only-p
(print! (start "Updating packages (this may take a while)...")) (print! (start "Updating pinned packages..."))
(print! (start "Updating all packages (this may take a while)...")))
(doom-packages--with-recipes recipes (recipe package type local-repo) (doom-packages--with-recipes recipes (recipe package type local-repo)
(cl-incf i) (cl-incf i)
(print-group! (print-group!
@ -412,11 +394,13 @@ declaration) or dependency thereof that hasn't already been."
(cl-return)) (cl-return))
(let ((default-directory (straight--repos-dir local-repo))) (let ((default-directory (straight--repos-dir local-repo)))
(unless (file-in-directory-p default-directory repo-dir) (unless (file-in-directory-p default-directory repo-dir)
(print! (warn "(%d/%d) Skipping %s because it is local") i total package) (print! (warn "(%d/%d) Skipping %s because it is out-of-tree...") i total package)
(cl-return)) (cl-return))
(when (eq type 'git) (when (eq type 'git)
(unless (file-exists-p ".git") (unless (file-exists-p ".git")
(error "%S is not a valid repository" package))) (error "%S is not a valid repository" package)))
(when (and pinned-only-p (not (assoc local-repo pinned)))
(cl-return))
(condition-case-unless-debug e (condition-case-unless-debug e
(let ((ref (straight-vc-get-commit type local-repo)) (let ((ref (straight-vc-get-commit type local-repo))
(target-ref (target-ref
@ -430,13 +414,6 @@ declaration) or dependency thereof that hasn't already been."
(doom-packages--straight-with (straight-vc-fetch-from-remote recipe) (doom-packages--straight-with (straight-vc-fetch-from-remote recipe)
(when .it (when .it
(straight-merge-package package) (straight-merge-package package)
;; (condition-case e
;; (straight-merge-package package)
;; (wrong-type-argument
;; (if (not (equal (cdr e) '(arrayp nil)))
;; (signal (car e) (cdr e))
;; (delete-directory (straight--build-dir local-repo) t)
;; (straight-use-package (intern package)))))
(setq target-ref (straight-vc-get-commit type local-repo)) (setq target-ref (straight-vc-get-commit type local-repo))
(setq output (doom-packages--commit-log-between ref target-ref) (setq output (doom-packages--commit-log-between ref target-ref)
commits (length (split-string output "\n" t))) commits (length (split-string output "\n" t)))
@ -464,7 +441,7 @@ declaration) or dependency thereof that hasn't already been."
(straight-vc-git-default-clone-depth 'full)) (straight-vc-git-default-clone-depth 'full))
(delete-directory repo 'recursive) (delete-directory repo 'recursive)
(print-group! (print-group!
(straight-use-package (intern package) nil 'no-build)) (straight-use-package (intern package) nil 'no-build))
(prog1 (file-directory-p repo) (prog1 (file-directory-p repo)
(or (not (eq type 'git)) (or (not (eq type 'git))
(setq output (doom-packages--commit-log-between ref target-ref) (setq output (doom-packages--commit-log-between ref target-ref)
@ -520,13 +497,14 @@ declaration) or dependency thereof that hasn't already been."
(princ "\033[K") (princ "\033[K")
(if (hash-table-empty-p packages-to-rebuild) (if (hash-table-empty-p packages-to-rebuild)
(ignore (print! (success "All %d packages are up-to-date") total)) (ignore (print! (success "All %d packages are up-to-date") total))
(doom-packages--cli-recipes-update)
(straight--transaction-finalize) (straight--transaction-finalize)
(let ((default-directory (straight--build-dir))) (let ((default-directory (straight--build-dir)))
(mapc (doom-rpartial #'delete-directory 'recursive) (mapc (doom-rpartial #'delete-directory 'recursive)
(hash-table-keys packages-to-rebuild))) (hash-table-keys packages-to-rebuild)))
(print! (success "Updated %d package(s)") (print! (success "Updated %d package(s)")
(hash-table-count packages-to-rebuild)) (hash-table-count packages-to-rebuild))
(doom-packages-build) (doom-packages-ensure)
t)))) t))))
@ -652,6 +630,7 @@ If ELPA-P, include packages installed with package.el (M-x package-install)."
(doom-initialize-packages) (doom-initialize-packages)
(doom-packages--barf-if-incomplete) (doom-packages--barf-if-incomplete)
(print! (start "Purging orphaned packages (for the emperor)...")) (print! (start "Purging orphaned packages (for the emperor)..."))
(quiet! (straight-prune-build-cache))
(cl-destructuring-bind (&optional builds-to-purge repos-to-purge repos-to-regraft) (cl-destructuring-bind (&optional builds-to-purge repos-to-purge repos-to-regraft)
(let ((rdirs (let ((rdirs
(and (or repos-p regraft-repos-p) (and (or repos-p regraft-repos-p)
@ -672,8 +651,7 @@ If ELPA-P, include packages installed with package.el (M-x package-install)."
nil (list nil (list
(if (not builds-p) (if (not builds-p)
(ignore (print! (item "Skipping builds"))) (ignore (print! (item "Skipping builds")))
(and (/= 0 (doom-packages--purge-builds builds-to-purge)) (/= 0 (doom-packages--purge-builds builds-to-purge)))
(quiet! (straight-prune-build-cache))))
(if (not elpa-p) (if (not elpa-p)
(ignore (print! (item "Skipping elpa packages"))) (ignore (print! (item "Skipping elpa packages")))
(/= 0 (doom-packages--purge-elpa))) (/= 0 (doom-packages--purge-elpa)))
@ -821,5 +799,31 @@ However, in batch mode, print to stdout instead of stderr."
"/dev/null"))) "/dev/null")))
(apply fn args))) (apply fn args)))
;; If the repo failed to clone correctly (usually due to a connection failure),
;; straight proceeds as normal until a later call produces a garbage result
;; (typically, when it fails to fetch the remote branch of the empty directory).
;; This causes Straight to throw an otherwise cryptic type error when it tries
;; to sanitize the result for its log buffer.
;;
;; This error is a common source of user confusion and false positive bug
;; reports, so this advice catches them to regurgitates a more cogent
;; explanation.
(defadvice! doom-cli--straight-throw-error-on-no-branch-a (fn &rest args)
:around #'straight--process-log
(letf! ((defun shell-quote-argument (&rest args)
(unless (car args)
(error "Package was not properly cloned due to a connection failure, please try again later"))
(apply shell-quote-argument args)))
(apply fn args)))
(defadvice! doom-cli--straight-regurgitate-empty-string-error-a (fn &rest args)
:around #'straight-vc-git-local-repo-name
(condition-case-unless-debug e
(apply fn args)
(wrong-type-argument
(if (eq (cadr e) 'stringp)
(error "Package was not properly cloned due to a connection failure, please try again later")
(signal (car e) (cdr e))))))
(provide 'doom-cli-packages) (provide 'doom-cli-packages)
;;; packages.el ends here ;;; packages.el ends here

View file

@ -14,18 +14,21 @@
(defvar doom-before-sync-hook () (defvar doom-before-sync-hook ()
"Hooks run before 'doom sync' synchronizes the user's config with Doom.") "Hooks run before 'doom sync' synchronizes the user's config with Doom.")
(defvar doom-cli-sync-info-file (file-name-concat doom-profile-data-dir "sync"))
;; ;;
;;; Commands ;;; Commands
(defcli-alias! (:before (sync s)) (:before build))
(defcli! ((sync s)) (defcli! ((sync s))
((noenvvar? ("-e") "Don't regenerate the envvar file") ((noenvvar? ("-e") "Don't regenerate the envvar file")
(noelc? ("-c") "Don't recompile config") (update? ("-u") "Update all installed packages after syncing")
(update? ("-u") "Update installed packages after syncing") (noupdate? ("-U") "Don't update any packages")
(purge? ("-p") "Purge orphaned package repos & regraft them") (purge? ("--gc") "Purge orphaned package repos & regraft them")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation")) (jobs ("-j" "--jobs" num) "How many threads to use for native compilation")
(rebuild? ("-b" "--rebuild") "Rebuild all installed packages, unconditionally")
(nobuild? ("-B") "Don't rebuild packages when hostname or Emacs version has changed")
&context context)
"Synchronize your config with Doom Emacs. "Synchronize your config with Doom Emacs.
This is the equivalent of running autoremove, install, autoloads, then This is the equivalent of running autoremove, install, autoloads, then
@ -33,8 +36,10 @@ recompile. Run this whenever you:
1. Modify your `doom!' block, 1. Modify your `doom!' block,
2. Add or remove `package!' blocks to your config, 2. Add or remove `package!' blocks to your config,
3. Add or remove autoloaded functions in module autoloaded files. 3. Add or remove autoloaded functions in module autoloaded files,
4. Update Doom outside of Doom (e.g. with git) 4. Update Doom outside of Doom (e.g. with git),
5. Move your Doom config (either $EMACSDIR or $DOOMDIR) to a new location.
6. When you up (or down) grade Emacs itself.
It will ensure that unneeded packages are removed, all needed packages are It will ensure that unneeded packages are removed, all needed packages are
installed, autoloads files are up-to-date and no byte-compiled files have gone installed, autoloads files are up-to-date and no byte-compiled files have gone
@ -47,26 +52,49 @@ OPTIONS:
:benchmark t :benchmark t
(when (doom-profiles-bootloadable-p) (when (doom-profiles-bootloadable-p)
(call! '(profiles sync "--reload"))) (call! '(profiles sync "--reload")))
(run-hooks 'doom-before-sync-hook)
(add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(when jobs (when jobs
(setq native-comp-async-jobs-number (truncate jobs))) (setq native-comp-async-jobs-number (truncate jobs)))
(print! (start "Synchronizing %S profile..." ) (run-hooks 'doom-before-sync-hook)
(or (car doom-profile) "default")) (add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(print! (item "Using Emacs %s @ %s") emacs-version (path invocation-directory invocation-name))
(print! (start "Synchronizing %S profile..." ) (or (car doom-profile) "default"))
(unwind-protect (unwind-protect
(print-group! (print-group!
(when (and (not noenvvar?) ;; If the user has up/downgraded Emacs since last sync, or copied their
(file-exists-p doom-env-file)) ;; config to a different system, then their packages need to be
(call! '(env))) ;; recompiled. This is necessary because Emacs byte-code is not
(doom-packages-install) ;; necessarily back/forward compatible across major versions, and many
(doom-packages-build) ;; packages bake in hardcoded data at compile-time.
(when update? (pcase-let ((`(,old-version . ,old-host) (doom-file-read doom-cli-sync-info-file :by 'read :noerror t))
(doom-packages-update)) (to-rebuild nil))
(doom-packages-purge purge? purge? purge? purge? purge?) (when (and old-version (not (equal old-version emacs-version)))
(when (doom-profile-generate) (print! (warn "Emacs version has changed since last sync (from %s to %s)") old-version emacs-version)
(print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect")) (setq to-rebuild t))
(run-hooks 'doom-after-sync-hook)) (when (and old-host (not (equal old-host (system-name))))
t) (print! (warn "Your system has changed since last sync"))
(setq to-rebuild t))
(when (and to-rebuild (not (doom-cli-context-suppress-prompts-p context)))
(cond (nobuild?
(print! (warn "Packages must be rebuilt, but -B has prevented it. Skipping...")))
((doom-cli-context-get context 'upgrading)
(print! (warn "Packages will be rebuilt"))
(setq rebuild? t))
((y-or-n-p (format! " %s" "Installed packages must be rebuilt. Do so now?"))
(setq rebuild? t))
((exit! 0)))))
(when (and (not noenvvar?)
(file-exists-p doom-env-file))
(call! '(env)))
(doom-packages-ensure rebuild?)
(unless noupdate? (doom-packages-update (not update?)))
(doom-packages-purge purge? purge? purge? purge? purge?)
(when (doom-profile-generate)
(print! (item "Restart Emacs or use 'M-x doom/reload' for changes to take effect"))
(run-hooks 'doom-after-sync-hook))
(when (and (not rebuild?) (not nobuild?))
(with-temp-file doom-cli-sync-info-file
(prin1 (cons emacs-version (system-name)) (current-buffer))))
t)
(remove-hook 'kill-emacs-hook #'doom-sync--abort-warning-h))) (remove-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)))

View file

@ -3,7 +3,6 @@
;;; Code: ;;; Code:
(load! "packages") (load! "packages")
(load! "compile")
;; ;;
@ -22,6 +21,7 @@
(defcli! ((upgrade up)) (defcli! ((upgrade up))
((packages? ("-p" "--packages") "Only upgrade packages, not Doom") ((packages? ("-p" "--packages") "Only upgrade packages, not Doom")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation") (jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation")
(nobuild? ("-B") "Don't rebuild packages when hostname or Emacs version has changed")
&context context) &context context)
"Updates Doom and packages. "Updates Doom and packages.
@ -30,10 +30,11 @@ following shell commands:
cd ~/.emacs.d cd ~/.emacs.d
git pull --rebase git pull --rebase
doom clean
doom sync -u" doom sync -u"
(let* ((force? (doom-cli-context-suppress-prompts-p context)) (let* ((force? (doom-cli-context-suppress-prompts-p context))
(sync-cmd (append '("sync" "-u") (if jobs `("-j" ,num))))) (sync-cmd (append '("sync" "-u")
(if nobuild? '("-B"))
(if jobs `("-j" ,num)))))
(cond (cond
(packages? (packages?
;; HACK It's messy to use straight to upgrade straight, due to the ;; HACK It's messy to use straight to upgrade straight, due to the
@ -54,7 +55,9 @@ following shell commands:
;; Reload Doom's CLI & libraries, in case there were any upstream changes. ;; Reload Doom's CLI & libraries, in case there were any upstream changes.
;; Major changes will still break, however ;; Major changes will still break, however
(print! (item "Reloading Doom Emacs")) (print! (item "Reloading Doom Emacs"))
(doom-cli-context-put context 'upgrading t)
(exit! "doom" "upgrade" "-p" (exit! "doom" "upgrade" "-p"
(if nobuild? "-B")
(if force? "--force") (if force? "--force")
(if jobs (format "--jobs=%d" jobs)))) (if jobs (format "--jobs=%d" jobs))))
@ -96,6 +99,8 @@ following shell commands:
(sh! "git" "reset" "--hard" (format "origin/%s" branch)) (sh! "git" "reset" "--hard" (format "origin/%s" branch))
(sh! "git" "clean" "-ffd"))) (sh! "git" "clean" "-ffd")))
;; In case of leftover state from a partial/incomplete 'doom upgrade'
(sh! "git" "branch" "-D" target-remote)
(sh! "git" "remote" "remove" doom-upgrade-remote) (sh! "git" "remote" "remove" doom-upgrade-remote)
(unwind-protect (unwind-protect
(let (result) (let (result)
@ -136,7 +141,6 @@ following shell commands:
(ignore (print! (error "Aborted"))) (ignore (print! (error "Aborted")))
(print! (start "Upgrading Doom Emacs...")) (print! (start "Upgrading Doom Emacs..."))
(print-group! (print-group!
(doom-compile-clean)
(doom-cli-context-put context 'straight-recipe (doom-upgrade--get-straight-recipe)) (doom-cli-context-put context 'straight-recipe (doom-upgrade--get-straight-recipe))
(or (and (zerop (car (sh! "git" "reset" "--hard" target-remote))) (or (and (zerop (car (sh! "git" "reset" "--hard" target-remote)))
(equal (cdr (sh! "git" "rev-parse" "HEAD")) new-rev)) (equal (cdr (sh! "git" "rev-parse" "HEAD")) new-rev))

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

@ -25,22 +25,22 @@
;; HACK: Load `cl' and site files manually to prevent polluting logs and ;; HACK: Load `cl' and site files manually to prevent polluting logs and
;; stdout with deprecation and/or file load messages. ;; stdout with deprecation and/or file load messages.
(let ((inhibit-message (not init-file-debug))) (quiet!
(require 'cl nil t) (require 'cl nil t)
(unless site-run-file (unless site-run-file
(let ((site-run-file "site-start") (let ((site-run-file "site-start")
(tail load-path) (tail load-path)
(lispdir (expand-file-name "../lisp" data-directory)) (lispdir (expand-file-name "../lisp" data-directory))
dir) dir)
(while tail (while tail
(setq dir (car tail)) (setq dir (car tail))
(let ((default-directory dir)) (let ((default-directory dir))
(load (expand-file-name "subdirs.el") t inhibit-message t)) (load (expand-file-name "subdirs.el") t inhibit-message t))
(unless (string-prefix-p lispdir dir) (unless (string-prefix-p lispdir dir)
(let ((default-directory dir)) (let ((default-directory dir))
(load (expand-file-name "leim-list.el") t inhibit-message t))) (load (expand-file-name "leim-list.el") t inhibit-message t)))
(setq tail (cdr tail))) (setq tail (cdr tail)))
(load site-run-file t inhibit-message)))) (load site-run-file t inhibit-message))))
(setq-default (setq-default
;; PERF: Don't generate superfluous files when writing temp buffers. ;; PERF: Don't generate superfluous files when writing temp buffers.
@ -92,15 +92,14 @@
:group 'doom) :group 'doom)
(defvar doom-cli-load-path (defvar doom-cli-load-path
(let ((paths (split-string (or (getenv "DOOMPATH") "") path-separator))) (append (when-let ((doompath (getenv "DOOMPATH")))
(if (member "" paths) (cl-loop for dir in (split-string doompath path-separator)
(cl-substitute (doom-path (dir!) "cli/") "" paths :test #'equal) collect (expand-file-name dir)))
paths)) (list (file-name-concat (dir!) "cli")))
"A list of paths to search for autoloaded Doom CLIs. "A list of paths to search for autoloaded Doom CLIs.
It is prefilled by the DOOMPATH envvar (a colon-separated list on Linux/macOS, It is prefilled by the DOOMPATH envvar (a colon-separated list on Linux/macOS,
semicolon otherwise). Empty entries in DOOMPATH are replaced with the semicolon otherwise).")
$EMACSDIR/cli/.")
;;; CLI definition variables ;;; CLI definition variables
(defvar doom-cli-argument-types (defvar doom-cli-argument-types
@ -1050,9 +1049,9 @@ considered as well."
"\n"))) "\n")))
(print! (warn "Wrote extended straight log to %s") (print! (warn "Wrote extended straight log to %s")
(path (let ((coding-system-for-write 'utf-8-auto)) (path (let ((coding-system-for-write 'utf-8-auto))
(with-temp-file error-file (with-file-modes #o600
(insert-buffer-substring (straight--process-buffer))) (with-temp-file error-file
(set-file-modes error-file #o600) (insert-buffer-substring (straight--process-buffer))))
error-file)))) error-file))))
((eq type 'error) ((eq type 'error)
(let* ((generic? (eq (car data) 'error)) (let* ((generic? (eq (car data) 'error))
@ -1123,11 +1122,12 @@ See `doom-cli-log-file-format' for details."
(let* ((buffer (doom-cli-context-stderr context)) (let* ((buffer (doom-cli-context-stderr context))
(file (doom-cli--output-file "log" context))) (file (doom-cli--output-file "log" context)))
(when (> (buffer-size buffer) 0) (when (> (buffer-size buffer) 0)
(make-directory (file-name-directory file) t) (with-file-modes #o700
(with-temp-file file (make-directory (file-name-directory file) t))
(insert-buffer-substring buffer) (with-file-modes #o600
(ansi-color-filter-region (point-min) (point-max))) (with-temp-file file
(set-file-modes file #o600))))) (insert-buffer-substring buffer)
(ansi-color-filter-region (point-min) (point-max))))))))
(defun doom-cli--output-benchmark-h (context) (defun doom-cli--output-benchmark-h (context)
"Write this session's benchmark to stdout or stderr, depending. "Write this session's benchmark to stdout or stderr, depending.
@ -1351,10 +1351,11 @@ ARGS are options passed to less. If DOOMPAGER is set, ARGS are ignored."
((let ((tmpfile (doom-cli--output-file 'output context)) ((let ((tmpfile (doom-cli--output-file 'output context))
(coding-system-for-write 'utf-8-auto)) (coding-system-for-write 'utf-8-auto))
(make-directory (file-name-directory tmpfile) t) (with-file-modes #o700
(with-temp-file tmpfile (make-directory (file-name-directory tmpfile) t))
(insert-buffer-substring (doom-cli-context-stdout context))) (with-file-modes #o600
(set-file-modes tmpfile #o600) (with-temp-file tmpfile
(insert-buffer-substring (doom-cli-context-stdout context))))
(doom-cli--restart (doom-cli--restart
(format "%s <%s; rm -f%s %s" (format "%s <%s; rm -f%s %s"
(or pager (or pager
@ -1782,7 +1783,7 @@ See `defcli!' for information about COMMANDSPEC.
TARGET is simply a command list. TARGET is simply a command list.
WHEN specifies what version this command was rendered obsolete." WHEN specifies what version this command was rendered obsolete."
`(let ((ncommand (doom-cli-command-normalize (backquote ,target) doom-cli--group-plist))) `(let ((ncommand (doom-cli-command-normalize (backquote ,target) doom-cli--group-plist)))
(defcli! ,commandspec (&context context &cli cli &rest args) (defcli! ,commandspec (&context _context &cli cli &rest args)
:docs (format "An obsolete alias for '%s'." (doom-cli-command-string ncommand)) :docs (format "An obsolete alias for '%s'." (doom-cli-command-string ncommand))
:hide t :hide t
(print! (warn "'%s' was deprecated in %s") (print! (warn "'%s' was deprecated in %s")

View file

@ -3,9 +3,12 @@
;;; Code: ;;; Code:
(defvar doom-detect-indentation-excluded-modes (defvar doom-detect-indentation-excluded-modes
'(fundamental-mode pascal-mode so-long-mode doom-docs-org-mode) '(pascal-mode
"A list of major modes in which indentation should be automatically so-long-mode
detected.") ;; Automatic indent detection in org files is meaningless. Not to mention, a
;; non-standard `tab-width' causes an error in org-mode.
org-mode)
"A list of major modes where indentation shouldn't be auto-detected.")
(defvar-local doom-inhibit-indent-detection nil (defvar-local doom-inhibit-indent-detection nil
"A buffer-local flag that indicates whether `dtrt-indent' should try to detect "A buffer-local flag that indicates whether `dtrt-indent' should try to detect
@ -130,7 +133,8 @@ or file path may exist now."
(let ((buffer (or (buffer-base-buffer) (current-buffer)))) (let ((buffer (or (buffer-base-buffer) (current-buffer))))
(and (buffer-file-name buffer) (and (buffer-file-name buffer)
(eq buffer (window-buffer (selected-window))) ; only visible buffers (eq buffer (window-buffer (selected-window))) ; only visible buffers
(set-auto-mode)))))) (set-auto-mode)
(not (eq major-mode 'fundamental-mode)))))))
(defadvice! doom--shut-up-autosave-a (fn &rest args) (defadvice! doom--shut-up-autosave-a (fn &rest args)
"If a file has autosaved data, `after-find-file' will pause for 1 second to "If a file has autosaved data, `after-find-file' will pause for 1 second to
@ -402,6 +406,11 @@ the unwritable tidbits."
(unless doom-large-file-p (unless doom-large-file-p
(apply fn args))) (apply fn args)))
(defadvice! doom--inhibit-saveplace-if-point-not-at-bol-a (&rest _)
"If something else has moved point, don't try to move it again."
:before-while #'save-place-find-file-hook
(bobp))
(defadvice! doom--dont-prettify-saveplace-cache-a (fn) (defadvice! doom--dont-prettify-saveplace-cache-a (fn)
"`save-place-alist-to-file' uses `pp' to prettify the contents of its cache. "`save-place-alist-to-file' uses `pp' to prettify the contents of its cache.
`pp' can be expensive for longer lists, and there's no reason to prettify cache `pp' can be expensive for longer lists, and there's no reason to prettify cache
@ -501,8 +510,9 @@ files, so this replace calls to `pp' with the much faster `prin1'."
(unless (or (not after-init-time) (unless (or (not after-init-time)
doom-inhibit-indent-detection doom-inhibit-indent-detection
doom-large-file-p doom-large-file-p
(memq major-mode doom-detect-indentation-excluded-modes) (eq major-mode 'fundamental-mode)
(member (substring (buffer-name) 0 1) '(" " "*"))) (member (substring (buffer-name) 0 1) '(" " "*"))
(apply #'derived-mode-p doom-detect-indentation-excluded-modes))
;; Don't display messages in the echo area, but still log them ;; Don't display messages in the echo area, but still log them
(let ((inhibit-message (not init-file-debug))) (let ((inhibit-message (not init-file-debug)))
(dtrt-indent-mode +1)))) (dtrt-indent-mode +1))))
@ -583,11 +593,9 @@ current buffer."
filename)) filename))
(prog1 (apply fn args) (prog1 (apply fn args)
(when (buffer-live-p buf) (when (buffer-live-p buf)
(with-current-buffer buf (goto-char pos))))))))) (with-current-buffer buf (goto-char pos))))))))
:config
(setq helpful-set-variable-function #'setq!))
;;;###package imenu
(add-hook 'imenu-after-jump-hook #'recenter)
(use-package! smartparens (use-package! smartparens

View file

@ -15,6 +15,12 @@
"An alternative leader prefix key, used for Insert and Emacs states, and for "An alternative leader prefix key, used for Insert and Emacs states, and for
non-evil users.") non-evil users.")
(defvar doom-leader-key-states '(normal visual motion)
"which evil modes to activate the leader key for")
(defvar doom-leader-alt-key-states '(emacs insert)
"which evil modes to activate the alternative leader key for")
(defvar doom-localleader-key "SPC m" (defvar doom-localleader-key "SPC m"
"The localleader prefix key, for major-mode specific commands.") "The localleader prefix key, for major-mode specific commands.")
@ -35,7 +41,7 @@ and Emacs states, and for non-evil users.")
;;; Global keybind settings ;;; Global keybind settings
(cond (cond
(IS-MAC (doom--system-macos-p
;; mac-* variables are used by the special emacs-mac build of Emacs by ;; mac-* variables are used by the special emacs-mac build of Emacs by
;; Yamamoto Mitsuharu, while other builds use ns-*. ;; Yamamoto Mitsuharu, while other builds use ns-*.
(setq mac-command-modifier 'super (setq mac-command-modifier 'super
@ -45,18 +51,18 @@ and Emacs states, and for non-evil users.")
;; Free up the right option for character composition ;; Free up the right option for character composition
mac-right-option-modifier 'none mac-right-option-modifier 'none
ns-right-option-modifier 'none)) ns-right-option-modifier 'none))
(IS-WINDOWS (doom--system-windows-p
(setq w32-lwindow-modifier 'super (setq w32-lwindow-modifier 'super
w32-rwindow-modifier 'super))) w32-rwindow-modifier 'super)))
;; HACK: Emacs cannot distinguish between C-i from TAB. This is largely a ;; HACK: Emacs cannot distinguish between C-i from TAB. This is largely a
;; byproduct of its history in the terminal, which can't distinguish them ;; byproduct of its history in the terminal, which can't distinguish them
;; either, however, when GUIs came about Emacs greated separate input events ;; either, however, when GUIs came about Emacs created separate input events
;; for more contentious keys like TAB and RET. Therefore [return] != RET, ;; for more contentious keys like TAB and RET. Therefore [return] != RET,
;; [tab] != TAB, and [backspace] != DEL. ;; [tab] != TAB, and [backspace] != DEL.
;; ;;
;; In the same vein, this keybind adds a [C-i] event, so users can bind to it. ;; In the same vein, this keybind adds a [C-i] event, so users can bind to it
;; Otherwise, it falls back to regular C-i keybinds. ;; independently of TAB. Otherwise, it falls back to keys bound to C-i.
(define-key key-translation-map [?\C-i] (define-key key-translation-map [?\C-i]
(cmd! (if (let ((keys (this-single-command-raw-keys))) (cmd! (if (let ((keys (this-single-command-raw-keys)))
(and keys (and keys
@ -98,19 +104,20 @@ all hooks after it are ignored.")
(defun doom/escape (&optional interactive) (defun doom/escape (&optional interactive)
"Run `doom-escape-hook'." "Run `doom-escape-hook'."
(interactive (list 'interactive)) (interactive (list 'interactive))
(cond ((minibuffer-window-active-p (minibuffer-window)) (let ((inhibit-quit t))
;; quit the minibuffer if open. (cond ((minibuffer-window-active-p (minibuffer-window))
(when interactive ;; quit the minibuffer if open.
(setq this-command 'abort-recursive-edit))
(abort-recursive-edit))
;; Run all escape hooks. If any returns non-nil, then stop there.
((run-hook-with-args-until-success 'doom-escape-hook))
;; don't abort macros
((or defining-kbd-macro executing-kbd-macro) nil)
;; Back to the default
((unwind-protect (keyboard-quit)
(when interactive (when interactive
(setq this-command 'keyboard-quit)))))) (setq this-command 'abort-recursive-edit))
(abort-recursive-edit))
;; Run all escape hooks. If any returns non-nil, then stop there.
((run-hook-with-args-until-success 'doom-escape-hook))
;; don't abort macros
((or defining-kbd-macro executing-kbd-macro) nil)
;; Back to the default
((unwind-protect (keyboard-quit)
(when interactive
(setq this-command 'keyboard-quit)))))))
(global-set-key [remap keyboard-quit] #'doom/escape) (global-set-key [remap keyboard-quit] #'doom/escape)

View file

@ -4,6 +4,7 @@
;;; Custom error types ;;; Custom error types
(define-error 'doom-error "An unexpected Doom error") (define-error 'doom-error "An unexpected Doom error")
(define-error 'doom-font-error "Could not find a font on your system" 'doom-error)
(define-error 'doom-nosync-error "Doom hasn't been initialized yet; did you remember to run 'doom sync' in the shell?" 'doom-error) (define-error 'doom-nosync-error "Doom hasn't been initialized yet; did you remember to run 'doom sync' in the shell?" 'doom-error)
(define-error 'doom-core-error "Unexpected error in Doom's core" 'doom-error) (define-error 'doom-core-error "Unexpected error in Doom's core" 'doom-error)
(define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error) (define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error)
@ -302,9 +303,9 @@ TRIGGER-HOOK is a list of quoted hooks and/or sharp-quoted functions."
(error "file!: cannot deduce the current file path"))) (error "file!: cannot deduce the current file path")))
(defmacro dir! () (defmacro dir! ()
"Return the directory of the file this macro was called." "Return the directory of the file in which this macro was called."
(let (file-name-handler-alist) (let (file-name-handler-alist)
(file-name-directory (macroexpand '(file!))))) (file-name-directory (macroexpand '(file!)))))
;; REVIEW Should I deprecate this? The macro's name is so long... ;; REVIEW Should I deprecate this? The macro's name is so long...
(defalias 'letenv! 'with-environment-variables) (defalias 'letenv! 'with-environment-variables)
@ -801,7 +802,7 @@ This macro accepts, in order:
func-forms))) func-forms)))
`(progn `(progn
,@defn-forms ,@defn-forms
(dolist (hook (nreverse ',hook-forms)) (dolist (hook ',(nreverse hook-forms))
(dolist (func (list ,@func-forms)) (dolist (func (list ,@func-forms))
,(if remove-p ,(if remove-p
`(remove-hook hook func ,local-p) `(remove-hook hook func ,local-p)
@ -882,16 +883,16 @@ testing advice (when combined with `rotate-text').
(dolist (target (cdr targets)) (dolist (target (cdr targets))
(advice-remove target #',symbol))))) (advice-remove target #',symbol)))))
;;
;;; Backports
(defmacro defbackport! (type symbol &rest body) (defmacro defbackport! (type symbol &rest body)
"Backport a function/macro/alias from later versions of Emacs." "Backport a function/macro/alias from later versions of Emacs."
(declare (indent defun) (doc-string 4)) (declare (indent defun) (doc-string 4))
(unless (fboundp (doom-unquote symbol)) (unless (fboundp (doom-unquote symbol))
`(,type ,symbol ,@body))) `(,type ,symbol ,@body)))
;;
;;; Backports
;; `format-spec' wasn't autoloaded until 28.1 ;; `format-spec' wasn't autoloaded until 28.1
(defbackport! autoload 'format-spec "format-spec") (defbackport! autoload 'format-spec "format-spec")

View file

@ -8,10 +8,19 @@
(defvar doom-modules (make-hash-table :test 'equal) (defvar doom-modules (make-hash-table :test 'equal)
"A hash table of enabled modules. Set by `doom-initialize-modules'.") "A hash table of enabled modules. Set by `doom-initialize-modules'.")
(defvar doom-modules-dirs (define-obsolete-variable-alias 'doom-modules-dirs 'doom-module-load-path "3.0.0")
(list (expand-file-name "modules/" doom-user-dir) (defvar doom-module-load-path
doom-modules-dir) (list (file-name-concat doom-user-dir "modules")
"A list of module root directories. Order determines priority.") (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 ;;; Module file variables
(defvar doom-module-init-file "init.el" (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 maintainers, checks, features, submodules, debug information, etc. And are used
to locate modules in the user's file tree.") 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 (defconst doom-obsolete-modules
'((:feature (version-control (:emacs vc) (:ui vc-gutter)) '((:feature (version-control (:emacs vc) (:ui vc-gutter))
(spellcheck (:checkers spell)) (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 your `doom!' block, a warning is emitted before replacing it with :emacs vc and
:ui vc-gutter.") :ui vc-gutter.")
(make-obsolete-variable 'doom-inhibit-module-warnings nil "3.0.0")
(defvar doom-inhibit-module-warnings (not noninteractive) (defvar doom-inhibit-module-warnings (not noninteractive)
"If non-nil, don't emit deprecated or missing module warnings at startup.") "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' ;;; `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 (eval-and-compile
(setplist 'doom-module-context '(index 0 initdepth 1 configdepth 2 (put 'doom-module-context 'keys '(:index 0 :initdepth 1 :configdepth 2
group 3 name 4 flags 5 features 6))) :group 3 :name 4 :flags 5 :features 6)))
(defvar doom-module-context doom--empty-module-context (defvar doom-module-context doom-module--empty-context
"A vector describing the module associated it with the active context. "A vector describing the module associated it with the active context.
Contains the following: [INDEX INITDEPTH CONFIGDEPTH :GROUP MODULE FLAGS FEATURES] 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.") Do not directly set this variable, only let-bind it.")
;; DEPRECATED: Remove this when byte-compilation is introduced to Doom core. ;; 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) (defun doom-module-context-get (field &optional context)
"Return the FIELD of 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', FIELD should be one of `index', `initdepth', `configdepth', `group', `name',
`flags', or `features'. CONTEXT should be a `doom-module-context' vector. If `flags', or `features'. CONTEXT should be a `doom-module-context' vector. If
omitted, defaults to `doom-module-context'." 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) (defun doom-module-context (group &optional name)
"Create a `doom-module-context' from a module by GROUP and 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))) (let ((key (if name (cons group name) group)))
(or (get (or (car-safe key) key) (or (get (or (car-safe key) key)
(cdr-safe key)) (cdr-safe key))
doom--empty-module-context))) doom-module--empty-context)))
(defun doom-module-context-key (&optional context) (defun doom-module-context-key (&optional context)
"Return the module of the active `doom-module-context' as a module key." "Return the module of the active `doom-module-context' as a module key."
(declare (side-effect-free t)) (declare (side-effect-free t))
(let ((context (or context doom-module-context))) (let ((context (or context doom-module-context)))
(cons (aref context (doom-module--context-field group)) (cons (aref context (doom-module--context-field :group))
(aref context (doom-module--context-field name))))) (aref context (doom-module--context-field :name)))))
(defmacro doom-module-context-with (module-key &rest body) (defmacro doom-module-context-with (module-key &rest body)
"Evaluate BODY with `doom-module-context' informed by MODULE-KEY." "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 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 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 (includes :core and :user). Modules that are enabled are sorted first by their
:depth, followed by disabled modules in lexicographical order (unless a :depth :depth, followed by disabled modules in lexicographical order (unless a :depth
is specified in their .doommodule). 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?)) (append (seq-remove #'cdr (doom-module-list nil initorder?))
(doom-files-in (if (listp paths-or-all) (doom-files-in (if (listp paths-or-all)
paths-or-all paths-or-all
doom-modules-dirs) doom-module-load-path)
:map #'doom-module-from-path :map #'doom-module-from-path
:type 'dirs :type 'dirs
:mindepth 1 :mindepth 1
@ -294,7 +309,7 @@ If the category isn't enabled this returns nil. For finding disabled modules use
path))) path)))
(defun doom-module-locate-path (category &optional module file) (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 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 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 (if file
;; PERF: locate-file-internal is a little faster for finding files, ;; PERF: locate-file-internal is a little faster for finding files,
;; but its interface for finding directories is clumsy. ;; but its interface for finding directories is clumsy.
(locate-file-internal path doom-modules-dirs '("" ".elc" ".el")) (locate-file-internal path doom-module-load-path '("" ".elc" ".el"))
(cl-loop for default-directory in doom-modules-dirs (cl-loop for default-directory in doom-module-load-path
if (file-exists-p path) if (file-exists-p path)
return (expand-file-name 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 MODULE-LIST is a list of cons cells (GROUP . NAME). See `doom-module-list' for
an example." an example."
(cl-loop with file = (file-name-sans-extension file) (cl-loop for (group . name) in (or module-list (doom-module-list))
for (group . name) in module-list
if (doom-module-locate-path group name file) if (doom-module-locate-path group name file)
collect it)) 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) ((file-in-directory-p path doom-user-dir)
(cons :user nil)))))) (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. "Return a list of file paths to activated modules.
The list is in no particular order and its file paths are absolute. If 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 MODULE-DIRS is non-nil, include all modules (even disabled ones) available in
those directories." those directories."
(declare (pure t) (side-effect-free t)) (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))) collect (doom-module-locate-path cat mod)))
(defun doom-module-mplist-map (fn mplist) (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 ;; PERF: This macro bypasses the module API to spare startup their runtime
;; cost, as `modulep!' gets called *a lot* during startup. In the future, ;; 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. ;; 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) (and (cond (flag (memq flag (aref (or (get category module) doom-module--empty-context)
(doom-module--context-field flags)))) (doom-module--context-field :flags))))
(module (get category module)) (module (get category module))
((aref doom-module-context 0) ((aref doom-module-context 0)
(memq category (aref doom-module-context (memq category (aref doom-module-context
(doom-module--context-field flags)))) (doom-module--context-field :flags))))
((let ((file ((let ((file
;; This must be expanded at the call site, not in ;; This must be expanded at the call site, not in
;; `modulep!'s definition, to get the file we want. ;; `modulep!'s definition, to get the file we want.
(macroexpand '(file!)))) (macroexpand '(file!))))
(if-let (module (doom-module-from-path file)) (if-let (module (doom-module-from-path file))
(memq category (aref (or (get (car module) (cdr module)) (memq category (aref (or (get (car module) (cdr module))
doom--empty-module-context) doom-module--empty-context)
(doom-module--context-field flags))) (doom-module--context-field :flags)))
(error "(modulep! %s %s %s) couldn't figure out what module it was called from (in %s)" (error "(modulep! %s %s %s) couldn't figure out what module it was called from (in %s)"
category module flag file))))) category module flag file)))))
t)) t))

View file

@ -119,11 +119,11 @@ uses a straight or package.el command directly).")
(append (apply fn args) ; lockfiles still take priority (append (apply fn args) ; lockfiles still take priority
(doom-package-pinned-list))) (doom-package-pinned-list)))
;; HACK: This fixes an issue present in recent builds of Emacs 29. See ;; HACK: This fixes an issue introduced in emacs-mirror/emacs@0d383b592c2f and
;; emacs-mirror/emacs@0d383b592c2f. Straight.el uses `loaddefs-generate' if it ;; is present in >=29: Straight.el uses `loaddefs-generate' if it is
;; is available, which activates `emacs-lisp-mode' to read autoloads files, ;; available, which activates `emacs-lisp-mode' to read autoloads files, but
;; but does so without suppressing its hooks. Some packages (like overseer) ;; does so without suppressing its hooks. Some packages (like overseer) add
;; add hooks to `emacs-lisp-mode-hook' in their autoloads, and once triggered, ;; hooks to `emacs-lisp-mode-hook' in their autoloads, and once triggered,
;; they will try to load their dependencies (like dash or pkg-info), causing ;; they will try to load their dependencies (like dash or pkg-info), causing
;; file errors. ;; file errors.
;; REVIEW: Report this upstream. ;; REVIEW: Report this upstream.

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") ";; This file was autogenerated; do not edit it by hand!\n")
;; Doom needs to be synced/rebuilt if either Doom or Emacs has been ;; Doom needs to be synced/rebuilt if either Doom or Emacs has been
;; up/downgraded. This is because byte-code isn't backwards ;; 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. ;; paths into their caches that need to be refreshed.
(prin1 `(unless (equal doom-version ,doom-version) (prin1 `(unless (equal doom-version ,doom-version)
(error ,(concat (error ,(concat
@ -368,7 +368,8 @@ Defaults to the profile at `doom-profile-default'."
;; FIX: Make sure this only runs at startup to protect us Emacs' interpreter ;; FIX: Make sure this only runs at startup to protect us Emacs' interpreter
;; re-evaluating this file when lazy-loading dynamic docstrings from the ;; re-evaluating this file when lazy-loading dynamic docstrings from the
;; byte-compiled init file. ;; byte-compiled init file.
`((when (doom-context-p 'init) `((when (or (doom-context-p 'init)
(doom-context-p 'reload))
,@(cl-loop for var in doom-autoloads-cached-vars ,@(cl-loop for var in doom-autoloads-cached-vars
if (boundp var) if (boundp var)
collect `(set-default ',var ',(symbol-value var))) collect `(set-default ',var ',(symbol-value var)))
@ -439,7 +440,7 @@ Defaults to the profile at `doom-profile-default'."
(doom-autoloads--scan (doom-autoloads--scan
(append (doom-glob doom-core-dir "lib/*.el") (append (doom-glob doom-core-dir "lib/*.el")
(cl-loop for dir (cl-loop for dir
in (append (doom-module-load-path doom-modules-dirs) in (append (doom-module-load-path)
(list doom-user-dir)) (list doom-user-dir))
if (doom-glob dir "autoload.el") collect (car it) if (doom-glob dir "autoload.el") collect (car it)
if (doom-glob dir "autoload/*.el") append it) if (doom-glob dir "autoload/*.el") append it)
@ -449,8 +450,8 @@ Defaults to the profile at `doom-profile-default'."
(defun doom-profile--generate-package-autoloads () (defun doom-profile--generate-package-autoloads ()
(doom-autoloads--scan (doom-autoloads--scan
(mapcar #'straight--autoloads-file (mapcar #'straight--autoloads-file
(seq-difference (hash-table-keys straight--build-cache) (nreverse (seq-difference (hash-table-keys straight--build-cache)
doom-autoloads-excluded-packages)) doom-autoloads-excluded-packages)))
doom-autoloads-excluded-files doom-autoloads-excluded-files
'literal)) 'literal))

View file

@ -23,6 +23,10 @@ debian, and derivatives). On most it's 'fd'.")
;; ;;
;;; Packages ;;; Packages
(after! project
(setq project-list-file (file-name-concat doom-data-dir "projects")))
;; DEPRECATED: Will be replaced with project.el
(use-package! projectile (use-package! projectile
:commands (projectile-project-root :commands (projectile-project-root
projectile-project-name projectile-project-name
@ -147,7 +151,7 @@ c) are not valid projectile projects."
(projectile-serialize-cache)))) (projectile-serialize-cache))))
;; Some MSYS utilities auto expanded the `/' path separator, so we need to prevent it. ;; 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 "MSYS_NO_PATHCONV" "1") ; Fix path in Git Bash
(setenv "MSYS2_ARG_CONV_EXCL" "--path-separator")) ; Fix path in MSYS2 (setenv "MSYS2_ARG_CONV_EXCL" "--path-separator")) ; Fix path in MSYS2
@ -192,11 +196,11 @@ And if it's a function, evaluate it."
(concat (format "%s . -0 -H --color=never --type file --type symlink --follow --exclude .git %s" (concat (format "%s . -0 -H --color=never --type file --type symlink --follow --exclude .git %s"
bin (if (version< version "8.3.0") bin (if (version< version "8.3.0")
"" "--strip-cwd-prefix")) "" "--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 ;; Otherwise, resort to ripgrep, which is also faster than find
((executable-find "rg" t) ((executable-find "rg" t)
(concat "rg -0 --files --follow --color=never --hidden -g!.git" (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")))) ("find . -type f -print0"))))
(defadvice! doom--projectile-default-generic-command-a (fn &rest args) (defadvice! doom--projectile-default-generic-command-a (fn &rest args)

View file

@ -100,13 +100,15 @@
;;; Disable UI elements early ;;; Disable UI elements early
;; PERF,UI: Doom strives to be keyboard-centric, so I consider these UI elements ;; PERF,UI: Doom strives to be keyboard-centric, so I consider these UI elements
;; clutter. Initializing them also costs a morsel of startup time. Whats more, ;; clutter. Initializing them also costs a morsel of startup time. What's
;; the menu bar exposes functionality that Doom doesn't endorse. Perhaps one ;; more, the menu bar exposes functionality that Doom doesn't endorse. Perhaps
;; day Doom will support these, but today is not that day. ;; one day Doom will support these, but today is not that day. By disabling
;; ;; them early, we save Emacs some time.
;; HACK: I intentionally avoid calling `menu-bar-mode', `tool-bar-mode', and ;; HACK: I intentionally avoid calling `menu-bar-mode', `tool-bar-mode', and
;; `scroll-bar-mode' because they do extra work to manipulate frame variables ;; `scroll-bar-mode' because their manipulation of frame parameters can
;; that isn't necessary this early in the startup process. ;; trigger/queue a superfluous (and expensive, depending on the window system)
;; frame redraw at startup.
(push '(menu-bar-lines . 0) default-frame-alist) (push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist) (push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist) (push '(vertical-scroll-bars) default-frame-alist)
@ -119,8 +121,8 @@
;; non-application window -- which means it doesn't automatically capture ;; non-application window -- which means it doesn't automatically capture
;; focus when it is started, among other things, so enable the menu-bar for ;; 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 ;; GUI frames, but keep it disabled in terminal frames because there it
;; activates an ugly, in-frame menu bar. ;; unavoidably 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) (add-hook! '(window-setup-hook after-make-frame-functions)
(defun doom-restore-menu-bar-in-gui-frames-h (&optional frame) (defun doom-restore-menu-bar-in-gui-frames-h (&optional frame)
(when-let (frame (or frame (selected-frame))) (when-let (frame (or frame (selected-frame)))
@ -136,8 +138,8 @@
;; a step too opinionated. ;; a step too opinionated.
(setq default-input-method nil) (setq default-input-method nil)
;; ...And the clipboard on Windows could be in a wider encoding (UTF-16), so ;; ...And the clipboard on Windows could be in a wider encoding (UTF-16), so
;; leave Emacs to its own devices. ;; leave Emacs to its own devices there.
(eval-when! IS-WINDOWS (eval-when! (not doom--system-windows-p)
(setq selection-coding-system 'utf-8)) (setq selection-coding-system 'utf-8))
@ -180,7 +182,7 @@
(defvar doom-incremental-packages '(t) (defvar doom-incremental-packages '(t)
"A list of packages to load incrementally after startup. Any large packages "A list of packages to load incrementally after startup. Any large packages
here may cause noticeable pauses, so it's recommended you break them up into here may cause noticeable pauses, so it's recommended you break them up into
sub-packages. For example, `org' is comprised of many packages, and can be sub-packages. For example, `org' is comprised of many packages, and might be
broken up into: broken up into:
(doom-load-packages-incrementally (doom-load-packages-incrementally
@ -192,16 +194,16 @@ broken up into:
This is already done by the lang/org module, however. This is already done by the lang/org module, however.
If you want to disable incremental loading altogether, either remove If you want to disable incremental loading altogether, either remove
`doom-load-packages-incrementally-h' from `emacs-startup-hook' or set `doom-load-packages-incrementally-h' from `doom-after-init-hook' or set
`doom-incremental-first-idle-timer' to nil. Incremental loading does not occur `doom-incremental-first-idle-timer' to nil. Incremental loading does not occur
in daemon sessions (they are loaded immediately at startup).") in daemon sessions (they are loaded immediately at startup).")
(defvar doom-incremental-first-idle-timer (if (daemonp) 0 2.0) (defvar doom-incremental-first-idle-timer (if (daemonp) 0 2.0)
"How long (in idle seconds) until incremental loading starts. "How long (in idle seconds) until incremental loading starts.
Set this to nil to disable incremental loading. Set this to nil to disable incremental loading at startup.
Set this to 0 to load all incrementally deferred packages immediately at Set this to 0 to load all incrementally deferred packages immediately at
`emacs-startup-hook'.") `doom-after-init-hook'.")
(defvar doom-incremental-idle-timer 0.75 (defvar doom-incremental-idle-timer 0.75
"How long (in idle seconds) in between incrementally loading packages.") "How long (in idle seconds) in between incrementally loading packages.")
@ -209,9 +211,13 @@ Set this to 0 to load all incrementally deferred packages immediately at
(defun doom-load-packages-incrementally (packages &optional now) (defun doom-load-packages-incrementally (packages &optional now)
"Registers PACKAGES to be loaded incrementally. "Registers PACKAGES to be loaded incrementally.
If NOW is non-nil, load PACKAGES incrementally, in `doom-incremental-idle-timer' If NOW is non-nil, PACKAGES will be marked for incremental loading next time
intervals." Emacs is idle for `doom-incremental-first-idle-timer' seconds (falls back to
(let ((gc-cons-threshold most-positive-fixnum)) `doom-incremental-idle-timer'), then in `doom-incremental-idle-timer' intervals
afterwards."
(let* ((gc-cons-threshold most-positive-fixnum)
(first-idle-timer (or doom-incremental-first-idle-timer
doom-incremental-idle-timer)))
(if (not now) (if (not now)
(cl-callf append doom-incremental-packages packages) (cl-callf append doom-incremental-packages packages)
(while packages (while packages
@ -222,7 +228,7 @@ intervals."
(condition-case-unless-debug e (condition-case-unless-debug e
(and (and
(or (null (setq idle-time (current-idle-time))) (or (null (setq idle-time (current-idle-time)))
(< (float-time idle-time) doom-incremental-first-idle-timer) (< (float-time idle-time) first-idle-timer)
(not (not
(while-no-input (while-no-input
(doom-log "start:iloader: Loading %s (%d left)" req (length packages)) (doom-log "start:iloader: Loading %s (%d left)" req (length packages))
@ -242,7 +248,7 @@ intervals."
(doom-log "start:iloader: Finished!") (doom-log "start:iloader: Finished!")
(run-at-time (if idle-time (run-at-time (if idle-time
doom-incremental-idle-timer doom-incremental-idle-timer
doom-incremental-first-idle-timer) first-idle-timer)
nil #'doom-load-packages-incrementally nil #'doom-load-packages-incrementally
packages t) packages t)
(setq packages nil)))))))) (setq packages nil))))))))

View file

@ -5,13 +5,13 @@
;; ;;
;;; Variables ;;; Variables
(defvar doom-theme nil (defcustom doom-theme nil
"A symbol representing the Emacs theme to load at startup. "A symbol representing the Emacs theme to load at startup.
Set to `nil' to load no theme at all. This variable is changed by Set to `nil' to load no theme at all. This variable is changed by
`load-theme'.") `load-theme'.")
(defvar doom-font nil (defcustom doom-font nil
"The default font to use. "The default font to use.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. Must be a `font-spec', a font object, an XFT font string, or an XLFD string.
@ -22,60 +22,72 @@ Examples:
(setq doom-font \"Terminus (TTF):pixelsize=12:antialias=off\") (setq doom-font \"Terminus (TTF):pixelsize=12:antialias=off\")
(setq doom-font \"Fira Code-14\")") (setq doom-font \"Fira Code-14\")")
(defvar doom-variable-pitch-font nil (defcustom doom-variable-pitch-font nil
"The default font to use for variable-pitch text. "The default font to use for variable-pitch text.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples. `doom-font' for examples.
An omitted font size means to inherit `doom-font''s size.") An omitted font size means to inherit `doom-font''s size.")
(defvar doom-serif-font nil (defcustom doom-serif-font nil
"The default font to use for the `fixed-pitch-serif' face. "The default font to use for the `fixed-pitch-serif' face.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples. `doom-font' for examples.
An omitted font size means to inherit `doom-font''s size.") An omitted font size means to inherit `doom-font''s size.")
(defvar doom-unicode-font nil (defcustom doom-symbol-font nil
"Fallback font for Unicode glyphs. "Fallback font for symbols.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples. `doom-font' for examples. Emacs defaults to Symbola.
The defaults on macOS and Linux are Apple Color Emoji and Symbola, respectively.
WARNING: if you specify a size for this font it will hard-lock any usage of this WARNING: if you specify a size for this font it will hard-lock any usage of this
font to that size. It's rarely a good idea to do so!") font to that size. It's rarely a good idea to do so!")
(defvar doom-emoji-fallback-font-families (define-obsolete-variable-alias 'doom-unicode-font 'doom-symbol-font "3.0.0")
(defcustom doom-emoji-font nil
"Fallback font for emoji.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
WARNING: if you specify a size for this font it will hard-lock any usage of this
font to that size. It's rarely a good idea to do so!")
(defconst doom-emoji-fallback-font-families
'("Apple Color Emoji" '("Apple Color Emoji"
"Segoe UI Emoji" "Segoe UI Emoji"
"Noto Color Emoji" "Noto Color Emoji"
"Noto Emoji") "Noto Emoji")
"A list of fallback font families to use for emojis.") "A list of fallback font families to use for emojis.
These are platform-specific fallbacks for internal use. If you
want to change your emoji font, use `doom-emoji-font'.")
(defvar doom-symbol-fallback-font-families (defconst doom-symbol-fallback-font-families
'("Segoe UI Symbol" '("Segoe UI Symbol"
"Apple Symbols") "Apple Symbols")
"A list of fallback font families for general symbol glyphs.") "A list of fallback font families for general symbol glyphs.
These are platform-specific fallbacks for internal use. If you
want to change your symbol font, use `doom-symbol-font'.")
;; ;;
;;; Custom hooks ;;; Custom hooks
(defvar doom-init-ui-hook nil (defcustom doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.") "List of hooks to run when the UI has been initialized.")
(defvar doom-load-theme-hook nil (defcustom doom-load-theme-hook nil
"Hook run after the theme is loaded with `load-theme' or reloaded with "Hook run after the theme is loaded with `load-theme' or reloaded with
`doom/reload-theme'.") `doom/reload-theme'.")
(defvar doom-switch-buffer-hook nil (defcustom doom-switch-buffer-hook nil
"A list of hooks run after changing the current buffer.") "A list of hooks run after changing the current buffer.")
(defvar doom-switch-window-hook nil (defcustom doom-switch-window-hook nil
"A list of hooks run after changing the focused windows.") "A list of hooks run after changing the focused windows.")
(defvar doom-switch-frame-hook nil (defcustom doom-switch-frame-hook nil
"A list of hooks run after changing the focused frame.") "A list of hooks run after changing the focused frame.")
(defun doom-run-switch-buffer-hooks-h (&optional _) (defun doom-run-switch-buffer-hooks-h (&optional _)
@ -156,8 +168,10 @@ or if the current buffer is read-only or not file-visiting."
;; cursor more than N lines past window edges (where N is the settings of ;; cursor more than N lines past window edges (where N is the settings of
;; `scroll-conservatively'). This is especially slow in larger files ;; `scroll-conservatively'). This is especially slow in larger files
;; during large-scale scrolling commands. If kept over 100, the window is ;; during large-scale scrolling commands. If kept over 100, the window is
;; never automatically recentered. ;; never automatically recentered. The default (0) triggers this too
scroll-conservatively 101 ;; aggressively, so I've set it to 10 to recenter if scrolling too far
;; off-screen.
scroll-conservatively 10
scroll-margin 0 scroll-margin 0
scroll-preserve-screen-position t scroll-preserve-screen-position t
;; Reduce cursor lag by a tiny bit by not auto-adjusting `window-vscroll' ;; Reduce cursor lag by a tiny bit by not auto-adjusting `window-vscroll'
@ -196,10 +210,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
`kill-current-buffer'." `kill-current-buffer'."
:before-until #'kill-current-buffer :before-until #'kill-current-buffer
(let ((buf (current-buffer))) (let ((buf (current-buffer)))
(cond ((window-dedicated-p) (cond ((eq buf (doom-fallback-buffer))
(delete-window)
t)
((eq buf (doom-fallback-buffer))
(message "Can't kill the fallback buffer.") (message "Can't kill the fallback buffer.")
t) t)
((doom-real-buffer-p buf) ((doom-real-buffer-p buf)
@ -314,9 +325,10 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
(setq compilation-always-kill t ; kill compilation process before starting another (setq compilation-always-kill t ; kill compilation process before starting another
compilation-ask-about-save nil ; save all buffers on `compile' compilation-ask-about-save nil ; save all buffers on `compile'
compilation-scroll-output 'first-error) compilation-scroll-output 'first-error)
;; Handle ansi codes in compilation buffer (add-hook 'compilation-filter-hook
;; DEPRECATED Use `ansi-color-compilation-filter' when dropping 27.x support (if (< emacs-major-version 28)
(add-hook 'compilation-filter-hook #'doom-apply-ansi-color-to-compilation-buffer-h) #'doom-apply-ansi-color-to-compilation-buffer-h
#'ansi-color-compilation-filter))
;; Automatically truncate compilation buffers so they don't accumulate too ;; Automatically truncate compilation buffers so they don't accumulate too
;; much data and bog down the rest of Emacs. ;; much data and bog down the rest of Emacs.
(autoload 'comint-truncate-buffer "comint" nil t) (autoload 'comint-truncate-buffer "comint" nil t)
@ -417,41 +429,17 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
;; ;;
;;; Third party packages ;;; Third party packages
(use-package! all-the-icons (use-package! nerd-icons
:commands (all-the-icons-octicon :commands (nerd-icons-octicon
all-the-icons-faicon nerd-icons-faicon
all-the-icons-fileicon nerd-icons-flicon
all-the-icons-wicon nerd-icons-wicon
all-the-icons-material nerd-icons-mdicon
all-the-icons-alltheicon) nerd-icons-codicon
:preface nerd-icons-devicon
(add-hook! 'after-setting-font-hook nerd-icons-ipsicon
(defun doom-init-all-the-icons-fonts-h () nerd-icons-pomicon
(when (fboundp 'set-fontset-font) nerd-icons-powerline))
(dolist (font (list "Weather Icons"
"github-octicons"
"FontAwesome"
"all-the-icons"
"file-icons"
"Material Icons"))
(set-fontset-font t 'unicode font nil 'append)))))
:config
(cond ((daemonp)
(defadvice! doom--disable-all-the-icons-in-tty-a (fn &rest args)
"Return a blank string in tty Emacs, which doesn't support multiple fonts."
:around '(all-the-icons-octicon all-the-icons-material
all-the-icons-faicon all-the-icons-fileicon
all-the-icons-wicon all-the-icons-alltheicon)
(if (or (not after-init-time) (display-multi-font-p))
(apply fn args)
"")))
((not (display-graphic-p))
(defadvice! doom--disable-all-the-icons-in-tty-a (&rest _)
"Return a blank string for tty users."
:override '(all-the-icons-octicon all-the-icons-material
all-the-icons-faicon all-the-icons-fileicon
all-the-icons-wicon all-the-icons-alltheicon)
""))))
;; Hide the mode line in completion popups and MAN pages because they serve ;; Hide the mode line in completion popups and MAN pages because they serve
;; little purpose there, and is better hidden. ;; little purpose there, and is better hidden.
@ -510,49 +498,63 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
(cons 'custom-theme-directory (cons 'custom-theme-directory
(delq 'custom-theme-directory custom-theme-load-path))) (delq 'custom-theme-directory custom-theme-load-path)))
(defun doom--make-font-specs (face font) (defun doom-init-fonts-h (&optional _reload)
(let* ((base-specs (cadr (assq 'user (get face 'theme-face)))) "Loads `doom-font', `doom-serif-font', and `doom-variable-pitch-font'."
(base-specs (or base-specs '((t nil)))) (let ((this-frame (selected-frame)))
(attrs '(:family :foundry :slant :weight :height :width)) (dolist (map `((default . ,doom-font)
(new-specs nil)) (fixed-pitch . ,doom-font)
(dolist (spec base-specs) (fixed-pitch-serif . ,doom-serif-font)
;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST) (variable-pitch . ,doom-variable-pitch-font)))
(let ((display (car spec)) (condition-case e
(plist (copy-tree (nth 1 spec)))) (when-let* ((face (car map))
;; Alter only DISPLAY conditions matching this frame. (font (cdr map)))
(when (or (memq display '(t default)) (dolist (frame (frame-list))
(face-spec-set-match-display display this-frame)) (when (display-multi-font-p frame)
(dolist (attr attrs) (set-face-attribute face frame
(setq plist (plist-put plist attr (face-attribute face attr))))) :width 'normal :weight 'normal
(push (list display plist) new-specs))) :slant 'normal :font font)))
(nreverse new-specs))) (custom-push-theme
'theme-face face 'user 'set
(defun doom-init-fonts-h (&optional reload) (let* ((base-specs (cadr (assq 'user (get face 'theme-face))))
"Loads `doom-font'." (base-specs (or base-specs '((t nil))))
(dolist (map `((default . ,doom-font) (attrs '(:family :foundry :slant :weight :height :width))
(fixed-pitch . ,doom-font) (new-specs nil))
(fixed-pitch-serif . ,doom-serif-font) (dolist (spec base-specs)
(variable-pitch . ,doom-variable-pitch-font))) ;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST)
(when-let* ((face (car map)) (let ((display (car spec))
(font (cdr map))) (plist (copy-tree (nth 1 spec))))
(dolist (frame (frame-list)) ;; Alter only DISPLAY conditions matching this frame.
(when (display-multi-font-p frame) (when (or (memq display '(t default))
(set-face-attribute face frame (face-spec-set-match-display display this-frame))
:width 'normal :weight 'normal (dolist (attr attrs)
:slant 'normal :font font))) (setq plist (plist-put plist attr (face-attribute face attr)))))
(let ((new-specs (doom--make-font-specs face font))) (push (list display plist) new-specs)))
;; Don't save to `customized-face' so it's omitted from `custom-file' (nreverse new-specs)))
;;(put face 'customized-face new-specs) (put face 'face-modified nil))
(custom-push-theme 'theme-face face 'user 'set new-specs) ('error
(put face 'face-modified nil)))) (ignore-errors (doom--reset-inhibited-vars-h))
(if (string-prefix-p "Font not available" (error-message-string e))
(signal 'doom-font-error (list (font-get (cdr map) :family)))
(signal (car e) (cdr e)))))))
(when (fboundp 'set-fontset-font) (when (fboundp 'set-fontset-font)
(let ((fn (doom-rpartial #'member (font-family-list)))) (let* ((fn (doom-rpartial #'member (font-family-list)))
(when-let (font (cl-find-if fn doom-symbol-fallback-font-families)) (symbol-font (or doom-symbol-font
(set-fontset-font t 'symbol font)) (cl-find-if fn doom-symbol-fallback-font-families)))
(when-let (font (cl-find-if fn doom-emoji-fallback-font-families)) (emoji-font (or doom-emoji-font
(set-fontset-font t 'unicode font)) (cl-find-if fn doom-emoji-fallback-font-families))))
(when doom-unicode-font (when symbol-font
(set-fontset-font t 'unicode doom-unicode-font)))) (dolist (script '(symbol mathematical))
(set-fontset-font t script symbol-font)))
(when emoji-font
;; DEPRECATED: make unconditional when we drop 27 support
(when (version<= "28.1" emacs-version)
(set-fontset-font t 'emoji emoji-font))
;; some characters in the Emacs symbol script are often covered by emoji
;; fonts
(set-fontset-font t 'symbol emoji-font nil 'append)))
;; Nerd Fonts use these Private Use Areas
(dolist (range '((#xe000 . #xf8ff) (#xf0000 . #xfffff)))
(set-fontset-font t range "Symbols Nerd Font Mono")))
;; Users should inject their own font logic in `after-setting-font-hook' ;; Users should inject their own font logic in `after-setting-font-hook'
(run-hooks 'after-setting-font-hook)) (run-hooks 'after-setting-font-hook))

View file

@ -59,9 +59,13 @@
;; - On first switched-to buffer: `doom-first-buffer-hook' ;; - On first switched-to buffer: `doom-first-buffer-hook'
;; - On first opened file: `doom-first-file-hook' ;; - On first opened file: `doom-first-file-hook'
;; ;;
;; This is Doom's heart, where I define all its major constants and variables, ;; This file is Doom's heart, where I define all its major constants and
;; set only its sanest global defaults, employ its hackiest (and least ;; variables, set only its sanest global defaults, employ its hackiest (and
;; offensive) optimizations, and load the minimum for all Doom sessions. ;; least offensive) optimizations, and load the minimum needed for all Doom
;; sessions, interactive or otherwise.
;;
;; See doom-start.el for initialization intended solely for interactive
;; sessions, and doom-cli.el for non-interactive sessions.
;; ;;
;;; Code: ;;; Code:
@ -99,7 +103,7 @@
;; Doom needs to be synced/rebuilt if either Doom or Emacs has been ;; 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 ;; 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. ;; to be refreshed.
(let ((old-version (eval-when-compile emacs-version))) (let ((old-version (eval-when-compile emacs-version)))
(unless (equal emacs-version old-version) (unless (equal emacs-version old-version)
@ -107,7 +111,31 @@
"recompile it.") "recompile it.")
emacs-version old-version))) 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. Module-specific
;; features are kept elsewhere, however.
(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 ;; Emacs needs a more consistent way to detect build features, and the docs
;; claim `system-configuration-features' is not da way. Some features (that ;; claim `system-configuration-features' is not da way. Some features (that
;; don't represent packages) can be found in `features' (which `featurep' ;; don't represent packages) can be found in `features' (which `featurep'
@ -116,35 +144,40 @@
(push 'dynamic-modules features)) (push 'dynamic-modules features))
(if (fboundp #'json-parse-string) (if (fboundp #'json-parse-string)
(push 'jansson features)) (push 'jansson features))
(let ((inhibit-changing-match-data t)) (if (string-match-p "HARFBUZZ" system-configuration-features) ; no alternative
(if (string-match "HARFBUZZ" system-configuration-features) ; no alternative (push 'harfbuzz features))
(push 'harfbuzz features)))
;; `native-compile' exists whether or not it is functional (e.g. libgcc is ;; The `native-compile' feature exists whether or not it is functional (e.g.
;; available or not). This seems silly, so pretend it doesn't exist if it ;; libgcc is available or not). This seems silly, so pretend it doesn't exist if
;; isn't available. ;; it isn't functional.
(if (featurep 'native-compile) (if (featurep 'native-compile)
(if (not (native-comp-available-p)) (if (not (native-comp-available-p))
(delq 'native-compile features))) (delq 'native-compile features)))
;;; Global constants
;; DEPRECATED remove in v3 ;; DEPRECATED remove in v3
(defconst IS-MAC (eq system-type 'darwin)) (with-no-warnings
(defconst IS-LINUX (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix))) (defconst IS-MAC doom--system-macos-p)
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos))) (defconst IS-LINUX doom--system-linux-p)
(defconst IS-BSD (memq system-type '(darwin berkeley-unix gnu/kfreebsd))) (defconst IS-WINDOWS doom--system-windows-p)
(defconst EMACS28+ (> emacs-major-version 27)) (defconst IS-BSD (memq 'bsd doom-features))
(defconst EMACS29+ (> emacs-major-version 28)) (defconst EMACS28+ (> emacs-major-version 27))
(defconst MODULES (featurep 'dynamic-modules)) (defconst EMACS29+ (> emacs-major-version 28))
(defconst NATIVECOMP (featurep 'native-compile)) (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 ;;; Fix $HOME on Windows
;; $HOME isn't normally defined on Windows, but many unix tools expect it. ;; $HOME isn't normally defined on Windows, but many unix tools expect it.
(when IS-WINDOWS (when doom--system-windows-p
(when-let (realhome (when-let (realhome
(and (null (getenv-internal "HOME")) (and (null (getenv-internal "HOME"))
(getenv "USERPROFILE"))) (getenv "USERPROFILE")))
@ -168,7 +201,7 @@
"Current version of Doom Emacs core.") "Current version of Doom Emacs core.")
;; DEPRECATED: Remove these when the modules are moved out of core. ;; DEPRECATED: Remove these when the modules are moved out of core.
(defconst doom-modules-version "23.08.0-pre" (defconst doom-modules-version "24.03.0-pre"
"Current version of Doom Emacs.") "Current version of Doom Emacs.")
(defvar doom-init-time nil (defvar doom-init-time nil
@ -228,7 +261,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") (define-obsolete-variable-alias 'doom-etc-dir 'doom-data-dir "3.0.0")
(defvar doom-data-dir (defvar doom-data-dir
(if doom-profile (if doom-profile
(if IS-WINDOWS (if doom--system-windows-p
(expand-file-name "doomemacs/data/" (getenv-internal "APPDATA")) (expand-file-name "doomemacs/data/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_DATA_HOME") "~/.local/share"))) (expand-file-name "doom/" (or (getenv-internal "XDG_DATA_HOME") "~/.local/share")))
;; DEPRECATED: .local will be removed entirely in 3.0 ;; DEPRECATED: .local will be removed entirely in 3.0
@ -237,7 +270,7 @@ These files should not be shared across systems. By default, it is used by
Data files contain shared and long-lived data that Doom, Emacs, and their 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 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') cause breakage, and require user intervention (e.g. a `doom sync` or `doom env`)
to restore. to restore.
Use this for: server binaries, package source, pulled module libraries, Use this for: server binaries, package source, pulled module libraries,
@ -247,17 +280,17 @@ For profile-local data files, use `doom-profile-data-dir' instead.")
(defvar doom-cache-dir (defvar doom-cache-dir
(if doom-profile (if doom-profile
(if IS-WINDOWS (if doom--system-windows-p
(expand-file-name "doomemacs/cache/" (getenv-internal "APPDATA")) (expand-file-name "doomemacs/cache/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_CACHE_HOME") "~/.cache"))) (expand-file-name "doom/" (or (getenv-internal "XDG_CACHE_HOME") "~/.cache")))
;; DEPRECATED: .local will be removed entirely in 3.0 ;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "cache/")) (file-name-concat doom-local-dir "cache/"))
"Where Doom stores its global cache files. "Where Doom stores its global cache files.
Cache files represent non-essential data that shouldn't be problematic when Cache files represent unessential data that shouldn't be problematic when
deleted (besides, perhaps, a one-time performance hit), lack portability (and so 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, shouldn't be copied to other systems/configs), and are regenerated when needed,
without user input (e.g. a 'doom sync'). without user input (e.g. a `doom sync`).
Some examples: images/data caches, elisp bytecode, natively compiled elisp, Some examples: images/data caches, elisp bytecode, natively compiled elisp,
session files, ELPA archives, authinfo files, org-persist, etc. session files, ELPA archives, authinfo files, org-persist, etc.
@ -266,18 +299,18 @@ For profile-local cache files, use `doom-profile-cache-dir' instead.")
(defvar doom-state-dir (defvar doom-state-dir
(if doom-profile (if doom-profile
(if IS-WINDOWS (if doom--system-windows-p
(expand-file-name "doomemacs/state/" (getenv-internal "APPDATA")) (expand-file-name "doomemacs/state/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_STATE_HOME") "~/.local/state"))) (expand-file-name "doom/" (or (getenv-internal "XDG_STATE_HOME") "~/.local/state")))
;; DEPRECATED: .local will be removed entirely in 3.0 ;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "state/")) (file-name-concat doom-local-dir "state/"))
"Where Doom stores its global state files. "Where Doom stores its global state files.
State files contain non-essential, unportable, but persistent data which, if State files contain unessential, unportable, but persistent data which, if lost
lost won't cause breakage, but may be inconvenient as they cannot be won't cause breakage, but may be inconvenient as they cannot be automatically
automatically regenerated or restored. For example, a recently-opened file list regenerated or restored. For example, a recently-opened file list is not
is not essential, but losing it means losing this record, and restoring it essential, but losing it means losing this record, and restoring it requires
requires revisiting all those files. revisiting all those files.
Use this for: history, logs, user-saved data, autosaves/backup files, known Use this for: history, logs, user-saved data, autosaves/backup files, known
projects, recent files, bookmarks. projects, recent files, bookmarks.
@ -331,19 +364,20 @@ users).")
;; `file-remote-p'). You get a noteable boost to startup time by unsetting ;; `file-remote-p'). You get a noteable boost to startup time by unsetting
;; or simplifying its value. ;; or simplifying its value.
(let ((old-value (default-toplevel-value 'file-name-handler-alist))) (let ((old-value (default-toplevel-value 'file-name-handler-alist)))
(setq file-name-handler-alist (set-default-toplevel-value
;; HACK: If the bundled elisp for this Emacs install isn't 'file-name-handler-alist
;; byte-compiled (but is compressed), then leave the gzip file ;; HACK: If the bundled elisp for this Emacs install isn't byte-compiled
;; handler there so Emacs won't forget how to read read them. ;; (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 ;; calc-loaddefs.el is our heuristic for this because it is built-in to
;; it uncompiled. This ensures that the only other, possible ;; all supported versions of Emacs, and calc.el explicitly loads it
;; fallback would be calc-loaddefs.el.gz. ;; uncompiled. This ensures that the only other, possible fallback would
(if (eval-when-compile ;; be calc-loaddefs.el.gz.
(locate-file-internal "calc-loaddefs.el" load-path)) (if (eval-when-compile
nil (locate-file-internal "calc-loaddefs.el" load-path))
(list (rassq 'jka-compr-handler old-value)))) nil
(list (rassq 'jka-compr-handler old-value))))
;; Make sure the new value survives any current let-binding. ;; Make sure the new value survives any current let-binding.
(set-default-toplevel-value 'file-name-handler-alist file-name-handler-alist) (set-default-toplevel-value 'file-name-handler-alist file-name-handler-alist)
;; Remember it so it can be reset where needed. ;; Remember it so it can be reset where needed.
@ -352,10 +386,11 @@ users).")
;; needed for handling encrypted or compressed files, among other things. ;; needed for handling encrypted or compressed files, among other things.
(add-hook! 'emacs-startup-hook :depth 101 (add-hook! 'emacs-startup-hook :depth 101
(defun doom--reset-file-handler-alist-h () (defun doom--reset-file-handler-alist-h ()
(setq file-name-handler-alist (set-default-toplevel-value
;; Merge instead of overwrite because there may have been changes to 'file-name-handler-alist
;; `file-name-handler-alist' since startup we want to preserve. ;; Merge instead of overwrite because there may have been changes to
(delete-dups (append file-name-handler-alist old-value)))))) ;; `file-name-handler-alist' since startup we want to preserve.
(delete-dups (append file-name-handler-alist old-value))))))
(unless noninteractive (unless noninteractive
;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or ;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or
@ -380,8 +415,9 @@ users).")
;; PERF: Shave seconds off startup time by starting the scratch buffer in ;; PERF: Shave seconds off startup time by starting the scratch buffer in
;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which ;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which
;; pull in a ton of packages. `doom/open-scratch-buffer' provides a better ;; pull in a ton of packages. This buffer is created whether or not we're
;; scratch buffer anyway. ;; in an interactive session. Plus, `doom/open-scratch-buffer' provides a
;; better scratch buffer, so keep the initial one blank.
(setq initial-major-mode 'fundamental-mode (setq initial-major-mode 'fundamental-mode
initial-scratch-message nil) initial-scratch-message nil)
@ -397,82 +433,102 @@ users).")
(doom-partial #'tty-run-terminal-initialization (doom-partial #'tty-run-terminal-initialization
(selected-frame) nil t)))) (selected-frame) nil t))))
(unless init-file-debug ;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..."
;; 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
;; messages in the echo area. Writing to the echo-area triggers a ;; redisplay, which can be expensive during startup. This may also cause
;; redisplay, which can be expensive during startup. This may also cause ;; an flash of white when creating the first frame. Needs to be undo
;; an flash of white when creating the first frame. ;; later, though.
(define-advice load-file (:override (file) silence) (define-advice load-file (:override (file) silence)
(load file nil 'nomessage)) (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 ;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on
;; `require' and `load'. Doom won't load any dmodules this early, so omit ;; each `require' and `load'. Doom won't load any modules this early, so
;; .so for a small startup boost. This is later restored in doom-start. ;; omit .so for a tiny startup boost. Is later restored in doom-start.
(put 'load-suffixes 'initial-value (default-toplevel-value 'load-suffixes)) (put 'load-suffixes 'initial-value (default-toplevel-value 'load-suffixes))
(put 'load-file-rep-suffixes 'initial-value (default-toplevel-value 'load-file-rep-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-suffixes '(".elc" ".el"))
(set-default-toplevel-value 'load-file-rep-suffixes '("")) (set-default-toplevel-value 'load-file-rep-suffixes '(""))
;; COMPAT: Undo any problematic startup optimizations; from this point, I make ;; COMPAT: Undo any problematic startup optimizations; from this point, I
;; no assumptions about what might be loaded in userland. ;; make no assumptions about what might be loaded in userland.
(add-hook! 'doom-before-init-hook (add-hook! 'doom-before-init-hook
(defun doom--reset-load-suffixes-h () (defun doom--reset-load-suffixes-h ()
(setq load-suffixes (get 'load-suffixes 'initial-value) (setq load-suffixes (get 'load-suffixes 'initial-value)
load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value)))) load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value))))
;; PERF: Doom uses `defcustom' to indicate variables that users are expected ;; PERF: Doom uses `defcustom' to indicate variables that users are
;; to reconfigure. Trouble is it fires off initializers meant to ;; expected to reconfigure. Trouble is it fires off initializers meant
;; accommodate any user attempts to configure them before they were ;; to accommodate any user attempts to configure them before they were
;; defined. This is unnecessary before $DOOMDIR/init.el is loaded, so I ;; defined. This is unnecessary work before $DOOMDIR/init.el is loaded,
;; disable them until it is. ;; so I disable them until it is.
(setq custom-dont-initialize t) (setq custom-dont-initialize t)
(add-hook! 'doom-before-init-hook (add-hook! 'doom-before-init-hook
(defun doom--reset-custom-dont-initialize-h () (defun doom--reset-custom-dont-initialize-h ()
(setq custom-dont-initialize nil))) (setq custom-dont-initialize nil)))
;; PERF: The mode-line procs a couple dozen times during startup. This is ;; PERF: Doom disables the UI elements by default, so that there's less
;; normally quite fast, but disabling the default mode-line and reducing the ;; for the frame to initialize. However, the toolbar is still populated
;; update delay timer seems to stave off ~30-50ms. ;; regardless, so I lazy load it until tool-bar-mode is actually used.
(put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format)) (advice-add #'tool-bar-setup :override #'ignore)
(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.
(defun doom--reset-inhibited-vars-h ()
(setq-default inhibit-redisplay nil
;; Inhibiting `message' only prevents redraws and
inhibit-message nil)
(redraw-frame))
(add-hook 'after-init-hook #'doom--reset-inhibited-vars-h)
(define-advice startup--load-user-init-file (:after (&rest _) undo-inhibit-vars)
(when init-file-had-error
(doom--reset-inhibited-vars-h))
(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 ;; PERF: The mode-line procs a couple dozen times during startup. This is
;; the frame to initialize. However, the toolbar is still populated ;; normally quite fast, but disabling the default mode-line and reducing
;; regardless, so I lazy load it until tool-bar-mode is actually used. ;; the update delay timer seems to stave off ~30-50ms.
(advice-add #'tool-bar-setup :override #'ignore) (put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format))
(define-advice startup--load-user-init-file (:before (&rest _) defer-tool-bar-setup) (setq-default mode-line-format nil)
(advice-remove #'tool-bar-setup #'ignore) (dolist (buf (buffer-list))
(add-transient-hook! 'tool-bar-mode (tool-bar-setup))) (with-current-buffer buf (setq mode-line-format nil)))
;; PERF,UX: Premature redisplays can substantially affect startup times
;; and/or produce ugly flashes of unstyled Emacs.
(setq-default inhibit-redisplay t
inhibit-message t)
;; COMPAT: Then reset 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.
(defun doom--reset-inhibited-vars-h ()
(setq-default inhibit-redisplay nil
;; Inhibiting `message' only prevents redraws and
inhibit-message nil)
(redraw-frame))
(add-hook 'after-init-hook #'doom--reset-inhibited-vars-h)
;; PERF: Unset a non-trivial list of command line options that aren't ;; PERF,UX: An annoying aspect of site-lisp files is that they're often
;; relevant to our current OS, but `command-line-1' still processes. ;; noisy (they emit load messages or other output to stdout). These
(unless IS-MAC ;; queue unnecessary redraws at startup, cost startup time, and pollute
(setq command-line-ns-option-alist nil)) ;; the logs. I get around it by suppressing it until we can load it
(unless (memq initial-window-system '(x pgtk)) ;; manually, later (in the `startup--load-user-init-file' advice below).
(setq command-line-x-option-alist nil))))) (put 'site-run-file 'initial-value site-run-file)
(setq site-run-file nil)
(define-advice startup--load-user-init-file (:around (fn &rest args) undo-inhibit-vars)
(let (--init--)
(unwind-protect
(progn
;; COMPAT: Onces startup is sufficiently complete, undo some
;; optimizations to reduce the scope of potential edge cases.
(advice-remove #'load-file #'load-file@silence)
(advice-remove #'tool-bar-setup #'ignore)
(add-transient-hook! 'tool-bar-mode (tool-bar-setup))
(when (setq site-run-file (get 'site-run-file 'initial-value))
(let ((inhibit-startup-screen inhibit-startup-screen))
(letf! (defun load (file &optional noerror _nomessage &rest args)
(apply load file noerror t args))
(load site-run-file t t))))
;; Then startup as normal.
(apply fn args)
(setq --init-- t))
(when (or (not --init--) init-file-had-error)
;; If we don't undo our inhibit-{message,redisplay} and there's an
;; error, we'll see nothing but a blank Emacs frame.
(doom--reset-inhibited-vars-h))
(unless (default-toplevel-value 'mode-line-format)
(setq-default mode-line-format (get 'mode-line-format 'initial-value))))))
;; PERF: Unset a non-trivial list of command line options that aren't
;; 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))))
;; ;;
@ -497,7 +553,7 @@ All valid contexts:
(put 'doom-context 'valid-values '(cli compile eval init modules packages reload doctor sandbox)) (put 'doom-context 'valid-values '(cli compile eval init modules packages reload doctor sandbox))
(put 'doom-context 'risky-local-variable t) (put 'doom-context 'risky-local-variable t)
(defun doom-context--check (context) (defun doom-context--assert (context)
(let ((valid (get 'doom-context 'valid-values))) (let ((valid (get 'doom-context 'valid-values)))
(unless (memq context valid) (unless (memq context valid)
(signal 'doom-context-error (signal 'doom-context-error
@ -512,7 +568,7 @@ All valid contexts:
Return non-nil if successful. Throws an error if CONTEXT is invalid." Return non-nil if successful. Throws an error if CONTEXT is invalid."
(unless (memq context doom-context) (unless (memq context doom-context)
(doom-context--check context) (doom-context--assert context)
(doom-log ":context: +%s %s" context doom-context) (doom-log ":context: +%s %s" context doom-context)
(push context doom-context))) (push context doom-context)))
@ -529,7 +585,7 @@ wasn't active when this was called."
(setq doom-context (delq context doom-context)))) (setq doom-context (delq context doom-context))))
(defmacro doom-context-with (contexts &rest body) (defmacro doom-context-with (contexts &rest body)
"Evaluate BODY with CONTEXT added to `doom-context'." "Evaluate BODY with CONTEXTS added to `doom-context'."
(declare (indent 1)) (declare (indent 1))
`(let ((doom-context doom-context)) `(let ((doom-context doom-context))
(dolist (context (ensure-list ,contexts)) (dolist (context (ensure-list ,contexts))
@ -607,7 +663,15 @@ Otherwise, `en/disable-command' (in novice.el.gz) is hardcoded to write them to
(and (null comp-num-cpus) (and (null comp-num-cpus)
(zerop native-comp-async-jobs-number) (zerop native-comp-async-jobs-number)
(setq comp-num-cpus (setq comp-num-cpus
(max 1 (/ (num-processors) (if noninteractive 1 4))))))) (max 1 (/ (num-processors) (if noninteractive 1 4))))))
(define-advice comp-run-async-workers (:around (fn &rest args) dont-litter-tmpdir)
"Normally, native-comp writes a ton to /tmp. This advice forces it to write
to `doom-cache-dir'/comp/ instead, so that Doom can safely clean it up as part
of 'doom sync' or 'doom gc'."
(let ((temporary-file-directory (expand-file-name "comp/" doom-profile-cache-dir)))
(make-directory temporary-file-directory t)
(apply fn args))))
;;; Suppress package.el ;;; Suppress package.el
;; Since Emacs 27, package initialization occurs before `user-init-file' is ;; Since Emacs 27, package initialization occurs before `user-init-file' is
@ -639,7 +703,7 @@ Otherwise, `en/disable-command' (in novice.el.gz) is hardcoded to write them to
gnutls-algorithm-priority gnutls-algorithm-priority
(when (boundp 'libgnutls-version) (when (boundp 'libgnutls-version)
(concat "SECURE128:+SECURE192:-VERS-ALL" (concat "SECURE128:+SECURE192:-VERS-ALL"
(if (and (not IS-WINDOWS) (if (and (not doom--system-windows-p)
(>= libgnutls-version 30605)) (>= libgnutls-version 30605))
":+VERS-TLS1.3") ":+VERS-TLS1.3")
":+VERS-TLS1.2")) ":+VERS-TLS1.2"))
@ -689,10 +753,22 @@ appropriately against `noninteractive' or the `cli' context."
;; ;;
;;; Last minute initialization ;;; Last minute initialization
(when (daemonp)
(message "Starting Doom Emacs in daemon mode!")
(unless doom-inhibit-log
(add-hook! 'doom-after-init-hook :depth 106
(unless doom-inhibit-log
(setq doom-inhibit-log (not (or noninteractive init-file-debug))))
(message "Disabling verbose mode. Have fun!"))
(add-hook! 'kill-emacs-hook :depth 110
(message "Killing Emacs. Sayonara!"))))
(add-hook! 'doom-before-init-hook :depth -105 (add-hook! 'doom-before-init-hook :depth -105
(defun doom--begin-init-h () (defun doom--begin-init-h ()
"Begin the startup process." "Begin the startup process."
(when (doom-context-push 'init) (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 ;; Remember these variables' initial values, so we can safely reset them at
;; a later time, or consult them without fear of contamination. ;; a later time, or consult them without fear of contamination.
(dolist (var '(exec-path load-path process-environment)) (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) (let ((load-file-name file)
(load-path (load-path
(append (list doom-user-dir) (append (list doom-user-dir)
doom-modules-dirs doom-module-load-path
load-path))) load-path)))
(condition-case _ (condition-case _
(while t (while t

View file

@ -59,9 +59,6 @@ symbol and CDR is the value to set it to when `doom-debug-mode' is activated.")
(let ((enabled doom-debug-mode)) (let ((enabled doom-debug-mode))
(doom-log "debug: enabled!") (doom-log "debug: enabled!")
(mapc #'doom-debug--set-var doom-debug-variables) (mapc #'doom-debug--set-var doom-debug-variables)
(when (called-interactively-p 'any)
(when (fboundp 'explain-pause-mode)
(explain-pause-mode (if enabled +1 -1))))
;; Watch for changes in `doom-debug-variables', or when packages load (and ;; Watch for changes in `doom-debug-variables', or when packages load (and
;; potentially define one of `doom-debug-variables'), in case some of them ;; potentially define one of `doom-debug-variables'), in case some of them
;; aren't defined when `doom-debug-mode' is first loaded. ;; aren't defined when `doom-debug-mode' is first loaded.
@ -260,7 +257,8 @@ ready to be pasted in a bug report on github."
(bound-and-true-p emacs-repository-branch) (bound-and-true-p emacs-repository-branch)
(and (stringp emacs-repository-version) (and (stringp emacs-repository-version)
(substring emacs-repository-version 0 9)) (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 (doom . ,(list doom-version
(if doom-profile (if doom-profile
(format "PROFILE=%s@%s" (format "PROFILE=%s@%s"
@ -300,7 +298,7 @@ ready to be pasted in a bug report on github."
'compiled-user-config) 'compiled-user-config)
(if (doom-files-in doom-core-dir :type 'files :match "\\.elc$") (if (doom-files-in doom-core-dir :type 'files :match "\\.elc$")
'compiled-core) '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))))) 'compiled-modules)))))
(custom (custom
,@(when (and (stringp custom-file) ,@(when (and (stringp custom-file)

View file

@ -19,24 +19,24 @@
(defvar doom-docs-header-specs (defvar doom-docs-header-specs
'(("/docs/index\\.org$" '(("/docs/index\\.org$"
(:label "FAQ" (:label "FAQ"
:icon "question_answer" :icon "nf-md-message_question_outline"
:link "doom-faq:" :link "doom-faq:"
:help-echo "Open the FAQ document")) :help-echo "Open the FAQ document"))
(("/docs/[^/]+\\.org$" "/modules/README\\.org$") (("/docs/[^/]+\\.org$" "/modules/README\\.org$")
(:label "Back to index" (:label "Back to index"
:icon "arrow_back" :icon "nf-md-arrow_left"
:link ("doom-index" . "") :link "doom-index"
:help-echo "Navigate to the root index")) :help-echo "Navigate to the root index"))
("/modules/[^/]+/README\\.org$" ("/modules/[^/]+/README\\.org$"
(:label "Back to module index" (:label "Back to module index"
:icon "arrow_back" :icon "nf-md-arrow_left"
:link "doom-module-index:")) :link "doom-module-index:"))
("/modules/[^/]+/[^/]+/README\\.org$" ("/modules/[^/]+/[^/]+/README\\.org$"
(:label "Back to module index" (:label "Back to module index"
:icon "arrow_back" :icon "nf-md-arrow_left"
:link "doom-module-index:") :link "doom-module-index:")
(:label "History" (:label "History"
:icon "history" :icon "nf-md-history"
:icon-face font-lock-variable-name-face :icon-face font-lock-variable-name-face
:link (lambda () :link (lambda ()
(cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name)) (cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name))
@ -44,7 +44,7 @@
:help-echo "View the module history" :help-echo "View the module history"
:align right) :align right)
(:label "Issues" (:label "Issues"
:icon "error_outline" :icon "nf-md-flag"
:icon-face error :icon-face error
:link (lambda () :link (lambda ()
(cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name)) (cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name))
@ -52,12 +52,12 @@
:align right)) :align right))
(t (t
(:label "Suggest edits" (:label "Suggest edits"
:icon "edit" :icon "nf-md-account_edit"
:icon-face warning :icon-face warning
:link "doom-suggest-edit" :link "doom-suggest-edit"
:align right) :align right)
(:label "Help" (:label "Help"
:icon "help_outline" :icon "nf-md-timeline_help_outline"
:icon-face font-lock-function-name-face :icon-face font-lock-function-name-face
:link (lambda () :link (lambda ()
(let ((title (cadar (org-collect-keywords '("TITLE"))))) (let ((title (cadar (org-collect-keywords '("TITLE")))))
@ -101,9 +101,10 @@
(defun doom-docs--make-header-link (spec) (defun doom-docs--make-header-link (spec)
"Create a header link according to SPEC." "Create a header link according to SPEC."
(let ((icon (and (plist-get spec :icon) (let ((icon (and (plist-get spec :icon)
(funcall (or (plist-get spec :icon-function) (with-demoted-errors "DOCS ERROR: %s"
#'all-the-icons-material) (funcall (or (plist-get spec :icon-function)
(plist-get spec :icon)))) #'nerd-icons-mdicon)
(plist-get spec :icon)))))
(label (pcase (plist-get spec :label) (label (pcase (plist-get spec :label)
((and (pred functionp) lab) ((and (pred functionp) lab)
(funcall lab)) (funcall lab))
@ -239,11 +240,9 @@
(beg (max (point-min) (1- (org-element-property :begin el)))) (beg (max (point-min) (1- (org-element-property :begin el))))
(end (org-element-property :end el)) (end (org-element-property :end el))
((memq (org-element-type el) '(drawer property-drawer)))) ((memq (org-element-type el) '(drawer property-drawer))))
(when (org-current-level) (when (org-element-property-inherited :level el)
(cl-decf end)) (cl-decf end))
(org-fold-core-region beg end doom-docs-mode 'doom-doc-hidden) (org-fold-core-region beg end doom-docs-mode 'doom-doc-hidden))))
(when doom-docs-mode
(org-fold-core-region beg end nil 'org-hide-drawer)))))
;; FIX: If the cursor remains within a newly folded region, that folk will ;; FIX: If the cursor remains within a newly folded region, that folk will
;; come undone, so we move it. ;; come undone, so we move it.
(if pt (goto-char pt)))) (if pt (goto-char pt))))
@ -373,7 +372,7 @@ depending.")
(defvar doom-docs--cookies nil) (defvar doom-docs--cookies nil)
;;;###autoload ;;;###autoload
(define-minor-mode doom-docs-mode (define-minor-mode doom-docs-mode
"Hides metadata, tags, & drawers and activates all org-mode pretiffications. "Hides metadata, tags, & drawers and activates all org-mode prettifications.
This primes `org-mode' for reading." This primes `org-mode' for reading."
:lighter " Doom Docs" :lighter " Doom Docs"
:after-hook (org-restart-font-lock) :after-hook (org-restart-font-lock)
@ -387,7 +386,7 @@ This primes `org-mode' for reading."
(if doom-docs-mode (if doom-docs-mode
(set (make-local-variable sym) t) (set (make-local-variable sym) t)
(kill-local-variable sym))) (kill-local-variable sym)))
`(org-pretty-entities '(org-pretty-entities
org-hide-emphasis-markers org-hide-emphasis-markers
org-hide-macro-markers)) org-hide-macro-markers))
(when doom-docs-mode (when doom-docs-mode
@ -428,13 +427,13 @@ This primes `org-mode' for reading."
(defvar doom-docs--id-locations nil) (defvar doom-docs--id-locations nil)
(defvar doom-docs--id-files nil) (defvar doom-docs--id-files nil)
(defvar doom-docs--id-location-file (file-name-concat doom-cache-dir "doom-docs-org-ids"))
;;;###autoload ;;;###autoload
(defun doom/reload-docs (&optional force) (defun doom/reload-docs (&optional force)
"Reload the ID locations in Doom's documentation and open docs buffers." "Reload the ID locations in Doom's documentation and open docs buffers."
(interactive (list 'interactive)) (interactive (list 'interactive))
(with-temp-buffer (with-temp-buffer
(let ((org-id-locations-file (let ((org-id-locations-file doom-docs--id-location-file)
(doom-path (file-truename doom-cache-dir) "doom-docs-org-ids"))
(org-id-track-globally t) (org-id-track-globally t)
org-agenda-files org-agenda-files
org-id-extra-files org-id-extra-files
@ -465,14 +464,26 @@ This primes `org-mode' for reading."
(let ((org-id-link-to-org-use-id t) (let ((org-id-link-to-org-use-id t)
(org-id-method 'uuid) (org-id-method 'uuid)
(org-id-track-globally t) (org-id-track-globally t)
(org-id-locations-file (doom-path doom-cache-dir "doom-docs-org-ids")) (org-id-locations-file doom-docs--id-location-file)
(org-id-locations doom-docs--id-locations) (org-id-locations doom-docs--id-locations)
(org-id-files doom-docs--id-files)) (org-id-files doom-docs--id-files))
(doom/reload-docs) (doom/reload-docs)
(let ((id (org-id-new))) (when-let (fname (buffer-file-name (buffer-base-buffer)))
(org-id-add-location (let ((id (org-id-new)))
id (buffer-file-name (buffer-base-buffer))) (org-id-add-location id fname)
id))) id))))
(defconst doom-docs-org-font-lock-keywords
'(("^\\( *\\)#\\+begin_quote\n\\1 \\([󰝗󱌣󰐃󰔓󰟶󰥔]\\) "
2 (pcase (match-string 2)
("󰝗" 'font-lock-comment-face)
("󱌣" 'font-lock-comment-face)
("󰐃" 'error)
("󰔓" 'success)
("󰟶" 'font-lock-keyword-face)
("󰥔" 'font-lock-constant-face)
("" 'warning))))
"Extra font-lock keywords for Doom documentation.")
;;;###autoload ;;;###autoload
(define-derived-mode doom-docs-org-mode org-mode "Doom Docs" (define-derived-mode doom-docs-org-mode org-mode "Doom Docs"
@ -481,6 +492,7 @@ This primes `org-mode' for reading."
Keeps track of its own IDs in `doom-docs-dir' and toggles `doom-docs-mode' when Keeps track of its own IDs in `doom-docs-dir' and toggles `doom-docs-mode' when
`read-only-mode' is activated." `read-only-mode' is activated."
:after-hook (visual-line-mode -1) :after-hook (visual-line-mode -1)
(font-lock-add-keywords nil doom-docs-org-font-lock-keywords)
(let ((gc-cons-threshold most-positive-fixnum) (let ((gc-cons-threshold most-positive-fixnum)
(gc-cons-percentage 1.0)) (gc-cons-percentage 1.0))
(require 'org-id) (require 'org-id)
@ -488,7 +500,7 @@ Keeps track of its own IDs in `doom-docs-dir' and toggles `doom-docs-mode' when
(setq-local org-id-link-to-org-use-id t (setq-local org-id-link-to-org-use-id t
org-id-method 'uuid org-id-method 'uuid
org-id-track-globally t org-id-track-globally t
org-id-locations-file (doom-path doom-cache-dir "doom-docs-org-ids") org-id-locations-file doom-docs--id-location-file
org-id-locations doom-docs--id-locations org-id-locations doom-docs--id-locations
org-id-files doom-docs--id-files org-id-files doom-docs--id-files
org-num-max-level 3 org-num-max-level 3

View file

@ -220,7 +220,7 @@ single file or nested compound statement of `and' and `or' statements."
(let* ((buffer-file-name (doom-path ,file)) (let* ((buffer-file-name (doom-path ,file))
(coding-system-for-read (or ,coding 'binary)) (coding-system-for-read (or ,coding 'binary))
(coding-system-for-write (or coding-system-for-write coding-system-for-read 'binary))) (coding-system-for-write (or coding-system-for-write coding-system-for-read 'binary)))
(unless (eq coding-system-for-read 'binary) (when (eq coding-system-for-read 'binary)
(set-buffer-multibyte nil) (set-buffer-multibyte nil)
(setq-local buffer-file-coding-system 'binary)) (setq-local buffer-file-coding-system 'binary))
,@body)) ,@body))
@ -245,7 +245,8 @@ special values:
'read* -- read all forms in FILE and return it as a list of S-exps. 'read* -- read all forms in FILE and return it as a list of S-exps.
'(read . N) -- read the first N (an integer) S-exps in FILE. '(read . N) -- read the first N (an integer) S-exps in FILE.
CODING dictates the encoding of the buffer. This defaults to `utf-8'. CODING dictates the encoding of the buffer. This defaults to `utf-8'. If set to
nil, `binary' is used.
If NOERROR is non-nil, don't throw an error if FILE doesn't exist. This will If NOERROR is non-nil, don't throw an error if FILE doesn't exist. This will
still throw an error if FILE is unreadable, however. still throw an error if FILE is unreadable, however.
@ -301,18 +302,21 @@ If CONTENTS is list of forms. Any literal strings in the list are inserted
verbatim, as text followed by a newline, with `insert'. Sexps are inserted with verbatim, as text followed by a newline, with `insert'. Sexps are inserted with
`prin1'. BY is the function to use to emit `prin1'. BY is the function to use to emit
MODE dictates the permissions of the file. If FILE already exists, its MODE dictates the permissions of created file and directories. MODE is either an
permissions will be changed. integer or a cons cell whose car is the mode for files and cdr the mode for
directories. If FILE already exists, its permissions will be changed. The
permissions of existing directories will never be changed.
CODING dictates the encoding to read/write with (see `coding-system-for-write'). CODING dictates the encoding to read/write with (see `coding-system-for-write').
If set to nil, `binary' is used. This defaults to `utf-8'. If set to nil, `binary' is used.
APPEND dictates where CONTENTS will be written. If neither is set, APPEND dictates where CONTENTS will be written. If neither is set,
the file will be overwritten. If both are, the contents will be written to both the file will be overwritten. If both are, the contents will be written to both
ends. Set either APPEND or PREPEND to `noerror' to silently ignore read errors." ends. Set either APPEND or PREPEND to `noerror' to silently ignore read errors."
(doom--with-prepared-file-buffer file coding mode (let ((mode (ensure-list mode))
(let ((contents (ensure-list contents)) (contents (ensure-list contents))
datum) datum)
(doom--with-prepared-file-buffer file coding (car mode)
(while (setq datum (pop contents)) (while (setq datum (pop contents))
(cond ((stringp datum) (cond ((stringp datum)
(funcall (funcall
@ -325,15 +329,21 @@ ends. Set either APPEND or PREPEND to `noerror' to silently ignore read errors."
((let ((standard-output (current-buffer)) ((let ((standard-output (current-buffer))
(print-quoted t) (print-quoted t)
(print-level nil) (print-level nil)
(print-length nil)) (print-length nil)
(funcall printfn datum)))))) ;; Escape special chars to avoid any shenanigans
(let (write-region-annotate-functions (print-escape-newlines t)
write-region-post-annotation-function) (print-escape-control-characters t)
(when mkdir (print-escape-nonascii t)
(make-directory (file-name-directory buffer-file-name) (print-escape-multibyte t))
(eq mkdir 'parents))) (funcall printfn datum)))))
(write-region nil nil buffer-file-name append :silent)) (let (write-region-annotate-functions
buffer-file-name)) write-region-post-annotation-function)
(when mkdir
(with-file-modes (or (cdr mode) (default-file-modes))
(make-directory (file-name-directory buffer-file-name)
(eq mkdir 'parents))))
(write-region nil nil buffer-file-name append :silent))
buffer-file-name)))
;;;###autoload ;;;###autoload
(defmacro with-file-contents! (file &rest body) (defmacro with-file-contents! (file &rest body)
@ -477,7 +487,7 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation."
(defun doom/sudo-find-file (file) (defun doom/sudo-find-file (file)
"Open FILE as root." "Open FILE as root."
(interactive "FOpen file as root: ") (interactive "FOpen file as root: ")
(find-file (doom--sudo-file-path file))) (find-file (doom--sudo-file-path (expand-file-name file))))
;;;###autoload ;;;###autoload
(defun doom/sudo-this-file () (defun doom/sudo-this-file ()
@ -517,5 +527,77 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation."
(recentf-save-list) (recentf-save-list)
(message "Removed %S from `recentf-list'" (abbreviate-file-name file))) (message "Removed %S from `recentf-list'" (abbreviate-file-name file)))
;;
;;; Backports
;; Introduced in Emacs 29.
;;;###autoload
(eval-when! (not (fboundp 'find-sibling-file))
(defvar find-sibling-rules nil)
(defun find-sibling-file (file)
"Visit a \"sibling\" file of FILE.
When called interactively, FILE is the currently visited file.
The \"sibling\" file is defined by the `find-sibling-rules' variable."
(interactive (progn
(unless buffer-file-name
(user-error "Not visiting a file"))
(list buffer-file-name)))
(unless find-sibling-rules
(user-error "The `find-sibling-rules' variable has not been configured"))
(let ((siblings (find-sibling-file-search (expand-file-name file)
find-sibling-rules)))
(cond
((null siblings)
(user-error "Couldn't find any sibling files"))
((length= siblings 1)
(find-file (car siblings)))
(t
(let ((relatives (mapcar (lambda (sibling)
(file-relative-name
sibling (file-name-directory file)))
siblings)))
(find-file
(completing-read (format-prompt "Find file" (car relatives))
relatives nil t nil nil (car relatives))))))))
(defun find-sibling-file-search (file &optional rules)
"Return a list of FILE's \"siblings\".
RULES should be a list on the form defined by `find-sibling-rules' (which
see), and if nil, defaults to `find-sibling-rules'."
(let ((results nil))
(pcase-dolist (`(,match . ,expansions) (or rules find-sibling-rules))
;; Go through the list and find matches.
(when (string-match match file)
(let ((match-data (match-data)))
(dolist (expansion expansions)
(let ((start 0))
;; Expand \\1 forms in the expansions.
(while (string-match "\\\\\\([&0-9]+\\)" expansion start)
(let ((index (string-to-number (match-string 1 expansion))))
(setq start (match-end 0)
expansion
(replace-match
(substring file
(elt match-data (* index 2))
(elt match-data (1+ (* index 2))))
t t expansion)))))
;; Then see which files we have that are matching. (And
;; expand from the end of the file's match, since we might
;; be doing a relative match.)
(let ((default-directory (substring file 0 (car match-data))))
;; Keep the first matches first.
(setq results
(nconc
results
(mapcar #'expand-file-name
(file-expand-wildcards expansion nil t)))))))))
;; Delete the file itself (in case it matched), and remove
;; duplicates, in case we have several expansions and some match
;; the same subsets of files.
(delete file (delete-dups results)))))
(provide 'doom-lib '(files)) (provide 'doom-lib '(files))
;;; files.el ends here ;;; files.el ends here

View file

@ -168,7 +168,8 @@ selection of all minor-modes, active or not."
(location (location
(goto-char location))) (goto-char location)))
(ignore-errors (ignore-errors
(when (outline-invisible-p) (when (memq (get-char-property (point) 'invisible)
'(outline org-fold-outline))
(save-excursion (save-excursion
(outline-previous-visible-heading 1) (outline-previous-visible-heading 1)
(org-show-subtree)))))) (org-show-subtree))))))
@ -575,7 +576,10 @@ If prefix arg is present, refresh the cache."
(pp-to-string recipe)))) (pp-to-string recipe))))
(package--print-help-section "Homepage") (package--print-help-section "Homepage")
(doom--help-insert-button (doom-package-homepage package))) (let ((homepage (doom-package-homepage package)))
(if homepage
(doom--help-insert-button homepage)
(insert "n/a"))))
(`elpa (insert "[M]ELPA ") (`elpa (insert "[M]ELPA ")
(doom--help-insert-button (doom-package-homepage package)) (doom--help-insert-button (doom-package-homepage package))

View file

@ -239,13 +239,14 @@ Must be run from a magit diff buffer."
(unless (= (length before) (length after)) (unless (= (length before) (length after))
(user-error "Uneven number of packages being bumped")) (user-error "Uneven number of packages being bumped"))
(dolist (p1 before) (dolist (p1 before)
(cl-destructuring-bind (package &key plist _beg _end &allow-other-keys) p1 (when (and (listp p1) (plist-get (cdr p1) :package))
(let ((p2 (cdr (assq package after)))) (cl-destructuring-bind (package &key plist _beg _end &allow-other-keys) p1
(if (null p2) (let ((p2 (cdr (assq package after))))
(push package errors) (if (null p2)
(let ((bstr1 (doom--package-to-bump-string package plist)) (push package errors)
(bstr2 (doom--package-to-bump-string package (plist-get p2 :plist)))) (let ((bstr1 (doom--package-to-bump-string package plist))
(cl-pushnew (format "%s -> %s" bstr1 bstr2) lines :test #'equal)))))) (bstr2 (doom--package-to-bump-string package (plist-get p2 :plist))))
(cl-pushnew (format "%s -> %s" bstr1 bstr2) lines :test #'equal)))))))
(if (null lines) (if (null lines)
(user-error "No bumps to bumpify") (user-error "No bumps to bumpify")
(prog1 (funcall (if interactive #'kill-new #'identity) (prog1 (funcall (if interactive #'kill-new #'identity)

View file

@ -84,7 +84,8 @@ and `format!' into colored output, where COLOR is any car of this list (or
(doom-print--indent (doom-print--indent
(if args (apply #'format str args) str) (if args (apply #'format str args) str)
"> "))) "> ")))
(path . abbreviate-file-name) (path . (lambda (&rest segments)
(abbreviate-file-name (apply #'doom-path segments))))
(symbol . symbol-name) (symbol . symbol-name)
(relpath . (lambda (str &optional dir) (relpath . (lambda (str &optional dir)
(if (or (not str) (if (or (not str)

View file

@ -149,14 +149,11 @@ If DIR is not a project, it will be indexed (but not cached)."
(if (doom-module-p :completion 'ivy) (if (doom-module-p :completion 'ivy)
#'counsel-projectile-find-file #'counsel-projectile-find-file
#'projectile-find-file))) #'projectile-find-file)))
((and (bound-and-true-p vertico-mode)
(fboundp '+vertico/find-file-in))
(+vertico/find-file-in default-directory))
((and (bound-and-true-p ivy-mode) ((and (bound-and-true-p ivy-mode)
(fboundp 'counsel-file-jump)) (fboundp 'counsel-file-jump))
(call-interactively #'counsel-file-jump)) (call-interactively #'counsel-file-jump))
((project-current nil dir) ((when-let ((pr (project-current nil dir)))
(project-find-file-in nil nil dir)) (project-find-file-in nil nil pr)))
((and (bound-and-true-p helm-mode) ((and (bound-and-true-p helm-mode)
(fboundp 'helm-find-files)) (fboundp 'helm-find-files))
(call-interactively #'helm-find-files)) (call-interactively #'helm-find-files))

View file

@ -4,8 +4,8 @@
(defun doom-system-distro () (defun doom-system-distro ()
"Return a symbol representing the installed distro." "Return a symbol representing the installed distro."
(with-memoization (get 'doom-system-distro 'cached-value) (with-memoization (get 'doom-system-distro 'cached-value)
(cond (IS-WINDOWS 'windows) (cond (doom--system-windows-p 'windows)
(IS-MAC 'macos) (doom--system-macos-p 'macos)
((ignore-errors ((ignore-errors
(with-file-contents! "/etc/os-release" (with-file-contents! "/etc/os-release"
(when (re-search-forward "^ID=\"?\\([^\"\n]+\\)\"?" nil t) (when (re-search-forward "^ID=\"?\\([^\"\n]+\\)\"?" nil t)
@ -52,8 +52,8 @@
(with-memoization (get 'doom-system-distro-icon 'cached-value) (with-memoization (get 'doom-system-distro-icon 'cached-value)
(propertize (propertize
(pcase (doom-system-distro) (pcase (doom-system-distro)
(`windows (all-the-icons-faicon "windows")) (`windows (nerd-icons-faicon "nf-fa-windows"))
(`macos (all-the-icons-faicon "apple")) (`macos (nerd-icons-faicon "nf-fa-apple"))
(`arch "\uF303") (`arch "\uF303")
(`debian "\uF306") (`debian "\uF306")
(`raspbian "\uF315") (`raspbian "\uF315")
@ -74,7 +74,7 @@
(`devuan "\uF307") (`devuan "\uF307")
(`manjaro "\uF312") (`manjaro "\uF312")
((or `void `artix) "\uF17c") ((or `void `artix) "\uF17c")
(_ (all-the-icons-faicon "linux"))) (_ (nerd-icons-faicon "nf-fa-linux")))
'face '(:height 1) 'face '(:height 1)
'display '(raise 0)))) 'display '(raise 0))))

View file

@ -88,10 +88,11 @@ Uses `evil-visual-beginning' if available."
"Return end position of selection. "Return end position of selection.
Uses `evil-visual-end' if available." Uses `evil-visual-end' if available."
(declare (side-effect-free t)) (declare (side-effect-free t))
(if (and (bound-and-true-p evil-local-mode) (or (and (bound-and-true-p evil-local-mode)
(evil-visual-state-p)) (evil-visual-state-p)
evil-visual-end (markerp evil-visual-end)
(region-end))) (marker-position evil-visual-end))
(region-end)))
;;;###autoload ;;;###autoload
(defun doom-thing-at-point-or-region (&optional thing prompt) (defun doom-thing-at-point-or-region (&optional thing prompt)

View file

@ -175,11 +175,18 @@ Use `winner-undo' to undo this. Alternatively, use
"Interactively change the current frame's opacity. "Interactively change the current frame's opacity.
OPACITY is an integer between 0 to 100, inclusive." OPACITY is an integer between 0 to 100, inclusive."
(interactive (interactive '(interactive))
(list (read-number "Opacity (0-100): " (let* ((parameter
(or (frame-parameter nil 'alpha) (if (eq window-system 'pgtk)
100)))) 'alpha-background
(set-frame-parameter nil 'alpha opacity)) 'alpha))
(opacity
(if (eq opacity 'interactive)
(read-number "Opacity (0-100): "
(or (frame-parameter nil parameter)
100))
opacity)))
(set-frame-parameter nil parameter opacity)))
(defvar doom--narrowed-base-buffer nil) (defvar doom--narrowed-base-buffer nil)
;;;###autoload ;;;###autoload
@ -191,12 +198,9 @@ narrowing doesn't affect other windows displaying the same buffer. Call
`doom/widen-indirectly-narrowed-buffer' to undo it (incrementally). `doom/widen-indirectly-narrowed-buffer' to undo it (incrementally).
Inspired from http://demonastery.org/2013/04/emacs-evil-narrow-region/" Inspired from http://demonastery.org/2013/04/emacs-evil-narrow-region/"
(interactive (interactive (if (region-active-p)
(list (or (bound-and-true-p evil-visual-beginning) (region-beginning)) (list (doom-region-beginning) (doom-region-end))
(or (bound-and-true-p evil-visual-end) (region-end)))) (list (bol) (eol))))
(unless (region-active-p)
(setq beg (line-beginning-position)
end (line-end-position)))
(deactivate-mark) (deactivate-mark)
(let ((orig-buffer (current-buffer))) (let ((orig-buffer (current-buffer)))
(with-current-buffer (switch-to-buffer (clone-indirect-buffer nil nil)) (with-current-buffer (switch-to-buffer (clone-indirect-buffer nil nil))
@ -235,12 +239,9 @@ If the current buffer is not an indirect buffer, it is `widen'ed."
;;;###autoload ;;;###autoload
(defun doom/toggle-narrow-buffer (beg end) (defun doom/toggle-narrow-buffer (beg end)
"Narrow the buffer to BEG END. If narrowed, widen it." "Narrow the buffer to BEG END. If narrowed, widen it."
(interactive (interactive (if (region-active-p)
(list (or (bound-and-true-p evil-visual-beginning) (region-beginning)) (list (doom-region-beginning) (doom-region-end))
(or (bound-and-true-p evil-visual-end) (region-end)))) (list (bol) (eol))))
(if (buffer-narrowed-p) (if (buffer-narrowed-p)
(widen) (widen)
(unless (region-active-p)
(setq beg (line-beginning-position)
end (line-end-position)))
(narrow-to-region beg end))) (narrow-to-region beg end)))

View file

@ -2,12 +2,13 @@
;;; lisp/packages.el ;;; lisp/packages.el
;; doom.el ;; doom.el
(package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") (package! auto-minor-mode
(package! gcmh :pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9") :pin "17cfa1b54800fdef2975c0c0531dad34846a5065")
(package! explain-pause-mode (package! compat
:recipe (:host github :recipe (:host github :repo "emacs-compat/compat")
:repo "lastquestion/explain-pause-mode") :pin "8d4e8a366681def88751f5e9975738ecd3180deb")
:pin "2356c8c3639cbeeb9751744dbe737267849b4b51") (package! gcmh
:pin "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9")
;; doom-packages.el ;; doom-packages.el
(package! straight (package! straight
@ -17,21 +18,21 @@
:branch ,straight-repository-branch :branch ,straight-repository-branch
:local-repo "straight.el" :local-repo "straight.el"
:files ("straight*.el")) :files ("straight*.el"))
:pin "5e84c4e2cd8ca79560477782ee4c9e5187725def") :pin "b1062df10ba4c10ff7a3c61b9e124b3242b11bb2")
;; doom-ui.el ;; doom-ui.el
(package! all-the-icons :pin "f491f39c21336d354e85bdb4cca281e0a0c2f880") (package! nerd-icons :pin "8095215a503d8048739de8b4ea4066598edb8cbb")
(package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942") (package! hide-mode-line :pin "bc5d293576c5e08c29e694078b96a5ed85631942")
(package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307") (package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307")
(package! rainbow-delimiters :pin "a32b39bdfe6c61c322c37226d66e1b6d4f107ed0") (package! rainbow-delimiters :pin "f40ece58df8b2f0fb6c8576b527755a552a5e763")
(package! restart-emacs :pin "1607da2bc657fe05ae01f7fdf26f716eafead02c") (package! restart-emacs :pin "1607da2bc657fe05ae01f7fdf26f716eafead02c")
;; doom-editor.el ;; doom-editor.el
(package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319") (package! better-jumper :pin "47622213783ece37d5337dc28d33b530540fc319")
(package! dtrt-indent :pin "be07f4979a5b402a0cf5311c86c30b89ca0e1ee4") (package! dtrt-indent :pin "5d1b44f9a1a484ca229cc14f8062609a10ef4891")
(package! helpful :pin "c57ff0d284b50ff430fe1f13fd48deaa0d1a910e") (package! helpful :pin "a32a5b3d959a7fccf09a71d97b3d7c888ac31c69")
(package! pcre2el :pin "b941ed8a96299868171fac625ecffec77de3e986") (package! pcre2el :pin "380723b2701cceb75c266440fb8db918f3340d50")
(package! smartparens :pin "79a338db115f441cd47bb91e6f75816c5e78a772") (package! smartparens :pin "ddc6233ea6fc2da7a3a8e44face465c15631b02b")
(package! ws-butler (package! ws-butler
;; Use my fork of ws-butler, which has a few choice improvements and ;; Use my fork of ws-butler, which has a few choice improvements and
;; optimizations (the original has been abandoned). ;; optimizations (the original has been abandoned).
@ -39,13 +40,9 @@
:pin "572a10c11b6cb88293de48acbb59a059d36f9ba5") :pin "572a10c11b6cb88293de48acbb59a059d36f9ba5")
;; doom-projects.el ;; doom-projects.el
(package! projectile :pin "971cd5c4f25ff1f84ab7e8337ffc7f89f67a1b52") (package! projectile :pin "0163b335a18af0f077a474d4dc6b36e22b5e3274")
(package! project :pin "6c41ad68edf1f44110abe478d17c36f57a517e66") (package! project :pin "b6989856abe9411872bdff5c8aa190bef4d86409")
;; doom-keybinds.el ;; doom-keybinds.el
(package! general :pin "833dea2c4a60e06fcd552b653dfc8960935c9fb4") (package! general :pin "ced143c30de8e20f5a3761a465e684a1dc48471e")
(package! which-key :pin "df6b0cb8449812e7fb200bc852107fa7eb708496") (package! which-key :pin "96911a1d3faf8426a33241f4821319e98421f380")
(package! compat
:recipe (:host github :repo "emacs-compat/compat")
:pin "75d0b8527f51aae42d23eee4aeb263e19055747e")

View file

@ -330,7 +330,7 @@ Modules that turn Emacs in an email client.
This module makes Emacs an email client, using [[https://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]]. This module makes Emacs an email client, using [[https://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]].
- Tidied mu4e headers view, with flags from [[doom-package:all-the-icons]]. - Tidied mu4e headers view, with flags from [[doom-package:nerd-icons]].
- Consistent coloring of reply depths (across compose and gnus modes). - Consistent coloring of reply depths (across compose and gnus modes).
- Prettified =mu4e:main= view. - Prettified =mu4e:main= view.
- Cooperative locking of the =mu= process. Another Emacs instance may request - Cooperative locking of the =mu= process. Another Emacs instance may request
@ -1152,8 +1152,8 @@ you'd expect from IDEs, like code completion, realtime linting, language-aware
As of this writing, this is the state of LSP support in Doom Emacs: As of this writing, this is the state of LSP support in Doom Emacs:
| Module | Major modes | Default language server | | Module | Major modes | Default language server |
|------------------+---------------------------------------------------------+---------------------------------------------------------------| |----------------------------------+---------------------------------------------------------+---------------------------------------------------------------|
| [[doom-module::lang cc]] | c-mode, c++-mode, objc-mode | ccls, clangd | | [[doom-module::lang cc]] | c-mode, c++-mode, objc-mode | ccls, clangd |
| [[doom-module::lang clojure]] | clojure-mode | clojure-lsp | | [[doom-module::lang clojure]] | clojure-mode | clojure-lsp |
| [[doom-module::lang csharp]] | csharp-mode | omnisharp | | [[doom-module::lang csharp]] | csharp-mode | omnisharp |
@ -1417,12 +1417,12 @@ emacs fontset to cover as many unicode glyphs as possible by scanning all
available glyphs from all available fonts. available glyphs from all available fonts.
When this module is enabled: When this module is enabled:
- Emacs will prefer to use the ~doom-unicode-font~ font to display non-latin - Emacs will prefer to use the ~doom-symbol-font~ font to display non-latin
glyphs if it provides coverage for them. glyphs if it provides coverage for them.
- The first time you run Emacs a unicode cache will be generated -- this will - The first time you run Emacs a unicode cache will be generated -- this will
take a while! take a while!
- The cache will be regenerated every time Emacs is made aware of new fonts or - The cache will be regenerated every time Emacs is made aware of new fonts or
you change the font configuration e.g. by modifying ~doom-unicode-font~. you change the font configuration e.g. by modifying ~doom-symbol-font~.
- The cache will be stored and should not be regenerated unless font-related - The cache will be stored and should not be regenerated unless font-related
configuration or the versions of relevant packages changes. configuration or the versions of relevant packages changes.

View file

@ -34,12 +34,12 @@ This module requires:
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Changing calendar sources ** Changing calendar sources
@ -74,5 +74,5 @@ to link your calendar with Google calendars.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -5,4 +5,4 @@
(package! calfw-org :pin "03abce97620a4a7f7ec5f911e669da9031ab9088") (package! calfw-org :pin "03abce97620a4a7f7ec5f911e669da9031ab9088")
(package! calfw-cal :pin "03abce97620a4a7f7ec5f911e669da9031ab9088") (package! calfw-cal :pin "03abce97620a4a7f7ec5f911e669da9031ab9088")
(package! calfw-ical :pin "03abce97620a4a7f7ec5f911e669da9031ab9088") (package! calfw-ical :pin "03abce97620a4a7f7ec5f911e669da9031ab9088")
(package! org-gcal :pin "9bb3720525ad1c45823abab8ce910dd1225e7dcd") (package! org-gcal :pin "a2d16b372e5a5972d8cc343cf999ee5f0ba1eea7")

View file

@ -34,7 +34,7 @@ These should be available through your OS package manager.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Keybinds ** Keybinds
@ -56,7 +56,7 @@ These should be available through your OS package manager.
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Troubleshooting * Troubleshooting
@ -70,5 +70,5 @@ Try [[kbd:][M-x +emms/mpd-restart-music-daemon]] then restart emacs.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; app/emms/packages.el ;;; app/emms/packages.el
(package! emms :pin "43c61412492229eb641fe572c89c826d8fcf64d9") (package! emms :pin "87d0d1fb0566a80229029d0d8d7c863138d70aae")

View file

@ -68,5 +68,5 @@ Most other behavior is implemented as hooks on ~emacs-everywhere-init-hooks~.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -8,19 +8,23 @@
:config :config
(set-yas-minor-mode! 'emacs-everywhere-mode) (set-yas-minor-mode! 'emacs-everywhere-mode)
;; HACK Inhibit MAJOR-MODE-local-vars-hook in emacs-everywhere buffers, ;; HACK: Inhibit MAJOR-MODE-local-vars-hook in emacs-everywhere buffers,
;; because Doom commonly starts servers and other extraneous services on ;; because Doom commonly starts servers and other extraneous services on
;; this hook, which will rarely work well in emacs-everywhere's temporary ;; this hook, which will rarely work well in emacs-everywhere's temporary
;; buffers anyway. ;; buffers anyway.
(setq-hook! 'emacs-everywhere-init-hooks doom-inhibit-local-var-hooks t) (setq-hook! 'emacs-everywhere-init-hooks doom-inhibit-local-var-hooks t)
;; REVIEW: Fixes tecosaur/emacs-everywhere#75. Remove when dealt with
;; upstream.
(define-key emacs-everywhere-mode-map "\C-c\C-c" #'emacs-everywhere-finish)
(after! doom-modeline (after! doom-modeline
(doom-modeline-def-segment emacs-everywhere (doom-modeline-def-segment emacs-everywhere
(concat (concat
(doom-modeline-spc) (doom-modeline-spc)
(when (emacs-everywhere-markdown-p) (when (emacs-everywhere-markdown-p)
(concat (concat
(all-the-icons-octicon "markdown" :face 'all-the-icons-green :v-adjust 0.02) (nerd-icons-octicon "nf-oct-markdown" :face 'nerd-icons-green :v-adjust 0.02)
(doom-modeline-spc))) (doom-modeline-spc)))
(propertize (emacs-everywhere-app-class emacs-everywhere-current-app) (propertize (emacs-everywhere-app-class emacs-everywhere-current-app)
'face 'doom-modeline-project-dir) 'face 'doom-modeline-project-dir)
@ -32,7 +36,7 @@
(doom-modeline-def-modeline 'emacs-everywhere (doom-modeline-def-modeline 'emacs-everywhere
'(bar modals emacs-everywhere buffer-position '(bar modals emacs-everywhere buffer-position
word-count parrot selection-info) word-count parrot selection-info)
'(input-method major-mode checker '(input-method major-mode check
#("" 0 1 ; "Exit to app" icon + a little padding #("" 0 1 ; "Exit to app" icon + a little padding
(rear-nonsticky t (rear-nonsticky t
display (raise -0.25) display (raise -0.25)

View file

@ -1,9 +1,9 @@
;;; app/everywhere/doctor.el -*- lexical-binding: t; -*- ;;; app/everywhere/doctor.el -*- lexical-binding: t; -*-
(when IS-WINDOWS (when (featurep :system 'windows)
(error! "emacs-everywhere package does not support windows.")) (error! "emacs-everywhere package does not support windows."))
(when IS-LINUX (when (featurep :system 'linux)
(let (unmet-deps) (let (unmet-deps)
(dolist (dep '("xclip" "xdotool" "xprop" "xwininfo")) (dolist (dep '("xclip" "xdotool" "xprop" "xwininfo"))
(unless (executable-find dep) (unless (executable-find dep)

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; app/everywhere/packages.el ;;; app/everywhere/packages.el
(package! emacs-everywhere :pin "b461c4b42093abc42e5ec0f73cb7021c2915cea8") (package! emacs-everywhere :pin "fbeff19825336777dccaefedf3f376dd622cd294")

View file

@ -52,7 +52,7 @@ environment.systemPackages = [ pkgs.gnutls ];
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
To connect to IRC use ~M-x =irc~. To connect to IRC use ~M-x =irc~.
@ -70,7 +70,7 @@ When in a circe buffer these keybindings will be available:
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
Use ~set-irc-server! SERVER PLIST~ to configure IRC servers. Its second argument Use ~set-irc-server! SERVER PLIST~ to configure IRC servers. Its second argument
@ -92,7 +92,7 @@ here are ways to avoid that:
** TODO Pass: the unix password manager ** TODO Pass: the unix password manager
#+begin_quote #+begin_quote
🔨 /This section is outdated and needs to be rewritten./ [[doom-contrib-module:][Rewrite it?]] 󱌣 /This section is outdated and needs to be rewritten./ [[doom-contrib-module:][Rewrite it?]]
#+end_quote #+end_quote
[[https://www.passwordstore.org/][Pass]] is my tool of choice. I use it to manage my passwords. If you activate the [[https://www.passwordstore.org/][Pass]] is my tool of choice. I use it to manage my passwords. If you activate the
@ -169,5 +169,5 @@ username: myusername
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -55,7 +55,8 @@ workspace for it."
circe-server-killed-confirmation) circe-server-killed-confirmation)
(when +irc--defer-timer (when +irc--defer-timer
(cancel-timer +irc--defer-timer)) (cancel-timer +irc--defer-timer))
(disable-circe-notifications) (when (fboundp #'disable-circe-notifications)
(disable-circe-notifications))
(mapc #'kill-buffer (doom-buffers-in-mode 'circe-mode (buffer-list) t)) (mapc #'kill-buffer (doom-buffers-in-mode 'circe-mode (buffer-list) t))
(when (modulep! :ui workspaces) (when (modulep! :ui workspaces)
(when (equal (+workspace-current-name) +irc--workspace-name) (when (equal (+workspace-current-name) +irc--workspace-name)

View file

@ -187,8 +187,8 @@ playback.")
(setq circe-notifications-watch-strings +irc-notifications-watch-strings (setq circe-notifications-watch-strings +irc-notifications-watch-strings
circe-notifications-emacs-focused nil circe-notifications-emacs-focused nil
circe-notifications-alert-style circe-notifications-alert-style
(cond (IS-MAC 'osx-notifier) (cond ((featurep :system 'macos) 'osx-notifier)
(IS-LINUX 'libnotify) ((featurep :system 'linux) 'libnotify)
(circe-notifications-alert-style)))) (circe-notifications-alert-style))))

View file

@ -0,0 +1,5 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; app/irc/doctor.el
(when (memq 'circe-notifications doom-disabled-packages)
(warn! "Circe Notifications has been disabled, You will not receive desktop notifications from IRC channels."))

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; app/irc/packages.el ;;; app/irc/packages.el
(package! circe :pin "57fe189d7c0b98b9b1b5a59767cea1c7e2c22b13") (package! circe :pin "d374042741cfd0691135f215d311dca8b7a47d19")
(package! circe-notifications :pin "291149ac12877bbd062da993479d3533a26862b0") (package! circe-notifications :pin "291149ac12877bbd062da993479d3533a26862b0")

View file

@ -39,7 +39,7 @@ Read RSS feeds in the comfort of Emacs.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
- As there isn't currently binding for ~elfeed-update~ you can run it with ~M-x - As there isn't currently binding for ~elfeed-update~ you can run it with ~M-x
@ -47,7 +47,7 @@ Read RSS feeds in the comfort of Emacs.
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Without +org ** Without +org
@ -78,7 +78,7 @@ configure feeds to follow:
- You can "name" feeds as you please with ~org-mode~ ~org-insert-link~ ([[kbd:][C-c C-l]]) - You can "name" feeds as you please with ~org-mode~ ~org-insert-link~ ([[kbd:][C-c C-l]])
and put name as you want into ~description~. and put name as you want into ~description~.
- If you don't want to use ~org-directory/elfeed.org~ file you can specify it - If you don't want to use ~org-directory/elfeed.org~ file you can specify it
with ~(setq rmh-elfeed-org-files '("path/to/your/elfeed/file.org))~ with ~(setq rmh-elfeed-org-files '("path/to/your/elfeed/file.org"))~
** Keybindings ** Keybindings
+ General + General
@ -128,5 +128,5 @@ Hook ~elfeed-update~ to ~elfeed-search-mode-hook~:
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -14,8 +14,9 @@ easier to scroll through.")
(defvar +rss-workspace-name "*rss*" (defvar +rss-workspace-name "*rss*"
"Name of the workspace that contains the elfeed buffer.") "Name of the workspace that contains the elfeed buffer.")
;; ;;
;; Packages ;;; Packages
(use-package! elfeed (use-package! elfeed
:commands elfeed :commands elfeed
@ -83,6 +84,7 @@ easier to scroll through.")
(message "elfeed-org: ignoring %S because it can't be read" file)) (message "elfeed-org: ignoring %S because it can't be read" file))
(setq rmh-elfeed-org-files (cl-remove-if-not #'file-exists-p files)))))) (setq rmh-elfeed-org-files (cl-remove-if-not #'file-exists-p files))))))
(use-package! elfeed-goodies (use-package! elfeed-goodies
:after elfeed :after elfeed
:config :config

View file

@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; app/rss/packages.el ;;; app/rss/packages.el
(package! elfeed :pin "162d7d545ed41c27967d108c04aa31f5a61c8e16") (package! elfeed :pin "55fb162fa27e71b88effa59a83c57842e262b00f")
(package! elfeed-goodies :pin "544ef42ead011d960a0ad1c1d34df5d222461a6b") (package! elfeed-goodies :pin "544ef42ead011d960a0ad1c1d34df5d222461a6b")
(when (modulep! +org) (when (modulep! +org)
(package! elfeed-org :pin "3242ec0519800a58f20480c8a6e3b3337d137084")) (package! elfeed-org :pin "d62d23e25c5e3be3d70b7fbe1eaeb6e43f93a061"))

View file

@ -3,6 +3,11 @@
#+created: October 11, 2019 #+created: October 11, 2019
#+since: 2.0.0 #+since: 2.0.0
#+begin_quote
*This module is deprecated.* Changes upstream to Twitter's API has rendered
twittering-mode non-functional, and there is no known alternative.
#+end_quote
* Description :unfold: * Description :unfold:
Enjoy twitter from emacs. Enjoy twitter from emacs.
@ -48,12 +53,12 @@ This module requires:
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Commands & Keybindings ** Commands & Keybindings
@ -96,6 +101,6 @@ key for evil users. To work around this issue you may use [[kbd:][M-SPC]] instea
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -2,4 +2,4 @@
;;; app/twitter/packages.el ;;; app/twitter/packages.el
(package! twittering-mode :pin "114891e8fdb4f06b1326a6cf795e49c205cf9e29") (package! twittering-mode :pin "114891e8fdb4f06b1326a6cf795e49c205cf9e29")
(package! avy :pin "955c8dedd68c74f3cf692c1249513f048518c4c9") (package! avy :pin "be612110cb116a38b8603df367942e2bb3d9bdbe")

View file

@ -41,7 +41,7 @@ will need to set ~langtool-language-tool-jar~ to its location.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Language Tool ** Language Tool
@ -49,7 +49,7 @@ will need to set ~langtool-language-tool-jar~ to its location.
stylistic issues in your writing. This requires Java 1.8+. stylistic issues in your writing. This requires Java 1.8+.
#+begin_quote #+begin_quote
🚧 This requires Java 1.8+ This requires Java 1.8+
#+end_quote #+end_quote
*** Commands *** Commands
@ -61,7 +61,7 @@ This minor mode highlights weasel words, duplication and passive voice.
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Troubleshooting * Troubleshooting
@ -72,5 +72,5 @@ This minor mode highlights weasel words, duplication and passive voice.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -13,7 +13,7 @@
(cond ((setq langtool-bin (cond ((setq langtool-bin
(or (executable-find "languagetool-commandline") (or (executable-find "languagetool-commandline")
(executable-find "languagetool")))) ; for nixpkgs.languagetool (executable-find "languagetool")))) ; for nixpkgs.languagetool
(IS-MAC ((featurep :system 'macos)
(cond (cond
;; is user using home brew? ;; is user using home brew?
((file-directory-p "/usr/local/Cellar/languagetool") ((file-directory-p "/usr/local/Cellar/languagetool")
@ -25,7 +25,7 @@
;; macports compatibility ;; macports compatibility
((file-directory-p "/opt/local/share/java/LanguageTool") ((file-directory-p "/opt/local/share/java/LanguageTool")
(setq langtool-java-classpath "/opt/local/share/java/LanguageTool/*")))) (setq langtool-java-classpath "/opt/local/share/java/LanguageTool/*"))))
(IS-LINUX ((featurep :system 'linux)
(setq langtool-java-classpath "/usr/share/languagetool:/usr/share/java/languagetool/*"))))) (setq langtool-java-classpath "/usr/share/languagetool:/usr/share/java/languagetool/*")))))

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; checkers/grammar/packages.el ;;; checkers/grammar/packages.el
(package! langtool :pin "8276eccc5587bc12fd205ee58a7a982f0a136e41") (package! langtool :pin "d86101eafe9a994eb0425e08e7c1795e9cb0cd42")
(package! writegood-mode :pin "ed42d918d98826ad88928b7af9f2597502afc6b0") (package! writegood-mode :pin "d54eadeedb8bf3aa0e0a584c0a7373c69644f4b8")

View file

@ -58,7 +58,7 @@ your system and in your =$PATH=. They also need dictionaries for your
language(s). language(s).
#+begin_quote #+begin_quote
🚧 If you *are not* using [[doom-module:+flyspell]], you will need =aspell= (and a dictionary) If you *are not* using [[doom-module:+flyspell]], you will need =aspell= (and a dictionary)
installed whether or not you have [[doom-module:+hunspell]] or [[doom-module:+enchant]] enabled. This is installed whether or not you have [[doom-module:+hunspell]] or [[doom-module:+enchant]] enabled. This is
because [[doom-package:spell-fu]] does not support generating the word list with anything because [[doom-package:spell-fu]] does not support generating the word list with anything
other than =aspell= yet. other than =aspell= yet.
@ -108,7 +108,7 @@ language(s).
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
When using [[doom-module:+everywhere]], spell checking is performed for as many major modes as When using [[doom-module:+everywhere]], spell checking is performed for as many major modes as
@ -117,7 +117,7 @@ major modes.
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
Dictionary is set by ~ispell-dictionary~ variable. Can be changed locally with Dictionary is set by ~ispell-dictionary~ variable. Can be changed locally with
@ -231,5 +231,5 @@ After the file is created, restart emacs and adding words should work.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -2,8 +2,10 @@
;;; checkers/spell/packages.el ;;; checkers/spell/packages.el
(if (not (modulep! +flyspell)) (if (not (modulep! +flyspell))
(package! spell-fu :pin "aed6e87aa31013534b7a6cbedb26e4f29ccea735") (package! spell-fu
(package! flyspell-correct :pin "7d7b6b01188bd28e20a13736ac9f36c3367bd16e") :recipe (:host github :repo "emacsmirror/spell-fu")
:pin "e4031935803c66eca2f076dce72b0a6a770d026c")
(package! flyspell-correct :pin "1e7a5a56362dd875dddf848b9a9e25d1395b9d37")
(cond ((modulep! :completion ivy) (cond ((modulep! :completion ivy)
(package! flyspell-correct-ivy)) (package! flyspell-correct-ivy))
((modulep! :completion helm) ((modulep! :completion helm)

View file

@ -40,7 +40,7 @@ find out if you're missing any dependencies.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
Most of flycheck's features are under [[kbd:][C-c !]], regardless of whether evil mode is Most of flycheck's features are under [[kbd:][C-c !]], regardless of whether evil mode is
@ -67,7 +67,7 @@ Evil Specific:
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Troubleshooting * Troubleshooting
@ -81,5 +81,5 @@ Evil Specific:
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -2,10 +2,10 @@
;;; checkers/syntax/packages.el ;;; checkers/syntax/packages.el
(unless (modulep! +flymake) (unless (modulep! +flymake)
(package! flycheck :pin "784f184cdd9f9cb4e3dbb997c09d93e954142842") (package! flycheck :pin "02148c6ce7edb0fd0986460db327cc9463939747")
(package! flycheck-popup-tip :pin "ef86aad907f27ca076859d8d9416f4f7727619c6") (package! flycheck-popup-tip :pin "ef86aad907f27ca076859d8d9416f4f7727619c6")
(when (modulep! +childframe) (when (modulep! +childframe)
(package! flycheck-posframe :pin "8f60c9bf124ab9597d681504a73fdf116a0bde12"))) (package! flycheck-posframe :pin "19896b922c76a0f460bf3fe8d8ebc2f9ac9028d8")))
;; Flymake ;; Flymake
(when (modulep! +flymake) (when (modulep! +flymake)

View file

@ -44,7 +44,7 @@ find out if you're missing any dependencies.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Code completion ** Code completion
@ -87,7 +87,7 @@ More information can be found [[https://github.com/oantolin/orderless#company][h
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** Enable company backend(s) in certain modes ** Enable company backend(s) in certain modes
@ -142,5 +142,5 @@ on changing what backends are available for that mode.
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -97,47 +97,46 @@
:config :config
(setq company-box-show-single-candidate t (setq company-box-show-single-candidate t
company-box-backends-colors nil company-box-backends-colors nil
company-box-max-candidates 50 company-box-tooltip-limit 50
company-box-icons-alist 'company-box-icons-all-the-icons company-box-icons-alist 'company-box-icons-nerd-icons
;; Move company-box-icons--elisp to the end, because it has a catch-all ;; Move company-box-icons--elisp to the end, because it has a catch-all
;; clause that ruins icons from other backends in elisp buffers. ;; clause that ruins icons from other backends in elisp buffers.
company-box-icons-functions company-box-icons-functions
(cons #'+company-box-icons--elisp-fn (cons #'+company-box-icons--elisp-fn
(delq 'company-box-icons--elisp (delq 'company-box-icons--elisp
company-box-icons-functions)) company-box-icons-functions))
company-box-icons-all-the-icons company-box-icons-nerd-icons
(let ((all-the-icons-scale-factor 0.8)) `((Unknown . ,(nerd-icons-codicon "nf-cod-code" :face 'font-lock-warning-face))
`((Unknown . ,(all-the-icons-material "find_in_page" :face 'all-the-icons-purple)) (Text . ,(nerd-icons-codicon "nf-cod-text_size" :face 'font-lock-doc-face))
(Text . ,(all-the-icons-material "text_fields" :face 'all-the-icons-green)) (Method . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
(Method . ,(all-the-icons-material "functions" :face 'all-the-icons-red)) (Function . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
(Function . ,(all-the-icons-material "functions" :face 'all-the-icons-red)) (Constructor . ,(nerd-icons-codicon "nf-cod-triangle_right" :face 'font-lock-function-name-face))
(Constructor . ,(all-the-icons-material "functions" :face 'all-the-icons-red)) (Field . ,(nerd-icons-codicon "nf-cod-symbol_field" :face 'font-lock-variable-name-face))
(Field . ,(all-the-icons-material "functions" :face 'all-the-icons-red)) (Variable . ,(nerd-icons-codicon "nf-cod-symbol_variable" :face 'font-lock-variable-name-face))
(Variable . ,(all-the-icons-material "adjust" :face 'all-the-icons-blue)) (Class . ,(nerd-icons-codicon "nf-cod-symbol_class" :face 'font-lock-type-face))
(Class . ,(all-the-icons-material "class" :face 'all-the-icons-red)) (Interface . ,(nerd-icons-codicon "nf-cod-symbol_interface" :face 'font-lock-type-face))
(Interface . ,(all-the-icons-material "settings_input_component" :face 'all-the-icons-red)) (Module . ,(nerd-icons-codicon "nf-cod-file_submodule" :face 'font-lock-preprocessor-face))
(Module . ,(all-the-icons-material "view_module" :face 'all-the-icons-red)) (Property . ,(nerd-icons-codicon "nf-cod-symbol_property" :face 'font-lock-variable-name-face))
(Property . ,(all-the-icons-material "settings" :face 'all-the-icons-red)) (Unit . ,(nerd-icons-codicon "nf-cod-symbol_ruler" :face 'font-lock-constant-face))
(Unit . ,(all-the-icons-material "straighten" :face 'all-the-icons-red)) (Value . ,(nerd-icons-codicon "nf-cod-symbol_field" :face 'font-lock-builtin-face))
(Value . ,(all-the-icons-material "filter_1" :face 'all-the-icons-red)) (Enum . ,(nerd-icons-codicon "nf-cod-symbol_enum" :face 'font-lock-builtin-face))
(Enum . ,(all-the-icons-material "plus_one" :face 'all-the-icons-red)) (Keyword . ,(nerd-icons-codicon "nf-cod-symbol_keyword" :face 'font-lock-keyword-face))
(Keyword . ,(all-the-icons-material "filter_center_focus" :face 'all-the-icons-red)) (Snippet . ,(nerd-icons-codicon "nf-cod-symbol_snippet" :face 'font-lock-string-face))
(Snippet . ,(all-the-icons-material "short_text" :face 'all-the-icons-red)) (Color . ,(nerd-icons-codicon "nf-cod-symbol_color" :face 'success))
(Color . ,(all-the-icons-material "color_lens" :face 'all-the-icons-red)) (File . ,(nerd-icons-codicon "nf-cod-symbol_file" :face 'font-lock-string-face))
(File . ,(all-the-icons-material "insert_drive_file" :face 'all-the-icons-red)) (Reference . ,(nerd-icons-codicon "nf-cod-references" :face 'font-lock-variable-name-face))
(Reference . ,(all-the-icons-material "collections_bookmark" :face 'all-the-icons-red)) (Folder . ,(nerd-icons-codicon "nf-cod-folder" :face 'font-lock-variable-name-face))
(Folder . ,(all-the-icons-material "folder" :face 'all-the-icons-red)) (EnumMember . ,(nerd-icons-codicon "nf-cod-symbol_enum_member" :face 'font-lock-builtin-face))
(EnumMember . ,(all-the-icons-material "people" :face 'all-the-icons-red)) (Constant . ,(nerd-icons-codicon "nf-cod-symbol_constant" :face 'font-lock-constant-face))
(Constant . ,(all-the-icons-material "pause_circle_filled" :face 'all-the-icons-red)) (Struct . ,(nerd-icons-codicon "nf-cod-symbol_structure" :face 'font-lock-variable-name-face))
(Struct . ,(all-the-icons-material "streetview" :face 'all-the-icons-red)) (Event . ,(nerd-icons-codicon "nf-cod-symbol_event" :face 'font-lock-warning-face))
(Event . ,(all-the-icons-material "event" :face 'all-the-icons-red)) (Operator . ,(nerd-icons-codicon "nf-cod-symbol_operator" :face 'font-lock-comment-delimiter-face))
(Operator . ,(all-the-icons-material "control_point" :face 'all-the-icons-red)) (TypeParameter . ,(nerd-icons-codicon "nf-cod-list_unordered" :face 'font-lock-type-face))
(TypeParameter . ,(all-the-icons-material "class" :face 'all-the-icons-red)) (Template . ,(nerd-icons-codicon "nf-cod-symbol_snippet" :face 'font-lock-string-face))
(Template . ,(all-the-icons-material "short_text" :face 'all-the-icons-green)) (ElispFunction . ,(nerd-icons-codicon "nf-cod-symbol_method" :face 'font-lock-function-name-face))
(ElispFunction . ,(all-the-icons-material "functions" :face 'all-the-icons-red)) (ElispVariable . ,(nerd-icons-codicon "nf-cod-symbol_variable" :face 'font-lock-variable-name-face))
(ElispVariable . ,(all-the-icons-material "check_circle" :face 'all-the-icons-blue)) (ElispFeature . ,(nerd-icons-codicon "nf-cod-globe" :face 'font-lock-builtin-face))
(ElispFeature . ,(all-the-icons-material "stars" :face 'all-the-icons-orange)) (ElispFace . ,(nerd-icons-codicon "nf-cod-symbol_color" :face 'success))))
(ElispFace . ,(all-the-icons-material "format_paint" :face 'all-the-icons-pink)))))
;; HACK Fix oversized scrollbar in some odd cases ;; HACK Fix oversized scrollbar in some odd cases
;; REVIEW `resize-mode' is deprecated and may stop working in the future. ;; REVIEW `resize-mode' is deprecated and may stop working in the future.

View file

@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/company/packages.el ;;; completion/company/packages.el
(package! company :pin "2ca3e29abf87392714bc2b26e50e1c0f4b9f4e2c") (package! company :pin "02903bd7088d65a87df0ae0f0d0a7118de147b69")
(package! company-dict :pin "cd7b8394f6014c57897f65d335d6b2bd65dab1f4") (package! company-dict :pin "cd7b8394f6014c57897f65d335d6b2bd65dab1f4")
(when (modulep! +childframe) (when (modulep! +childframe)
(package! company-box :pin "766546b2668b5ef4eb4abbde632c9acd370c7788")) (package! company-box :pin "b6f53e26adf948aca55c3ff6c22c21a6a6614253"))

View file

@ -0,0 +1,269 @@
#+title: :completion corfu
#+subtitle: Complete with cap(f), cape and a flying feather
#+created: September 9, 2022
#+since: 3.0.0 (#7002)
* Description :unfold:
This module provides code completion, powered by [[doom-package:corfu]].
It is recommended to enable either this or [[doom-module::completion company]] in
case you desire pre-configured auto-completion. Corfu is much lighter weight and
focused, plus it's built on native Emacs functionality, whereas Company is heavy
and highly non-native, but has some extra features and more maturity.
If you choose Corfu, we also highly recomend reading [[https://github.com/minad/corfu][its README]] and [[https://github.com/minad/cape][cape's
README]], as the backend is very configurable and provides many power-user
utilities for fine-tuning. Only some of common behaviors are documented here.
** Maintainers
- [[doom-user:][@LuigiPiucco]]
- [[doom-user:][@LemonBreezes]]
[[doom-contrib-maintainer:][Become a maintainer?]]
** Module flags
- +icons ::
Display icons beside completion suggestions.
- +orderless ::
Pull in [[doom-package:orderless]] if necessary and apply multi-component
completion (still needed if [[doom-module::completion vertico]] is active).
- +dabbrev ::
Enable and configure [[doom-package:dabbrev]] as a close-to-universal CAPF
fallback.
** Packages
- [[doom-package:corfu]]
- [[doom-package:cape]]
- [[doom-package:nerd-icons-corfu]] if [[doom-module::completion corfu +icons]]
- [[doom-package:orderless]] if [[doom-module::completion corfu +orderless]]
- [[doom-package:corfu-terminal]] if [[doom-module::os tty]]
- [[doom-package:yasnippet-capf]] if [[doom-module::editor snippets]]
** Hacks
/No hacks documented for this module./
** TODO Changelog
# This section will be machine generated. Don't edit it by hand.
/This module does not have a changelog yet./
* Installation
Enable this module in your ~doom!~ block.
This module has no direct requirements, but some languages may have their own
requirements to fulfill before you get code completion in them (and some
languages may lack code completion support altogether). Run ~$ doom doctor~ to
find out if you're missing any dependencies. Note that Corfu may have support
for completions in languages that have no development intelligence, since it
supports generic, context insensitive candidates such as file names or recurring
words. Snippets may also appear in the candidate list if available.
* TODO Usage
#+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote
By default, completion gets triggered after typing 2 non-space consecutive
characters, by means of [[kbd:][C-SPC]] at any moment or [[kbd:][TAB]] on a line with proper
indentation. Many styles of completion are documented below, which can be
composed to suit the user. The following keybindings are generally available:
| Keybind | Description |
|---------+--------------------------------------------|
| [[kbd:][C-n]] | Go to next candidate |
| [[kbd:][C-p]] | Go to previous candidate |
| [[kbd:][C-S-n]] | Go to next doc line |
| [[kbd:][C-S-p]] | Go to previous doc line |
| [[kbd:][C-S-s]] | Export to minibuffer |
| [[kbd:][TAB]] | (when not completing) Indent or complete |
| [[kbd:][C-SPC]] | (when not completing) Complete |
| [[kbd:][C-u]] | (evil) Go to next candidate page |
| [[kbd:][C-d]] | (evil) Go to previous candidate page |
| [[kbd:][C-h]] | (evil) Toggle documentation (if available) |
| [[kbd:][M-t]] | (emacs) (when not completing) Complete |
Bindings in the following sections are additive, and unless otherwise noted, are
enabled by default with configurable behavior. Additionally, for users of evil,
[[kdb:][C-SPC]] is smart regarding your state. In normal-like states, enter insert then
start corfu; in visual-like states, perform [[help:evil-change][evil-change]] (which leaves you in
insert state) then start corfu; in insert-like states, start corfu immediatelly.
** Commit preview on type
When the completion popup is visible, by default the current candidate is
previewed into the buffer, and further input commits that candidate as previewed
(note it does not perform candidate exit actions, such as expanding snippets).
The feature is in line with other common editors, but if you prefer the preview
to be only visual or for there to be no preview, configure
[[var:corfu-preview-current]].
#+begin_src emacs-lisp
;; Non-inserting preview
(setq corfu-preview-current t)
;; No preview
(setq corfu-preview-current nil)
#+end_src
** Commit on [[kbd:][RET]] with pass-through
A lot of people like to use [[kbd:][RET]] to commit, so here we bind it to Corfu's
insertion function. Note that Corfu allows "no candidate" to be selected, and in
that case, we have a custom binding to quit completion and pass-through. To make
it less obtrusive by default, the popup starts in this unselected state. See
[[var:corfu-preselect]] to alter the initial behavior; it can start with the first
one selected, for instance. Then, you have to move one candidate backwards to
pass-through The exact action of [[kbd:][RET]] can be changed via
[[var:+corfu-want-ret-to-confirm]].
| Keybind | Description |
|---------+-----------------------|
| [[kbd:][RET]] | Insert candidate DWIM |
** Cycle directionally
If you'd rather think in directions rather than next/previous, arrow keys and vi
movements to control the selection and documentation view are bound by default.
You may unbind them by setting to nil, see ~map!~'s documentation.
| Keybind | Description |
|----------+---------------------------------|
| [[kbd:][<down>]] | Go to next candidate |
| [[kbd:][<up>]] | Go to previous candidate |
| [[kbd:][C-j]] | (evil) Go to next candidate |
| [[kbd:][C-k]] | (evil) Go to previous candidate |
| [[kbd:][C-<down>]] | Go to next doc line |
| [[kbd:][C-<up>]] | Go to previous doc line |
| [[kbd:][C-S-j]] | (evil) Go to next doc line |
| [[kbd:][C-S-k]] | (evil) Go to previous doc line |
** Cycle with [[kbd:][TAB]]
[[kbd:][TAB]]-based cycling alternatives are also bound according to the table below:
| Keybind | Description |
|---------+--------------------------|
| [[kbd:][TAB]] | Go to next candidate |
| [[kbd:][S-TAB]] | Go to previous candidate |
** Searching with multiple keywords (~+orderless~)
If the [[doom-module::completion corfu +orderless]] flag is enabled, users can
perform code completion with multiple search keywords by use of space as the
separator. More information can be found [[https://github.com/oantolin/orderless#company][here]]. Pressing [[kdb:][C-SPC]] again while
completing inserts a space as separator. This allows searching with
space-separated terms; each piece will match individually and in any order, with
smart casing. Pressing just [[kbd:][SPC]] acts as normal and quits completion, so that
when typing sentences it doesn't try to complete the whole sentence instead of
just the word. Pressing [[kdb:][C-SPC]] with point after a separator escapes it with a
backslash, including the space in the search term, and pressing it with an
already escaped separator before point deletes it. Thus, you can cycle back if
you accidentaly press more than needed.
| Keybind | Description |
|---------+-------------------------------------------------|
| [[kbd:][C-SPC]] | (evil) (when completing) Insert separator DWIM |
| [[kbd:][M-SPC]] | (emacs) (when completing) Insert separator DWIM |
| [[kbd:][SPC]] | (when completing) Quit autocompletion |
| [[kbd:][SPC]] | (when completing with separators) Self-insert |
** Exporting to the minibuffer
The entries shown in the completion popup can be exported to a ~completing-read~
minibuffer, giving access to all the manipulations that suite allows. Using
Vertico for instance, one could use this to export with [[doom-package:embark]] via
[[kbd:][C-c C-l]] and get a buffer with all candidates.
* Configuration
A few variables may be set to change behavior of this module:
- [[var:completion-at-point-functions]] ::
This is not a module/package variable, but a builtin Emacs one. Even so, it's
very important to how Corfu works, so we document it here. It contains a list
of functions that are called in turn to generate completion candidates. The
regular (non-lexical) value should contain few entries and they should
generally be context aware, so as to predict what you need. Additional
functions can be added as you get into more and more specific contexts. Also,
there may be cases where you know beforehand the kind of candidate needed, and
want to enable only that one. For this, the variable may be lexically bound to
the correct value, or you may call the CAPF interactively if a single function
is all you need.
- [[var:corfu-auto-delay]] ::
Number of seconds till completion occurs automatically. Defaults to 0.1.
- [[var:corfu-auto-prefix]] ::
Number of characters till auto-completion starts to happen. Defaults to 2.
- [[var:corfu-on-exact-match]] ::
Configures behavior for exact matches.
- [[var:corfu-preselect]] ::
Configures startup selection, choosing between the first candidate or the
prompt.
- [[var:corfu-preview-current]] ::
Configures current candidate preview.
- [[var:+corfu-want-ret-to-confirm]] ::
Enables commiting with [[RET]] when the popup is visible. Default is ~t~, may be set to
~'minibuffer~ if you want to commit both the completion and the minibuffer when
active. When ~nil~, it is always passed-through.
- [[var:+corfu-buffer-scanning-size-limit]] ::
Sets the maximum buffer size to be scanned by ~cape-dabbrev~. Defaults to 1 MB.
Set this if you are having performance problems using the CAPF.
- [[var:+corfu-want-minibuffer-completion]] ::
Whether to enable Corfu in the minibuffer. See its documentation for
additional tweaks.
** Adding CAPFs to a mode
To add other CAPFs on a mode-per-mode basis, put either of the following in your
~config.el~:
#+begin_src emacs-lisp
(add-hook! some-mode (add-hook 'completion-at-point-functions #'some-capf depth t))
;; OR, but note the different call signature
(add-hook 'some-mode-hook (lambda () (add-hook 'completion-at-point-functions #'some-capf depth t)))
#+end_src
~DEPTH~ above is an integer between -100, 100, and defaults to 0 if nil. Also
see ~add-hook!~'s documentation for additional ways to call it. ~add-hook~ only
accepts the quoted arguments form above.
** Adding CAPFs to a key
To add other CAPFs to keys, adapt the snippet below into your ~config.el~:
#+begin_src emacs-lisp
(map! :map some-mode-map
"C-x e" #'cape-emoji)
#+end_src
It's okay to add to the mode directly because ~completion-at-point~ works
regardless of Corfu (the latter is an enhanced UI for the former). Just note not
all CAPFs are interactive to be called this way, in which case you can use
[[doom-package:cape]]'s adapter to enable this.
* Troubleshooting
[[doom-report:][Report an issue?]]
If you have performance issues with ~cape-dabbrev~, the first thing I recommend
doing is to look at the list of buffers Dabbrev is scanning:
#+begin_src emacs-lisp
(dabbrev--select-buffers) ; => (#<buffer README.org> #<buffer config.el<3>> #<buffer cape.el> ...)
(length (dabbrev--select-buffers)) ; => 37
#+end_src
... and modify ~dabbrev-ignored-buffer-regexps~ or ~dabbrev-ignored-buffer-modes~
accordingly.
If you see garbage completion candidates, you can use the following command to
debug the issue:
#+begin_src emacs-lisp
;;;###autoload
(defun search-in-dabbrev-buffers (search-string)
"Search for SEARCH-STRING in all buffers returned by `dabbrev--select-buffers'."
(interactive "sSearch string: ")
(let ((buffers (dabbrev--select-buffers)))
(multi-occur buffers search-string)))
;; Example usage:
;; Why are these weird characters appearing in my completions?
(search-in-dabbrev-buffers "\342\200\231")
#+end_src
* Frequently asked questions
/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]]
* TODO Appendix
#+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote

View file

@ -0,0 +1,39 @@
;;; completion/corfu/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +corfu-move-to-minibuffer ()
"Move the current list of candidates to your choice of minibuffer completion UI."
(interactive)
(pcase completion-in-region--data
(`(,beg ,end ,table ,pred ,extras)
(let ((completion-extra-properties extras)
completion-cycle-threshold completion-cycling)
(cond ((and (modulep! :completion vertico)
(fboundp #'consult-completion-in-region))
(consult-completion-in-region beg end table pred))
((and (modulep! :completion ivy)
(fboundp #'ivy-completion-in-region))
(ivy-completion-in-region (marker-position beg) (marker-position end) table pred))
;; Important: `completion-in-region-function' is set to corfu at
;; this moment, so `completion-in-region' (single -) doesn't work
;; below.
((modulep! :completion helm)
;; Helm is special and wants to _wrap_ `completion--in-region'
;; instead of replacing it in `completion-in-region-function'.
;; But because the advice is too unreliable we "fake" the wrapping.
(helm--completion-in-region #'completion--in-region beg end table pred))
((modulep! :completion ido)
(completion--in-region beg end table pred))
(t (error "No minibuffer completion UI available for moving to!")))))))
;;;###autoload
(defun +corfu-smart-sep-toggle-escape ()
"Insert `corfu-separator' or toggle escape if it's already there."
(interactive)
(cond ((and (char-equal (char-before) corfu-separator)
(char-equal (char-before (1- (point))) ?\\))
(save-excursion (delete-char -2)))
((char-equal (char-before) corfu-separator)
(save-excursion (backward-char 1)
(insert-char ?\\)))
(t (call-interactively #'corfu-insert-separator))))

View file

@ -0,0 +1,185 @@
;;; completion/corfu/config.el -*- lexical-binding: t; -*-
(defvar +corfu-want-ret-to-confirm t
"Configure how the user expects RET to behave.
Possible values are:
- t (default): Insert candidate if one is selected, pass-through otherwise;
- `minibuffer': Insert candidate if one is selected, pass-through otherwise,
and immediatelly exit if in the minibuffer;
- nil: Pass-through without inserting.")
(defvar +corfu-buffer-scanning-size-limit (* 1 1024 1024) ; 1 MB
"Size limit for a buffer to be scanned by `cape-dabbrev'.")
(defvar +corfu-want-minibuffer-completion t
"Whether to enable Corfu in the minibuffer.
Setting this to `aggressive' will enable Corfu in more commands which
use the minibuffer such as `query-replace'.")
;;
;;; Packages
(use-package! corfu
:hook (doom-first-input . global-corfu-mode)
:init
(add-hook! 'minibuffer-setup-hook
(defun +corfu-enable-in-minibuffer ()
"Enable Corfu in the minibuffer."
(when (pcase +corfu-want-minibuffer-completion
('aggressive
(not (or (bound-and-true-p mct--active)
(bound-and-true-p vertico--input)
(eq (current-local-map) read-passwd-map)
(and (featurep 'helm-core) (helm--alive-p))
(and (featurep 'ido) (ido-active))
(where-is-internal 'minibuffer-complete
(list (current-local-map)))
(memq #'ivy--queue-exhibit post-command-hook))))
('nil nil)
(_ (where-is-internal #'completion-at-point
(list (current-local-map)))))
(setq-local corfu-echo-delay nil)
(corfu-mode +1))))
:config
(setq corfu-auto t
corfu-auto-delay 0.18
corfu-auto-prefix 2
global-corfu-modes '((not
erc-mode
circe-mode
help-mode
gud-mode
vterm-mode)
t)
corfu-cycle t
corfu-preselect 'prompt
corfu-count 16
corfu-max-width 120
corfu-on-exact-match nil
corfu-quit-at-boundary (if (or (modulep! :completion vertico)
(modulep! +orderless))
'separator t)
corfu-quit-no-match corfu-quit-at-boundary
tab-always-indent 'complete)
(add-to-list 'completion-category-overrides `(lsp-capf (styles ,@completion-styles)))
(add-to-list 'corfu-auto-commands #'lispy-colon)
(add-to-list 'corfu-continue-commands #'+corfu-move-to-minibuffer)
(add-to-list 'corfu-continue-commands #'+corfu-smart-sep-toggle-escape)
(add-hook 'evil-insert-state-exit-hook #'corfu-quit)
;; If you want to update the visual hints after completing minibuffer commands
;; with Corfu and exiting, you have to do it manually.
(defadvice! +corfu--insert-before-exit-minibuffer-a ()
:before #'exit-minibuffer
(when (or (and (frame-live-p corfu--frame)
(frame-visible-p corfu--frame))
(and (featurep 'corfu-terminal)
(popon-live-p corfu-terminal--popon)))
(when (member isearch-lazy-highlight-timer timer-idle-list)
(apply (timer--function isearch-lazy-highlight-timer)
(timer--args isearch-lazy-highlight-timer)))
(when (member (bound-and-true-p anzu--update-timer) timer-idle-list)
(apply (timer--function anzu--update-timer)
(timer--args anzu--update-timer)))
(when (member (bound-and-true-p evil--ex-search-update-timer)
timer-idle-list)
(apply (timer--function evil--ex-search-update-timer)
(timer--args evil--ex-search-update-timer)))))
;; HACK: If your dictionaries aren't set up in text-mode buffers, ispell will
;; continuously pester you about errors. This ensures it only happens once
;; per session.
(defadvice! +corfu--auto-disable-ispell-capf-a (fn &rest args)
"If ispell isn't properly set up, only complain once per session."
:around #'ispell-completion-at-point
(condition-case-unless-debug e
(apply fn args)
('error
(message "Error: %s" (error-message-string e))
(message "Auto-disabling `text-mode-ispell-word-completion'")
(setq text-mode-ispell-word-completion nil)
(remove-hook 'completion-at-point-functions #'ispell-completion-at-point t)))))
(use-package! cape
:defer t
:init
(add-hook! prog-mode
(defun +corfu-add-cape-file-h ()
(add-hook 'completion-at-point-functions #'cape-file -10 t)))
(add-hook! (org-mode markdown-mode)
(defun +corfu-add-cape-elisp-block-h ()
(add-hook 'completion-at-point-functions #'cape-elisp-block 0 t)))
;; Enable Dabbrev completion basically everywhere as a fallback.
(when (modulep! +dabbrev)
(setq cape-dabbrev-check-other-buffers t)
;; Set up `cape-dabbrev' options.
(defun +dabbrev-friend-buffer-p (other-buffer)
(< (buffer-size other-buffer) +corfu-buffer-scanning-size-limit))
(add-hook! (prog-mode text-mode conf-mode comint-mode minibuffer-setup
eshell-mode)
(defun +corfu-add-cape-dabbrev-h ()
(add-hook 'completion-at-point-functions #'cape-dabbrev 20 t)))
(after! dabbrev
(setq dabbrev-friend-buffer-function #'+dabbrev-friend-buffer-p
dabbrev-ignored-buffer-regexps
'("^ "
"\\(TAGS\\|tags\\|ETAGS\\|etags\\|GTAGS\\|GRTAGS\\|GPATH\\)\\(<[0-9]+>\\)?")
dabbrev-upcase-means-case-search t)
(add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)))
;; Make these capfs composable.
(advice-add #'lsp-completion-at-point :around #'cape-wrap-noninterruptible)
(advice-add #'lsp-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'comint-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'eglot-completion-at-point :around #'cape-wrap-nonexclusive)
(advice-add #'pcomplete-completions-at-point :around #'cape-wrap-nonexclusive)
;; From the `cape' readme. Without this, Eshell autocompletion is broken on
;; Emacs28.
(when (< emacs-major-version 29)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)))
(use-package! yasnippet-capf
:when (modulep! :editor snippets)
:defer t
:init
(add-hook! 'yas-minor-mode-hook
(defun +corfu-add-yasnippet-capf-h ()
(add-hook 'completion-at-point-functions #'yasnippet-capf 30 t))))
(use-package! corfu-terminal
:when (modulep! :os tty)
:when (not (display-graphic-p))
:hook ((corfu-mode . corfu-terminal-mode)))
;;
;;; Extensions
(use-package! corfu-history
:hook ((corfu-mode . corfu-history-mode))
:config
(after! savehist (add-to-list 'savehist-additional-variables 'corfu-history)))
(use-package! corfu-popupinfo
:hook ((corfu-mode . corfu-popupinfo-mode))
:config
(setq corfu-popupinfo-delay '(0.5 . 1.0)))
(use-package! nerd-icons-corfu
:when (modulep! +icons)
:defer t
:init
(after! corfu
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)))
;; If vertico is not enabled, orderless will be installed but not configured.
;; That may break smart separator behavior, so we conditionally configure it.
(use-package! orderless
:when (and (not (modulep! :completion vertico))
(modulep! +orderless))
:config
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles orderless partial-completion)))
orderless-component-separator #'orderless-escapable-split-on-space)
(set-face-attribute 'completions-first-difference nil :inherit nil))

View file

@ -0,0 +1,17 @@
;; -*- no-byte-compile: t; -*-
;;; completion/corfu/packages.el
(package! corfu :pin "c1e7b6190b00158e67347b4db0a8f7964e5d2f8b")
(package! cape :pin "a397a0c92de38277b7f835fa999fac400a764908")
(when (modulep! +icons)
(package! nerd-icons-corfu :pin "7077bb76fefc15aed967476406a19dc5c2500b3c"))
(when (and (not (modulep! :completion vertico))
(modulep! +orderless))
;; enabling +orderless without vertico should be fairly niche enough that to
;; save contributor headaches we should only pin vertico's orderless and leave
;; this one unpinned
(package! orderless))
(when (modulep! :os tty)
(package! corfu-terminal :pin "501548c3d51f926c687e8cd838c5865ec45d03cc"))
(when (modulep! :editor snippets)
(package! yasnippet-capf :pin "9043f8275176a8f198ce8e81fadab1870fa165bb"))

View file

@ -22,7 +22,7 @@ For official documentation about Helm, see:
Enable fuzzy completion for Helm searches. Enable fuzzy completion for Helm searches.
- +icons :: - +icons ::
Display icons on completion results (where possible) using either Display icons on completion results (where possible) using either
[[doom-package:all-the-icons]] or [[doom-package:treemacs]] iconsets. [[doom-package:nerd-icons]] or [[doom-package:treemacs]] iconsets.
** Packages ** Packages
- [[doom-package:helm]] - [[doom-package:helm]]
@ -40,7 +40,7 @@ For official documentation about Helm, see:
** TODO Hacks ** TODO Hacks
#+begin_quote #+begin_quote
🔨 This module's hacks haven't been documented yet. [[doom-contrib-module:][Document them?]] 󱌣 This module's hacks haven't been documented yet. [[doom-contrib-module:][Document them?]]
#+end_quote #+end_quote
** TODO Changelog ** TODO Changelog
@ -74,18 +74,18 @@ its highlights will be covered here.
** Jump-to navigation ** Jump-to navigation
Similar to Ivy, this module provides an interface to navigate within a project Similar to Ivy, this module provides an interface to navigate within a project
using [[doom-package:projectile]]: using [[doom-package:projectile]]:
| Keybind | Description | | Keybind | Description |
|------------------+---------------------------------------------------------| |--------------------------------------+-------------------------------------------------------|
| [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Jump to file in project (~+helm/projectile-find-file~) | | [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Jump to file in project (~+helm/projectile-find-file~) |
| [[kbd:][SPC f f]], [[kbd:][SPC .]] | Jump to file from current directory (~helm-find-files~) | | [[kbd:][SPC f f]], [[kbd:][SPC .]] | Jump to file from current directory (~helm-find-files~) |
| [[kbd:][SPC s i]] | Jump to symbol in file (~helm-semantic-or-imenu~) | | [[kbd:][SPC s i]] | Jump to symbol in file (~helm-semantic-or-imenu~) |
** Project search & replace ** Project search & replace
This module also provides interactive text search and replace using [[https://github.com/BurntSushi/ripgrep][Ripgrep]]. This module also provides interactive text search and replace using [[https://github.com/BurntSushi/ripgrep][Ripgrep]].
*** Search *** Search
| Keybind | Description | | Keybind | Description |
|---------+-----------------------------------------------------------| |-------------------+---------------------------------------------------------|
| [[kbd:][SPC s p]] | Search project (~+default/search-project~) | | [[kbd:][SPC s p]] | Search project (~+default/search-project~) |
| [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) | | [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) |
| [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) | | [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) |
@ -96,8 +96,8 @@ otherwise) changes the behavior of these commands, instructing the underlying
search engine to include ignored files. search engine to include ignored files.
This module also provides Ex Commands for evil users: This module also provides Ex Commands for evil users:
| Ex command | Description | | Ex command | Description |
|------------------------+------------------------------------------------------------------| |----------------------+----------------------------------------------------------------|
| ~:pg[rep][!] [QUERY]~ | Search project (if ~!~, include hidden files) | | ~:pg[rep][!] [QUERY]~ | Search project (if ~!~, include hidden files) |
| ~:pg[rep]d[!] [QUERY]~ | Search from current directory (if ~!~, don't search recursively) | | ~:pg[rep]d[!] [QUERY]~ | Search from current directory (if ~!~, don't search recursively) |
@ -106,8 +106,8 @@ commands.
*** Replace *** Replace
These keybindings are available while a search is active: These keybindings are available while a search is active:
| Keybind | Description | | Keybind | Description |
|---------+-----------------------------------------------| |-------------------+-----------------------------------------------|
| [[kbd:][C-c C-o]] | Open a buffer with your search results | | [[kbd:][C-c C-o]] | Open a buffer with your search results |
| [[kbd:][C-c C-e]] | Open a writable buffer of your search results | | [[kbd:][C-c C-e]] | Open a writable buffer of your search results |
| [[kbd:][C-SPC]] | Preview the current candidate | | [[kbd:][C-SPC]] | Preview the current candidate |
@ -131,38 +131,38 @@ A [[doom-package:wgrep]] buffer can be opened from swiper with [[kbd:][C-c C-e]]
Helm also has a number of overrides for built-in functionality: Helm also has a number of overrides for built-in functionality:
*** General *** General
| Keybind | Description | | Keybind | Description |
|------------+---------------------------| |--------------------------------+---------------------------|
| [[kbd:][M-x]], [[kbd:][SPC :]] | Smarter, smex-powered M-x | | [[kbd:][M-x]], [[kbd:][SPC :]] | Smarter, smex-powered M-x |
| [[kbd:][SPC ']] | Resume last ivy session | | [[kbd:][SPC ']] | Resume last ivy session |
*** Jump to files, buffers or projects *** Jump to files, buffers or projects
| Keybind | Description | | Keybind | Description |
|---------+----------------------------------------------------------------------| |-------------------+--------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project | | [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[kbd:][SPC s b]] | Search the current buffer (~+default/search-buffer~) | | [[kbd:][SPC s b]] | Search the current buffer (~+default/search-buffer~) |
| [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) | | [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) |
| [[kbd:][SPC s D]] | Search another directory (~+default/search-other-cwd~) | | [[kbd:][SPC s D]] | Search another directory (~+default/search-other-cwd~) |
| [[kbd:][SPC s i]] | Search for symbol in current buffer | | [[kbd:][SPC s i]] | Search for symbol in current buffer |
| [[kbd:][SPC s p]] | Search project (~+default/search-project~) | | [[kbd:][SPC s p]] | Search project (~+default/search-project~) |
| [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) | | [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) |
| [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) | | [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) |
*** Search *** Search
| Keybind | Description | | Keybind | Description |
|---------+----------------------------------------------------------------------| |-------------------+--------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project | | [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[kbd:][SPC s b]] | Search the current buffer (~+default/search-buffer~) | | [[kbd:][SPC s b]] | Search the current buffer (~+default/search-buffer~) |
| [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) | | [[kbd:][SPC s d]] | Search this directory (~+default/search-cwd~) |
| [[kbd:][SPC s D]] | Search another directory (~+default/search-other-cwd~) | | [[kbd:][SPC s D]] | Search another directory (~+default/search-other-cwd~) |
| [[kbd:][SPC s i]] | Search for symbol in current buffer | | [[kbd:][SPC s i]] | Search for symbol in current buffer |
| [[kbd:][SPC s p]] | Search project (~+default/search-project~) | | [[kbd:][SPC s p]] | Search project (~+default/search-project~) |
| [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) | | [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) |
| [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) | | [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) |
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** helm-mode ** helm-mode
@ -182,9 +182,9 @@ makes sense to exempt ~foo~ with the following:
** Icons ** Icons
There are two icon "themes" available for this module: There are two icon "themes" available for this module:
[[doom-package:all-the-icons]] and [[doom-package:treemacs]]. By default, and to [[doom-package:nerd-icons]] and [[doom-package:treemacs]]. By default, and to
maintain consistency with other icons across Doom's modules, maintain consistency with other icons across Doom's modules,
[[doom-package:all-the-icons]] is used. To change this: [[doom-package:nerd-icons]] is used. To change this:
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; add to $DOOMDIR/config.el ;; add to $DOOMDIR/config.el
(after! helm (after! helm
@ -202,5 +202,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -148,7 +148,7 @@ Can be negative.")
(defvar helm-generic-files-map (make-sparse-keymap)) (defvar helm-generic-files-map (make-sparse-keymap))
(after! helm-locate (after! helm-locate
(when (and IS-MAC (when (and (featurep :system 'macos)
(null helm-locate-command) (null helm-locate-command)
(executable-find "mdfind")) (executable-find "mdfind"))
(setq helm-locate-command "mdfind -name %s")) (setq helm-locate-command "mdfind -name %s"))
@ -195,7 +195,4 @@ Can be negative.")
:when (modulep! +icons) :when (modulep! +icons)
:hook (helm-mode . helm-icons-enable) :hook (helm-mode . helm-icons-enable)
:init :init
(setq helm-icons-provider 'all-the-icons) (setq helm-icons-provider 'nerd-icons))
:config
(when (eq helm-icons-provider 'all-the-icons)
(setq helm-icons-mode->icon nil)))

View file

@ -0,0 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; completion/helm/doctor.el
(dolist (module '(ivy ido vertico))
(when (doom-module-p :completion module)
(error! "This module is incompatible with :completion %s; disable one or the other"
module)))

View file

@ -1,20 +1,20 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/helm/packages.el ;;; completion/helm/packages.el
(package! helm :pin "dfd6403947c5cd9f32afcd6bc92a1756cc958c82") (package! helm :pin "f34ea6b702648e5c7535a704bdb6c4d7afb4b3b8")
(package! helm-company :pin "6eb5c2d730a60e394e005b47c1db018697094dde") (package! helm-company :pin "4622b82353220ee6cc33468f710fa5b6b253b7f1")
(package! helm-c-yasnippet :pin "e214eec8b2875d8a7cd09006dfb6a8e15e9e4079") (package! helm-c-yasnippet :pin "c5880e740da101fde7a995e94a7b16c330e57583")
(package! helm-descbinds :pin "b72515982396b6e336ad7beb6767e95a80fca192") (package! helm-descbinds :pin "b72515982396b6e336ad7beb6767e95a80fca192")
(package! helm-describe-modes :pin "11fb36af119b784539d31c6160002de1957408aa") (package! helm-describe-modes :pin "11fb36af119b784539d31c6160002de1957408aa")
(package! helm-projectile :pin "35a2111d00c0c0c9d8743280d3f1243bb217118a") (package! helm-projectile :pin "e2e38825c975269a4971df25e79b2ae98929624e")
(package! helm-rg :pin "ee0a3c09da0c843715344919400ab0a0190cc9dc") (package! helm-rg :pin "ee0a3c09da0c843715344919400ab0a0190cc9dc")
(package! swiper-helm :pin "93fb6db87bc6a5967898b5fd3286954cc72a0008") (package! swiper-helm :pin "93fb6db87bc6a5967898b5fd3286954cc72a0008")
(when (modulep! +childframe) (when (modulep! +childframe)
(package! helm-posframe :pin "87461b52b6f3f378c63642a33f584d4a4ba28351")) (package! helm-posframe :pin "0b6bb016f0ff4980860a9d00574de311748c40b0"))
(when (modulep! +fuzzy) (when (modulep! +fuzzy)
(package! helm-flx :pin "5220099e695a3586dba2d59640217fe378e66310")) (package! helm-flx :pin "5220099e695a3586dba2d59640217fe378e66310"))
(when (modulep! +icons) (when (modulep! +icons)
(package! helm-icons :pin "8d2f5e705c8b78a390677cf242024739c932fc95")) (package! helm-icons :pin "0d113719ee72cb7b6bb7db29f7200d667bd86607"))
(when (modulep! :lang org) (when (modulep! :lang org)
(package! helm-org :pin "d67186d3a64e610c03a5f3d583488f018fb032e4")) (package! helm-org :pin "c80e53315ce6b096e2d0e630702df924bf00bf6a"))

View file

@ -33,12 +33,12 @@ Interactive DO things. The completion engine that is /mostly/ built-into Emacs.
* Usage * Usage
#+begin_quote #+begin_quote
🔨 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Configuration * Configuration
#+begin_quote #+begin_quote
🔨 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Troubleshooting * Troubleshooting
@ -52,5 +52,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* Appendix * Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -0,0 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; completion/ido/doctor.el
(dolist (module '(helm ivy vertico))
(when (doom-module-p :completion module)
(error! "This module is incompatible with :completion %s; disable one or the other"
module)))

View file

@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/ido/packages.el ;;; completion/ido/packages.el
(package! flx-ido :pin "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2") (package! flx-ido :pin "4b1346eb9a8a76ee9c9dede69738c63ad97ac5b6")
(package! ido-completing-read+ :pin "49e7967ea8c0ab0a206b40d70fc19be115083fa1") (package! ido-completing-read+ :pin "5995b4605b4f2d568489491704ef21bc49ddecd5")
(package! ido-sort-mtime :pin "f638ff0c922af862f5211779f2311a27fde428eb") (package! ido-sort-mtime :pin "f638ff0c922af862f5211779f2311a27fde428eb")
(package! ido-vertical-mode :pin "b1659e967da0687abceca733b389ace24004fa66") (package! ido-vertical-mode :pin "b1659e967da0687abceca733b389ace24004fa66")
(package! crm-custom :pin "f1aaccf64306a5f99d9bf7ba815d7ea41c15518d") (package! crm-custom :pin "f1aaccf64306a5f99d9bf7ba815d7ea41c15518d")

View file

@ -27,7 +27,7 @@ lighter, simpler and faster in many cases.
Enable prescient filtering and sorting for Ivy searches. Enable prescient filtering and sorting for Ivy searches.
** Packages ** Packages
- [[doom-package:all-the-icons-ivy]]* if [[doom-module:+icons]] - [[doom-package:nerd-icons-ivy]]* if [[doom-module:+icons]]
- [[doom-package:amx]] - [[doom-package:amx]]
- [[doom-package:counsel]] - [[doom-package:counsel]]
- [[doom-package:counsel-projectile]] - [[doom-package:counsel-projectile]]
@ -64,7 +64,7 @@ use their associated Helm command or plugin.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
[[doom-package:ivy]] is a /large/ framework for completing things. Covering all its features is [[doom-package:ivy]] is a /large/ framework for completing things. Covering all its features is
@ -169,14 +169,23 @@ A wgrep buffer can be opened from swiper with [[kbd:][C-c C-e]].
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
** TODO Enable fuzzy/non-fuzzy search for specific commands ** TODO Enable fuzzy/non-fuzzy search for specific commands
** TODO Change the position of the ivy childframe ** TODO Change the position of the ivy childframe
* TODO Troubleshooting * TODO Troubleshooting
/There are no known problems with this module./ [[doom-report:][Report one?]] ** Sorting is not applied at all sometimes
If the number of candidates is greater than ~ivy-sort-max-size~, sorting will be
disabled completely. Doom lowers the default value to prevent performance
issues, so increasing the value may fix your issue:
#+begin_src elisp
;;; add to $DOOMDIR/config.el
(after! ivy
(setq ivy-sort-max-size 30000)) ; Doom sets this to 7500, but Ivy's default is 30k
#+end_src
* Frequently asked questions * Frequently asked questions
[[doom-suggest-faq:][Ask a question?]] [[doom-suggest-faq:][Ask a question?]]
@ -186,5 +195,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -34,22 +34,6 @@ Buffers that are considered unreal (see `doom-real-buffer-p') are dimmed with
(ivy-append-face candidate 'ivy-modified-buffer)) (ivy-append-face candidate 'ivy-modified-buffer))
(candidate)))) (candidate))))
;;;###autoload
(defun +ivy-rich-buffer-icon (candidate)
"Display the icon for CANDIDATE buffer."
;; NOTE This is inspired by `all-the-icons-ivy-buffer-transformer', minus the
;; buffer name and extra padding as those are handled by `ivy-rich'.
(propertize "\t" 'display
(if-let* ((buffer (get-buffer candidate))
(mode (buffer-local-value 'major-mode buffer)))
(or
(all-the-icons-ivy--icon-for-mode mode)
(all-the-icons-ivy--icon-for-mode (get mode 'derived-mode-parent))
(funcall
all-the-icons-ivy-family-fallback-for-buffer
all-the-icons-ivy-name-fallback-for-buffer))
(all-the-icons-icon-for-file candidate))))
;;;###autoload ;;;###autoload
(defun +ivy-rich-describe-variable-transformer (cand) (defun +ivy-rich-describe-variable-transformer (cand)
"Previews the value of the variable in the minibuffer" "Previews the value of the variable in the minibuffer"

View file

@ -116,12 +116,6 @@ results buffer.")
:config :config
(setq ivy-rich-parse-remote-buffer nil) (setq ivy-rich-parse-remote-buffer nil)
(when (modulep! +icons)
(cl-pushnew '(+ivy-rich-buffer-icon)
(cadr (plist-get ivy-rich-display-transformers-list
'ivy-switch-buffer))
:test #'equal))
(defun ivy-rich-bookmark-filename-or-empty (candidate) (defun ivy-rich-bookmark-filename-or-empty (candidate)
(let ((filename (ivy-rich-bookmark-filename candidate))) (let ((filename (ivy-rich-bookmark-filename candidate)))
(if (not filename) "" filename))) (if (not filename) "" filename)))
@ -155,25 +149,16 @@ results buffer.")
(switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns)))) (switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns))))
(setcar switch-buffer-alist '+ivy-rich-buffer-name)) (setcar switch-buffer-alist '+ivy-rich-buffer-name))
(when (modulep! +icons)
(nerd-icons-ivy-rich-mode +1))
(ivy-rich-mode +1) (ivy-rich-mode +1)
(ivy-rich-project-root-cache-mode +1)) (ivy-rich-project-root-cache-mode +1))
(use-package! all-the-icons-ivy (use-package! nerd-icons-ivy-rich
:when (modulep! +icons) :when (modulep! +icons)
:after ivy :commands (nerd-icons-ivy-rich-mode)
:config :after counsel-projectile)
;; `all-the-icons-ivy' is incompatible with ivy-rich's switch-buffer
;; modifications, so we disable them and merge them ourselves
(setq all-the-icons-ivy-buffer-commands nil)
(all-the-icons-ivy-setup)
(after! counsel-projectile
(let ((all-the-icons-ivy-file-commands
'(counsel-projectile
counsel-projectile-find-file
counsel-projectile-find-dir)))
(all-the-icons-ivy-setup))))
(use-package! counsel (use-package! counsel
@ -237,7 +222,6 @@ results buffer.")
;; Record in jumplist when opening files via counsel-{ag,rg,pt,git-grep} ;; Record in jumplist when opening files via counsel-{ag,rg,pt,git-grep}
(add-hook 'counsel-grep-post-action-hook #'better-jumper-set-jump) (add-hook 'counsel-grep-post-action-hook #'better-jumper-set-jump)
(add-hook 'counsel-grep-post-action-hook #'recenter)
(ivy-add-actions (ivy-add-actions
'counsel-rg ; also applies to `counsel-rg' 'counsel-rg ; also applies to `counsel-rg'
'(("O" +ivy-git-grep-other-window-action "open in other window"))) '(("O" +ivy-git-grep-other-window-action "open in other window")))
@ -253,7 +237,7 @@ results buffer.")
(add-to-list 'ivy-sort-functions-alist '(counsel-imenu)) (add-to-list 'ivy-sort-functions-alist '(counsel-imenu))
;; `counsel-locate' ;; `counsel-locate'
(when IS-MAC (when (featurep :system 'macos)
;; Use spotlight on mac by default since it doesn't need any additional setup ;; Use spotlight on mac by default since it doesn't need any additional setup
(setq counsel-locate-cmd #'counsel-locate-cmd-mdfind)) (setq counsel-locate-cmd #'counsel-locate-cmd-mdfind))
@ -292,13 +276,13 @@ results buffer.")
(cl-loop for dir in projectile-globally-ignored-directories (cl-loop for dir in projectile-globally-ignored-directories
collect "--exclude" collect "--exclude"
collect dir) collect dir)
(if IS-WINDOWS '("--path-separator=/"))))) (if (featurep :system 'windows) '("--path-separator=/")))))
((executable-find "rg" t) ((executable-find "rg" t)
(append (list "rg" "--hidden" "--files" "--follow" "--color=never" "--no-messages") (append (list "rg" "--hidden" "--files" "--follow" "--color=never" "--no-messages")
(cl-loop for dir in projectile-globally-ignored-directories (cl-loop for dir in projectile-globally-ignored-directories
collect "--glob" collect "--glob"
collect (concat "!" dir)) collect (concat "!" dir))
(if IS-WINDOWS '("--path-separator=/")))) (if (featurep :system 'windows) '("--path-separator=/"))))
((cons find-program args))) ((cons find-program args)))
(unless (listp args) (unless (listp args)
(user-error "`counsel-file-jump-args' is a list now, please customize accordingly.")) (user-error "`counsel-file-jump-args' is a list now, please customize accordingly."))
@ -315,7 +299,7 @@ results buffer.")
(use-package! counsel-projectile (use-package! counsel-projectile
:defer t :after ivy-rich
:init :init
(define-key! (define-key!
[remap projectile-find-file] #'+ivy/projectile-find-file [remap projectile-find-file] #'+ivy/projectile-find-file

View file

@ -1,3 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*- ;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; completion/ivy/doctor.el ;;; completion/ivy/doctor.el
(dolist (module '(helm ido vertico))
(when (doom-module-p :completion module)
(error! "This module is incompatible with :completion %s; disable one or the other"
module)))

View file

@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/ivy/packages.el ;;; completion/ivy/packages.el
(package! swiper :pin "9d630d800e856a2c984c5a62a6f0ad313a9d2228") (package! swiper :pin "8c30f4cab5948aa8d942a3b2bbf5fb6a94d9441d")
(package! ivy) (package! ivy)
(package! ivy-hydra) (package! ivy-hydra)
(package! ivy-avy) (package! ivy-avy)
@ -10,15 +10,15 @@
(package! amx :pin "5b3aa1aae84f4a225cb8d26ab79a32f97693f023") (package! amx :pin "5b3aa1aae84f4a225cb8d26ab79a32f97693f023")
(package! counsel-projectile :pin "40d1e1d4bb70acb00fddd6f4df9778bf2c52734b") (package! counsel-projectile :pin "40d1e1d4bb70acb00fddd6f4df9778bf2c52734b")
(package! ivy-rich :pin "aff9b6bd53e0fdcf350ab83c90e64e651b47dba4") (package! ivy-rich :pin "aff9b6bd53e0fdcf350ab83c90e64e651b47dba4")
(package! wgrep :pin "3132abd3750b8c87cbcf6942db952acfab5edccd") (package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4")
(if (modulep! +prescient) (if (modulep! +prescient)
(package! ivy-prescient :pin "d7cc55dad453c465af9ececbab94426202b5b32b") (package! ivy-prescient :pin "4b875be52e75f7b81e68a16b62cfbb2f2584042c")
(when (modulep! +fuzzy) (when (modulep! +fuzzy)
(package! flx :pin "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2"))) (package! flx :pin "4b1346eb9a8a76ee9c9dede69738c63ad97ac5b6")))
(when (modulep! +childframe) (when (modulep! +childframe)
(package! ivy-posframe :pin "533a8e368fcabfd534761a5c685ce713376fa594")) (package! ivy-posframe :pin "533a8e368fcabfd534761a5c685ce713376fa594"))
(when (modulep! +icons) (when (modulep! +icons)
(package! all-the-icons-ivy :pin "a70cbfa1effe36efc946a823a580cec686d5e88d")) (package! nerd-icons-ivy-rich :pin "7197614b27fd562e64b11c91d41bed4443aded90"))

View file

@ -31,7 +31,7 @@ like [[doom-package:ivy]] and [[doom-package:helm]] do. The primary packages are
Add icons to =file= and =buffer= category completion selections. Add icons to =file= and =buffer= category completion selections.
** Packages ** Packages
- [[doom-package:all-the-icons-completion]] if [[doom-module:+icons]] - [[doom-package:nerd-icons-completion]] if [[doom-module:+icons]]
- [[doom-package:consult]] - [[doom-package:consult]]
- [[doom-package:consult-flycheck]] if [[doom-module::checkers syntax]] - [[doom-package:consult-flycheck]] if [[doom-module::checkers syntax]]
- [[doom-package:embark]] - [[doom-package:embark]]
@ -63,7 +63,7 @@ intend to use their associated Helm command or plugin.
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
The packages in this module modify and use the built-in ~completing-read~ The packages in this module modify and use the built-in ~completing-read~
@ -76,16 +76,16 @@ Doom-specific additions:
When in an active Vertico completion session, the following doom added When in an active Vertico completion session, the following doom added
keybindings are available: keybindings are available:
| Keybind | Description | | Keybind | Description |
|-------------------+----------------------------------------------------------------| |---------------------------------------+--------------------------------------------------------------|
| [[kbd:][C-k]] | (evil) Go to previous candidate | | [[kbd:][C-k]] | (evil) Go to previous candidate |
| [[kbd:][C-j]] | (evil) Go to next candidate | | [[kbd:][C-j]] | (evil) Go to next candidate |
| [[kbd:][C-M-k]] | (evil) Go to previous group | | [[kbd:][C-M-k]] | (evil) Go to previous group |
| [[kbd:][C-M-j]] | (evil) Go to next group | | [[kbd:][C-M-j]] | (evil) Go to next group |
| [[kbd:][C-;]] or [[kbd:][<leader> a]] | Open an ~embark-act~ menu to chose a useful action | | [[kbd:][C-;]] or [[kbd:][<leader> a]] | Open an ~embark-act~ menu to chose a useful action |
| [[kbd:][C-c C-;]] | export the current candidate list to a buffer | | [[kbd:][C-c C-;]] | export the current candidate list to a buffer |
| [[kbd:][C-c C-l]] | ~embark-collect~ the current candidate list (collect verbatim) | | [[kbd:][C-c C-l]] | ~embark-collect~ the current candidate list (collect verbatim) |
| [[kbd:][C-SPC]] | Preview the current candidate | | [[kbd:][C-SPC]] | Preview the current candidate |
~embark-act~ will prompt you with a =which-key= menu with useful commands on the ~embark-act~ will prompt you with a =which-key= menu with useful commands on the
selected candidate or candidate list, depending on the completion category. Note selected candidate or candidate list, depending on the completion category. Note
@ -99,17 +99,17 @@ This module provides an interface to navigate within a project using
https://assets.doomemacs.org/completion/vertico/projectile.png https://assets.doomemacs.org/completion/vertico/projectile.png
| Keybind | Description | | Keybind | Description |
|------------------+-------------------------------------| |--------------------------------------+-------------------------------------|
| [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Jump to file in project | | [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Jump to file in project |
| [[kbd:][SPC f f]], [[kbd:][SPC .]] | Jump to file from current directory | | [[kbd:][SPC f f]], [[kbd:][SPC .]] | Jump to file from current directory |
| [[kbd:][SPC s i]] | Jump to symbol in file | | [[kbd:][SPC s i]] | Jump to symbol in file |
** Project search & replace ** Project search & replace
This module provides interactive text search and replace using ripgrep. This module provides interactive text search and replace using ripgrep.
| Keybind | Description | | Keybind | Description |
|---------+--------------------------| |------------------------+--------------------------|
| [[kbd:][<leader> s p]] | Search project | | [[kbd:][<leader> s p]] | Search project |
| [[kbd:][<leader> s P]] | Search another project | | [[kbd:][<leader> s P]] | Search another project |
| [[kbd:][<leader> s d]] | Search this directory | | [[kbd:][<leader> s d]] | Search this directory |
@ -153,19 +153,19 @@ An ~occur-edit~ buffer can be opened from ~consult-line~ with [[kbd:][C-c C-e]].
** Vertico integration for various completing commands ** Vertico integration for various completing commands
*** General *** General
| Keybind | Description | | Keybind | Description |
|------------+-----------------------------| |--------------------------------+-----------------------------|
| [[kbd:][M-x]], [[kbd:][SPC :]] | Enhanced M-x | | [[kbd:][M-x]], [[kbd:][SPC :]] | Enhanced M-x |
| [[kbd:][SPC ']] | Resume last Vertico session | | [[kbd:][SPC ']] | Resume last Vertico session |
*** Jump to files, buffers or projects *** Jump to files, buffers or projects
| Keybind | Description | | Keybind | Description |
|------------------+---------------------------------------| |--------------------------------------+---------------------------------------|
| [[kbd:][SPC RET]] | Find bookmark | | [[kbd:][SPC RET]] | Find bookmark |
| [[kbd:][SPC f f]], [[kbd:][SPC .]] | Browse from current directory | | [[kbd:][SPC f f]], [[kbd:][SPC .]] | Browse from current directory |
| [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Find file in project | | [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Find file in project |
| [[kbd:][SPC f r]] | Find recently opened file | | [[kbd:][SPC f r]] | Find recently opened file |
| [[kbd:][SPC p p]] | Open another project | | [[kbd:][SPC p p]] | Open another project |
| [[kbd:][SPC b b]], [[kbd:][SPC ,]] | Switch to buffer in current workspace | | [[kbd:][SPC b b]], [[kbd:][SPC ,]] | Switch to buffer in current workspace |
| [[kbd:][SPC b B]], [[kbd:][SPC <]] | Switch to buffer | | [[kbd:][SPC b B]], [[kbd:][SPC <]] | Switch to buffer |
@ -177,8 +177,8 @@ the last workspace by typing [[kbd:][0 SPC]].
[[kbd:][SPC f f]] and [[kbd:][SPC .]] support exporting to a [[kbd:][wdired]] buffer using [[kbd:][C-c C-e]]. [[kbd:][SPC f f]] and [[kbd:][SPC .]] support exporting to a [[kbd:][wdired]] buffer using [[kbd:][C-c C-e]].
*** Search *** Search
| Keybind | Description | | Keybind | Description |
|---------+-------------------------------------------| |-------------------+-------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project | | [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[kbd:][SPC s b]] | Search the current buffer | | [[kbd:][SPC s b]] | Search the current buffer |
| [[kbd:][SPC s d]] | Search this directory | | [[kbd:][SPC s d]] | Search this directory |
@ -200,10 +200,10 @@ to =~/=.
*** Multiple candidate search *** Multiple candidate search
This module modifies the default keybindings used in This module modifies the default keybindings used in
~consult-completing-read-multiple~: ~consult-completing-read-multiple~:
| Keybind | Description | | Keybind | Description |
|---------+-------------------------------------------------------------| |---------------+-------------------------------------------------------------|
| [[kbd:][TAB]] | Select or deselect current candidate | | [[kbd:][TAB]] | Select or deselect current candidate |
| [[kbd:][RET]] | Enters selected candidates (also toggles current candidate) | | [[kbd:][RET]] | Enters selected candidates (also toggles current candidate) |
*** Async search commands *** Async search commands
:PROPERTIES: :PROPERTIES:
@ -226,9 +226,9 @@ filtering should be done after a second =#=.
For more information [[https://github.com/minad/consult#asynchronous-search][see here]]. For more information [[https://github.com/minad/consult#asynchronous-search][see here]].
** Marginalia ** Marginalia
| Keybind | Description | | Keybind | Description |
|---------+---------------------------------| |---------------+---------------------------------|
| [[kbd:][M-A]] | Cycle between annotation levels | | [[kbd:][M-A]] | Cycle between annotation levels |
Marginalia annotations for symbols (e.g. [[kbd:][SPC h f]] and [[kbd:][SPC h v]]) come with extra Marginalia annotations for symbols (e.g. [[kbd:][SPC h f]] and [[kbd:][SPC h v]]) come with extra
information the nature of the symbol. For the meaning of the annotations see information the nature of the symbol. For the meaning of the annotations see
@ -260,7 +260,7 @@ you can use to further specify each space separated input in the following ways:
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 󱌣 /This module's configuration documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote #+end_quote
If you want to further configure this module, here are some good places to If you want to further configure this module, here are some good places to
@ -302,5 +302,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]
#+end_quote #+end_quote

View file

@ -13,7 +13,9 @@
:in PATH :in PATH
Sets what directory to base the search out of. Defaults to the current project's root. Sets what directory to base the search out of. Defaults to the current project's root.
:recursive BOOL :recursive BOOL
Whether or not to search files recursively from the base directory." Whether or not to search files recursively from the base directory.
:args LIST
Arguments to be appended to `consult-ripgrep-args'."
(declare (indent defun)) (declare (indent defun))
(unless (executable-find "rg") (unless (executable-find "rg")
(user-error "Couldn't find ripgrep in your PATH")) (user-error "Couldn't find ripgrep in your PATH"))
@ -29,7 +31,7 @@
"--path-separator / --smart-case --no-heading " "--path-separator / --smart-case --no-heading "
"--with-filename --line-number --search-zip " "--with-filename --line-number --search-zip "
"--hidden -g !.git -g !.svn -g !.hg " "--hidden -g !.git -g !.svn -g !.hg "
(mapconcat #'shell-quote-argument args " "))) (mapconcat #'identity args " ")))
(prompt (if (stringp prompt) (string-trim prompt) "Search")) (prompt (if (stringp prompt) (string-trim prompt) "Search"))
(query (or query (query (or query
(when (doom-region-active-p) (when (doom-region-active-p)
@ -135,26 +137,6 @@ Supports exporting consult-grep to wgrep, file to wdeired, and consult-location
(+vertico/embark-preview) (+vertico/embark-preview)
(user-error (vertico-directory-enter))))) (user-error (vertico-directory-enter)))))
(defvar +vertico/find-file-in--history nil)
;;;###autoload
(defun +vertico/find-file-in (&optional dir initial)
"Jump to file under DIR (recursive).
If INITIAL is non-nil, use as initial input."
(interactive)
(require 'consult)
(let* ((default-directory (or dir default-directory))
(prompt-dir (consult--directory-prompt "Find" default-directory))
(cmd (split-string-and-unquote +vertico-consult-fd-args " ")))
(find-file
(consult--read
(split-string (cdr (apply #'doom-call-process cmd)) "\n" t)
:prompt default-directory
:sort nil
:initial (if initial (shell-quote-argument initial))
:add-history (thing-at-point 'filename)
:category 'file
:history '(:input +vertico/find-file-in--history)))))
;;;###autoload ;;;###autoload
(defun +vertico/jump-list (jump) (defun +vertico/jump-list (jump)
"Go to an entry in evil's (or better-jumper's) jumplist." "Go to an entry in evil's (or better-jumper's) jumplist."
@ -227,27 +209,23 @@ targets."
(not (string-suffix-p "-argument" (cdr binding)))))))) (not (string-suffix-p "-argument" (cdr binding))))))))
;;;###autoload ;;;###autoload
(defun +vertico--consult--fd-make-builder () (defun +vertico/consult-fd-or-find (&optional dir initial)
(let ((cmd (split-string-and-unquote +vertico-consult-fd-args))) "Runs consult-fd if fd version > 8.6.0 exists, consult-find otherwise.
(lambda (input) See URL `https://github.com/minad/consult/issues/770'."
(pcase-let* ((`(,arg . ,opts) (consult--command-split input))
(`(,re . ,hl) (funcall consult--regexp-compiler
arg 'extended t)))
(when re
(cons (append cmd
(list (consult--join-regexps re 'extended))
opts)
hl))))))
(autoload #'consult--directory-prompt "consult")
;;;###autoload
(defun +vertico/consult-fd (&optional dir initial)
(interactive "P") (interactive "P")
(if doom-projectile-fd-binary ;; TODO this condition was adapted from a similar one in lisp/doom-projects.el, to be replaced with a more robust check post v3
(pcase-let* ((`(,prompt ,paths ,dir) (consult--directory-prompt "Fd" dir)) (if (when-let*
(default-directory dir) ((bin (if (ignore-errors (file-remote-p default-directory nil t))
(builder (consult--find-make-builder paths))) (cl-find-if (doom-rpartial #'executable-find t)
(find-file (consult--find prompt builder initial))) (list "fdfind" "fd"))
doom-projectile-fd-binary))
(version (with-memoization doom-projects--fd-version
(cadr (split-string (cdr (doom-call-process bin "--version"))
" " t))))
((ignore-errors (version-to-list version))))
;; TODO remove once fd 8.6.0 is widespread enough to be the minimum version for doom
(version< "8.6.0" version))
(consult-fd dir initial)
(consult-find dir initial))) (consult-find dir initial)))
;;;###autoload ;;;###autoload

View file

@ -86,8 +86,8 @@ buffer will be opened in the current workspace instead."
(funcall consult--buffer-display (car buffer))))))) (funcall consult--buffer-display (car buffer)))))))
;;;###autoload ;;;###autoload
(defun +vertico/embark-open-in-new-workspace (x) (defun +vertico/embark-open-in-new-workspace (file)
"Open X (a file) in a new workspace." "Open file in a new workspace."
(interactive) (interactive "GFile:")
(+workspace/new) (+workspace/new)
(find-file x)) (find-file file))

View file

@ -7,8 +7,11 @@ The completion/vertico module uses the orderless completion style by default,
but this returns too broad a candidate set for company completion. This variable but this returns too broad a candidate set for company completion. This variable
overrides `completion-styles' during company completion sessions.") overrides `completion-styles' during company completion sessions.")
(defvar +vertico-consult-fd-args nil (defvar +vertico-consult-dir-container-executable "docker"
"Shell command and arguments the vertico module uses for fd.") "Command to call for listing container hosts.")
(defvar +vertico-consult-dir-container-args nil
"Command to call for listing container hosts.")
;; ;;
;;; Packages ;;; Packages
@ -80,6 +83,9 @@ orderless."
((string= "!" pattern) `(orderless-literal . "")) ((string= "!" pattern) `(orderless-literal . ""))
;; Without literal ;; Without literal
((string-prefix-p "!" pattern) `(orderless-without-literal . ,(substring pattern 1))) ((string-prefix-p "!" pattern) `(orderless-without-literal . ,(substring pattern 1)))
;; Annotation
((string-prefix-p "&" pattern) `(orderless-annotation . ,(substring pattern 1)))
((string-suffix-p "&" pattern) `(orderless-annotation . ,(substring pattern 0 -1)))
;; Character folding ;; Character folding
((string-prefix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 1))) ((string-prefix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 1)))
((string-suffix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 0 -1))) ((string-suffix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 0 -1)))
@ -104,7 +110,7 @@ orderless."
;; find-file etc. ;; find-file etc.
completion-category-overrides '((file (styles +vertico-basic-remote orderless partial-completion))) completion-category-overrides '((file (styles +vertico-basic-remote orderless partial-completion)))
orderless-style-dispatchers '(+vertico-orderless-dispatch) orderless-style-dispatchers '(+vertico-orderless-dispatch)
orderless-component-separator "[ &]") orderless-component-separator #'orderless-escapable-split-on-space)
;; ...otherwise find-file gets different highlighting than other commands ;; ...otherwise find-file gets different highlighting than other commands
(set-face-attribute 'completions-first-difference nil :inherit nil)) (set-face-attribute 'completions-first-difference nil :inherit nil))
@ -130,25 +136,26 @@ orderless."
[remap yank-pop] #'consult-yank-pop [remap yank-pop] #'consult-yank-pop
[remap persp-switch-to-buffer] #'+vertico/switch-workspace-buffer) [remap persp-switch-to-buffer] #'+vertico/switch-workspace-buffer)
:config :config
(defadvice! +vertico--consult-recent-file-a (&rest _args) (defadvice! +vertico--consult-recentf-a (&rest _args)
"`consult-recent-file' needs to have `recentf-mode' on to work correctly" "`consult-recent-file' needs to have `recentf-mode' on to work correctly.
:before #'consult-recent-file `consult-buffer' needs `recentf-mode' to show file candidates."
:before (list #'consult-recent-file #'consult-buffer)
(recentf-mode +1)) (recentf-mode +1))
(setq consult-project-root-function #'doom-project-root (setq consult-project-function #'doom-project-root
consult-narrow-key "<" consult-narrow-key "<"
consult-line-numbers-widen t consult-line-numbers-widen t
consult-async-min-input 2 consult-async-min-input 2
consult-async-refresh-delay 0.15 consult-async-refresh-delay 0.15
consult-async-input-throttle 0.2 consult-async-input-throttle 0.2
consult-async-input-debounce 0.1) consult-async-input-debounce 0.1
(unless +vertico-consult-fd-args consult-fd-args
(setq +vertico-consult-fd-args '((if (executable-find "fdfind" 'remote) "fdfind" "fd")
(if doom-projectile-fd-binary "--color=never"
(format "%s --color=never -i -H -E .git --regex %s" ;; https://github.com/sharkdp/fd/issues/839
doom-projectile-fd-binary "--full-path --absolute-path"
(if IS-WINDOWS "--path-separator=/" "")) "--hidden --exclude .git"
consult-find-args))) (if (featurep :system 'windows) "--path-separator=/")))
(consult-customize (consult-customize
consult-ripgrep consult-git-grep consult-grep consult-ripgrep consult-git-grep consult-grep
@ -191,28 +198,42 @@ orderless."
(use-package! consult-dir (use-package! consult-dir
:bind (([remap list-directory] . consult-dir) :defer t
:init
(map! [remap list-directory] #'consult-dir
(:after vertico
:map vertico-map :map vertico-map
("C-x C-d" . consult-dir) "C-x C-d" #'consult-dir
("C-x C-j" . consult-dir-jump-file)) "C-x C-j" #'consult-dir-jump-file))
:config :config
(when (modulep! :tools docker) (when (modulep! :tools docker)
;; TODO: Replace with `tramp-container--completion-function' when we drop
;; support for <29
(defun +vertico--consult-dir-container-hosts (host)
"Get a list of hosts from HOST."
(cl-loop for line in (cdr
(ignore-errors
(apply #'process-lines +vertico-consult-dir-container-executable
(append +vertico-consult-dir-container-args (list "ps")))))
for cand = (split-string line "[[:space:]]+" t)
collect (format "/%s:%s:/" host (car (last cand)))))
(defun +vertico--consult-dir-podman-hosts ()
(let ((+vertico-consult-dir-container-executable "podman"))
(+vertico--consult-dir-container-hosts "podman")))
(defun +vertico--consult-dir-docker-hosts () (defun +vertico--consult-dir-docker-hosts ()
"Get a list of hosts from docker." (let ((+vertico-consult-dir-container-executable "docker"))
(when (if (>= emacs-major-version 29) (+vertico--consult-dir-container-hosts "docker")))
(require 'tramp-container nil t)
(setq-local docker-tramp-use-names t) (defvar +vertico--consult-dir-source-tramp-podman
(require 'docker-tramp nil t)) `(:name "Podman"
(let ((hosts) :narrow ?p
(docker-query-fn #'docker-tramp--parse-running-containers)) :category file
(when (>= emacs-major-version 29) :face consult-file
(setq docker-query-fn #'tramp-docker--completion-function)) :history file-name-history
(dolist (cand (funcall docker-query-fn)) :items ,#'+vertico--consult-dir-podman-hosts)
(let ((user (unless (string-empty-p (car cand)) "Podman candidate source for `consult-dir'.")
(concat (car cand) "@")))
(host (car (cdr cand))))
(push (concat "/docker:" user host ":/") hosts)))
hosts)))
(defvar +vertico--consult-dir-source-tramp-docker (defvar +vertico--consult-dir-source-tramp-docker
`(:name "Docker" `(:name "Docker"
@ -221,8 +242,9 @@ orderless."
:face consult-file :face consult-file
:history file-name-history :history file-name-history
:items ,#'+vertico--consult-dir-docker-hosts) :items ,#'+vertico--consult-dir-docker-hosts)
"Docker candiadate source for `consult-dir'.") "Docker candidate source for `consult-dir'.")
(add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-podman t)
(add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-docker t)) (add-to-list 'consult-dir-sources '+vertico--consult-dir-source-tramp-docker t))
(add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t) (add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t)
@ -233,6 +255,11 @@ orderless."
(not (modulep! :checkers syntax +flymake))) (not (modulep! :checkers syntax +flymake)))
:after (consult flycheck)) :after (consult flycheck))
(use-package! consult-yasnippet
:when (modulep! :editor snippets)
:defer t
:init (map! [remap yas-insert-snippet] #'consult-yasnippet))
(use-package! embark (use-package! embark
:defer t :defer t
@ -253,14 +280,16 @@ orderless."
(set-popup-rule! "^\\*Embark Export:" :size 0.35 :ttl 0 :quit nil) (set-popup-rule! "^\\*Embark Export:" :size 0.35 :ttl 0 :quit nil)
(defadvice! +vertico--embark-which-key-prompt-a (fn &rest args) (after! which-key
"Hide the which-key indicator immediately when using the completing-read prompter." (defadvice! +vertico--embark-which-key-prompt-a (fn &rest args)
:around #'embark-completing-read-prompter "Hide the which-key indicator immediately when using the completing-read prompter."
(which-key--hide-popup-ignore-command) :around #'embark-completing-read-prompter
(let ((embark-indicators (which-key--hide-popup-ignore-command)
(remq #'embark-which-key-indicator embark-indicators))) (let ((embark-indicators
(apply fn args))) (remq #'embark-which-key-indicator embark-indicators)))
(cl-nsubstitute #'+vertico-embark-which-key-indicator #'embark-mixed-indicator embark-indicators) (apply fn args)))
(cl-nsubstitute #'+vertico-embark-which-key-indicator #'embark-mixed-indicator embark-indicators))
;; add the package! target finder before the file target finder, ;; add the package! target finder before the file target finder,
;; so we don't get a false positive match. ;; so we don't get a false positive match.
(let ((pos (or (cl-position (let ((pos (or (cl-position
@ -282,9 +311,10 @@ orderless."
(map! (:map embark-file-map (map! (:map embark-file-map
:desc "Open target with sudo" "s" #'doom/sudo-find-file :desc "Open target with sudo" "s" #'doom/sudo-find-file
(:when (modulep! :tools magit) (:when (modulep! :tools magit)
:desc "Open magit-status of target" "g" #'+vertico/embark-magit-status) :desc "Open magit-status of target" "g" #'+vertico/embark-magit-status)
(:when (modulep! :ui workspaces) (:when (modulep! :ui workspaces)
:desc "Open in new workspace" "TAB" #'+vertico/embark-open-in-new-workspace)))) :desc "Open in new workspace" "TAB" #'+vertico/embark-open-in-new-workspace
:desc "Open in new workspace" "<tab>" #'+vertico/embark-open-in-new-workspace))))
(use-package! marginalia (use-package! marginalia
@ -294,7 +324,7 @@ orderless."
:desc "Cycle marginalia views" "M-A" #'marginalia-cycle) :desc "Cycle marginalia views" "M-A" #'marginalia-cycle)
:config :config
(when (modulep! +icons) (when (modulep! +icons)
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)) (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
(advice-add #'marginalia--project-root :override #'doom-project-root) (advice-add #'marginalia--project-root :override #'doom-project-root)
(pushnew! marginalia-command-categories (pushnew! marginalia-command-categories
'(+default/find-file-under-here . file) '(+default/find-file-under-here . file)
@ -320,3 +350,44 @@ orderless."
:hook (vertico-mode . vertico-posframe-mode) :hook (vertico-mode . vertico-posframe-mode)
:config :config
(add-hook 'doom-after-reload-hook #'posframe-delete-all)) (add-hook 'doom-after-reload-hook #'posframe-delete-all))
;; From https://github.com/minad/vertico/wiki#candidate-display-transformations-custom-candidate-highlighting
;;
;; Uses `add-face-text-property' instead of `propertize' unlike the above snippet
;; because `'append' is necessary to not override the match font lock
;; See: https://github.com/minad/vertico/issues/389
(use-package! vertico-multiform
:hook (vertico-mode . vertico-multiform-mode)
:config
(defvar +vertico-transform-functions nil)
(cl-defmethod vertico--format-candidate :around
(cand prefix suffix index start &context ((not +vertico-transform-functions) null))
(dolist (fun (ensure-list +vertico-transform-functions))
(setq cand (funcall fun cand)))
(cl-call-next-method cand prefix suffix index start))
(defun +vertico-highlight-directory (file)
"If FILE ends with a slash, highlight it as a directory."
(when (string-suffix-p "/" file)
(add-face-text-property 0 (length file) 'marginalia-file-priv-dir 'append file))
file)
(defun +vertico-highlight-enabled-mode (cmd)
"If MODE is enabled, highlight it as font-lock-constant-face."
(let ((sym (intern cmd)))
(with-current-buffer (nth 1 (buffer-list))
(if (or (eq sym major-mode)
(and
(memq sym minor-mode-list)
(boundp sym)
(symbol-value sym)))
(add-face-text-property 0 (length cmd) 'font-lock-constant-face 'append cmd)))
cmd))
(add-to-list 'vertico-multiform-categories
'(file
(+vertico-transform-functions . +vertico-highlight-directory)))
(add-to-list 'vertico-multiform-commands
'(execute-extended-command
(+vertico-transform-functions . +vertico-highlight-enabled-mode))))

View file

@ -1,4 +1,10 @@
;;; completion/vertico/doctor.el -*- lexical-binding: t; -*- ;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; completion/vertico/doctor.el
(dolist (module '(ivy helm ido))
(when (doom-module-p :completion module)
(error! "This module is incompatible with :completion %s; disable one or the other"
module)))
(when (require 'consult nil t) (when (require 'consult nil t)
;; FIXME: This throws an error if grep is missing. ;; FIXME: This throws an error if grep is missing.

View file

@ -1,29 +1,29 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/vertico/packages.el ;;; completion/vertico/packages.el
(package! vertico (package! vertico :pin "68cbd47589446e9674921bae0b98ff8fbe28be23")
:recipe (:host github :repo "minad/vertico"
:files ("*.el" "extensions/*.el"))
:pin "a28370d07f35c5387c7a9ec2e5b67f0d4598058d")
(package! orderless :pin "e6784026717a8a6a7dcd0bf31fd3414f148c542e") (package! orderless :pin "dc7a781acf2e58ac7d20d1b522be0cde5213e057")
(package! consult :pin "fe49dedd71802ff97be7b89f1ec4bd61b98c2b13") (package! consult :pin "b48ff6bf0527baeb6bfd07c6da9d303ff0b79c3d")
(package! consult-dir :pin "ed8f0874d26f10f5c5b181ab9f2cf4107df8a0eb") (package! consult-dir :pin "3f5f4b71ebe819392cb090cda71bd39a93bd830a")
(when (and (modulep! :checkers syntax) (when (and (modulep! :checkers syntax)
(not (modulep! :checkers syntax +flymake))) (not (modulep! :checkers syntax +flymake)))
(package! consult-flycheck :pin "3f2a7c17cc2fe64e0c07e3bf90e33c885c0d7062")) (package! consult-flycheck :pin "754f5497d827f7d58009256a21af614cc44378a3"))
(package! embark :pin "9a44418c349e41020cdc5ad1bd21e8c77a429062") (package! embark :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e")
(package! embark-consult :pin "9a44418c349e41020cdc5ad1bd21e8c77a429062") (package! embark-consult :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e")
(package! marginalia :pin "866e50aee4f066b0903752c69b33e9b7cab93f97") (package! marginalia :pin "f6fe86b989a177355ab3ff7e97a384e10a7b0bb1")
(package! wgrep :pin "3132abd3750b8c87cbcf6942db952acfab5edccd") (package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4")
(when (modulep! +icons) (when (modulep! +icons)
(package! all-the-icons-completion :pin "8eb3e410d63f5d0657b41829e7898793e81f31c0")) (package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010"))
(when (modulep! +childframe) (when (modulep! +childframe)
(package! vertico-posframe (package! vertico-posframe
:recipe (:host github :repo "tumashu/vertico-posframe") :recipe (:host github :repo "tumashu/vertico-posframe")
:pin "7da6d648ff4202a48eb6647ee7dce8d65de48779")) :pin "2e0e09e5bbd6ec576ddbe566ab122575ef051fab"))
(when (modulep! :editor snippets)
(package! consult-yasnippet :pin "834d39acfe8a7d2c304afbe4d649b9372118c756"))

View file

@ -126,6 +126,9 @@
:desc "Search .emacs.d" "e" #'+default/search-emacsd :desc "Search .emacs.d" "e" #'+default/search-emacsd
:desc "Locate file" "f" #'+lookup/file :desc "Locate file" "f" #'+lookup/file
:desc "Jump to symbol" "i" #'imenu :desc "Jump to symbol" "i" #'imenu
:desc "Jump to symbol in open buffers" "I"
(cond ((modulep! :completion vertico) #'consult-imenu-multi)
((modulep! :completion helm) #'helm-imenu-in-all-buffers))
:desc "Jump to visible link" "l" #'link-hint-open-link :desc "Jump to visible link" "l" #'link-hint-open-link
:desc "Jump to link" "L" #'ffap-menu :desc "Jump to link" "L" #'ffap-menu
:desc "Jump to bookmark" "m" #'bookmark-jump :desc "Jump to bookmark" "m" #'bookmark-jump
@ -145,7 +148,10 @@
;;; <leader> i --- insert ;;; <leader> i --- insert
(:prefix-map ("i" . "insert") (:prefix-map ("i" . "insert")
:desc "Emoji" "e" #'emojify-insert-emoji (:when (> emacs-major-version 28)
:desc "Emoji" "e" #'emoji-search)
(:when (modulep! :ui emoji)
:desc "Emoji" "e" #'emojify-insert-emoji)
:desc "Current file name" "f" #'+default/insert-file-path :desc "Current file name" "f" #'+default/insert-file-path
:desc "Current file path" "F" (cmd!! #'+default/insert-file-path t) :desc "Current file path" "F" (cmd!! #'+default/insert-file-path t)
:desc "Snippet" "s" #'yas-insert-snippet :desc "Snippet" "s" #'yas-insert-snippet
@ -505,7 +511,7 @@
"C-x C-b" #'ibuffer "C-x C-b" #'ibuffer
"C-x K" #'doom/kill-this-buffer-in-all-windows "C-x K" #'doom/kill-this-buffer-in-all-windows
;;; company-mode ;;; completion (in-buffer)
(:when (modulep! :completion company) (:when (modulep! :completion company)
"C-;" #'+company/complete "C-;" #'+company/complete
(:after company (:after company

View file

@ -43,7 +43,10 @@
#'yas-expand #'yas-expand
(and (bound-and-true-p company-mode) (and (bound-and-true-p company-mode)
(modulep! :completion company +tng)) (modulep! :completion company +tng))
#'company-indent-or-complete-common) #'company-indent-or-complete-common
(and (bound-and-true-p corfu-mode)
(modulep! :completion corfu))
#'completion-at-point)
:m [tab] (cmds! (and (modulep! :editor snippets) :m [tab] (cmds! (and (modulep! :editor snippets)
(evil-visual-state-p) (evil-visual-state-p)
(or (eq evil-visual-selection 'line) (or (eq evil-visual-selection 'line)
@ -127,7 +130,7 @@
;; ;;
;;; Module keybinds ;;; Module keybinds
;;; :completion ;;; :completion (in-buffer)
(map! (:when (modulep! :completion company) (map! (:when (modulep! :completion company)
:i "C-@" (cmds! (not (minibufferp)) #'company-complete-common) :i "C-@" (cmds! (not (minibufferp)) #'company-complete-common)
:i "C-SPC" (cmds! (not (minibufferp)) #'company-complete-common) :i "C-SPC" (cmds! (not (minibufferp)) #'company-complete-common)
@ -156,7 +159,38 @@
"C-s" #'company-filter-candidates "C-s" #'company-filter-candidates
[escape] #'company-search-abort))) [escape] #'company-search-abort)))
(:when (modulep! :completion ivy) (:when (modulep! :completion corfu)
(:after corfu
(:map corfu-mode-map
:i "C-SPC" #'completion-at-point
:n "C-SPC" (cmd! (call-interactively #'evil-insert-state)
(call-interactively #'completion-at-point))
:v "C-SPC" (cmd! (call-interactively #'evil-change)
(call-interactively #'completion-at-point)))
(:map corfu-map
:i "C-SPC" #'corfu-insert-separator
"C-k" #'corfu-previous
"C-j" #'corfu-next
"C-u" (cmd! (let (corfu-cycle)
(funcall-interactively #'corfu-next (- corfu-count))))
"C-d" (cmd! (let (corfu-cycle)
(funcall-interactively #'corfu-next corfu-count)))))
(:after corfu-popupinfo
:map corfu-popupinfo-map
"C-h" #'corfu-popupinfo-toggle
;; Reversed because popupinfo assumes opposite of what feels intuitive
;; with evil.
"C-S-k" #'corfu-popupinfo-scroll-down
"C-S-j" #'corfu-popupinfo-scroll-up
"C-<up>" #'corfu-popupinfo-scroll-down
"C-<down>" #'corfu-popupinfo-scroll-up
"C-S-p" #'corfu-popupinfo-scroll-down
"C-S-n" #'corfu-popupinfo-scroll-up
"C-S-u" (cmd!! #'corfu-popupinfo-scroll-down nil corfu-popupinfo-min-height)
"C-S-d" (cmd!! #'corfu-popupinfo-scroll-up nil corfu-popupinfo-min-height))))
;;; :completion (separate)
(map! (:when (modulep! :completion ivy)
(:after ivy (:after ivy
:map ivy-minibuffer-map :map ivy-minibuffer-map
"C-SPC" #'ivy-call-and-recenter ; preview file "C-SPC" #'ivy-call-and-recenter ; preview file
@ -169,7 +203,8 @@
[C-return] #'+ivy/git-grep-other-window-action)) [C-return] #'+ivy/git-grep-other-window-action))
(:when (modulep! :completion helm) (:when (modulep! :completion helm)
(:after helm :map helm-map (:after helm
:map helm-map
[remap next-line] #'helm-next-line [remap next-line] #'helm-next-line
[remap previous-line] #'helm-previous-line [remap previous-line] #'helm-previous-line
[left] #'left-char [left] #'left-char
@ -228,7 +263,7 @@
:g "M-8" #'+workspace/switch-to-7 :g "M-8" #'+workspace/switch-to-7
:g "M-9" #'+workspace/switch-to-8 :g "M-9" #'+workspace/switch-to-8
:g "M-0" #'+workspace/switch-to-final :g "M-0" #'+workspace/switch-to-final
(:when IS-MAC (:when (featurep :system 'macos)
:g "s-t" #'+workspace/new :g "s-t" #'+workspace/new
:g "s-T" #'+workspace/display :g "s-T" #'+workspace/display
:n "s-1" #'+workspace/switch-to-0 :n "s-1" #'+workspace/switch-to-0
@ -371,8 +406,11 @@
;;; <leader> c --- code ;;; <leader> c --- code
(:prefix-map ("c" . "code") (:prefix-map ("c" . "code")
(:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot))) (:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot)))
:desc "LSP Execute code action" "a" #'lsp-execute-code-action :desc "LSP Execute code action" "a" #'lsp-execute-code-action
:desc "LSP Organize imports" "o" #'lsp-organize-imports :desc "LSP Organize imports" "o" #'lsp-organize-imports
:desc "LSP" "l" #'+default/lsp-command-map
:desc "LSP Rename" "r" #'lsp-rename
:desc "Symbols" "S" #'lsp-treemacs-symbols
(:when (modulep! :completion ivy) (:when (modulep! :completion ivy)
:desc "Jump to symbol in current workspace" "j" #'lsp-ivy-workspace-symbol :desc "Jump to symbol in current workspace" "j" #'lsp-ivy-workspace-symbol
:desc "Jump to symbol in any workspace" "J" #'lsp-ivy-global-workspace-symbol) :desc "Jump to symbol in any workspace" "J" #'lsp-ivy-global-workspace-symbol)
@ -386,10 +424,7 @@
:desc "Errors list" "X" #'lsp-treemacs-errors-list :desc "Errors list" "X" #'lsp-treemacs-errors-list
:desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy :desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy
:desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy t) :desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy t)
:desc "References tree" "R" (cmd!! #'lsp-treemacs-references t) :desc "References tree" "R" (cmd!! #'lsp-treemacs-references t)))
:desc "Symbols" "S" #'lsp-treemacs-symbols)
:desc "LSP" "l" #'+default/lsp-command-map
:desc "LSP Rename" "r" #'lsp-rename)
(:when (modulep! :tools lsp +eglot) (:when (modulep! :tools lsp +eglot)
:desc "LSP Execute code action" "a" #'eglot-code-actions :desc "LSP Execute code action" "a" #'eglot-code-actions
:desc "LSP Rename" "r" #'eglot-rename :desc "LSP Rename" "r" #'eglot-rename
@ -496,7 +531,10 @@
;;; <leader> i --- insert ;;; <leader> i --- insert
(:prefix-map ("i" . "insert") (:prefix-map ("i" . "insert")
:desc "Emoji" "e" #'emojify-insert-emoji (:when (> emacs-major-version 28)
:desc "Emoji" "e" #'emoji-search)
(:when (modulep! :ui emoji)
:desc "Emoji" "e" #'emojify-insert-emoji)
:desc "Current file name" "f" #'+default/insert-file-path :desc "Current file name" "f" #'+default/insert-file-path
:desc "Current file path" "F" (cmd!! #'+default/insert-file-path t) :desc "Current file path" "F" (cmd!! #'+default/insert-file-path t)
:desc "Evil ex path" "p" (cmd! (evil-ex "R!echo ")) :desc "Evil ex path" "p" (cmd! (evil-ex "R!echo "))
@ -674,7 +712,7 @@
:desc "Configure project" "g" #'projectile-configure-project :desc "Configure project" "g" #'projectile-configure-project
:desc "Invalidate project cache" "i" #'projectile-invalidate-cache :desc "Invalidate project cache" "i" #'projectile-invalidate-cache
:desc "Kill project buffers" "k" #'projectile-kill-buffers :desc "Kill project buffers" "k" #'projectile-kill-buffers
:desc "Find other file" "o" #'projectile-find-other-file :desc "Find sibling file" "o" #'find-sibling-file
:desc "Switch project" "p" #'projectile-switch-project :desc "Switch project" "p" #'projectile-switch-project
:desc "Find recent project files" "r" #'projectile-recentf :desc "Find recent project files" "r" #'projectile-recentf
:desc "Run project" "R" #'projectile-run-project :desc "Run project" "R" #'projectile-run-project
@ -736,6 +774,9 @@
:desc "Search .emacs.d" "e" #'+default/search-emacsd :desc "Search .emacs.d" "e" #'+default/search-emacsd
:desc "Locate file" "f" #'locate :desc "Locate file" "f" #'locate
:desc "Jump to symbol" "i" #'imenu :desc "Jump to symbol" "i" #'imenu
:desc "Jump to symbol in open buffers" "I"
(cond ((modulep! :completion vertico) #'consult-imenu-multi)
((modulep! :completion helm) #'helm-imenu-in-all-buffers))
:desc "Jump to visible link" "l" #'link-hint-open-link :desc "Jump to visible link" "l" #'link-hint-open-link
:desc "Jump to link" "L" #'ffap-menu :desc "Jump to link" "L" #'ffap-menu
:desc "Jump list" "j" #'evil-show-jumps :desc "Jump list" "j" #'evil-show-jumps
@ -754,8 +795,9 @@
((modulep! :completion helm) #'swiper-isearch-thing-at-point)) ((modulep! :completion helm) #'swiper-isearch-thing-at-point))
:desc "Dictionary" "t" #'+lookup/dictionary-definition :desc "Dictionary" "t" #'+lookup/dictionary-definition
:desc "Thesaurus" "T" #'+lookup/synonyms :desc "Thesaurus" "T" #'+lookup/synonyms
(:when (fboundp 'vundo) :desc "Undo history" "u"
:desc "Undo history" "u" #'vundo)) (cond ((modulep! :emacs undo +tree) #'undo-tree-visualize)
((modulep! :emacs undo) #'vundo)))
;;; <leader> t --- toggle ;;; <leader> t --- toggle
(:prefix-map ("t" . "toggle") (:prefix-map ("t" . "toggle")

View file

@ -43,12 +43,12 @@ This module provides a set of reasonable defaults, including:
* TODO Usage * TODO Usage
#+begin_quote #+begin_quote
🔨 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no usage documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* TODO Configuration * TODO Configuration
#+begin_quote #+begin_quote
🔨 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]] 󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote #+end_quote
* Troubleshooting * Troubleshooting
@ -59,7 +59,7 @@ This module provides a set of reasonable defaults, including:
* TODO Appendix * TODO Appendix
#+begin_quote #+begin_quote
🔨 /This module's appendix is incomplete./ [[doom-contrib-module:][Write more?]] 󱌣 /This module's appendix is incomplete./ [[doom-contrib-module:][Write more?]]
#+end_quote #+end_quote
** Commands ** Commands

View file

@ -24,15 +24,16 @@ If ARG (universal argument), runs `compile' from the current directory."
generate `completing-read' candidates." generate `completing-read' candidates."
(interactive) (interactive)
(call-interactively (call-interactively
(if (and (not IS-MAC) (executable-find "man")) (if (and (not (featurep :system 'macos)) (executable-find "man"))
#'man (or (command-remapping #'man)
#'man)
#'woman))) #'woman)))
;;;###autoload ;;;###autoload
(defun +default/new-buffer () (defun +default/new-buffer ()
"TODO" "TODO"
(interactive) (interactive)
(if (modulep! 'evil) (if (modulep! +evil)
(call-interactively #'evil-buffer-new) (call-interactively #'evil-buffer-new)
(let ((buffer (generate-new-buffer "*new*"))) (let ((buffer (generate-new-buffer "*new*")))
(set-window-buffer nil buffer) (set-window-buffer nil buffer)
@ -51,7 +52,7 @@ generate `completing-read' candidates."
;;;###autoload ;;;###autoload
(defun +default/diagnostics (&rest arg) (defun +default/diagnostics (&rest arg)
"List diagnostics for the current buffer/project. "List diagnostics for the current buffer/project.
If the the vertico and lsp modules are active, list lsp diagnostics for the If the vertico and lsp modules are active, list lsp diagnostics for the
current project. Otherwise list them for the current buffer" current project. Otherwise list them for the current buffer"
(interactive) (interactive)
(cond ((and (modulep! :completion vertico) (cond ((and (modulep! :completion vertico)

View file

@ -59,11 +59,16 @@
(after! woman (after! woman
;; The woman-manpath default value does not necessarily match man. If we have ;; The woman-manpath default value does not necessarily match man. If we have
;; man available but aren't using it for performance reasons, we can extract ;; man available but aren't using it for performance reasons, we can extract
;; it's manpath. ;; its manpath.
(when (executable-find "man") (let ((manpath (cond
(setq woman-manpath ((executable-find "manpath")
(split-string (cdr (doom-call-process "man" "--path")) (split-string (cdr (doom-call-process "manpath"))
path-separator t)))) path-separator t))
((executable-find "man")
(split-string (cdr (doom-call-process "man" "--path"))
path-separator t)))))
(when manpath
(setq woman-manpath manpath))))
(use-package! drag-stuff (use-package! drag-stuff
@ -76,7 +81,7 @@
;;;###package tramp ;;;###package tramp
(unless IS-WINDOWS (unless (featurep :system 'windows)
(setq tramp-default-method "ssh")) ; faster than the default scp (setq tramp-default-method "ssh")) ; faster than the default scp
@ -295,7 +300,7 @@ Continues comments if executed from a commented line. Consults
(define-key tabulated-list-mode-map "q" #'quit-window)) (define-key tabulated-list-mode-map "q" #'quit-window))
;; OS specific fixes ;; OS specific fixes
(when IS-MAC (when (featurep :system 'macos)
;; Fix MacOS shift+tab ;; Fix MacOS shift+tab
(define-key key-translation-map [S-iso-lefttab] [backtab]) (define-key key-translation-map [S-iso-lefttab] [backtab])
;; Fix conventional OS keys in Emacs ;; Fix conventional OS keys in Emacs
@ -453,6 +458,48 @@ Continues comments if executed from a commented line. Consults
'(evil-ex-completion-map))) '(evil-ex-completion-map)))
"C-s" command)) "C-s" command))
(map! :when (modulep! :completion corfu)
:after corfu
(:map corfu-map
[remap corfu-insert-separator] #'+corfu-smart-sep-toggle-escape
"C-S-s" #'+corfu-move-to-minibuffer
"C-p" #'corfu-previous
"C-n" #'corfu-next
"S-TAB" #'corfu-previous
[backtab] #'corfu-previous
"TAB" #'corfu-next
[tab] #'corfu-next))
(let ((cmds-del
`(menu-item "Reset completion" corfu-reset
:filter ,(lambda (cmd)
(when (and (>= corfu--index 0)
(eq corfu-preview-current 'insert))
cmd))))
(cmds-ret
`(menu-item "Insert completion DWIM" corfu-insert
:filter ,(lambda (cmd)
(interactive)
(cond ((null +corfu-want-ret-to-confirm)
(corfu-quit)
nil)
((eq +corfu-want-ret-to-confirm 'minibuffer)
(funcall-interactively cmd)
nil)
((and (or (not (minibufferp nil t))
(eq +corfu-want-ret-to-confirm t))
(>= corfu--index 0))
cmd)
((or (not (minibufferp nil t))
(eq +corfu-want-ret-to-confirm t))
nil)
(t cmd))))))
(map! :when (modulep! :completion corfu)
:map corfu-map
[backspace] cmds-del
"DEL" cmds-del
:gi [return] cmds-ret
:gi "RET" cmds-ret))
;; Smarter C-a/C-e for both Emacs and Evil. C-a will jump to indentation. ;; Smarter C-a/C-e for both Emacs and Evil. C-a will jump to indentation.
;; Pressing it again will send you to the true bol. Same goes for C-e, except ;; Pressing it again will send you to the true bol. Same goes for C-e, except
;; it will ignore comments+trailing whitespace before jumping to eol. ;; it will ignore comments+trailing whitespace before jumping to eol.
@ -482,7 +529,7 @@ Continues comments if executed from a commented line. Consults
:gi "C-S-RET" #'+default/newline-above :gi "C-S-RET" #'+default/newline-above
:gn [C-S-return] #'+default/newline-above :gn [C-S-return] #'+default/newline-above
(:when IS-MAC (:when (featurep :system 'macos)
:gn "s-RET" #'+default/newline-below :gn "s-RET" #'+default/newline-below
:gn [s-return] #'+default/newline-below :gn [s-return] #'+default/newline-below
:gn "S-s-RET" #'+default/newline-above :gn "S-s-RET" #'+default/newline-above

Some files were not shown because too many files have changed in this diff Show more