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
description: Report something that isn't working as intended
labels: ["is:bug", "needs-triage"]
projects: ["doomemacs/2"]
body:
- type: markdown
attributes:
@ -32,9 +33,8 @@ body:
Doom.
required: true
- label: >
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
version ending in .50 or .9x)*
The issue can be reproduced on a stable release of Emacs, such as 27,
28, or 29. *(Unstable versions end in .50, .60, or .9x)*
required: true
- type: markdown
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
/profiles/*.el
/.local*/

View file

@ -1,6 +1,6 @@
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
a copy of this software and associated documentation files (the

View file

@ -5,7 +5,7 @@
[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)
![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)
![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]
@ -98,20 +98,23 @@ Check out [the FAQ][FAQ] for answers to common questions about the project.
# Prerequisites
+ Git 2.23+
+ Emacs 27.129.1 (**Recommended: 29.1 +
- Git 2.23+
- Emacs 27.129.2 (**Recommended: 29.2 +
[native-comp](https://www.emacswiki.org/emacs/GccEmacs)**)
> :warning: Unstable and pre-release builds of Emacs -- which end in `.50`,
> `.60`, or `.9X` (e.g. `28.1.91`) -- **are not officially supported**. There
> *is* some effort to support Emacs HEAD, however. [Follow this Discourse
> post](https://discourse.doomemacs.org/t/3241) for details.
+ [ripgrep] 11.0+
+ GNU `find`
+ *OPTIONAL:* [fd] 7.3.0+ (improves file indexing performance for some commands)
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.
- [ripgrep] 11.0+
- GNU `find`
- *OPTIONAL:* [fd] 7.3.0+ (improves file indexing performance for some commands)
> [!WARNING]
> Unstable and pre-release builds of Emacs -- which end in `.50`, `.60`, or
> `.9X` (e.g. `28.1.91`) -- **are not officially supported**. There *is* some
> effort to support Emacs HEAD, however. [Follow this Discourse
> post](https://discourse.doomemacs.org/t/3241) for details.
> [!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
@ -135,8 +138,6 @@ commands you should know about:
+ `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
things.
+ `doom build` to recompile all installed packages (use this if you up/downgrade
Emacs).
# Roadmap

View file

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

View file

@ -173,7 +173,7 @@
behaviour for known commands.
#+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]].
#+end_quote

View file

@ -5,6 +5,12 @@
#+subtitle: Samples of Emacs/Doom dotfiles, concepts, and sub-projects
#+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
Examples speak louder than technical explanations, so this file exists to house
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
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 Emacs package
*** 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
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
*** =profiles.el=
:PROPERTIES:
@ -779,7 +109,7 @@ Here is an exhaustive example of all its syntax and capabilities:
(profile3
...))
#+end_src
*** =.doomprofile=
:PROPERTIES:
:ID: ac37ac6f-6082-4c34-b98c-962bc1e528c9

View file

@ -5,6 +5,12 @@
#+subtitle: Answers to common issues and questions
#+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
:PROPERTIES:
: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
variable-pitch-mode or mixed-pitch-mode). Popular for text modes, like Org or
Markdown.
- [[var:doom-unicode-font]]: used for rendering unicode glyphs. This is ~Symbola~ by
default. It is ignored if the [[doom-module::ui unicode]] module is enabled.
- [[var:doom-emoji-font]]: used for rendering emoji. Only needed if you want to use
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]]
face is used.
- [[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
(setq doom-font (font-spec :family "JetBrainsMono" :size 12 :weight 'light)
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))
#+end_src
#+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
issues are /rarely/ Doom issues!*
#+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?
*Short answer:* it is safe to sync =$DOOMDIR= across systems, but not
=$EMACSDIR=. Once moved, use ~$ doom sync && doom build~ to ensure everything is
set up correctly.
=$EMACSDIR=. Once moved, use ~$ doom sync~ to ensure everything is set up
correctly.
*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
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
moved.
should be solved by running ~$ doom sync~ on the other end, once moved.
** Start over, in case something went terribly wrong?
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
(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
the [[doom-module::ui ligatures]] module altogether.
@ -618,7 +624,7 @@ keybinds to work:
#+end_src
#+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.
#+end_quote
** 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.
#+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!
#+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?
#+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]].
#+end_quote
** TODO How does Doom Emacs improve runtime performance?
#+begin_quote
🔨 *This post is a work in progress!*
󱌣 *This post is a work in progress!*
#+end_quote
** 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.
#+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.
#+end_quote

View file

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

View file

@ -27,16 +27,17 @@
;;; Code:
;; 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
;; cause stuttering/freezes.
;; off, but will be reset later by `gcmh-mode' (or in doom-cli.el, if in a
;; noninteractive session). Not resetting it later causes stuttering/freezes.
(setq gc-cons-threshold most-positive-fixnum)
;; PERF: Don't use precious startup time checking mtime on elisp bytecode.
;; 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)
;; 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.
(when (getenv-internal "DEBUG")
(setq init-file-debug t
@ -48,17 +49,17 @@
(or
;; 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,
;; a more complete version of this optimization can be found in lisp/doom.el.
;; notable saving in startup time. This is just a stopgap though; this
;; optimization is continued more comprehensively in lisp/doom.el.
(let (file-name-handler-alist)
(let* (;; FIX: Unset `command-line-args' in noninteractive sessions, to
;; ensure upstream switches aren't misinterpreted.
(command-line-args (unless noninteractive command-line-args))
;; I avoid using `command-switch-alist' to process --profile (and
;; --init-directory) because it is processed too late to change
;; `user-emacs-directory' in time.
(profile (or (cadr (member "--profile" command-line-args))
(getenv-internal "DOOMPROFILE"))))
(let (;; FIX: Unset `command-line-args' in noninteractive sessions, to
;; ensure upstream switches aren't misinterpreted.
(command-line-args (unless noninteractive command-line-args))
;; I avoid using `command-switch-alist' to process --profile (and
;; --init-directory) because it is processed too late to change
;; `user-emacs-directory' in time.
(profile (or (cadr (member "--profile" command-line-args))
(getenv-internal "DOOMPROFILE"))))
(if (null profile)
;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped.
(let ((init-dir (or (cadr (member "--init-directory" command-line-args))
@ -84,7 +85,10 @@
(or (load (expand-file-name
(format (let ((lfile (getenv-internal "DOOMPROFILELOADFILE")))
(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")
"profiles/load.%d.elc"))
emacs-major-version)
@ -94,33 +98,33 @@
;; PERF: When `load'ing or `require'ing files, each permutation of
;; `load-suffixes' and `load-file-rep-suffixes' (then `load-suffixes' +
;; `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
;; hundreds/thousands of files Emacs needs to load.
;; `load-file-rep-suffixes') is used to locate the file. Each permutation
;; amounts to at least one file op, which is normally very fast, but can
;; add up over the hundreds/thousands of files Emacs loads.
;;
;; 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
;; `load'. See the docs of `load' for details.
;; this early -- I remove `.so' from `load-suffixes' and pass the
;; `must-suffix' arg to `load'. See the docs of `load' for details.
(if (let ((load-suffixes '(".elc" ".el")))
;; I avoid `load's NOERROR argument because other, legitimate errors
;; (like permission or IO errors) should not be suppressed or
;; interpreted as "this is not a Doom config".
(condition-case _
;; I avoid `load's NOERROR argument because it suppresses other,
;; legitimate errors (like permission or IO errors), which gets
;; incorrectly interpreted as "this is not a Doom config".
(condition-case-unless-debug _
;; Load the heart of Doom Emacs.
(load (expand-file-name "lisp/doom" user-emacs-directory)
nil (not init-file-debug) nil 'must-suffix)
;; Failing that, assume that we're loading a non-Doom config.
(file-missing
;; HACK: `startup--load-user-init-file' resolves $EMACSDIR from a
;; lexically bound `startup-init-directory', which means changes
;; to `user-emacs-directory' won't be respected when loading
;; $EMACSDIR/init.el, so I force it to:
;; lexical (and so, not-trivially-modifiable)
;; `startup-init-directory', so Emacs will fail to locate the
;; correct $EMACSDIR/init.el without help.
(define-advice startup--load-user-init-file (:filter-args (args) reroute-to-profile)
(list (lambda () (expand-file-name "init.el" user-emacs-directory))
nil (nth 2 args)))
;; Set `user-init-file' for the `load' call further below, and do so
;; here while our `file-name-handler-alist' optimization is still
;; effective (benefits `expand-file-name'). BTW: Emacs resets
;; (Re)set `user-init-file' for the `load' call further below, and
;; do so here while our `file-name-handler-alist' optimization is
;; still effective (benefits `expand-file-name'). BTW: Emacs resets
;; `user-init-file' and `early-init-file' after this file is loaded.
(setq user-init-file (expand-file-name "early-init" user-emacs-directory))
;; 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.
(setq gc-cons-threshold (* 16 1024 1024))
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))))
;; 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")))
(print! (start "Checking for Emacs config conflicts..."))
(when (file-exists-p "~/.emacs")
(warn! "Detected an ~/.emacs file, which may prevent Doom from loading")
(explain! "If Emacs finds an ~/.emacs file, it will ignore ~/.emacs.d, where Doom is "
"typically installed. If you're seeing a vanilla Emacs splash screen, this "
"may explain why. If you use Chemacs, you may ignore this warning."))
(print-group!
(unless (or (file-equal-p doom-emacs-dir "~/.emacs.d")
(file-equal-p doom-emacs-dir "~/.config/emacs"))
(print! (warn "Doom is installed in a non-standard location"))
(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..."))
(unless (functionp 'json-serialize)
(warn! "Emacs was not built with native JSON support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"jansson support (i.e. a native JSON library), particularly LSP users. "
"You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-json option."))
(unless (featurep 'native-compile)
(warn! "Emacs was not built with native compilation support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"native compilation support, availible in emacs 28+."
"You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-native-compilation option."))
(print! (start "Checking for missing Emacs features..."))
(print-group!
(unless (functionp 'json-serialize)
(warn! "Emacs was not built with native JSON support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"jansson support (i.e. a native JSON library), particularly LSP users. "
"You must install a prebuilt Emacs binary with this included, or compile "
"Emacs with the --with-json option."))
(unless (featurep 'native-compile)
(warn! "Emacs was not built with native compilation support")
(explain! "Users will see a substantial performance gain by building Emacs with "
"native compilation support, availible in emacs 28+."
"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..."))
(let* ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config")
"/doom/"))
(doom-dir (or (getenv "DOOMDIR")
"~/.doom.d/"))
(dir (if (file-directory-p xdg-dir)
xdg-dir
doom-dir)))
(when (file-equal-p dir doom-emacs-dir)
(print! (error "Doom was cloned to %S, not ~/.emacs.d or ~/.config/emacs"
(path dir)))
(explain! "Doom's source and your private Doom config have to live in separate directories. "
"Putting them in the same directory (without changing the DOOMDIR environment "
"variable) will cause errors on startup."))
(when (and (not (file-equal-p xdg-dir doom-dir))
(file-directory-p xdg-dir)
(file-directory-p doom-dir))
(print! (warn "Detected two private configs, in %s and %s")
(abbreviate-file-name xdg-dir)
doom-dir)
(explain! "The second directory will be ignored, as it has lower precedence.")))
(print-group!
(let* ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME")
"~/.config")
"/doom/"))
(doom-dir (or (getenv "DOOMDIR")
"~/.doom.d/"))
(dir (if (file-directory-p xdg-dir)
xdg-dir
doom-dir)))
(when (file-equal-p dir doom-emacs-dir)
(print! (error "Doom was cloned to %S, not ~/.emacs.d or ~/.config/emacs"
(path dir)))
(explain! "Doom's source and your private Doom config have to live in separate directories. "
"Putting them in the same directory (without changing the DOOMDIR environment "
"variable) will cause errors on startup."))
(when (and (not (file-equal-p xdg-dir doom-dir))
(file-directory-p xdg-dir)
(file-directory-p doom-dir))
(print! (warn "Detected two private configs, in %s and %s")
(abbreviate-file-name xdg-dir)
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..."))
(elc-check-dir doom-core-dir)
@ -205,13 +243,13 @@ in."
;; Check for fonts
(if (not (executable-find "fc-list"))
(warn! "Warning: unable to detect fonts because fontconfig isn't installed")
;; all-the-icons fonts
;; nerd-icons fonts
(when (and (pcase system-type
(`gnu/linux (concat (or (getenv "XDG_DATA_HOME")
"~/.local/share")
"/fonts/"))
(`darwin "~/Library/Fonts/"))
(require 'all-the-icons nil t))
(require 'nerd-icons nil t))
(with-temp-buffer
(let ((errors 0))
(cl-destructuring-bind (status . output)
@ -219,15 +257,16 @@ in."
(if (not (zerop status))
(print! (error "There was an error running `fc-list'. Is fontconfig installed correctly?"))
(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))
(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)
(explain! "Some all-the-icons fonts were missing.\n\n"
"You can install them by running `M-x all-the-icons-install-fonts' within Emacs.\n"
"This could also mean you've installed them in non-standard locations, in which "
"case feel free to ignore this warning.")))))))))
(explain! "Some needed fonts are not properly installed on your system. To download and "
"install them, run `M-x nerd-icons-install-fonts' from within Doom Emacs. "
"However, on Windows this command will only download them; the fonts must "
"be installed manually afterwards.")))))))))
(print! (start "Checking for stale elc files in your DOOMDIR..."))
(when (file-directory-p doom-user-dir)

View file

@ -33,7 +33,8 @@
"^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$" "^\\(SSH\\|GPG\\)_TTY$"
"^GPG_AGENT_INFO$"
;; Internal Doom envvars
"^DEBUG$" "^INSECURE$" "^\\(EMACS\\|DOOM\\)DIR$" "^DOOMPROFILE$" "^__")
"^DEBUG$" "^INSECURE$" "^\\(EMACS\\|DOOM\\)DIR$"
"^DOOM\\(PATH\\|PROFILE\\)$" "^__")
"Environment variables to omit from envvar files.
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?")
(envfile? ("--env" :yes) "(Re)generate an envvars file? (see `$ doom help env`)")
(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?")
&context context)
"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,
4. Prompts you to generate an envvar file (same as `$ doom env`),
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.
@ -55,20 +55,19 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
(setq doom-user-dir (expand-file-name "doom/" xdg-config-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)
(print! (success "Created %s") (relpath doom-user-dir)))
(print! (success "Created %s") (path doom-user-dir)))
;; Create init.el, config.el & packages.el
(print-group!
(mapc (lambda (file)
(cl-destructuring-bind (filename . template) file
(if (file-exists-p! filename doom-user-dir)
(print! (item "Skipping %s (already exists)")
(path filename))
(print! (item "Creating %s%s") (relpath doom-user-dir) filename)
(with-temp-file (doom-path doom-user-dir filename)
(insert-file-contents template))
(setq filename (doom-path doom-user-dir filename))
(if (file-exists-p filename)
(print! (item "Skipping %s (already exists)...") (path filename))
(print! (item "Creating %s...") (path filename))
(with-temp-file filename (insert-file-contents template))
(print! (success "Done!")))))
(let ((template-dir (doom-path doom-emacs-dir "templates")))
`((,doom-module-init-file
@ -96,7 +95,7 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
(if (eq install? :no)
(print! (warn "Not installing plugins, as requested"))
(print! "Installing plugins")
(doom-packages-install))
(doom-packages-ensure))
(print! "Regenerating autoloads files")
(doom-profile-generate)
@ -110,22 +109,6 @@ Change `$DOOMDIR' with the `--doomdir' option, e.g.
('user-error
(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")
(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)))
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))))))
(defun doom-cli-help--similarity (a b)
(- 1 (/ (float (doom-cli-help--string-distance a b))
(max (length a) (length b)))))
(defun doom-cli-help--string-distance (a b)
"Calculate the Restricted Damerau-Levenshtein distance between A and B.
This is also known as the Optimal String Alignment algorithm.
It is assumed that A and B are both strings, and before processing both are
converted to lowercase.
This returns the minimum number of edits required to transform A
to B, where each edit is a deletion, insertion, substitution, or
transposition of a character, with the restriction that no
substring is edited more than once."
(let ((a (downcase a))
(b (downcase b))
(alen (length a))
(blen (length b))
(start 0))
(when (> alen blen)
(let ((c a)
(clen alen))
(setq a b alen blen
b c blen clen)))
(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
;; TODO Parameterize optional args with `cl-defun'

View file

@ -13,28 +13,12 @@
;;
;;; Commands
(defcli! (:before (build b purge p)) (&context context)
(require 'comp nil t)
(doom-initialize-core-packages))
(defcli-obsolete! ((build b)) (sync "--rebuild") "v3.0.0")
;; DEPRECATED Replace with "doom sync --rebuild"
(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)
(defcli-obsolete! ((purge p)) (gc) "v3.0.0")
;; 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")
(noelpa-p ("-p" "--no-elpa") "Don't purge ELPA packages")
(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
list remains lean."
:benchmark t
(require 'comp nil t)
(doom-initialize-core-packages)
(straight-check-all)
(when (doom-packages-purge
(not noelpa-p)
@ -242,154 +228,149 @@ list remains lean."
(defun doom-packages--write-missing-eln-errors ()
"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
for eln-name = (doom-packages--eln-file-name file)
for eln-file = (doom-packages--eln-output-file eln-name)
for error-file = (doom-packages--eln-error-file eln-name)
for error-dir = (file-name-directory error-file)
unless (or (file-exists-p eln-file)
(file-newer-than-file-p error-file file)
(not (file-writable-p error-dir)))
do (make-directory error-dir 'parents)
(write-region "" nil error-file)
(doom-log "Wrote %s" error-file))
(setq doom-packages--eln-output-expected nil)))
(cl-loop for file in doom-packages--eln-output-expected
for eln-name = (doom-packages--eln-file-name file)
for eln-file = (doom-packages--eln-output-file eln-name)
for error-file = (doom-packages--eln-error-file eln-name)
for error-dir = (file-name-directory error-file)
unless (or (file-exists-p eln-file)
(file-newer-than-file-p error-file file)
(not (file-writable-p error-dir)))
do (make-directory error-dir 'parents)
(write-region "" nil error-file)
(doom-log "Wrote %s" error-file))
(setq doom-packages--eln-output-expected nil))
(defun doom-packages--compile-site-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
unless (file-in-directory-p path doom-local-dir)
collect path)
for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$")
if (and (file-exists-p (byte-compile-dest-file file))
(not (doom-packages--find-eln-file (doom-packages--eln-file-name file)))
(not (cl-some (fn! (string-match-p % file))
native-comp-deferred-compilation-deny-list))) do
(doom-log "Compiling %s" file)
(native-compile-async file))))
(cl-loop with paths = (cl-loop for path in load-path
unless (file-in-directory-p path doom-local-dir)
collect path)
for file in (doom-files-in paths :match "\\.el\\(?:\\.gz\\)?$")
if (and (file-exists-p (byte-compile-dest-file file))
(not (doom-packages--find-eln-file (doom-packages--eln-file-name file)))
(not (cl-some (fn! (string-match-p % file))
native-comp-deferred-compilation-deny-list))) do
(doom-log "Compiling %s" file)
(native-compile-async file)))
(defun doom-packages-install ()
"Installs missing packages.
This function will install any primary package (i.e. a package with a `package!'
declaration) or dependency thereof that hasn't already been."
(defun doom-packages-ensure (&optional force-p)
"Ensure packages are installed, built"
(doom-initialize-packages)
(print! (start "Installing packages..."))
(let ((pinned (doom-package-pinned-list)))
(print-group!
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h)
(if-let (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 " ""))
(if (not (file-directory-p (straight--repos-dir)))
(print! (start "Installing all packages for the first time (this may take a while)..."))
(if force-p
(print! (start "Rebuilding all packages (this may take a while)..."))
(print! (start "Ensuring packages are installed and built..."))))
(print-group!
(let ((straight-check-for-modifications
(when (file-directory-p (straight--modified-dir))
'(find-when-checking)))
(straight--allow-find
(and straight-check-for-modifications
(executable-find straight-find-executable)
t))
(straight--packages-not-to-rebuild
(or straight--packages-not-to-rebuild (make-hash-table :test #'equal)))
(straight--packages-to-rebuild
(or (if force-p :all straight--packages-to-rebuild)
(make-hash-table :test #'equal)))
(recipes (doom-package-recipe-list)))
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h)
(unless force-p
(straight--make-build-cache-available))
(if-let (built
(doom-packages--with-recipes recipes (package local-repo recipe)
(unless force-p
;; Ensure packages with outdated files/bytecode are rebuilt
(let* ((build-dir (straight--build-dir package))
(repo-dir (straight--repos-dir local-repo))
(build (if (plist-member recipe :build)
(plist-get recipe :build)
t))
(want-byte-compile
(or (eq build t)
(memq 'compile build)))
(want-native-compile
(or (eq build t)
(memq 'native-compile build))))
(and (eq (car-safe build) :not)
(setq want-byte-compile (not want-byte-compile)
want-native-compile (not want-native-compile)))
(unless (featurep 'native-compile)
(setq want-native-compile nil))
(and (or want-byte-compile want-native-compile)
(or (file-newer-than-file-p repo-dir build-dir)
(file-exists-p (straight--modified-dir (or local-repo package)))
(cl-loop with outdated = nil
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 want-native-compile (doom-packages--eln-file-outdated-p file)))
do (setq outdated t)
(let ((straight-check-for-modifications
(when (file-directory-p (straight--modified-dir))
'(find-when-checking)))
(straight--allow-find
(and straight-check-for-modifications
(executable-find straight-find-executable)
t))
(straight--packages-not-to-rebuild
(or straight--packages-not-to-rebuild (make-hash-table :test #'equal)))
(straight--packages-to-rebuild
(or (if force-p :all straight--packages-to-rebuild)
(make-hash-table :test #'equal)))
(recipes (doom-package-recipe-list))
(pinned (doom-package-pinned-list)))
(add-hook 'native-comp-async-cu-done-functions #'doom-packages--native-compile-done-h)
(straight--make-build-cache-available)
(if-let (built
(doom-packages--with-recipes recipes (package local-repo recipe)
(let ((repo-dir (straight--repos-dir (or local-repo package)))
(build-dir (straight--build-dir package)))
(unless force-p
;; Ensure packages with outdated files/bytecode are rebuilt
(let* ((build (if (plist-member recipe :build)
(plist-get recipe :build)
t))
(want-byte-compile
(or (eq build t)
(memq 'compile build)))
(want-native-compile
(or (eq build t)
(memq 'native-compile build))))
(and (eq (car-safe build) :not)
(setq want-byte-compile (not want-byte-compile)
want-native-compile (not want-native-compile)))
(unless (featurep 'native-compile)
(setq want-native-compile nil))
(and (or want-byte-compile want-native-compile)
(or (file-newer-than-file-p repo-dir build-dir)
(file-exists-p (straight--modified-dir (or local-repo package)))
(cl-loop with outdated = nil
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 want-native-compile (doom-packages--eln-file-outdated-p file)))
do (setq outdated t)
(when want-native-compile
(push file doom-packages--eln-output-expected))
finally return outdated))
(puthash package t straight--packages-to-rebuild))))
(straight-use-package (intern package))))
(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[KRebuilt %d package(s)") (length built)))
(print! (item "No packages need rebuilding"))
nil))))
finally return outdated))
(puthash package t straight--packages-to-rebuild))))
(unless (file-directory-p repo-dir)
(doom-packages--cli-recipes-update))
(condition-case-unless-debug e
(let ((straight-vc-git-post-clone-hook
(cons (lambda! (&key repo-dir commit)
(print-group!
(if-let (pin (cdr (assoc package pinned)))
(print! (item "Pinned to %s") pin)
(print! (item "Checked out %s") commit)))
;; 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 #2637), so have git handle
;; 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."
(doom-initialize-packages)
(doom-packages--barf-if-incomplete)
(doom-packages--cli-recipes-update)
(let* ((repo-dir (straight--repos-dir))
(pinned (doom-package-pinned-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))
(total (length recipes))
(esc (unless init-file-debug "\033[1A"))
(i 0)
errors)
(print! (start "Updating packages (this may take a while)..."))
(i 0))
(if pinned-only-p
(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)
(cl-incf i)
(print-group!
@ -412,11 +394,13 @@ declaration) or dependency thereof that hasn't already been."
(cl-return))
(let ((default-directory (straight--repos-dir local-repo)))
(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))
(when (eq type 'git)
(unless (file-exists-p ".git")
(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
(let ((ref (straight-vc-get-commit type local-repo))
(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)
(when .it
(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 output (doom-packages--commit-log-between ref target-ref)
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))
(delete-directory repo 'recursive)
(print-group!
(straight-use-package (intern package) nil 'no-build))
(straight-use-package (intern package) nil 'no-build))
(prog1 (file-directory-p repo)
(or (not (eq type 'git))
(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")
(if (hash-table-empty-p packages-to-rebuild)
(ignore (print! (success "All %d packages are up-to-date") total))
(doom-packages--cli-recipes-update)
(straight--transaction-finalize)
(let ((default-directory (straight--build-dir)))
(mapc (doom-rpartial #'delete-directory 'recursive)
(hash-table-keys packages-to-rebuild)))
(print! (success "Updated %d package(s)")
(hash-table-count packages-to-rebuild))
(doom-packages-build)
(doom-packages-ensure)
t))))
@ -652,6 +630,7 @@ If ELPA-P, include packages installed with package.el (M-x package-install)."
(doom-initialize-packages)
(doom-packages--barf-if-incomplete)
(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)
(let ((rdirs
(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
(if (not builds-p)
(ignore (print! (item "Skipping builds")))
(and (/= 0 (doom-packages--purge-builds builds-to-purge))
(quiet! (straight-prune-build-cache))))
(/= 0 (doom-packages--purge-builds builds-to-purge)))
(if (not elpa-p)
(ignore (print! (item "Skipping elpa packages")))
(/= 0 (doom-packages--purge-elpa)))
@ -821,5 +799,31 @@ However, in batch mode, print to stdout instead of stderr."
"/dev/null")))
(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)
;;; packages.el ends here

View file

@ -14,18 +14,21 @@
(defvar doom-before-sync-hook ()
"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
(defcli-alias! (:before (sync s)) (:before build))
(defcli! ((sync s))
((noenvvar? ("-e") "Don't regenerate the envvar file")
(noelc? ("-c") "Don't recompile config")
(update? ("-u") "Update installed packages after syncing")
(purge? ("-p") "Purge orphaned package repos & regraft them")
(jobs ("-j" "--jobs" num) "How many CPUs to use for native compilation"))
(update? ("-u") "Update all installed packages after syncing")
(noupdate? ("-U") "Don't update any packages")
(purge? ("--gc") "Purge orphaned package repos & regraft them")
(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.
This is the equivalent of running autoremove, install, autoloads, then
@ -33,8 +36,10 @@ recompile. Run this whenever you:
1. Modify your `doom!' block,
2. Add or remove `package!' blocks to your config,
3. Add or remove autoloaded functions in module autoloaded files.
4. Update Doom outside of Doom (e.g. with git)
3. Add or remove autoloaded functions in module autoloaded files,
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
installed, autoloads files are up-to-date and no byte-compiled files have gone
@ -47,26 +52,49 @@ OPTIONS:
:benchmark t
(when (doom-profiles-bootloadable-p)
(call! '(profiles sync "--reload")))
(run-hooks 'doom-before-sync-hook)
(add-hook 'kill-emacs-hook #'doom-sync--abort-warning-h)
(when jobs
(setq native-comp-async-jobs-number (truncate jobs)))
(print! (start "Synchronizing %S profile..." )
(or (car doom-profile) "default"))
(run-hooks 'doom-before-sync-hook)
(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
(print-group!
(when (and (not noenvvar?)
(file-exists-p doom-env-file))
(call! '(env)))
(doom-packages-install)
(doom-packages-build)
(when update?
(doom-packages-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))
t)
;; If the user has up/downgraded Emacs since last sync, or copied their
;; config to a different system, then their packages need to be
;; recompiled. This is necessary because Emacs byte-code is not
;; necessarily back/forward compatible across major versions, and many
;; packages bake in hardcoded data at compile-time.
(pcase-let ((`(,old-version . ,old-host) (doom-file-read doom-cli-sync-info-file :by 'read :noerror t))
(to-rebuild nil))
(when (and old-version (not (equal old-version emacs-version)))
(print! (warn "Emacs version has changed since last sync (from %s to %s)") old-version emacs-version)
(setq to-rebuild t))
(when (and old-host (not (equal old-host (system-name))))
(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)))

View file

@ -3,7 +3,6 @@
;;; Code:
(load! "packages")
(load! "compile")
;;
@ -22,6 +21,7 @@
(defcli! ((upgrade up))
((packages? ("-p" "--packages") "Only upgrade packages, not Doom")
(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)
"Updates Doom and packages.
@ -30,10 +30,11 @@ following shell commands:
cd ~/.emacs.d
git pull --rebase
doom clean
doom sync -u"
(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
(packages?
;; 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.
;; Major changes will still break, however
(print! (item "Reloading Doom Emacs"))
(doom-cli-context-put context 'upgrading t)
(exit! "doom" "upgrade" "-p"
(if nobuild? "-B")
(if force? "--force")
(if jobs (format "--jobs=%d" jobs))))
@ -96,6 +99,8 @@ following shell commands:
(sh! "git" "reset" "--hard" (format "origin/%s" branch))
(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)
(unwind-protect
(let (result)
@ -136,7 +141,6 @@ following shell commands:
(ignore (print! (error "Aborted")))
(print! (start "Upgrading Doom Emacs..."))
(print-group!
(doom-compile-clean)
(doom-cli-context-put context 'straight-recipe (doom-upgrade--get-straight-recipe))
(or (and (zerop (car (sh! "git" "reset" "--hard" target-remote)))
(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
;; stdout with deprecation and/or file load messages.
(let ((inhibit-message (not init-file-debug)))
(require 'cl nil t)
(unless site-run-file
(let ((site-run-file "site-start")
(tail load-path)
(lispdir (expand-file-name "../lisp" data-directory))
dir)
(while tail
(setq dir (car tail))
(let ((default-directory dir))
(load (expand-file-name "subdirs.el") t inhibit-message t))
(unless (string-prefix-p lispdir dir)
(let ((default-directory dir))
(load (expand-file-name "leim-list.el") t inhibit-message t)))
(setq tail (cdr tail)))
(load site-run-file t inhibit-message))))
(quiet!
(require 'cl nil t)
(unless site-run-file
(let ((site-run-file "site-start")
(tail load-path)
(lispdir (expand-file-name "../lisp" data-directory))
dir)
(while tail
(setq dir (car tail))
(let ((default-directory dir))
(load (expand-file-name "subdirs.el") t inhibit-message t))
(unless (string-prefix-p lispdir dir)
(let ((default-directory dir))
(load (expand-file-name "leim-list.el") t inhibit-message t)))
(setq tail (cdr tail)))
(load site-run-file t inhibit-message))))
(setq-default
;; PERF: Don't generate superfluous files when writing temp buffers.
@ -92,15 +92,14 @@
:group 'doom)
(defvar doom-cli-load-path
(let ((paths (split-string (or (getenv "DOOMPATH") "") path-separator)))
(if (member "" paths)
(cl-substitute (doom-path (dir!) "cli/") "" paths :test #'equal)
paths))
(append (when-let ((doompath (getenv "DOOMPATH")))
(cl-loop for dir in (split-string doompath path-separator)
collect (expand-file-name dir)))
(list (file-name-concat (dir!) "cli")))
"A list of paths to search for autoloaded Doom CLIs.
It is prefilled by the DOOMPATH envvar (a colon-separated list on Linux/macOS,
semicolon otherwise). Empty entries in DOOMPATH are replaced with the
$EMACSDIR/cli/.")
semicolon otherwise).")
;;; CLI definition variables
(defvar doom-cli-argument-types
@ -1050,9 +1049,9 @@ considered as well."
"\n")))
(print! (warn "Wrote extended straight log to %s")
(path (let ((coding-system-for-write 'utf-8-auto))
(with-temp-file error-file
(insert-buffer-substring (straight--process-buffer)))
(set-file-modes error-file #o600)
(with-file-modes #o600
(with-temp-file error-file
(insert-buffer-substring (straight--process-buffer))))
error-file))))
((eq type '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))
(file (doom-cli--output-file "log" context)))
(when (> (buffer-size buffer) 0)
(make-directory (file-name-directory file) t)
(with-temp-file file
(insert-buffer-substring buffer)
(ansi-color-filter-region (point-min) (point-max)))
(set-file-modes file #o600)))))
(with-file-modes #o700
(make-directory (file-name-directory file) t))
(with-file-modes #o600
(with-temp-file file
(insert-buffer-substring buffer)
(ansi-color-filter-region (point-min) (point-max))))))))
(defun doom-cli--output-benchmark-h (context)
"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))
(coding-system-for-write 'utf-8-auto))
(make-directory (file-name-directory tmpfile) t)
(with-temp-file tmpfile
(insert-buffer-substring (doom-cli-context-stdout context)))
(set-file-modes tmpfile #o600)
(with-file-modes #o700
(make-directory (file-name-directory tmpfile) t))
(with-file-modes #o600
(with-temp-file tmpfile
(insert-buffer-substring (doom-cli-context-stdout context))))
(doom-cli--restart
(format "%s <%s; rm -f%s %s"
(or pager
@ -1782,7 +1783,7 @@ See `defcli!' for information about COMMANDSPEC.
TARGET is simply a command list.
WHEN specifies what version this command was rendered obsolete."
`(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))
:hide t
(print! (warn "'%s' was deprecated in %s")

View file

@ -3,9 +3,12 @@
;;; Code:
(defvar doom-detect-indentation-excluded-modes
'(fundamental-mode pascal-mode so-long-mode doom-docs-org-mode)
"A list of major modes in which indentation should be automatically
detected.")
'(pascal-mode
so-long-mode
;; 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
"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))))
(and (buffer-file-name buffer)
(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)
"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
(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)
"`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
@ -501,8 +510,9 @@ files, so this replace calls to `pp' with the much faster `prin1'."
(unless (or (not after-init-time)
doom-inhibit-indent-detection
doom-large-file-p
(memq major-mode doom-detect-indentation-excluded-modes)
(member (substring (buffer-name) 0 1) '(" " "*")))
(eq major-mode 'fundamental-mode)
(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
(let ((inhibit-message (not init-file-debug)))
(dtrt-indent-mode +1))))
@ -583,11 +593,9 @@ current buffer."
filename))
(prog1 (apply fn args)
(when (buffer-live-p buf)
(with-current-buffer buf (goto-char pos)))))))))
;;;###package imenu
(add-hook 'imenu-after-jump-hook #'recenter)
(with-current-buffer buf (goto-char pos))))))))
:config
(setq helpful-set-variable-function #'setq!))
(use-package! smartparens

View file

@ -15,6 +15,12 @@
"An alternative leader prefix key, used for Insert and Emacs states, and for
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"
"The localleader prefix key, for major-mode specific commands.")
@ -35,7 +41,7 @@ and Emacs states, and for non-evil users.")
;;; Global keybind settings
(cond
(IS-MAC
(doom--system-macos-p
;; mac-* variables are used by the special emacs-mac build of Emacs by
;; Yamamoto Mitsuharu, while other builds use ns-*.
(setq mac-command-modifier 'super
@ -45,18 +51,18 @@ and Emacs states, and for non-evil users.")
;; Free up the right option for character composition
mac-right-option-modifier 'none
ns-right-option-modifier 'none))
(IS-WINDOWS
(doom--system-windows-p
(setq w32-lwindow-modifier 'super
w32-rwindow-modifier 'super)))
;; 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
;; 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,
;; [tab] != TAB, and [backspace] != DEL.
;;
;; 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.
;; In the same vein, this keybind adds a [C-i] event, so users can bind to it
;; independently of TAB. Otherwise, it falls back to keys bound to C-i.
(define-key key-translation-map [?\C-i]
(cmd! (if (let ((keys (this-single-command-raw-keys)))
(and keys
@ -98,19 +104,20 @@ all hooks after it are ignored.")
(defun doom/escape (&optional interactive)
"Run `doom-escape-hook'."
(interactive (list 'interactive))
(cond ((minibuffer-window-active-p (minibuffer-window))
;; quit the minibuffer if open.
(when interactive
(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)
(let ((inhibit-quit t))
(cond ((minibuffer-window-active-p (minibuffer-window))
;; quit the minibuffer if open.
(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)

View file

@ -4,6 +4,7 @@
;;; Custom error types
(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-core-error "Unexpected error in Doom's core" '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")))
(defmacro dir! ()
"Return the directory of the file this macro was called."
(let (file-name-handler-alist)
(file-name-directory (macroexpand '(file!)))))
"Return the directory of the file in which this macro was called."
(let (file-name-handler-alist)
(file-name-directory (macroexpand '(file!)))))
;; REVIEW Should I deprecate this? The macro's name is so long...
(defalias 'letenv! 'with-environment-variables)
@ -801,7 +802,7 @@ This macro accepts, in order:
func-forms)))
`(progn
,@defn-forms
(dolist (hook (nreverse ',hook-forms))
(dolist (hook ',(nreverse hook-forms))
(dolist (func (list ,@func-forms))
,(if remove-p
`(remove-hook hook func ,local-p)
@ -882,16 +883,16 @@ testing advice (when combined with `rotate-text').
(dolist (target (cdr targets))
(advice-remove target #',symbol)))))
;;
;;; Backports
(defmacro defbackport! (type symbol &rest body)
"Backport a function/macro/alias from later versions of Emacs."
(declare (indent defun) (doc-string 4))
(unless (fboundp (doom-unquote symbol))
`(,type ,symbol ,@body)))
;;
;;; Backports
;; `format-spec' wasn't autoloaded until 28.1
(defbackport! autoload 'format-spec "format-spec")

View file

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

View file

@ -119,11 +119,11 @@ uses a straight or package.el command directly).")
(append (apply fn args) ; lockfiles still take priority
(doom-package-pinned-list)))
;; HACK: This fixes an issue present in recent builds of Emacs 29. See
;; emacs-mirror/emacs@0d383b592c2f. Straight.el uses `loaddefs-generate' if it
;; is available, which activates `emacs-lisp-mode' to read autoloads files,
;; but does so without suppressing its hooks. Some packages (like overseer)
;; add hooks to `emacs-lisp-mode-hook' in their autoloads, and once triggered,
;; HACK: This fixes an issue introduced in emacs-mirror/emacs@0d383b592c2f and
;; is present in >=29: Straight.el uses `loaddefs-generate' if it is
;; available, which activates `emacs-lisp-mode' to read autoloads files, but
;; does so without suppressing its hooks. Some packages (like overseer) add
;; 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
;; file errors.
;; 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")
;; Doom needs to be synced/rebuilt if either Doom or Emacs has been
;; up/downgraded. This is because byte-code isn't backwards
;; compatible, and many packages (including Doom), make in absolute
;; compatible, and many packages (including Doom), bake in absolute
;; paths into their caches that need to be refreshed.
(prin1 `(unless (equal doom-version ,doom-version)
(error ,(concat
@ -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
;; re-evaluating this file when lazy-loading dynamic docstrings from the
;; 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
if (boundp var)
collect `(set-default ',var ',(symbol-value var)))
@ -439,7 +440,7 @@ Defaults to the profile at `doom-profile-default'."
(doom-autoloads--scan
(append (doom-glob doom-core-dir "lib/*.el")
(cl-loop for dir
in (append (doom-module-load-path doom-modules-dirs)
in (append (doom-module-load-path)
(list doom-user-dir))
if (doom-glob dir "autoload.el") collect (car it)
if (doom-glob dir "autoload/*.el") append it)
@ -449,8 +450,8 @@ Defaults to the profile at `doom-profile-default'."
(defun doom-profile--generate-package-autoloads ()
(doom-autoloads--scan
(mapcar #'straight--autoloads-file
(seq-difference (hash-table-keys straight--build-cache)
doom-autoloads-excluded-packages))
(nreverse (seq-difference (hash-table-keys straight--build-cache)
doom-autoloads-excluded-packages)))
doom-autoloads-excluded-files
'literal))

View file

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

View file

@ -100,13 +100,15 @@
;;; Disable UI elements early
;; 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,
;; the menu bar exposes functionality that Doom doesn't endorse. Perhaps one
;; day Doom will support these, but today is not that day.
;;
;; clutter. Initializing them also costs a morsel of startup time. What's
;; more, the menu bar exposes functionality that Doom doesn't endorse. Perhaps
;; 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
;; `scroll-bar-mode' because they do extra work to manipulate frame variables
;; that isn't necessary this early in the startup process.
;; `scroll-bar-mode' because their manipulation of frame parameters can
;; trigger/queue a superfluous (and expensive, depending on the window system)
;; frame redraw at startup.
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
@ -119,8 +121,8 @@
;; non-application window -- which means it doesn't automatically capture
;; focus when it is started, among other things, so enable the menu-bar for
;; GUI frames, but keep it disabled in terminal frames because there it
;; activates an ugly, in-frame menu bar.
(eval-when! IS-MAC
;; unavoidably activates an ugly, in-frame menu bar.
(eval-when! doom--system-macos-p
(add-hook! '(window-setup-hook after-make-frame-functions)
(defun doom-restore-menu-bar-in-gui-frames-h (&optional frame)
(when-let (frame (or frame (selected-frame)))
@ -136,8 +138,8 @@
;; a step too opinionated.
(setq default-input-method nil)
;; ...And the clipboard on Windows could be in a wider encoding (UTF-16), so
;; leave Emacs to its own devices.
(eval-when! IS-WINDOWS
;; leave Emacs to its own devices there.
(eval-when! (not doom--system-windows-p)
(setq selection-coding-system 'utf-8))
@ -180,7 +182,7 @@
(defvar doom-incremental-packages '(t)
"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
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:
(doom-load-packages-incrementally
@ -192,16 +194,16 @@ broken up into:
This is already done by the lang/org module, however.
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
in daemon sessions (they are loaded immediately at startup).")
(defvar doom-incremental-first-idle-timer (if (daemonp) 0 2.0)
"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
`emacs-startup-hook'.")
`doom-after-init-hook'.")
(defvar doom-incremental-idle-timer 0.75
"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)
"Registers PACKAGES to be loaded incrementally.
If NOW is non-nil, load PACKAGES incrementally, in `doom-incremental-idle-timer'
intervals."
(let ((gc-cons-threshold most-positive-fixnum))
If NOW is non-nil, PACKAGES will be marked for incremental loading next time
Emacs is idle for `doom-incremental-first-idle-timer' seconds (falls back to
`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)
(cl-callf append doom-incremental-packages packages)
(while packages
@ -222,7 +228,7 @@ intervals."
(condition-case-unless-debug e
(and
(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
(while-no-input
(doom-log "start:iloader: Loading %s (%d left)" req (length packages))
@ -242,7 +248,7 @@ intervals."
(doom-log "start:iloader: Finished!")
(run-at-time (if idle-time
doom-incremental-idle-timer
doom-incremental-first-idle-timer)
first-idle-timer)
nil #'doom-load-packages-incrementally
packages t)
(setq packages nil))))))))

View file

@ -5,13 +5,13 @@
;;
;;; Variables
(defvar doom-theme nil
(defcustom doom-theme nil
"A symbol representing the Emacs theme to load at startup.
Set to `nil' to load no theme at all. This variable is changed by
`load-theme'.")
(defvar doom-font nil
(defcustom doom-font nil
"The default font to use.
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 \"Fira Code-14\")")
(defvar doom-variable-pitch-font nil
(defcustom doom-variable-pitch-font nil
"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
`doom-font' for examples.
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.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
An omitted font size means to inherit `doom-font''s size.")
(defvar doom-unicode-font nil
"Fallback font for Unicode glyphs.
(defcustom doom-symbol-font nil
"Fallback font for symbols.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
The defaults on macOS and Linux are Apple Color Emoji and Symbola, respectively.
`doom-font' for examples. Emacs defaults to Symbola.
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!")
(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"
"Segoe UI Emoji"
"Noto Color 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"
"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
(defvar doom-init-ui-hook nil
(defcustom doom-init-ui-hook nil
"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
`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.")
(defvar doom-switch-window-hook nil
(defcustom doom-switch-window-hook nil
"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.")
(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
;; `scroll-conservatively'). This is especially slow in larger files
;; during large-scale scrolling commands. If kept over 100, the window is
;; never automatically recentered.
scroll-conservatively 101
;; never automatically recentered. The default (0) triggers this too
;; aggressively, so I've set it to 10 to recenter if scrolling too far
;; off-screen.
scroll-conservatively 10
scroll-margin 0
scroll-preserve-screen-position t
;; 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'."
:before-until #'kill-current-buffer
(let ((buf (current-buffer)))
(cond ((window-dedicated-p)
(delete-window)
t)
((eq buf (doom-fallback-buffer))
(cond ((eq buf (doom-fallback-buffer))
(message "Can't kill the fallback buffer.")
t)
((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
compilation-ask-about-save nil ; save all buffers on `compile'
compilation-scroll-output 'first-error)
;; Handle ansi codes in compilation buffer
;; DEPRECATED Use `ansi-color-compilation-filter' when dropping 27.x support
(add-hook 'compilation-filter-hook #'doom-apply-ansi-color-to-compilation-buffer-h)
(add-hook 'compilation-filter-hook
(if (< emacs-major-version 28)
#'doom-apply-ansi-color-to-compilation-buffer-h
#'ansi-color-compilation-filter))
;; Automatically truncate compilation buffers so they don't accumulate too
;; much data and bog down the rest of Emacs.
(autoload 'comint-truncate-buffer "comint" nil t)
@ -417,41 +429,17 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
;;
;;; Third party packages
(use-package! all-the-icons
:commands (all-the-icons-octicon
all-the-icons-faicon
all-the-icons-fileicon
all-the-icons-wicon
all-the-icons-material
all-the-icons-alltheicon)
:preface
(add-hook! 'after-setting-font-hook
(defun doom-init-all-the-icons-fonts-h ()
(when (fboundp 'set-fontset-font)
(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)
""))))
(use-package! nerd-icons
:commands (nerd-icons-octicon
nerd-icons-faicon
nerd-icons-flicon
nerd-icons-wicon
nerd-icons-mdicon
nerd-icons-codicon
nerd-icons-devicon
nerd-icons-ipsicon
nerd-icons-pomicon
nerd-icons-powerline))
;; Hide the mode line in completion popups and MAN pages because they serve
;; 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
(delq 'custom-theme-directory custom-theme-load-path)))
(defun doom--make-font-specs (face font)
(let* ((base-specs (cadr (assq 'user (get face 'theme-face))))
(base-specs (or base-specs '((t nil))))
(attrs '(:family :foundry :slant :weight :height :width))
(new-specs nil))
(dolist (spec base-specs)
;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST)
(let ((display (car spec))
(plist (copy-tree (nth 1 spec))))
;; Alter only DISPLAY conditions matching this frame.
(when (or (memq display '(t default))
(face-spec-set-match-display display this-frame))
(dolist (attr attrs)
(setq plist (plist-put plist attr (face-attribute face attr)))))
(push (list display plist) new-specs)))
(nreverse new-specs)))
(defun doom-init-fonts-h (&optional reload)
"Loads `doom-font'."
(dolist (map `((default . ,doom-font)
(fixed-pitch . ,doom-font)
(fixed-pitch-serif . ,doom-serif-font)
(variable-pitch . ,doom-variable-pitch-font)))
(when-let* ((face (car map))
(font (cdr map)))
(dolist (frame (frame-list))
(when (display-multi-font-p frame)
(set-face-attribute face frame
:width 'normal :weight 'normal
:slant 'normal :font font)))
(let ((new-specs (doom--make-font-specs face font)))
;; Don't save to `customized-face' so it's omitted from `custom-file'
;;(put face 'customized-face new-specs)
(custom-push-theme 'theme-face face 'user 'set new-specs)
(put face 'face-modified nil))))
(defun doom-init-fonts-h (&optional _reload)
"Loads `doom-font', `doom-serif-font', and `doom-variable-pitch-font'."
(let ((this-frame (selected-frame)))
(dolist (map `((default . ,doom-font)
(fixed-pitch . ,doom-font)
(fixed-pitch-serif . ,doom-serif-font)
(variable-pitch . ,doom-variable-pitch-font)))
(condition-case e
(when-let* ((face (car map))
(font (cdr map)))
(dolist (frame (frame-list))
(when (display-multi-font-p frame)
(set-face-attribute face frame
:width 'normal :weight 'normal
:slant 'normal :font font)))
(custom-push-theme
'theme-face face 'user 'set
(let* ((base-specs (cadr (assq 'user (get face 'theme-face))))
(base-specs (or base-specs '((t nil))))
(attrs '(:family :foundry :slant :weight :height :width))
(new-specs nil))
(dolist (spec base-specs)
;; Each SPEC has the form (DISPLAY ATTRIBUTE-PLIST)
(let ((display (car spec))
(plist (copy-tree (nth 1 spec))))
;; Alter only DISPLAY conditions matching this frame.
(when (or (memq display '(t default))
(face-spec-set-match-display display this-frame))
(dolist (attr attrs)
(setq plist (plist-put plist attr (face-attribute face attr)))))
(push (list display plist) new-specs)))
(nreverse new-specs)))
(put face 'face-modified nil))
('error
(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)
(let ((fn (doom-rpartial #'member (font-family-list))))
(when-let (font (cl-find-if fn doom-symbol-fallback-font-families))
(set-fontset-font t 'symbol font))
(when-let (font (cl-find-if fn doom-emoji-fallback-font-families))
(set-fontset-font t 'unicode font))
(when doom-unicode-font
(set-fontset-font t 'unicode doom-unicode-font))))
(let* ((fn (doom-rpartial #'member (font-family-list)))
(symbol-font (or doom-symbol-font
(cl-find-if fn doom-symbol-fallback-font-families)))
(emoji-font (or doom-emoji-font
(cl-find-if fn doom-emoji-fallback-font-families))))
(when symbol-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'
(run-hooks 'after-setting-font-hook))

View file

@ -59,9 +59,13 @@
;; - On first switched-to buffer: `doom-first-buffer-hook'
;; - On first opened file: `doom-first-file-hook'
;;
;; This is Doom's heart, where I define all its major constants and variables,
;; set only its sanest global defaults, employ its hackiest (and least
;; offensive) optimizations, and load the minimum for all Doom sessions.
;; This file is Doom's heart, where I define all its major constants and
;; variables, set only its sanest global defaults, employ its hackiest (and
;; least offensive) optimizations, and load the minimum 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:
@ -99,7 +103,7 @@
;; Doom needs to be synced/rebuilt if either Doom or Emacs has been
;; up/downgraded. This is because byte-code isn't backwards compatible, and many
;; packages (including Doom), make in absolute paths into their caches that need
;; packages (including Doom), bake in absolute paths into their caches that need
;; to be refreshed.
(let ((old-version (eval-when-compile emacs-version)))
(unless (equal emacs-version old-version)
@ -107,7 +111,31 @@
"recompile it.")
emacs-version old-version)))
;;; Custom features
;;; Custom features & global constants
;; Doom has its own features that its modules, CLI, and user extensions can
;; announce, and don't belong in `features', so they are stored here, which can
;; include information about the external system environment. 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
;; claim `system-configuration-features' is not da way. Some features (that
;; don't represent packages) can be found in `features' (which `featurep'
@ -116,35 +144,40 @@
(push 'dynamic-modules features))
(if (fboundp #'json-parse-string)
(push 'jansson features))
(let ((inhibit-changing-match-data t))
(if (string-match "HARFBUZZ" system-configuration-features) ; no alternative
(push 'harfbuzz features)))
;; `native-compile' exists whether or not it is functional (e.g. libgcc is
;; available or not). This seems silly, so pretend it doesn't exist if it
;; isn't available.
(if (string-match-p "HARFBUZZ" system-configuration-features) ; no alternative
(push 'harfbuzz features))
;; The `native-compile' feature exists whether or not it is functional (e.g.
;; libgcc is available or not). This seems silly, so pretend it doesn't exist if
;; it isn't functional.
(if (featurep 'native-compile)
(if (not (native-comp-available-p))
(delq 'native-compile features)))
;;; Global constants
;; DEPRECATED remove in v3
(defconst IS-MAC (eq system-type 'darwin))
(defconst IS-LINUX (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix)))
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))
(defconst IS-BSD (memq system-type '(darwin berkeley-unix gnu/kfreebsd)))
(defconst EMACS28+ (> emacs-major-version 27))
(defconst EMACS29+ (> emacs-major-version 28))
(defconst MODULES (featurep 'dynamic-modules))
(defconst NATIVECOMP (featurep 'native-compile))
(with-no-warnings
(defconst IS-MAC doom--system-macos-p)
(defconst IS-LINUX doom--system-linux-p)
(defconst IS-WINDOWS doom--system-windows-p)
(defconst IS-BSD (memq 'bsd doom-features))
(defconst EMACS28+ (> emacs-major-version 27))
(defconst EMACS29+ (> emacs-major-version 28))
(defconst MODULES (featurep 'dynamic-modules))
(defconst NATIVECOMP (featurep 'native-compile))
(make-obsolete-variable 'IS-MAC "Use (featurep :system 'macos) instead" "3.0.0")
(make-obsolete-variable 'IS-LINUX "Use (featurep :system 'linux) instead" "3.0.0")
(make-obsolete-variable 'IS-WINDOWS "Use (featurep :system 'windows) instead" "3.0.0")
(make-obsolete-variable 'IS-BSD "Use (featurep :system 'bsd) instead" "3.0.0")
(make-obsolete-variable 'EMACS28+ "Use (>= emacs-major-version 28) instead" "3.0.0")
(make-obsolete-variable 'EMACS29+ "Use (>= emacs-major-version 29) instead" "3.0.0")
(make-obsolete-variable 'MODULES "Use (featurep 'dynamic-modules) instead" "3.0.0")
(make-obsolete-variable 'NATIVECOMP "Use (featurep 'native-compile) instead" "3.0.0"))
(make-obsolete-variable 'EMACS28+ "Use (>= emacs-major-version 28) instead" "3.0.0")
(make-obsolete-variable 'EMACS29+ "Use (>= emacs-major-version 29) instead" "3.0.0")
(make-obsolete-variable 'MODULES "Use (featurep 'dynamic-modules) instead" "3.0.0")
(make-obsolete-variable 'NATIVECOMP "Use (featurep 'native-compile) instead" "3.0.0")
;;; Fix $HOME on Windows
;; $HOME isn't normally defined on Windows, but many unix tools expect it.
(when IS-WINDOWS
(when doom--system-windows-p
(when-let (realhome
(and (null (getenv-internal "HOME"))
(getenv "USERPROFILE")))
@ -168,7 +201,7 @@
"Current version of Doom Emacs 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.")
(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")
(defvar doom-data-dir
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(expand-file-name "doomemacs/data/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_DATA_HOME") "~/.local/share")))
;; DEPRECATED: .local will be removed entirely in 3.0
@ -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
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.
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
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(expand-file-name "doomemacs/cache/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_CACHE_HOME") "~/.cache")))
;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "cache/"))
"Where Doom stores its global cache files.
Cache files represent non-essential data that shouldn't be problematic when
Cache files represent unessential data that shouldn't be problematic when
deleted (besides, perhaps, a one-time performance hit), lack portability (and so
shouldn't be copied to other systems/configs), and are regenerated when needed,
without user input (e.g. a 'doom sync').
without user input (e.g. a `doom sync`).
Some examples: images/data caches, elisp bytecode, natively compiled elisp,
session files, ELPA archives, authinfo files, org-persist, etc.
@ -266,18 +299,18 @@ For profile-local cache files, use `doom-profile-cache-dir' instead.")
(defvar doom-state-dir
(if doom-profile
(if IS-WINDOWS
(if doom--system-windows-p
(expand-file-name "doomemacs/state/" (getenv-internal "APPDATA"))
(expand-file-name "doom/" (or (getenv-internal "XDG_STATE_HOME") "~/.local/state")))
;; DEPRECATED: .local will be removed entirely in 3.0
(file-name-concat doom-local-dir "state/"))
"Where Doom stores its global state files.
State files contain non-essential, unportable, but persistent data which, if
lost won't cause breakage, but may be inconvenient as they cannot be
automatically regenerated or restored. For example, a recently-opened file list
is not essential, but losing it means losing this record, and restoring it
requires revisiting all those files.
State files contain unessential, unportable, but persistent data which, if lost
won't cause breakage, but may be inconvenient as they cannot be automatically
regenerated or restored. For example, a recently-opened file list is not
essential, but losing it means losing this record, and restoring it requires
revisiting all those files.
Use this for: history, logs, user-saved data, autosaves/backup files, known
projects, recent files, bookmarks.
@ -331,19 +364,20 @@ users).")
;; `file-remote-p'). You get a noteable boost to startup time by unsetting
;; or simplifying its value.
(let ((old-value (default-toplevel-value 'file-name-handler-alist)))
(setq file-name-handler-alist
;; HACK: If the bundled elisp for this Emacs install isn't
;; byte-compiled (but is compressed), then leave the gzip file
;; handler there so Emacs won't forget how to read read them.
;;
;; calc-loaddefs.el is our heuristic for this because it is built-in
;; to all supported versions of Emacs, and calc.el explicitly loads
;; it uncompiled. This ensures that the only other, possible
;; fallback would be calc-loaddefs.el.gz.
(if (eval-when-compile
(locate-file-internal "calc-loaddefs.el" load-path))
nil
(list (rassq 'jka-compr-handler old-value))))
(set-default-toplevel-value
'file-name-handler-alist
;; HACK: If the bundled elisp for this Emacs install isn't byte-compiled
;; (but is compressed), then leave the gzip file handler there so Emacs
;; won't forget how to read read them.
;;
;; calc-loaddefs.el is our heuristic for this because it is built-in to
;; all supported versions of Emacs, and calc.el explicitly loads it
;; uncompiled. This ensures that the only other, possible fallback would
;; be calc-loaddefs.el.gz.
(if (eval-when-compile
(locate-file-internal "calc-loaddefs.el" load-path))
nil
(list (rassq 'jka-compr-handler old-value))))
;; Make sure the new value survives any current let-binding.
(set-default-toplevel-value 'file-name-handler-alist file-name-handler-alist)
;; Remember it so it can be reset where needed.
@ -352,10 +386,11 @@ users).")
;; needed for handling encrypted or compressed files, among other things.
(add-hook! 'emacs-startup-hook :depth 101
(defun doom--reset-file-handler-alist-h ()
(setq file-name-handler-alist
;; Merge instead of overwrite because there may have been changes to
;; `file-name-handler-alist' since startup we want to preserve.
(delete-dups (append file-name-handler-alist old-value))))))
(set-default-toplevel-value
'file-name-handler-alist
;; Merge instead of overwrite because there may have been changes to
;; `file-name-handler-alist' since startup we want to preserve.
(delete-dups (append file-name-handler-alist old-value))))))
(unless noninteractive
;; PERF: Resizing the Emacs frame (to accommodate fonts that are smaller or
@ -380,8 +415,9 @@ users).")
;; PERF: Shave seconds off startup time by starting the scratch buffer in
;; `fundamental-mode', rather than, say, `org-mode' or `text-mode', which
;; pull in a ton of packages. `doom/open-scratch-buffer' provides a better
;; scratch buffer anyway.
;; pull in a ton of packages. This buffer is created whether or not we're
;; 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
initial-scratch-message nil)
@ -397,82 +433,102 @@ users).")
(doom-partial #'tty-run-terminal-initialization
(selected-frame) nil t))))
(unless init-file-debug
;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..."
;; messages in the echo area. Writing to the echo-area triggers a
;; redisplay, which can be expensive during startup. This may also cause
;; an flash of white when creating the first frame.
(define-advice load-file (:override (file) silence)
(load file nil 'nomessage))
;; COMPAT: But undo our `load-file' advice later, as to limit the scope of
;; any edge cases it could induce.
(define-advice startup--load-user-init-file (:before (&rest _) undo-silence)
(advice-remove #'load-file #'load-file@silence))
;; PERF,UX: Site files tend to use `load-file', which emits "Loading X..."
;; messages in the echo area. Writing to the echo-area triggers a
;; redisplay, which can be expensive during startup. This may also cause
;; an flash of white when creating the first frame. Needs to be undo
;; later, though.
(define-advice load-file (:override (file) silence)
(load file nil 'nomessage))
;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on each
;; `require' and `load'. Doom won't load any dmodules this early, so omit
;; .so for a small startup boost. This is later restored in doom-start.
(put 'load-suffixes 'initial-value (default-toplevel-value 'load-suffixes))
(put 'load-file-rep-suffixes 'initial-value (default-toplevel-value 'load-file-rep-suffixes))
(set-default-toplevel-value 'load-suffixes '(".elc" ".el"))
(set-default-toplevel-value 'load-file-rep-suffixes '(""))
;; COMPAT: Undo any problematic startup optimizations; from this point, I make
;; no assumptions about what might be loaded in userland.
(add-hook! 'doom-before-init-hook
(defun doom--reset-load-suffixes-h ()
(setq load-suffixes (get 'load-suffixes 'initial-value)
load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value))))
;; PERF: `load-suffixes' and `load-file-rep-suffixes' are consulted on
;; each `require' and `load'. Doom won't load any modules this early, so
;; 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-file-rep-suffixes 'initial-value (default-toplevel-value 'load-file-rep-suffixes))
(set-default-toplevel-value 'load-suffixes '(".elc" ".el"))
(set-default-toplevel-value 'load-file-rep-suffixes '(""))
;; COMPAT: Undo any problematic startup optimizations; from this point, I
;; make no assumptions about what might be loaded in userland.
(add-hook! 'doom-before-init-hook
(defun doom--reset-load-suffixes-h ()
(setq load-suffixes (get 'load-suffixes 'initial-value)
load-file-rep-suffixes (get 'load-file-rep-suffixes 'initial-value))))
;; PERF: Doom uses `defcustom' to indicate variables that users are expected
;; to reconfigure. Trouble is it fires off initializers meant to
;; accommodate any user attempts to configure them before they were
;; defined. This is unnecessary before $DOOMDIR/init.el is loaded, so I
;; disable them until it is.
(setq custom-dont-initialize t)
(add-hook! 'doom-before-init-hook
(defun doom--reset-custom-dont-initialize-h ()
(setq custom-dont-initialize nil)))
;; PERF: Doom uses `defcustom' to indicate variables that users are
;; expected to reconfigure. Trouble is it fires off initializers meant
;; to accommodate any user attempts to configure them before they were
;; defined. This is unnecessary work before $DOOMDIR/init.el is loaded,
;; so I disable them until it is.
(setq custom-dont-initialize t)
(add-hook! 'doom-before-init-hook
(defun doom--reset-custom-dont-initialize-h ()
(setq custom-dont-initialize nil)))
;; PERF: The mode-line procs a couple dozen times during startup. This is
;; normally quite fast, but disabling the default mode-line and reducing the
;; update delay timer seems to stave off ~30-50ms.
(put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format))
(setq-default mode-line-format nil)
(dolist (buf (buffer-list))
(with-current-buffer buf (setq mode-line-format nil)))
;; PERF,UX: Premature redisplays can substantially affect startup times and
;; produce ugly flashes of unstyled Emacs.
(setq-default inhibit-redisplay t
inhibit-message t)
;; COMPAT: Then reset it with advice, because `startup--load-user-init-file'
;; will never be interrupted by errors. And if these settings are left
;; set, Emacs could appear frozen or garbled.
(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 the frame to initialize. However, the toolbar is still populated
;; regardless, so I lazy load it until tool-bar-mode is actually used.
(advice-add #'tool-bar-setup :override #'ignore)
;; PERF: Doom disables the UI elements by default, so that there's less for
;; the frame to initialize. However, the toolbar is still populated
;; regardless, so I lazy load it until tool-bar-mode is actually used.
(advice-add #'tool-bar-setup :override #'ignore)
(define-advice startup--load-user-init-file (:before (&rest _) defer-tool-bar-setup)
(advice-remove #'tool-bar-setup #'ignore)
(add-transient-hook! 'tool-bar-mode (tool-bar-setup)))
;; PERF: The mode-line procs a couple dozen times during startup. This is
;; normally quite fast, but disabling the default mode-line and reducing
;; the update delay timer seems to stave off ~30-50ms.
(put 'mode-line-format 'initial-value (default-toplevel-value 'mode-line-format))
(setq-default mode-line-format nil)
(dolist (buf (buffer-list))
(with-current-buffer buf (setq mode-line-format nil)))
;; PERF,UX: Premature redisplays can substantially affect startup times
;; and/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
;; relevant to our current OS, but `command-line-1' still processes.
(unless IS-MAC
(setq command-line-ns-option-alist nil))
(unless (memq initial-window-system '(x pgtk))
(setq command-line-x-option-alist nil)))))
;; PERF,UX: An annoying aspect of site-lisp files is that they're often
;; noisy (they emit load messages or other output to stdout). These
;; queue unnecessary redraws at startup, cost startup time, and pollute
;; the logs. I get around it by suppressing it until we can load it
;; manually, later (in the `startup--load-user-init-file' advice below).
(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 'risky-local-variable t)
(defun doom-context--check (context)
(defun doom-context--assert (context)
(let ((valid (get 'doom-context 'valid-values)))
(unless (memq context valid)
(signal 'doom-context-error
@ -512,7 +568,7 @@ All valid contexts:
Return non-nil if successful. Throws an error if CONTEXT is invalid."
(unless (memq context doom-context)
(doom-context--check context)
(doom-context--assert context)
(doom-log ":context: +%s %s" 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))))
(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))
`(let ((doom-context doom-context))
(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)
(zerop native-comp-async-jobs-number)
(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
;; 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
(when (boundp 'libgnutls-version)
(concat "SECURE128:+SECURE192:-VERS-ALL"
(if (and (not IS-WINDOWS)
(if (and (not doom--system-windows-p)
(>= libgnutls-version 30605))
":+VERS-TLS1.3")
":+VERS-TLS1.2"))
@ -689,10 +753,22 @@ appropriately against `noninteractive' or the `cli' context."
;;
;;; 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
(defun doom--begin-init-h ()
"Begin the startup process."
(when (doom-context-push 'init)
;; HACK: Ensure OS checks are as fast as possible (given their ubiquity).
(setq features (cons :system (delq :system features)))
;; Remember these variables' initial values, so we can safely reset them at
;; a later time, or consult them without fear of contamination.
(dolist (var '(exec-path load-path process-environment))

View file

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

View file

@ -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))
(doom-log "debug: enabled!")
(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
;; potentially define one of `doom-debug-variables'), in case some of them
;; 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)
(and (stringp emacs-repository-version)
(substring emacs-repository-version 0 9))
(symlink-path doom-emacs-dir))))
(format "EMACSDIR=%s" (symlink-path doom-emacs-dir))
(format "EMACS=%s" (expand-file-name invocation-name invocation-directory)))))
(doom . ,(list doom-version
(if doom-profile
(format "PROFILE=%s@%s"
@ -300,7 +298,7 @@ ready to be pasted in a bug report on github."
'compiled-user-config)
(if (doom-files-in doom-core-dir :type 'files :match "\\.elc$")
'compiled-core)
(if (doom-files-in doom-modules-dirs :type 'files :match "\\.elc$")
(if (doom-files-in doom-module-load-path :type 'files :match "\\.elc$")
'compiled-modules)))))
(custom
,@(when (and (stringp custom-file)

View file

@ -19,24 +19,24 @@
(defvar doom-docs-header-specs
'(("/docs/index\\.org$"
(:label "FAQ"
:icon "question_answer"
:icon "nf-md-message_question_outline"
:link "doom-faq:"
:help-echo "Open the FAQ document"))
(("/docs/[^/]+\\.org$" "/modules/README\\.org$")
(:label "Back to index"
:icon "arrow_back"
:link ("doom-index" . "")
:icon "nf-md-arrow_left"
:link "doom-index"
:help-echo "Navigate to the root index"))
("/modules/[^/]+/README\\.org$"
(:label "Back to module index"
:icon "arrow_back"
:icon "nf-md-arrow_left"
:link "doom-module-index:"))
("/modules/[^/]+/[^/]+/README\\.org$"
(:label "Back to module index"
:icon "arrow_back"
:icon "nf-md-arrow_left"
:link "doom-module-index:")
(:label "History"
:icon "history"
:icon "nf-md-history"
:icon-face font-lock-variable-name-face
:link (lambda ()
(cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name))
@ -44,7 +44,7 @@
:help-echo "View the module history"
:align right)
(:label "Issues"
:icon "error_outline"
:icon "nf-md-flag"
:icon-face error
:link (lambda ()
(cl-destructuring-bind (category . module) (doom-module-from-path (buffer-file-name))
@ -52,12 +52,12 @@
:align right))
(t
(:label "Suggest edits"
:icon "edit"
:icon "nf-md-account_edit"
:icon-face warning
:link "doom-suggest-edit"
:align right)
(:label "Help"
:icon "help_outline"
:icon "nf-md-timeline_help_outline"
:icon-face font-lock-function-name-face
:link (lambda ()
(let ((title (cadar (org-collect-keywords '("TITLE")))))
@ -101,9 +101,10 @@
(defun doom-docs--make-header-link (spec)
"Create a header link according to SPEC."
(let ((icon (and (plist-get spec :icon)
(funcall (or (plist-get spec :icon-function)
#'all-the-icons-material)
(plist-get spec :icon))))
(with-demoted-errors "DOCS ERROR: %s"
(funcall (or (plist-get spec :icon-function)
#'nerd-icons-mdicon)
(plist-get spec :icon)))))
(label (pcase (plist-get spec :label)
((and (pred functionp) lab)
(funcall lab))
@ -239,11 +240,9 @@
(beg (max (point-min) (1- (org-element-property :begin el))))
(end (org-element-property :end el))
((memq (org-element-type el) '(drawer property-drawer))))
(when (org-current-level)
(when (org-element-property-inherited :level el)
(cl-decf end))
(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)))))
(org-fold-core-region beg end doom-docs-mode 'doom-doc-hidden))))
;; FIX: If the cursor remains within a newly folded region, that folk will
;; come undone, so we move it.
(if pt (goto-char pt))))
@ -373,7 +372,7 @@ depending.")
(defvar doom-docs--cookies nil)
;;;###autoload
(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."
:lighter " Doom Docs"
:after-hook (org-restart-font-lock)
@ -387,7 +386,7 @@ This primes `org-mode' for reading."
(if doom-docs-mode
(set (make-local-variable sym) t)
(kill-local-variable sym)))
`(org-pretty-entities
'(org-pretty-entities
org-hide-emphasis-markers
org-hide-macro-markers))
(when doom-docs-mode
@ -428,13 +427,13 @@ This primes `org-mode' for reading."
(defvar doom-docs--id-locations nil)
(defvar doom-docs--id-files nil)
(defvar doom-docs--id-location-file (file-name-concat doom-cache-dir "doom-docs-org-ids"))
;;;###autoload
(defun doom/reload-docs (&optional force)
"Reload the ID locations in Doom's documentation and open docs buffers."
(interactive (list 'interactive))
(with-temp-buffer
(let ((org-id-locations-file
(doom-path (file-truename doom-cache-dir) "doom-docs-org-ids"))
(let ((org-id-locations-file doom-docs--id-location-file)
(org-id-track-globally t)
org-agenda-files
org-id-extra-files
@ -465,14 +464,26 @@ This primes `org-mode' for reading."
(let ((org-id-link-to-org-use-id t)
(org-id-method 'uuid)
(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-files doom-docs--id-files))
(doom/reload-docs)
(let ((id (org-id-new)))
(org-id-add-location
id (buffer-file-name (buffer-base-buffer)))
id)))
(when-let (fname (buffer-file-name (buffer-base-buffer)))
(let ((id (org-id-new)))
(org-id-add-location id fname)
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
(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
`read-only-mode' is activated."
:after-hook (visual-line-mode -1)
(font-lock-add-keywords nil doom-docs-org-font-lock-keywords)
(let ((gc-cons-threshold most-positive-fixnum)
(gc-cons-percentage 1.0))
(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
org-id-method 'uuid
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-files doom-docs--id-files
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))
(coding-system-for-read (or ,coding '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)
(setq-local buffer-file-coding-system 'binary))
,@body))
@ -245,7 +245,8 @@ special values:
'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.
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
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
`prin1'. BY is the function to use to emit
MODE dictates the permissions of the file. If FILE already exists, its
permissions will be changed.
MODE dictates the permissions of created file and directories. MODE is either an
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').
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,
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."
(doom--with-prepared-file-buffer file coding mode
(let ((contents (ensure-list contents))
datum)
(let ((mode (ensure-list mode))
(contents (ensure-list contents))
datum)
(doom--with-prepared-file-buffer file coding (car mode)
(while (setq datum (pop contents))
(cond ((stringp datum)
(funcall
@ -325,15 +329,21 @@ ends. Set either APPEND or PREPEND to `noerror' to silently ignore read errors."
((let ((standard-output (current-buffer))
(print-quoted t)
(print-level nil)
(print-length nil))
(funcall printfn datum))))))
(let (write-region-annotate-functions
write-region-post-annotation-function)
(when mkdir
(make-directory (file-name-directory buffer-file-name)
(eq mkdir 'parents)))
(write-region nil nil buffer-file-name append :silent))
buffer-file-name))
(print-length nil)
;; Escape special chars to avoid any shenanigans
(print-escape-newlines t)
(print-escape-control-characters t)
(print-escape-nonascii t)
(print-escape-multibyte t))
(funcall printfn datum)))))
(let (write-region-annotate-functions
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
(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)
"Open 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
(defun doom/sudo-this-file ()
@ -517,5 +527,77 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation."
(recentf-save-list)
(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))
;;; files.el ends here

View file

@ -168,7 +168,8 @@ selection of all minor-modes, active or not."
(location
(goto-char location)))
(ignore-errors
(when (outline-invisible-p)
(when (memq (get-char-property (point) 'invisible)
'(outline org-fold-outline))
(save-excursion
(outline-previous-visible-heading 1)
(org-show-subtree))))))
@ -575,7 +576,10 @@ If prefix arg is present, refresh the cache."
(pp-to-string recipe))))
(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 ")
(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))
(user-error "Uneven number of packages being bumped"))
(dolist (p1 before)
(cl-destructuring-bind (package &key plist _beg _end &allow-other-keys) p1
(let ((p2 (cdr (assq package after))))
(if (null p2)
(push package errors)
(let ((bstr1 (doom--package-to-bump-string package plist))
(bstr2 (doom--package-to-bump-string package (plist-get p2 :plist))))
(cl-pushnew (format "%s -> %s" bstr1 bstr2) lines :test #'equal))))))
(when (and (listp p1) (plist-get (cdr p1) :package))
(cl-destructuring-bind (package &key plist _beg _end &allow-other-keys) p1
(let ((p2 (cdr (assq package after))))
(if (null p2)
(push package errors)
(let ((bstr1 (doom--package-to-bump-string package plist))
(bstr2 (doom--package-to-bump-string package (plist-get p2 :plist))))
(cl-pushnew (format "%s -> %s" bstr1 bstr2) lines :test #'equal)))))))
(if (null lines)
(user-error "No bumps to bumpify")
(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
(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)
(relpath . (lambda (str &optional dir)
(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)
#'counsel-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)
(fboundp 'counsel-file-jump))
(call-interactively #'counsel-file-jump))
((project-current nil dir)
(project-find-file-in nil nil dir))
((when-let ((pr (project-current nil dir)))
(project-find-file-in nil nil pr)))
((and (bound-and-true-p helm-mode)
(fboundp 'helm-find-files))
(call-interactively #'helm-find-files))

View file

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

View file

@ -88,10 +88,11 @@ Uses `evil-visual-beginning' if available."
"Return end position of selection.
Uses `evil-visual-end' if available."
(declare (side-effect-free t))
(if (and (bound-and-true-p evil-local-mode)
(evil-visual-state-p))
evil-visual-end
(region-end)))
(or (and (bound-and-true-p evil-local-mode)
(evil-visual-state-p)
(markerp evil-visual-end)
(marker-position evil-visual-end))
(region-end)))
;;;###autoload
(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.
OPACITY is an integer between 0 to 100, inclusive."
(interactive
(list (read-number "Opacity (0-100): "
(or (frame-parameter nil 'alpha)
100))))
(set-frame-parameter nil 'alpha opacity))
(interactive '(interactive))
(let* ((parameter
(if (eq window-system 'pgtk)
'alpha-background
'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)
;;;###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).
Inspired from http://demonastery.org/2013/04/emacs-evil-narrow-region/"
(interactive
(list (or (bound-and-true-p evil-visual-beginning) (region-beginning))
(or (bound-and-true-p evil-visual-end) (region-end))))
(unless (region-active-p)
(setq beg (line-beginning-position)
end (line-end-position)))
(interactive (if (region-active-p)
(list (doom-region-beginning) (doom-region-end))
(list (bol) (eol))))
(deactivate-mark)
(let ((orig-buffer (current-buffer)))
(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
(defun doom/toggle-narrow-buffer (beg end)
"Narrow the buffer to BEG END. If narrowed, widen it."
(interactive
(list (or (bound-and-true-p evil-visual-beginning) (region-beginning))
(or (bound-and-true-p evil-visual-end) (region-end))))
(interactive (if (region-active-p)
(list (doom-region-beginning) (doom-region-end))
(list (bol) (eol))))
(if (buffer-narrowed-p)
(widen)
(unless (region-active-p)
(setq beg (line-beginning-position)
end (line-end-position)))
(narrow-to-region beg end)))

View file

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

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]].
- 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).
- Prettified =mu4e:main= view.
- 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:
| 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 clojure]] | clojure-mode | clojure-lsp |
| [[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.
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.
- The first time you run Emacs a unicode cache will be generated -- this will
take a while!
- 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
configuration or the versions of relevant packages changes.

View file

@ -34,12 +34,12 @@ This module requires:
* TODO Usage
#+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
* TODO Configuration
#+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
** Changing calendar sources
@ -74,5 +74,5 @@ to link your calendar with Google calendars.
* TODO Appendix
#+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

View file

@ -5,4 +5,4 @@
(package! calfw-org :pin "03abce97620a4a7f7ec5f911e669da9031ab9088")
(package! calfw-cal :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
#+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
** Keybinds
@ -56,7 +56,7 @@ These should be available through your OS package manager.
* TODO Configuration
#+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
* Troubleshooting
@ -70,5 +70,5 @@ Try [[kbd:][M-x +emms/mpd-restart-music-daemon]] then restart emacs.
* TODO Appendix
#+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

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; 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
#+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

View file

@ -8,19 +8,23 @@
:config
(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
;; this hook, which will rarely work well in emacs-everywhere's temporary
;; buffers anyway.
(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
(doom-modeline-def-segment emacs-everywhere
(concat
(doom-modeline-spc)
(when (emacs-everywhere-markdown-p)
(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)))
(propertize (emacs-everywhere-app-class emacs-everywhere-current-app)
'face 'doom-modeline-project-dir)
@ -32,7 +36,7 @@
(doom-modeline-def-modeline 'emacs-everywhere
'(bar modals emacs-everywhere buffer-position
word-count parrot selection-info)
'(input-method major-mode checker
'(input-method major-mode check
#("" 0 1 ; "Exit to app" icon + a little padding
(rear-nonsticky t
display (raise -0.25)

View file

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

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*-
;;; 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
#+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
To connect to IRC use ~M-x =irc~.
@ -70,7 +70,7 @@ When in a circe buffer these keybindings will be available:
* TODO Configuration
#+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
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
#+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
[[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
#+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

View file

@ -55,7 +55,8 @@ workspace for it."
circe-server-killed-confirmation)
(when +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))
(when (modulep! :ui workspaces)
(when (equal (+workspace-current-name) +irc--workspace-name)

View file

@ -187,8 +187,8 @@ playback.")
(setq circe-notifications-watch-strings +irc-notifications-watch-strings
circe-notifications-emacs-focused nil
circe-notifications-alert-style
(cond (IS-MAC 'osx-notifier)
(IS-LINUX 'libnotify)
(cond ((featurep :system 'macos) 'osx-notifier)
((featurep :system 'linux) 'libnotify)
(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; -*-
;;; app/irc/packages.el
(package! circe :pin "57fe189d7c0b98b9b1b5a59767cea1c7e2c22b13")
(package! circe :pin "d374042741cfd0691135f215d311dca8b7a47d19")
(package! circe-notifications :pin "291149ac12877bbd062da993479d3533a26862b0")

View file

@ -39,7 +39,7 @@ Read RSS feeds in the comfort of Emacs.
* TODO Usage
#+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
- 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
#+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
** 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]])
and put name as you want into ~description~.
- 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
+ General
@ -128,5 +128,5 @@ Hook ~elfeed-update~ to ~elfeed-search-mode-hook~:
* TODO Appendix
#+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

View file

@ -14,8 +14,9 @@ easier to scroll through.")
(defvar +rss-workspace-name "*rss*"
"Name of the workspace that contains the elfeed buffer.")
;;
;; Packages
;;; Packages
(use-package! elfeed
:commands elfeed
@ -83,6 +84,7 @@ easier to scroll through.")
(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))))))
(use-package! elfeed-goodies
:after elfeed
:config

View file

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

View file

@ -3,6 +3,11 @@
#+created: October 11, 2019
#+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:
Enjoy twitter from emacs.
@ -48,12 +53,12 @@ This module requires:
* TODO Usage
#+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
* TODO Configuration
#+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
** Commands & Keybindings
@ -96,6 +101,6 @@ key for evil users. To work around this issue you may use [[kbd:][M-SPC]] instea
* TODO Appendix
#+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

View file

@ -2,4 +2,4 @@
;;; app/twitter/packages.el
(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
#+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
** 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+.
#+begin_quote
🚧 This requires Java 1.8+
This requires Java 1.8+
#+end_quote
*** Commands
@ -61,7 +61,7 @@ This minor mode highlights weasel words, duplication and passive voice.
* TODO Configuration
#+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
* Troubleshooting
@ -72,5 +72,5 @@ This minor mode highlights weasel words, duplication and passive voice.
* TODO Appendix
#+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

View file

@ -13,7 +13,7 @@
(cond ((setq langtool-bin
(or (executable-find "languagetool-commandline")
(executable-find "languagetool")))) ; for nixpkgs.languagetool
(IS-MAC
((featurep :system 'macos)
(cond
;; is user using home brew?
((file-directory-p "/usr/local/Cellar/languagetool")
@ -25,7 +25,7 @@
;; macports compatibility
((file-directory-p "/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/*")))))

View file

@ -1,5 +1,5 @@
;; -*- no-byte-compile: t; -*-
;;; checkers/grammar/packages.el
(package! langtool :pin "8276eccc5587bc12fd205ee58a7a982f0a136e41")
(package! writegood-mode :pin "ed42d918d98826ad88928b7af9f2597502afc6b0")
(package! langtool :pin "d86101eafe9a994eb0425e08e7c1795e9cb0cd42")
(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).
#+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
because [[doom-package:spell-fu]] does not support generating the word list with anything
other than =aspell= yet.
@ -108,7 +108,7 @@ language(s).
* TODO Usage
#+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
When using [[doom-module:+everywhere]], spell checking is performed for as many major modes as
@ -117,7 +117,7 @@ major modes.
* TODO Configuration
#+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
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
#+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

View file

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

View file

@ -40,7 +40,7 @@ find out if you're missing any dependencies.
* TODO Usage
#+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
Most of flycheck's features are under [[kbd:][C-c !]], regardless of whether evil mode is
@ -67,7 +67,7 @@ Evil Specific:
* TODO Configuration
#+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
* Troubleshooting
@ -81,5 +81,5 @@ Evil Specific:
* TODO Appendix
#+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

View file

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

View file

@ -44,7 +44,7 @@ find out if you're missing any dependencies.
* TODO Usage
#+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
** Code completion
@ -87,7 +87,7 @@ More information can be found [[https://github.com/oantolin/orderless#company][h
* TODO Configuration
#+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
** Enable company backend(s) in certain modes
@ -142,5 +142,5 @@ on changing what backends are available for that mode.
* TODO Appendix
#+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

View file

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

View file

@ -1,7 +1,7 @@
;; -*- no-byte-compile: t; -*-
;;; completion/company/packages.el
(package! company :pin "2ca3e29abf87392714bc2b26e50e1c0f4b9f4e2c")
(package! company :pin "02903bd7088d65a87df0ae0f0d0a7118de147b69")
(package! company-dict :pin "cd7b8394f6014c57897f65d335d6b2bd65dab1f4")
(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.
- +icons ::
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
- [[doom-package:helm]]
@ -40,7 +40,7 @@ For official documentation about Helm, see:
** TODO Hacks
#+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
** TODO Changelog
@ -74,18 +74,18 @@ its highlights will be covered here.
** Jump-to navigation
Similar to Ivy, this module provides an interface to navigate within a project
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 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
This module also provides interactive text search and replace using [[https://github.com/BurntSushi/ripgrep][Ripgrep]].
*** Search
| Keybind | Description |
|---------+-----------------------------------------------------------|
| Keybind | Description |
|-------------------+---------------------------------------------------------|
| [[kbd:][SPC s p]] | Search project (~+default/search-project~) |
| [[kbd:][SPC s P]] | Search another project (~+default/search-other-project~) |
| [[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.
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]d[!] [QUERY]~ | Search from current directory (if ~!~, don't search recursively) |
@ -106,8 +106,8 @@ commands.
*** Replace
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-e]] | Open a writable buffer of your search results |
| [[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:
*** General
| Keybind | Description |
|------------+---------------------------|
| Keybind | Description |
|--------------------------------+---------------------------|
| [[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
| Keybind | Description |
|---------+----------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| Keybind | Description |
|-------------------+--------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[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 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 another project (~+default/search-other-project~) |
| [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) |
*** Search
| Keybind | Description |
|---------+----------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| Keybind | Description |
|-------------------+--------------------------------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[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 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 another project (~+default/search-other-project~) |
| [[kbd:][SPC s s]] | Search the current buffer (incrementally) (~+default/search-buffer~) |
* TODO Configuration
#+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
** helm-mode
@ -182,9 +182,9 @@ makes sense to exempt ~foo~ with the following:
** Icons
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,
[[doom-package:all-the-icons]] is used. To change this:
[[doom-package:nerd-icons]] is used. To change this:
#+begin_src emacs-lisp
;; add to $DOOMDIR/config.el
(after! helm
@ -202,5 +202,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* TODO Appendix
#+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

View file

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

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; -*-
;;; completion/helm/packages.el
(package! helm :pin "dfd6403947c5cd9f32afcd6bc92a1756cc958c82")
(package! helm-company :pin "6eb5c2d730a60e394e005b47c1db018697094dde")
(package! helm-c-yasnippet :pin "e214eec8b2875d8a7cd09006dfb6a8e15e9e4079")
(package! helm :pin "f34ea6b702648e5c7535a704bdb6c4d7afb4b3b8")
(package! helm-company :pin "4622b82353220ee6cc33468f710fa5b6b253b7f1")
(package! helm-c-yasnippet :pin "c5880e740da101fde7a995e94a7b16c330e57583")
(package! helm-descbinds :pin "b72515982396b6e336ad7beb6767e95a80fca192")
(package! helm-describe-modes :pin "11fb36af119b784539d31c6160002de1957408aa")
(package! helm-projectile :pin "35a2111d00c0c0c9d8743280d3f1243bb217118a")
(package! helm-projectile :pin "e2e38825c975269a4971df25e79b2ae98929624e")
(package! helm-rg :pin "ee0a3c09da0c843715344919400ab0a0190cc9dc")
(package! swiper-helm :pin "93fb6db87bc6a5967898b5fd3286954cc72a0008")
(when (modulep! +childframe)
(package! helm-posframe :pin "87461b52b6f3f378c63642a33f584d4a4ba28351"))
(package! helm-posframe :pin "0b6bb016f0ff4980860a9d00574de311748c40b0"))
(when (modulep! +fuzzy)
(package! helm-flx :pin "5220099e695a3586dba2d59640217fe378e66310"))
(when (modulep! +icons)
(package! helm-icons :pin "8d2f5e705c8b78a390677cf242024739c932fc95"))
(package! helm-icons :pin "0d113719ee72cb7b6bb7db29f7200d667bd86607"))
(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
#+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
* Configuration
#+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
* Troubleshooting
@ -52,5 +52,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* Appendix
#+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

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; -*-
;;; completion/ido/packages.el
(package! flx-ido :pin "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2")
(package! ido-completing-read+ :pin "49e7967ea8c0ab0a206b40d70fc19be115083fa1")
(package! flx-ido :pin "4b1346eb9a8a76ee9c9dede69738c63ad97ac5b6")
(package! ido-completing-read+ :pin "5995b4605b4f2d568489491704ef21bc49ddecd5")
(package! ido-sort-mtime :pin "f638ff0c922af862f5211779f2311a27fde428eb")
(package! ido-vertical-mode :pin "b1659e967da0687abceca733b389ace24004fa66")
(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.
** 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:counsel]]
- [[doom-package:counsel-projectile]]
@ -64,7 +64,7 @@ use their associated Helm command or plugin.
* TODO Usage
#+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
[[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
#+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
** TODO Enable fuzzy/non-fuzzy search for specific commands
** TODO Change the position of the ivy childframe
* 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
[[doom-suggest-faq:][Ask a question?]]
@ -186,5 +195,5 @@ See [[id:4f36ae11-1da8-4624-9c30-46b764e849fc][this answer]].
* TODO Appendix
#+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

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))
(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
(defun +ivy-rich-describe-variable-transformer (cand)
"Previews the value of the variable in the minibuffer"

View file

@ -116,12 +116,6 @@ results buffer.")
:config
(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)
(let ((filename (ivy-rich-bookmark-filename candidate)))
(if (not filename) "" filename)))
@ -155,25 +149,16 @@ results buffer.")
(switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns))))
(setcar switch-buffer-alist '+ivy-rich-buffer-name))
(when (modulep! +icons)
(nerd-icons-ivy-rich-mode +1))
(ivy-rich-mode +1)
(ivy-rich-project-root-cache-mode +1))
(use-package! all-the-icons-ivy
(use-package! nerd-icons-ivy-rich
:when (modulep! +icons)
:after ivy
:config
;; `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))))
:commands (nerd-icons-ivy-rich-mode)
:after counsel-projectile)
(use-package! counsel
@ -237,7 +222,6 @@ results buffer.")
;; 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 #'recenter)
(ivy-add-actions
'counsel-rg ; also applies to `counsel-rg'
'(("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))
;; `counsel-locate'
(when IS-MAC
(when (featurep :system 'macos)
;; Use spotlight on mac by default since it doesn't need any additional setup
(setq counsel-locate-cmd #'counsel-locate-cmd-mdfind))
@ -292,13 +276,13 @@ results buffer.")
(cl-loop for dir in projectile-globally-ignored-directories
collect "--exclude"
collect dir)
(if IS-WINDOWS '("--path-separator=/")))))
(if (featurep :system 'windows) '("--path-separator=/")))))
((executable-find "rg" t)
(append (list "rg" "--hidden" "--files" "--follow" "--color=never" "--no-messages")
(cl-loop for dir in projectile-globally-ignored-directories
collect "--glob"
collect (concat "!" dir))
(if IS-WINDOWS '("--path-separator=/"))))
(if (featurep :system 'windows) '("--path-separator=/"))))
((cons find-program args)))
(unless (listp args)
(user-error "`counsel-file-jump-args' is a list now, please customize accordingly."))
@ -315,7 +299,7 @@ results buffer.")
(use-package! counsel-projectile
:defer t
:after ivy-rich
:init
(define-key!
[remap projectile-find-file] #'+ivy/projectile-find-file

View file

@ -1,3 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; 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; -*-
;;; completion/ivy/packages.el
(package! swiper :pin "9d630d800e856a2c984c5a62a6f0ad313a9d2228")
(package! swiper :pin "8c30f4cab5948aa8d942a3b2bbf5fb6a94d9441d")
(package! ivy)
(package! ivy-hydra)
(package! ivy-avy)
@ -10,15 +10,15 @@
(package! amx :pin "5b3aa1aae84f4a225cb8d26ab79a32f97693f023")
(package! counsel-projectile :pin "40d1e1d4bb70acb00fddd6f4df9778bf2c52734b")
(package! ivy-rich :pin "aff9b6bd53e0fdcf350ab83c90e64e651b47dba4")
(package! wgrep :pin "3132abd3750b8c87cbcf6942db952acfab5edccd")
(package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4")
(if (modulep! +prescient)
(package! ivy-prescient :pin "d7cc55dad453c465af9ececbab94426202b5b32b")
(package! ivy-prescient :pin "4b875be52e75f7b81e68a16b62cfbb2f2584042c")
(when (modulep! +fuzzy)
(package! flx :pin "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2")))
(package! flx :pin "4b1346eb9a8a76ee9c9dede69738c63ad97ac5b6")))
(when (modulep! +childframe)
(package! ivy-posframe :pin "533a8e368fcabfd534761a5c685ce713376fa594"))
(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.
** 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-flycheck]] if [[doom-module::checkers syntax]]
- [[doom-package:embark]]
@ -63,7 +63,7 @@ intend to use their associated Helm command or plugin.
* TODO Usage
#+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
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
keybindings are available:
| Keybind | Description |
|-------------------+----------------------------------------------------------------|
| [[kbd:][C-k]] | (evil) Go to previous candidate |
| [[kbd:][C-j]] | (evil) Go to next candidate |
| [[kbd:][C-M-k]] | (evil) Go to previous group |
| [[kbd:][C-M-j]] | (evil) Go to next group |
| Keybind | Description |
|---------------------------------------+--------------------------------------------------------------|
| [[kbd:][C-k]] | (evil) Go to previous candidate |
| [[kbd:][C-j]] | (evil) Go to next candidate |
| [[kbd:][C-M-k]] | (evil) Go to previous 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-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-SPC]] | Preview the current candidate |
| [[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-SPC]] | Preview the current candidate |
~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
@ -99,17 +99,17 @@ This module provides an interface to navigate within a project using
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 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
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 another project |
| [[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
*** General
| Keybind | Description |
|------------+-----------------------------|
| Keybind | Description |
|--------------------------------+-----------------------------|
| [[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
| Keybind | Description |
|------------------+---------------------------------------|
| [[kbd:][SPC RET]] | Find bookmark |
| Keybind | Description |
|--------------------------------------+---------------------------------------|
| [[kbd:][SPC RET]] | Find bookmark |
| [[kbd:][SPC f f]], [[kbd:][SPC .]] | Browse from current directory |
| [[kbd:][SPC p f]], [[kbd:][SPC SPC]] | Find file in project |
| [[kbd:][SPC f r]] | Find recently opened file |
| [[kbd:][SPC p p]] | Open another project |
| [[kbd:][SPC f r]] | Find recently opened file |
| [[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 |
@ -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]].
*** Search
| Keybind | Description |
|---------+-------------------------------------------|
| Keybind | Description |
|-------------------+-------------------------------------------|
| [[kbd:][SPC p t]] | List all TODO/FIXMEs in project |
| [[kbd:][SPC s b]] | Search the current buffer |
| [[kbd:][SPC s d]] | Search this directory |
@ -200,10 +200,10 @@ to =~/=.
*** Multiple candidate search
This module modifies the default keybindings used in
~consult-completing-read-multiple~:
| Keybind | Description |
|---------+-------------------------------------------------------------|
| [[kbd:][TAB]] | Select or deselect current candidate |
| [[kbd:][RET]] | Enters selected candidates (also toggles current candidate) |
| Keybind | Description |
|---------------+-------------------------------------------------------------|
| [[kbd:][TAB]] | Select or deselect current candidate |
| [[kbd:][RET]] | Enters selected candidates (also toggles current candidate) |
*** Async search commands
:PROPERTIES:
@ -226,9 +226,9 @@ filtering should be done after a second =#=.
For more information [[https://github.com/minad/consult#asynchronous-search][see here]].
** Marginalia
| Keybind | Description |
|---------+---------------------------------|
| [[kbd:][M-A]] | Cycle between annotation levels |
| Keybind | Description |
|---------------+---------------------------------|
| [[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
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
#+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
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
#+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

View file

@ -13,7 +13,9 @@
:in PATH
Sets what directory to base the search out of. Defaults to the current project's root.
: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))
(unless (executable-find "rg")
(user-error "Couldn't find ripgrep in your PATH"))
@ -29,7 +31,7 @@
"--path-separator / --smart-case --no-heading "
"--with-filename --line-number --search-zip "
"--hidden -g !.git -g !.svn -g !.hg "
(mapconcat #'shell-quote-argument args " ")))
(mapconcat #'identity args " ")))
(prompt (if (stringp prompt) (string-trim prompt) "Search"))
(query (or query
(when (doom-region-active-p)
@ -135,26 +137,6 @@ Supports exporting consult-grep to wgrep, file to wdeired, and consult-location
(+vertico/embark-preview)
(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
(defun +vertico/jump-list (jump)
"Go to an entry in evil's (or better-jumper's) jumplist."
@ -227,27 +209,23 @@ targets."
(not (string-suffix-p "-argument" (cdr binding))))))))
;;;###autoload
(defun +vertico--consult--fd-make-builder ()
(let ((cmd (split-string-and-unquote +vertico-consult-fd-args)))
(lambda (input)
(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)
(defun +vertico/consult-fd-or-find (&optional dir initial)
"Runs consult-fd if fd version > 8.6.0 exists, consult-find otherwise.
See URL `https://github.com/minad/consult/issues/770'."
(interactive "P")
(if doom-projectile-fd-binary
(pcase-let* ((`(,prompt ,paths ,dir) (consult--directory-prompt "Fd" dir))
(default-directory dir)
(builder (consult--find-make-builder paths)))
(find-file (consult--find prompt builder initial)))
;; TODO this condition was adapted from a similar one in lisp/doom-projects.el, to be replaced with a more robust check post v3
(if (when-let*
((bin (if (ignore-errors (file-remote-p default-directory nil t))
(cl-find-if (doom-rpartial #'executable-find t)
(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)))
;;;###autoload

View file

@ -86,8 +86,8 @@ buffer will be opened in the current workspace instead."
(funcall consult--buffer-display (car buffer)))))))
;;;###autoload
(defun +vertico/embark-open-in-new-workspace (x)
"Open X (a file) in a new workspace."
(interactive)
(defun +vertico/embark-open-in-new-workspace (file)
"Open file in a new workspace."
(interactive "GFile:")
(+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
overrides `completion-styles' during company completion sessions.")
(defvar +vertico-consult-fd-args nil
"Shell command and arguments the vertico module uses for fd.")
(defvar +vertico-consult-dir-container-executable "docker"
"Command to call for listing container hosts.")
(defvar +vertico-consult-dir-container-args nil
"Command to call for listing container hosts.")
;;
;;; Packages
@ -80,6 +83,9 @@ orderless."
((string= "!" pattern) `(orderless-literal . ""))
;; Without literal
((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
((string-prefix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 1)))
((string-suffix-p "%" pattern) `(char-fold-to-regexp . ,(substring pattern 0 -1)))
@ -104,7 +110,7 @@ orderless."
;; find-file etc.
completion-category-overrides '((file (styles +vertico-basic-remote orderless partial-completion)))
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
(set-face-attribute 'completions-first-difference nil :inherit nil))
@ -130,25 +136,26 @@ orderless."
[remap yank-pop] #'consult-yank-pop
[remap persp-switch-to-buffer] #'+vertico/switch-workspace-buffer)
:config
(defadvice! +vertico--consult-recent-file-a (&rest _args)
"`consult-recent-file' needs to have `recentf-mode' on to work correctly"
:before #'consult-recent-file
(defadvice! +vertico--consult-recentf-a (&rest _args)
"`consult-recent-file' needs to have `recentf-mode' on to work correctly.
`consult-buffer' needs `recentf-mode' to show file candidates."
:before (list #'consult-recent-file #'consult-buffer)
(recentf-mode +1))
(setq consult-project-root-function #'doom-project-root
(setq consult-project-function #'doom-project-root
consult-narrow-key "<"
consult-line-numbers-widen t
consult-async-min-input 2
consult-async-refresh-delay 0.15
consult-async-input-throttle 0.2
consult-async-input-debounce 0.1)
(unless +vertico-consult-fd-args
(setq +vertico-consult-fd-args
(if doom-projectile-fd-binary
(format "%s --color=never -i -H -E .git --regex %s"
doom-projectile-fd-binary
(if IS-WINDOWS "--path-separator=/" ""))
consult-find-args)))
consult-async-input-debounce 0.1
consult-fd-args
'((if (executable-find "fdfind" 'remote) "fdfind" "fd")
"--color=never"
;; https://github.com/sharkdp/fd/issues/839
"--full-path --absolute-path"
"--hidden --exclude .git"
(if (featurep :system 'windows) "--path-separator=/")))
(consult-customize
consult-ripgrep consult-git-grep consult-grep
@ -191,28 +198,42 @@ orderless."
(use-package! consult-dir
:bind (([remap list-directory] . consult-dir)
:defer t
:init
(map! [remap list-directory] #'consult-dir
(:after vertico
:map vertico-map
("C-x C-d" . consult-dir)
("C-x C-j" . consult-dir-jump-file))
"C-x C-d" #'consult-dir
"C-x C-j" #'consult-dir-jump-file))
:config
(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 ()
"Get a list of hosts from docker."
(when (if (>= emacs-major-version 29)
(require 'tramp-container nil t)
(setq-local docker-tramp-use-names t)
(require 'docker-tramp nil t))
(let ((hosts)
(docker-query-fn #'docker-tramp--parse-running-containers))
(when (>= emacs-major-version 29)
(setq docker-query-fn #'tramp-docker--completion-function))
(dolist (cand (funcall docker-query-fn))
(let ((user (unless (string-empty-p (car cand))
(concat (car cand) "@")))
(host (car (cdr cand))))
(push (concat "/docker:" user host ":/") hosts)))
hosts)))
(let ((+vertico-consult-dir-container-executable "docker"))
(+vertico--consult-dir-container-hosts "docker")))
(defvar +vertico--consult-dir-source-tramp-podman
`(:name "Podman"
:narrow ?p
:category file
:face consult-file
:history file-name-history
:items ,#'+vertico--consult-dir-podman-hosts)
"Podman candidate source for `consult-dir'.")
(defvar +vertico--consult-dir-source-tramp-docker
`(:name "Docker"
@ -221,8 +242,9 @@ orderless."
:face consult-file
:history file-name-history
: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 'consult-dir--source-tramp-ssh t)
@ -233,6 +255,11 @@ orderless."
(not (modulep! :checkers syntax +flymake)))
:after (consult flycheck))
(use-package! consult-yasnippet
:when (modulep! :editor snippets)
:defer t
:init (map! [remap yas-insert-snippet] #'consult-yasnippet))
(use-package! embark
:defer t
@ -253,14 +280,16 @@ orderless."
(set-popup-rule! "^\\*Embark Export:" :size 0.35 :ttl 0 :quit nil)
(defadvice! +vertico--embark-which-key-prompt-a (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
:around #'embark-completing-read-prompter
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-indicator embark-indicators)))
(apply fn args)))
(cl-nsubstitute #'+vertico-embark-which-key-indicator #'embark-mixed-indicator embark-indicators)
(after! which-key
(defadvice! +vertico--embark-which-key-prompt-a (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
:around #'embark-completing-read-prompter
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-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,
;; so we don't get a false positive match.
(let ((pos (or (cl-position
@ -282,9 +311,10 @@ orderless."
(map! (:map embark-file-map
:desc "Open target with sudo" "s" #'doom/sudo-find-file
(: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)
: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
@ -294,7 +324,7 @@ orderless."
:desc "Cycle marginalia views" "M-A" #'marginalia-cycle)
:config
(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)
(pushnew! marginalia-command-categories
'(+default/find-file-under-here . file)
@ -320,3 +350,44 @@ orderless."
:hook (vertico-mode . vertico-posframe-mode)
:config
(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)
;; FIXME: This throws an error if grep is missing.

View file

@ -1,29 +1,29 @@
;; -*- no-byte-compile: t; -*-
;;; completion/vertico/packages.el
(package! vertico
:recipe (:host github :repo "minad/vertico"
:files ("*.el" "extensions/*.el"))
:pin "a28370d07f35c5387c7a9ec2e5b67f0d4598058d")
(package! vertico :pin "68cbd47589446e9674921bae0b98ff8fbe28be23")
(package! orderless :pin "e6784026717a8a6a7dcd0bf31fd3414f148c542e")
(package! orderless :pin "dc7a781acf2e58ac7d20d1b522be0cde5213e057")
(package! consult :pin "fe49dedd71802ff97be7b89f1ec4bd61b98c2b13")
(package! consult-dir :pin "ed8f0874d26f10f5c5b181ab9f2cf4107df8a0eb")
(package! consult :pin "b48ff6bf0527baeb6bfd07c6da9d303ff0b79c3d")
(package! consult-dir :pin "3f5f4b71ebe819392cb090cda71bd39a93bd830a")
(when (and (modulep! :checkers syntax)
(not (modulep! :checkers syntax +flymake)))
(package! consult-flycheck :pin "3f2a7c17cc2fe64e0c07e3bf90e33c885c0d7062"))
(package! embark :pin "9a44418c349e41020cdc5ad1bd21e8c77a429062")
(package! embark-consult :pin "9a44418c349e41020cdc5ad1bd21e8c77a429062")
(package! consult-flycheck :pin "754f5497d827f7d58009256a21af614cc44378a3"))
(package! embark :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e")
(package! embark-consult :pin "c93abadc8220c0caa6fea805f7a736c346d47e7e")
(package! marginalia :pin "866e50aee4f066b0903752c69b33e9b7cab93f97")
(package! marginalia :pin "f6fe86b989a177355ab3ff7e97a384e10a7b0bb1")
(package! wgrep :pin "3132abd3750b8c87cbcf6942db952acfab5edccd")
(package! wgrep :pin "208b9d01cfffa71037527e3a324684b3ce45ddc4")
(when (modulep! +icons)
(package! all-the-icons-completion :pin "8eb3e410d63f5d0657b41829e7898793e81f31c0"))
(package! nerd-icons-completion :pin "c2db8557a3c1a9588d111f8c8e91cae96ee85010"))
(when (modulep! +childframe)
(package! 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 "Locate file" "f" #'+lookup/file
: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 link" "L" #'ffap-menu
:desc "Jump to bookmark" "m" #'bookmark-jump
@ -145,7 +148,10 @@
;;; <leader> 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 path" "F" (cmd!! #'+default/insert-file-path t)
:desc "Snippet" "s" #'yas-insert-snippet
@ -505,7 +511,7 @@
"C-x C-b" #'ibuffer
"C-x K" #'doom/kill-this-buffer-in-all-windows
;;; company-mode
;;; completion (in-buffer)
(:when (modulep! :completion company)
"C-;" #'+company/complete
(:after company

View file

@ -43,7 +43,10 @@
#'yas-expand
(and (bound-and-true-p company-mode)
(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)
(evil-visual-state-p)
(or (eq evil-visual-selection 'line)
@ -127,7 +130,7 @@
;;
;;; Module keybinds
;;; :completion
;;; :completion (in-buffer)
(map! (:when (modulep! :completion company)
:i "C-@" (cmds! (not (minibufferp)) #'company-complete-common)
:i "C-SPC" (cmds! (not (minibufferp)) #'company-complete-common)
@ -156,7 +159,38 @@
"C-s" #'company-filter-candidates
[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
:map ivy-minibuffer-map
"C-SPC" #'ivy-call-and-recenter ; preview file
@ -169,7 +203,8 @@
[C-return] #'+ivy/git-grep-other-window-action))
(:when (modulep! :completion helm)
(:after helm :map helm-map
(:after helm
:map helm-map
[remap next-line] #'helm-next-line
[remap previous-line] #'helm-previous-line
[left] #'left-char
@ -228,7 +263,7 @@
:g "M-8" #'+workspace/switch-to-7
:g "M-9" #'+workspace/switch-to-8
:g "M-0" #'+workspace/switch-to-final
(:when IS-MAC
(:when (featurep :system 'macos)
:g "s-t" #'+workspace/new
:g "s-T" #'+workspace/display
:n "s-1" #'+workspace/switch-to-0
@ -371,8 +406,11 @@
;;; <leader> c --- code
(:prefix-map ("c" . "code")
(:when (and (modulep! :tools lsp) (not (modulep! :tools lsp +eglot)))
:desc "LSP Execute code action" "a" #'lsp-execute-code-action
:desc "LSP Organize imports" "o" #'lsp-organize-imports
:desc "LSP Execute code action" "a" #'lsp-execute-code-action
: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)
: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)
@ -386,10 +424,7 @@
:desc "Errors list" "X" #'lsp-treemacs-errors-list
:desc "Incoming call hierarchy" "y" #'lsp-treemacs-call-hierarchy
:desc "Outgoing call hierarchy" "Y" (cmd!! #'lsp-treemacs-call-hierarchy 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)
:desc "References tree" "R" (cmd!! #'lsp-treemacs-references t)))
(:when (modulep! :tools lsp +eglot)
:desc "LSP Execute code action" "a" #'eglot-code-actions
:desc "LSP Rename" "r" #'eglot-rename
@ -496,7 +531,10 @@
;;; <leader> 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 path" "F" (cmd!! #'+default/insert-file-path t)
:desc "Evil ex path" "p" (cmd! (evil-ex "R!echo "))
@ -674,7 +712,7 @@
:desc "Configure project" "g" #'projectile-configure-project
:desc "Invalidate project cache" "i" #'projectile-invalidate-cache
: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 "Find recent project files" "r" #'projectile-recentf
:desc "Run project" "R" #'projectile-run-project
@ -736,6 +774,9 @@
:desc "Search .emacs.d" "e" #'+default/search-emacsd
:desc "Locate file" "f" #'locate
: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 link" "L" #'ffap-menu
:desc "Jump list" "j" #'evil-show-jumps
@ -754,8 +795,9 @@
((modulep! :completion helm) #'swiper-isearch-thing-at-point))
:desc "Dictionary" "t" #'+lookup/dictionary-definition
:desc "Thesaurus" "T" #'+lookup/synonyms
(:when (fboundp 'vundo)
:desc "Undo history" "u" #'vundo))
:desc "Undo history" "u"
(cond ((modulep! :emacs undo +tree) #'undo-tree-visualize)
((modulep! :emacs undo) #'vundo)))
;;; <leader> t --- toggle
(:prefix-map ("t" . "toggle")

View file

@ -43,12 +43,12 @@ This module provides a set of reasonable defaults, including:
* TODO Usage
#+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
* TODO Configuration
#+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
* Troubleshooting
@ -59,7 +59,7 @@ This module provides a set of reasonable defaults, including:
* TODO Appendix
#+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
** Commands

View file

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

View file

@ -59,11 +59,16 @@
(after! woman
;; 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
;; it's manpath.
(when (executable-find "man")
(setq woman-manpath
(split-string (cdr (doom-call-process "man" "--path"))
path-separator t))))
;; its manpath.
(let ((manpath (cond
((executable-find "manpath")
(split-string (cdr (doom-call-process "manpath"))
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
@ -76,7 +81,7 @@
;;;###package tramp
(unless IS-WINDOWS
(unless (featurep :system 'windows)
(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))
;; OS specific fixes
(when IS-MAC
(when (featurep :system 'macos)
;; Fix MacOS shift+tab
(define-key key-translation-map [S-iso-lefttab] [backtab])
;; Fix conventional OS keys in Emacs
@ -453,6 +458,48 @@ Continues comments if executed from a commented line. Consults
'(evil-ex-completion-map)))
"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.
;; 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.
@ -482,7 +529,7 @@ Continues comments if executed from a commented line. Consults
:gi "C-S-RET" #'+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-return] #'+default/newline-below
:gn "S-s-RET" #'+default/newline-above

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