Showing preview only (3,768K chars total). Download the full file or copy to clipboard to get everything.
Repository: doomemacs/doomemacs
Branch: master
Commit: ebf77f71c43c
Files: 1095
Total size: 3.4 MB
Directory structure:
gitextract_iw40yntc/
├── .doom
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ └── config.yml
│ └── workflows/
│ ├── lint-commits.yml
│ └── triage.yml
├── .gitignore
├── LICENSE
├── README.md
├── bin/
│ ├── doom
│ ├── doom.ps1
│ ├── doom.sh
│ ├── doomscript
│ └── org-capture
├── docs/
│ ├── appendix.org
│ ├── contributing.org
│ ├── examples.org
│ ├── faq.org
│ ├── getting_started.org
│ └── index.org
├── early-init.el
├── lisp/
│ ├── .doommodule
│ ├── cli/
│ │ ├── ci.el
│ │ ├── doctor.el
│ │ ├── emacs.el
│ │ ├── env.el
│ │ ├── gc.el
│ │ ├── info.el
│ │ ├── install.el
│ │ ├── make/
│ │ │ └── completions.el
│ │ ├── make.el
│ │ ├── profile.el
│ │ ├── run.el
│ │ ├── sync.el
│ │ ├── test.el
│ │ └── upgrade.el
│ ├── demos.org
│ ├── doom-cli.el
│ ├── doom-compat.el
│ ├── doom-editor.el
│ ├── doom-elpaca.el
│ ├── doom-keybinds.el
│ ├── doom-lib.el
│ ├── doom-projects.el
│ ├── doom-start.el
│ ├── doom-straight.el
│ ├── doom-ui.el
│ ├── doom.el
│ ├── init.el
│ ├── lib/
│ │ ├── autoloads.el
│ │ ├── buffers.el
│ │ ├── config.el
│ │ ├── debug.el
│ │ ├── docs.el
│ │ ├── files.el
│ │ ├── fonts.el
│ │ ├── git.el
│ │ ├── help.el
│ │ ├── indent.el
│ │ ├── modules.el
│ │ ├── packages.el
│ │ ├── plist.el
│ │ ├── print.el
│ │ ├── process.el
│ │ ├── profiles.el
│ │ ├── projects.el
│ │ ├── sandbox.el
│ │ ├── scratch.el
│ │ ├── sessions.el
│ │ ├── store.el
│ │ ├── strings.el
│ │ ├── system.el
│ │ ├── text.el
│ │ ├── themes.el
│ │ └── ui.el
│ ├── modules/
│ │ ├── .doommodule
│ │ ├── cli/
│ │ │ └── .doommodule
│ │ ├── compat/
│ │ │ └── .doommodule
│ │ └── emacs/
│ │ └── .doommodule
│ └── packages.el
├── modules/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.org
│ ├── app/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── calendar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── emms/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── everywhere/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── cli.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── irc/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── irc.el
│ │ │ │ ├── ivy.el
│ │ │ │ ├── settings.el
│ │ │ │ └── vertico.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── rss/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── checkers/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── grammar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── spell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── +flyspell.el
│ │ │ │ └── +spell-fu.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── syntax/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── completion/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── company/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── corfu/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── helm/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ └── helm.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ido/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ivy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ ├── ivy.el
│ │ │ │ └── posframe.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── vertico/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── evil.el
│ │ │ ├── magit.el
│ │ │ ├── vertico.el
│ │ │ └── workspaces.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── config/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── default/
│ │ │ ├── +emacs-bindings.el
│ │ │ ├── +evil-bindings.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── default.el
│ │ │ │ ├── deferred.el
│ │ │ │ ├── files.el
│ │ │ │ ├── search.el
│ │ │ │ └── text.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── literate/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── cli.el
│ │ └── use-package/
│ │ ├── .doommodule
│ │ ├── init.el
│ │ └── packages.el
│ ├── editor/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── evil/
│ │ │ ├── +commands.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ ├── embrace.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── ex.el
│ │ │ │ ├── files.el
│ │ │ │ ├── textobjects.el
│ │ │ │ └── unimpaired.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── file-templates/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── packages.el
│ │ │ └── templates/
│ │ │ ├── android-mode/
│ │ │ │ └── __build.gradle
│ │ │ ├── c++-mode/
│ │ │ │ ├── __cpp
│ │ │ │ ├── __hpp
│ │ │ │ ├── __main.cpp
│ │ │ │ └── __winmain.cpp
│ │ │ ├── c-mode/
│ │ │ │ ├── __c
│ │ │ │ ├── __h
│ │ │ │ └── __main.c
│ │ │ ├── direnv-envrc-mode/
│ │ │ │ └── __envrc
│ │ │ ├── dockerfile-mode/
│ │ │ │ └── __
│ │ │ ├── emacs-ert-mode/
│ │ │ │ └── __
│ │ │ ├── emacs-lisp-mode/
│ │ │ │ ├── __doom-doctor
│ │ │ │ ├── __doom-module
│ │ │ │ ├── __doom-packages
│ │ │ │ ├── __doom-test
│ │ │ │ ├── __doommodulerc
│ │ │ │ ├── __doomrc
│ │ │ │ ├── __doomrc_el
│ │ │ │ └── __package
│ │ │ ├── fish-mode/
│ │ │ │ └── __
│ │ │ ├── gitignore-mode/
│ │ │ │ └── __
│ │ │ ├── go-mode/
│ │ │ │ ├── __.go
│ │ │ │ └── __main.go
│ │ │ ├── java-mode/
│ │ │ │ ├── __annotation-type
│ │ │ │ ├── __class
│ │ │ │ ├── __enum
│ │ │ │ ├── __interface
│ │ │ │ ├── __main
│ │ │ │ └── __record
│ │ │ ├── js-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __gulpfile.js
│ │ │ │ ├── __node
│ │ │ │ └── __webpack.config.js
│ │ │ ├── json-mode/
│ │ │ │ ├── __bower.json
│ │ │ │ └── __package.json
│ │ │ ├── love-mode/
│ │ │ │ ├── __conf.lua
│ │ │ │ └── __main.lua
│ │ │ ├── makefile-gmake-mode/
│ │ │ │ ├── __
│ │ │ │ └── __cpp
│ │ │ ├── markdown-mode/
│ │ │ │ ├── __
│ │ │ │ └── __jekyll-post
│ │ │ ├── nix-mode/
│ │ │ │ ├── __
│ │ │ │ └── __shell.nix
│ │ │ ├── nose-mode/
│ │ │ │ └── __
│ │ │ ├── nxml-mode/
│ │ │ │ └── __
│ │ │ ├── org-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __contact.org
│ │ │ │ ├── __doom-category-readme
│ │ │ │ ├── __doom-docs
│ │ │ │ ├── __doom-readme
│ │ │ │ ├── __invoice.org
│ │ │ │ └── __project.org
│ │ │ ├── php-mode/
│ │ │ │ ├── __
│ │ │ │ └── __.class.php
│ │ │ ├── python-mode/
│ │ │ │ ├── __
│ │ │ │ └── __setup.py
│ │ │ ├── rspec-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __.rspec
│ │ │ │ └── __helper
│ │ │ ├── ruby-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __.gemspec
│ │ │ │ ├── __Gemfile
│ │ │ │ ├── __Rakefile
│ │ │ │ └── __module
│ │ │ ├── rust-mode/
│ │ │ │ ├── __Cargo.toml
│ │ │ │ └── __main.rs
│ │ │ ├── scss-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __master.scss
│ │ │ │ └── __normalize.scss
│ │ │ ├── sh-mode/
│ │ │ │ ├── __
│ │ │ │ └── __zunit
│ │ │ ├── slim-mode/
│ │ │ │ └── __
│ │ │ ├── snippet-mode/
│ │ │ │ └── __
│ │ │ ├── solidity-mode/
│ │ │ │ └── __sol
│ │ │ ├── text-mode/
│ │ │ │ ├── __license
│ │ │ │ ├── __license-apache
│ │ │ │ ├── __license-apache-bp
│ │ │ │ ├── __license-bsd2
│ │ │ │ ├── __license-bsd3
│ │ │ │ ├── __license-gpl3
│ │ │ │ ├── __license-gpl3-bp
│ │ │ │ ├── __license-lgpl3
│ │ │ │ ├── __license-mit
│ │ │ │ ├── __license-mozilla
│ │ │ │ ├── __license-mozilla-bp
│ │ │ │ └── __license-unlicense
│ │ │ ├── web-mode/
│ │ │ │ ├── __.html
│ │ │ │ └── __jekyll-layout.html
│ │ │ └── yaml-mode/
│ │ │ └── __docker-compose.yml
│ │ ├── fold/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── fold.el
│ │ │ │ └── hideshow.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── format/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ ├── format.el
│ │ │ │ ├── lsp.el
│ │ │ │ ├── org.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── god/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lispy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── multiple-cursors/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── evil-mc.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── objed/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── parinfer/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── rotate-text/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── packages.el
│ │ ├── snippets/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── settings.el
│ │ │ │ └── snippets.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── whitespace/
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── word-wrap/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── emacs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── dired/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── electric/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── config.el
│ │ ├── eww/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── ibuffer/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── workspaces.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── tramp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── config.el
│ │ ├── undo/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── vc/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── vc.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── email/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── mu4e/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ ├── email.el
│ │ │ │ ├── evil.el
│ │ │ │ └── mu-lock.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── notmuch/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── wanderlust/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── input/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── bidi/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── config.el
│ │ ├── chinese/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── japanese/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── layout/
│ │ ├── +azerty.el
│ │ ├── +bepo.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── bepo.el
│ │ └── config.el
│ ├── lang/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── ada/
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── agda/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── beancount/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ └── beancount.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── cc/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── clojure/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── common-lisp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── common-lisp.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── coq/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── crystal/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── csharp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── dart/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── data/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── dhall/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── elixir/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── elm/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── emacs-lisp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── emacs-lisp.el
│ │ │ │ └── helpful.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── erlang/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ess/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── factor/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── faust/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── fortran/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── doctor.el
│ │ ├── fsharp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── fstar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── gdscript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── go/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── graphql/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── graphviz/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── haskell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── hy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── idris/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── janet/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── java/
│ │ │ ├── +lsp.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── java.el
│ │ │ │ └── lsp.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── javascript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── json/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── julia/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── kotlin/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── latex/
│ │ │ ├── +fontification.el
│ │ │ ├── +ref.el
│ │ │ ├── +viewers.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── lean/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ledger/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lua/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── lua.el
│ │ │ │ └── moonscript.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── markdown/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── nim/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── nix/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ocaml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── org/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── contrib-present.el
│ │ │ │ ├── contrib-roam.el
│ │ │ │ ├── org-attach.el
│ │ │ │ ├── org-avy.el
│ │ │ │ ├── org-babel.el
│ │ │ │ ├── org-capture.el
│ │ │ │ ├── org-export.el
│ │ │ │ ├── org-link.el
│ │ │ │ ├── org-refile.el
│ │ │ │ ├── org-tables.el
│ │ │ │ └── org.el
│ │ │ ├── cli.el
│ │ │ ├── config.el
│ │ │ ├── contrib/
│ │ │ │ ├── dragndrop.el
│ │ │ │ ├── journal.el
│ │ │ │ ├── jupyter.el
│ │ │ │ ├── noter.el
│ │ │ │ ├── present.el
│ │ │ │ ├── pretty.el
│ │ │ │ └── roam.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── php/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── plantuml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── purescript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── python/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat-28.1.el
│ │ │ │ ├── conda.el
│ │ │ │ ├── pyenv.el
│ │ │ │ ├── python.el
│ │ │ │ └── uv.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── qt/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── racket/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── raku/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── rest/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── rst/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ruby/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── rust/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat.el
│ │ │ │ └── rust.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── scala/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── scheme/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── sh/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── sml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── solidity/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── swift/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── terra/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── web/
│ │ │ ├── +css.el
│ │ │ ├── +html.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── css.el
│ │ │ │ ├── evil.el
│ │ │ │ └── html.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── yaml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── zig/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── os/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── macos/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── tty/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── term/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── eshell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── commands.el
│ │ │ │ ├── company.el
│ │ │ │ ├── eshell.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── prompts.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── shell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── term/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── vterm/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── themes/
│ │ ├── .doommodule
│ │ └── doom/
│ │ └── .doommodule
│ ├── tools/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── ansible/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── biblio/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── collab/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── debugger/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── debugger.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── direnv/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── docker/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── editorconfig/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── ein/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── eval/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── eval.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── repl.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── llm/
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── lookup/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── docsets.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── lookup.el
│ │ │ │ ├── online.el
│ │ │ │ └── xwidget.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lsp/
│ │ │ ├── +eglot.el
│ │ │ ├── +lsp.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── common.el
│ │ │ │ ├── eglot.el
│ │ │ │ └── lsp-mode.el
│ │ │ ├── config.el
│ │ │ ├── demos.org
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── magit/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── make/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── packages.el
│ │ ├── pass/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── consult.el
│ │ │ │ ├── ivy.el
│ │ │ │ └── pass.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── pdf/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── terraform/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── tmux/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── autoload/
│ │ │ ├── evil.el
│ │ │ └── tmux.el
│ │ ├── tree-sitter/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat-30.el
│ │ │ │ └── tree-sitter.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── upload/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ └── ui/
│ ├── .doommodule
│ ├── README.org
│ ├── dashboard/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── config.el
│ ├── deft/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── doom/
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── doom-dashboard/
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── config.el
│ ├── doom-quit/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ └── config.el
│ ├── emoji/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── hl-todo/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── indent-guides/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── ligatures/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── ligatures.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── minimap/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── modeline/
│ │ ├── +light.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── nav-flash/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── neotree/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── ophints/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── popup/
│ │ ├── +hacks.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── popup.el
│ │ │ └── settings.el
│ │ └── config.el
│ ├── smooth-scroll/
│ │ ├── README.org
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── tabs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── treemacs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── unicode/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── packages.el
│ ├── vc-gutter/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── diff-hl.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── vi-tilde-fringe/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── packages.el
│ ├── window-select/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── workspaces/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── evil.el
│ │ │ └── workspaces.el
│ │ ├── config.el
│ │ └── packages.el
│ └── zen/
│ ├── .doommodule
│ ├── README.org
│ ├── autoload.el
│ ├── config.el
│ └── packages.el
├── profiles/
│ ├── README.org
│ └── safe-mode/
│ └── init.el
├── shell.nix
└── static/
├── BUG_REPORT
├── QUICKSTART_INTRO
├── VANILLA_SANDBOX
├── config.example.el
├── init.example.el
└── packages.example.el
================================================
FILE CONTENTS
================================================
================================================
FILE: .doom
================================================
"3.0.0-pre"
((name . doom)
(version . "3.0.0-pre")
(homepage . "https://doomemacs.org")
(commit
(preset doom-conventional-commits)
(types "module")
(scopes "cli" "lib"
(module)
(release "modules")
(docs
"install"
(lambda (scope _plist)
"Allow any filename in docs/* as a scope for docs commits."
(member
scope (doom-files-in (doom-path (dir!) "../docs")
:match "\\.org$"
:map #'file-name-base))))
(lambda (scope _plist)
"Only allow :CATEGORY or MODULE scopes if they actually exist."
(doom-glob
(dir!) "modules" (if (string-prefix-p ":" scope)
(format "%s" (substring scope 1))
(format "*/%s" scope))))))
(make
("LICENSE"
"The MIT License (MIT)\n"
,(lambda (_)
(insert (format-time-string "Copyright (c) 2014-%Y Henrik Lissner.\n\n")))
"Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
\"Software\"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:\n"
"The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.\n"
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.")
(".github/CODEOWNERS"
"# -*- mode: conf -*-"
"# Auto-generated by 'doom make .github/CODEOWNERS', do not edit it by hand.\n"
"* @doomemacs/maintainers\n" ; default until another takes precedence
"# Module maintainers"
,(lambda (rc)
(mapc (lambda (line) (insert line "\n"))
(cl-sort
(cl-loop for path in (doom-module-load-path (list doom-modules-dir))
if (string-match "/modules/\\([^/]+\\)/\\([^/]+\\)$" path)
collect (format "%-35s @doomemacs/%s-%s"
(substring (match-string 0 path) 1)
(match-string 1 path)
(match-string 2 path)))
#'string-lessp)))))
(publish
(targets "docs/index.org" "docs" "modules/*/README.org")
(env
(global-menus
("± Suggest edits" . "doom-suggest-edit:")
("? Help"
. ,(lambda! (&key title)
(cond ((equal title "Changelog") "doom-help-changelog:")
((string-prefix-p ":" title) "doom-help-modules:")
("doom-help:")))))
(menus
(("docs/*.org" "modules/README.org")
(left ("← Back to index" . "doom-index:")))
("docs/index.org"
(left ("↖ FAQ" . "doom-faq:")))
("modules/*/README.org"
(left ("← Back to module index" . "doom-module-index:")))
("modules/*/*/README.org"
(left ("← Back to module index" . "doom-module-index:"))
(right ("↖ History"
. ,(lambda! (&key category module)
(format "doom-module-history:%s/%s" (doom-keyword-name category) module)))
("! Issues"
. ,(lambda! (&key category module)
(format "doom-module-issues::%s %s" category module))))))))
(sources
(doom
(title . "Doom Core Modules")
(version . "25.01.0-pre")
(paths "lisp/" "lisp/modules/*/"))
(doom+
(title . "Doom Official Modules")
(version . "25.01.0-pre")
(paths "modules/*/" "modules/*/*/"))
(doom++
(title . "Doom Community Modules")
(version . "25.01.0-pre")
(paths "modules/*/" "modules/*/*/")))
(profiles
(test
(sources doom)
(modules :doom (cli +ci +buttercup))
(packages)))
(packages
(straight :host github
:repo "radian-software/straight.el"
:branch "develop"
:local-repo "straight.el"
:files ("straight*.el")
:pin "33fb4695066781c634ff1c3c81ba96e880deccf7")
;; (elpaca :repo "https://github.com/progfolio/elpaca.git"
;; :pin "34b1d1b19d24470758b62ab1d10ed70068186c12"
;; :depth 1
;; :files (:defaults "elpaca-test.el" (:exclude "extensions"))
;; :build (:not elpaca--activate-package))
))
================================================
FILE: .github/CODEOWNERS
================================================
# -*- mode: conf -*-
# Auto-generated by 'doom make .github/CODEOWNERS', do not edit it by hand.
* @doomemacs/maintainers
# Module maintainers
modules/app/calendar @doomemacs/app-calendar
modules/app/emms @doomemacs/app-emms
modules/app/everywhere @doomemacs/app-everywhere
modules/app/irc @doomemacs/app-irc
modules/app/rss @doomemacs/app-rss
modules/checkers/grammar @doomemacs/checkers-grammar
modules/checkers/spell @doomemacs/checkers-spell
modules/checkers/syntax @doomemacs/checkers-syntax
modules/completion/company @doomemacs/completion-company
modules/completion/corfu @doomemacs/completion-corfu
modules/completion/helm @doomemacs/completion-helm
modules/completion/ido @doomemacs/completion-ido
modules/completion/ivy @doomemacs/completion-ivy
modules/completion/vertico @doomemacs/completion-vertico
modules/config/default @doomemacs/config-default
modules/config/literate @doomemacs/config-literate
modules/config/use-package @doomemacs/config-use-package
modules/core/cli @doomemacs/core-cli
modules/core/defaults @doomemacs/core-defaults
modules/editor/evil @doomemacs/editor-evil
modules/editor/file-templates @doomemacs/editor-file-templates
modules/editor/fold @doomemacs/editor-fold
modules/editor/format @doomemacs/editor-format
modules/editor/god @doomemacs/editor-god
modules/editor/lispy @doomemacs/editor-lispy
modules/editor/multiple-cursors @doomemacs/editor-multiple-cursors
modules/editor/objed @doomemacs/editor-objed
modules/editor/parinfer @doomemacs/editor-parinfer
modules/editor/rotate-text @doomemacs/editor-rotate-text
modules/editor/snippets @doomemacs/editor-snippets
modules/editor/word-wrap @doomemacs/editor-word-wrap
modules/emacs/dired @doomemacs/emacs-dired
modules/emacs/electric @doomemacs/emacs-electric
modules/emacs/eww @doomemacs/emacs-eww
modules/emacs/ibuffer @doomemacs/emacs-ibuffer
modules/emacs/tramp @doomemacs/emacs-tramp
modules/emacs/undo @doomemacs/emacs-undo
modules/emacs/vc @doomemacs/emacs-vc
modules/email/mu4e @doomemacs/email-mu4e
modules/email/notmuch @doomemacs/email-notmuch
modules/email/wanderlust @doomemacs/email-wanderlust
modules/input/bidi @doomemacs/input-bidi
modules/input/chinese @doomemacs/input-chinese
modules/input/japanese @doomemacs/input-japanese
modules/input/layout @doomemacs/input-layout
modules/lang/ada @doomemacs/lang-ada
modules/lang/agda @doomemacs/lang-agda
modules/lang/beancount @doomemacs/lang-beancount
modules/lang/cc @doomemacs/lang-cc
modules/lang/clojure @doomemacs/lang-clojure
modules/lang/common-lisp @doomemacs/lang-common-lisp
modules/lang/coq @doomemacs/lang-coq
modules/lang/crystal @doomemacs/lang-crystal
modules/lang/csharp @doomemacs/lang-csharp
modules/lang/dart @doomemacs/lang-dart
modules/lang/data @doomemacs/lang-data
modules/lang/dhall @doomemacs/lang-dhall
modules/lang/elixir @doomemacs/lang-elixir
modules/lang/elm @doomemacs/lang-elm
modules/lang/emacs-lisp @doomemacs/lang-emacs-lisp
modules/lang/erlang @doomemacs/lang-erlang
modules/lang/ess @doomemacs/lang-ess
modules/lang/factor @doomemacs/lang-factor
modules/lang/faust @doomemacs/lang-faust
modules/lang/fortran @doomemacs/lang-fortran
modules/lang/fsharp @doomemacs/lang-fsharp
modules/lang/fstar @doomemacs/lang-fstar
modules/lang/gdscript @doomemacs/lang-gdscript
modules/lang/go @doomemacs/lang-go
modules/lang/graphql @doomemacs/lang-graphql
modules/lang/graphviz @doomemacs/lang-graphviz
modules/lang/haskell @doomemacs/lang-haskell
modules/lang/hy @doomemacs/lang-hy
modules/lang/idris @doomemacs/lang-idris
modules/lang/janet @doomemacs/lang-janet
modules/lang/java @doomemacs/lang-java
modules/lang/javascript @doomemacs/lang-javascript
modules/lang/json @doomemacs/lang-json
modules/lang/julia @doomemacs/lang-julia
modules/lang/kotlin @doomemacs/lang-kotlin
modules/lang/latex @doomemacs/lang-latex
modules/lang/lean @doomemacs/lang-lean
modules/lang/ledger @doomemacs/lang-ledger
modules/lang/lua @doomemacs/lang-lua
modules/lang/markdown @doomemacs/lang-markdown
modules/lang/nim @doomemacs/lang-nim
modules/lang/nix @doomemacs/lang-nix
modules/lang/ocaml @doomemacs/lang-ocaml
modules/lang/org @doomemacs/lang-org
modules/lang/php @doomemacs/lang-php
modules/lang/plantuml @doomemacs/lang-plantuml
modules/lang/purescript @doomemacs/lang-purescript
modules/lang/python @doomemacs/lang-python
modules/lang/qt @doomemacs/lang-qt
modules/lang/racket @doomemacs/lang-racket
modules/lang/raku @doomemacs/lang-raku
modules/lang/rest @doomemacs/lang-rest
modules/lang/rst @doomemacs/lang-rst
modules/lang/ruby @doomemacs/lang-ruby
modules/lang/rust @doomemacs/lang-rust
modules/lang/scala @doomemacs/lang-scala
modules/lang/scheme @doomemacs/lang-scheme
modules/lang/sh @doomemacs/lang-sh
modules/lang/sml @doomemacs/lang-sml
modules/lang/solidity @doomemacs/lang-solidity
modules/lang/swift @doomemacs/lang-swift
modules/lang/terra @doomemacs/lang-terra
modules/lang/web @doomemacs/lang-web
modules/lang/yaml @doomemacs/lang-yaml
modules/lang/zig @doomemacs/lang-zig
modules/os/macos @doomemacs/os-macos
modules/os/tty @doomemacs/os-tty
modules/term/eshell @doomemacs/term-eshell
modules/term/shell @doomemacs/term-shell
modules/term/term @doomemacs/term-term
modules/term/vterm @doomemacs/term-vterm
modules/themes/doom @doomemacs/themes-doom
modules/tools/ansible @doomemacs/tools-ansible
modules/tools/biblio @doomemacs/tools-biblio
modules/tools/collab @doomemacs/tools-collab
modules/tools/debugger @doomemacs/tools-debugger
modules/tools/direnv @doomemacs/tools-direnv
modules/tools/docker @doomemacs/tools-docker
modules/tools/editorconfig @doomemacs/tools-editorconfig
modules/tools/ein @doomemacs/tools-ein
modules/tools/eval @doomemacs/tools-eval
modules/tools/llm @doomemacs/tools-llm
modules/tools/lookup @doomemacs/tools-lookup
modules/tools/lsp @doomemacs/tools-lsp
modules/tools/magit @doomemacs/tools-magit
modules/tools/make @doomemacs/tools-make
modules/tools/pass @doomemacs/tools-pass
modules/tools/pdf @doomemacs/tools-pdf
modules/tools/terraform @doomemacs/tools-terraform
modules/tools/tmux @doomemacs/tools-tmux
modules/tools/tree-sitter @doomemacs/tools-tree-sitter
modules/tools/upload @doomemacs/tools-upload
modules/ui/dashboard @doomemacs/ui-dashboard
modules/ui/deft @doomemacs/ui-deft
modules/ui/doom @doomemacs/ui-doom
modules/ui/doom-dashboard @doomemacs/ui-doom-dashboard
modules/ui/doom-quit @doomemacs/ui-doom-quit
modules/ui/emoji @doomemacs/ui-emoji
modules/ui/hl-todo @doomemacs/ui-hl-todo
modules/ui/indent-guides @doomemacs/ui-indent-guides
modules/ui/ligatures @doomemacs/ui-ligatures
modules/ui/minimap @doomemacs/ui-minimap
modules/ui/modeline @doomemacs/ui-modeline
modules/ui/nav-flash @doomemacs/ui-nav-flash
modules/ui/neotree @doomemacs/ui-neotree
modules/ui/ophints @doomemacs/ui-ophints
modules/ui/popup @doomemacs/ui-popup
modules/ui/smooth-scroll @doomemacs/ui-smooth-scroll
modules/ui/tabs @doomemacs/ui-tabs
modules/ui/treemacs @doomemacs/ui-treemacs
modules/ui/unicode @doomemacs/ui-unicode
modules/ui/vc-gutter @doomemacs/ui-vc-gutter
modules/ui/vi-tilde-fringe @doomemacs/ui-vi-tilde-fringe
modules/ui/window-select @doomemacs/ui-window-select
modules/ui/workspaces @doomemacs/ui-workspaces
modules/ui/zen @doomemacs/ui-zen
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
---
name: 📝 Bug Report
description: Report something that isn't working as intended
labels: ["is:bug", "needs-triage"]
projects: ["doomemacs/2"]
body:
- type: markdown
attributes:
value: |
> [!IMPORTANT]
> Before you fill out this bug report, please be aware of the following:
>
> - This is not the place for feature requests, general user support, PSAs, or discussions/RFCs. Those belong on [our Github discussion board](https://doomemacs.org/discuss) or [our Discord server](https://doomemacs.org/discord) — whichever you prefer.
> - Make sure your issue hasn't already been reported or addressed: search the issue tracker, [documentation](https://docs.doomemacs.org), [FAQ](https://docs.doomemacs.org/-/faq), [discussion board](https://doomemacs.org/discuss), and [Google](https://google.com).
> - Read [the debugging guide](https://discourse.doomemacs.org/t/55) for ways to extract more information from your issue.
> - Include [backtraces](https://discourse.doomemacs.org/t/85) for any error messages.
>
> Bug reports that are unactionable, vague, or too broad (or are otherwise unhelpful to posterity) **will be closed and queued for deletion**, with notice. Please understand that we get *many* false positives and open-ended bug reports that we lack the manpower to investigate at length. Keeping them around only pollutes search engines indices and makes it harder to find and follow legitimate issues.
- type: textarea
attributes:
label: Describe your issue
description: |
Include as much information as possible. Such as:
- **A [backtrace](https://discourse.doomemacs.org/t/85) for any error messages.**
- Any recent errors/warnings in the \*Messages\* buffer (`C-h e` to open it).
- Better explanations than "X does not work".
- Any attempts you made to resolve the issue yourself, and their result.
- Screenshots or screencasts, if possible.
- Please disclose what parts are written by AI.
**Please format code and large text dumps with [code fences](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks) or use [pastebin](https://pastebin.com) (or similar).**
placeholder: |
When I do X, it should do Y, but it does Z instead, which throws an error. Here is the backtrace:
```
Debugger entered--Lisp error: (error "Beep Boop")
error("Beep Boop")
pp-eval-expression((error "Beep Boop"))
\#<subr funcall-interactively>(pp-eval-expression (error "Beep Boop"))
apply(#<subr funcall-interactively> (pp-eval-expression (error "Beep Boop")))
funcall-interactively(pp-eval-expression (error "Beep Boop"))
```
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
placeholder: |
1. Open Emacs,
2. `M-x doom/info` and be prompted to visit pastebin.com,
3. Press `y` to open pastebin.com in browser,
4. Paste the contents of my clipboard into text box,
5. Click "Create New Paste,"
6. Post it in the "System information" text box below.
validations:
required: true
- type: input
id: doominfo
attributes:
label: System information
description: |
Grab the output from `M-x doom/info` or `$EMACSDIR/bin/doom info` and post it to [pastebin](https://pastebin.com) (or similar), then paste the link below. **Please do not paste your `doom-info` directly into this text box!**
placeholder: https://pastebin.com/fakeurl
validations:
required: true
- type: checkboxes
attributes:
label: Disclosures
description:
Check off any that apply to help us assess your issue(s) more accurately.
options:
- label: This issue was written with/by AI.
- type: markdown
attributes:
value: |
-----
:heart: **Thank you for taking the time to file this bug report!**
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: 📝 Feature Request
url: https://doomemacs.org/discuss/new?category=ideas
about: "Suggest or request a new feature or change"
- name: 📝 User Support
url: https://doomemacs.org/discuss/new?category=questions
about: "Ask the community for help"
- name: 📝 Bump Request
url: https://doomemacs.org/discuss/new?category=re-modules&title=[Bump Request] &body=%23%23%23%20Packages%20to%20bump%0A%0A-%20PackageA%0A-%20PackageB%0A-%20PackageB%0A%0A%23%23%23%20Why%20should%20they%20be%20bumped%20outside%20of%20the%20normal%20bump%20schedule%3F%0A%0ABecause%20...%3F
about: "Request a pinned package be bumped"
- name: 📣 Announcements
url: https://github.com/doomemacs/community/discussions/categories/announcements
about: "Follow project news, releases, and announcements"
- name: Official Documentation
url: https://docs.doomemacs.org
about: "Also available from within Doom: `M-x doom/help`"
# - name: Community Wiki
# url: https://wiki.doomemacs.org
# about: "The Community-maintained wiki"
- name: Frequently asked questions
url: https://docs.doomemacs.org/latest/faq
about: "Answers to common questions and solutions for frequently brought up issues"
- name: Do-not-PR list
url: https://doomemacs.org/donotpr
about: "A list of pull requests that won't be accepted"
- name: Visit our Discussions board
url: https://doomemacs.org/discuss
about: "Our public discussion and support forum"
- name: Visit our Discord
url: https://doomemacs.org/discord
about: "A less formal space to chat, get to know the community, and get help quick"
================================================
FILE: .github/workflows/lint-commits.yml
================================================
name: Lint commits
on: [push, pull_request]
jobs:
lint-commits:
uses: doomemacs/ci/.github/workflows/lint-commits.yml@legacy
================================================
FILE: .github/workflows/triage.yml
================================================
name: Mark stale issues and lock closed threads
on:
schedule:
- cron: '0 */12 * * *' # twice, daily
jobs:
triage:
use: doomemacs/ci/.github/workflows/triage.yml@legacy
================================================
FILE: .gitignore
================================================
# project dotfiles
.*
!.doom*
!.dir-locals.el
!.gitignore
!/.github
# generated by doom
/profiles/*.el
/.local*/
# possible user config files (if $DOOMDIR == $EMACSDIR)
/*.el
!/early-init.el
/user-lisp/
/themes/
/snippets/
# generated by elisp packages
\#*
*~
*.*~
*.cache*
*.log
*.elc
*.eln
*.lib
*.fas
*.dat
*.eld
*.rel
*_archive
*_flymake.*
flycheck_*.el
/auto/
/auto-save-list/
/cask/
/ede-projects.el
/eln-cache/
/elpa/
/eshell/
/network-security.data
/places
/semanticdb
/server/
/smex-items
/tramp
/transient/
/var/
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014-2026 Henrik Lissner.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
<div align="center">
# Doom Emacs
[Install](#install) • [Documentation] • [FAQ] • [Screenshots] • [Contribute](#contribute)



<!--  -->
[][discord]
[][discuss]

</div>
---
### Table of Contents
- [Introduction](#introduction)
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Install](#install)
- [Roadmap](#roadmap)
- [Getting help](#getting-help)
- [Contribute](#contribute)
# Introduction
<a href="http://ultravioletbat.deviantart.com/art/Yay-Evil-111710573">
<img src="https://raw.githubusercontent.com/doomemacs/doomemacs/screenshots/cacochan.png" align="right" />
</a>
> It is a story as old as time. A stubborn, shell-dwelling, and melodramatic
> vimmer—envious of the features of modern text editors—spirals into
> despair before he succumbs to the [dark side][evil-mode]. This is his config.
Doom is a configuration framework for [GNU Emacs] tailored for Emacs bankruptcy
veterans who want less framework in their frameworks, a modicum of stability
(and reproducibility) from their package manager, and the performance of a hand
rolled config (or better). It can be a foundation for your own config or a
resource for Emacs enthusiasts to learn more about our favorite operating
system.
Its design is guided by these mantras:
+ **Gotta go fast.** Startup and run-time performance are priorities. Doom goes
beyond by modifying packages to be snappier and load lazier.
+ **Close to metal.** There's less between you and vanilla Emacs by design.
That's less to grok and less to work around when you tinker. Internals ought
to be written as if reading them were part of Doom's UX, and it is!
+ **Opinionated, but not stubborn.** Doom is about reasonable defaults and
curated opinions, but use as little or as much of it as you like.
+ **Your system, your rules.** You know better. At least, Doom hopes so! It
won't *automatically* install system dependencies (and will force plugins not
to either). Rely on `doom doctor` to tell you what's missing.
+ **Nix/Guix is a great idea!** The Emacs ecosystem is temperamental. Things
break and they break often. Disaster recovery should be a priority! Doom's
package management should be declarative and your private config reproducible,
and comes with a means to roll back releases and updates (still a WIP).
Check out [the FAQ][FAQ] for answers to common questions about the project.
# Features
- Minimalistic good looks inspired by modern editors.
- Curated and sane defaults for many packages, (major) OSes, and Emacs itself.
- A modular organizational structure for separating concerns in your config.
- A standard library designed to simplify your elisp bike shedding.
- A declarative [package management system][package-management] (powered by
[straight.el]) with a command line interface. Install packages from anywhere,
not just (M)ELPA, and pin them to any commit.
- Optional vim emulation powered by [evil-mode], including ports of popular vim
plugins like [vim-sneak], [vim-easymotion], [vim-unimpaired] and
[more][ported-vim-plugins]!
- Opt-in LSP integration for many languages, using [lsp-mode] or [eglot]
- Support for *many* programming languages. Includes syntax highlighting,
linters/checker integration, inline code evaluation, code completion (where
possible), REPLs, documentation lookups, snippets, and more!
- Support for *many* tools, like docker, pass, ansible, terraform, and more.
- A Spacemacs-esque [keybinding scheme][bindings], centered around leader
and localleader prefix keys (<kbd>SPC</kbd> and <kbd>SPC</kbd><kbd>m</kbd> for
evil users, <kbd>C-c</kbd> and <kbd>C-c l</kbd> for vanilla users).
- A rule-based [popup manager][popup-system] to control how temporary buffers
are displayed (and disposed of).
- Per-file indentation style detection and [editorconfig] integration. Let
someone else argue about tabs vs **_spaces_**.
- Project-management tools and framework-specific minor modes with their own
snippets libraries.
- Project search (and replace) utilities, powered by [ripgrep] and [ivy] or
[helm].
- Isolated and persistent workspaces (also substitutes for vim tabs).
- Support for Chinese and Japanese input systems.
- Save a snapshot of your shell environment to a file for Emacs to load at
startup. No more struggling to get Emacs to inherit your `PATH`, among other
things.
# Prerequisites
- **Required:**
- GNU Emacs 27.1–30.2 (30.2 is recommended)
- If only using Doom's core, 27.1+ is required.
- If using Doom's modules, 28.1+ is required.
- Tree-sitter support requires 29.1+, but much improved in 30.1+.
- Git >= 2.23
- [ripgrep] >= 11.0
- **Optional, but recommended:**
- [fd] 7.3.0+ (used to improve file indexing performance)
- GNU variants of `find`, `ls`, and `tar` (on MacOS and BSD *nix)
- Symbola font (Emacs' fallback font for glyphs it can't display)
> [!WARNING]
> **Avoid unstable and pre-release builds of Emacs.** These end in `.50`, `.60`,
> or `.9X` (e.g. `28.1.91`). Doom should generally work on Emacs HEAD (the
> maintainer dogfoods it), but support lags behind the bleeding edge by at least
> a month or so.
> [!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
``` sh
git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs
~/.config/emacs/bin/doom install
```
Then [read our Getting Started guide][getting-started] to be walked through
installing, configuring and maintaining Doom Emacs.
It's a good idea to add `~/.config/emacs/bin` to your `PATH`! Other `bin/doom`
commands you should know about:
+ `doom sync` to synchronize your private config with Doom by installing missing
packages, removing orphaned packages, and regenerating caches. Run this
whenever you modify your private `init.el` or `packages.el`, or install/remove
an Emacs package through your OS package manager (e.g. mu4e or agda).
+ `doom upgrade` to update Doom to the latest release & all installed packages.
+ `doom doctor` to diagnose common issues with your system and config.
+ `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.
# Roadmap
Doom is an active and ongoing project. To make that development more
transparent, its roadmap (and other concerns) are published across three github
project boards and a newsletter:
- [Development Roadmap](https://doomemacs.org/roadmap)
- [Packages under review](https://doomemacs.org/packages-under-review):
lists plugins we are watching and considering for inclusion, and what their
status for inclusion is. Please consult this list before requesting new
packages/features.
+ [Upstream bugs](https://github.com/orgs/doomemacs/projects/7): lists
issues that originate from elsewhere, and whether or not we have local
workarounds or temporary fixes for them.
+ ~~Doom's newsletter~~ (not finished) will contain changelogs in between
releases.
# Getting help
Emacs is no journey of a mere thousand miles. You _will_ run into problems and
mysterious errors. When you do, here are some places you can look for help:
+ [Our documentation][documentation] covers many use cases.
+ [The Configuration section][configuration] covers how to configure Doom and
its packages.
+ [The Package Management section][package-management] covers how to install
and disable packages.
+ [This section][bin/doom] explains the `bin/doom` script's most important
commands.
+ [This section][common-mistakes] lists some common configuration mistakes new
users make, when migrating a config from another distro or their own.
+ [This answer][change-theme] shows you how to add your own themes to your
private config.
+ [This answer][change-font] shows you how to change the default font.
+ Your issue may be documented in the [FAQ].
+ With Emacs built-in help system documentation is a keystroke away:
+ For functions: <kbd>SPC h f</kbd> or <kbd>C-h f</kbd>
+ For variables: <kbd>SPC h v</kbd> or <kbd>C-h v</kbd>
+ For a keybind: <kbd>SPC h k</kbd> or <kbd>C-h k</kbd>
+ To search available keybinds: <kbd>SPC h b b</kbd> or <kbd>C-h b b</kbd>
+ Run `bin/doom doctor` to detect common issues with your development
environment and private config.
+ Check out the [FAQ] or [Community FAQs][community-faq], in case your question
has already been answered.
+ Search [Doom's issue tracker](https://github.com/doomemacs/doomemacs/issues)
in case your issue was already reported.
+ Hop on [our Discord server][discord]; it's active and friendly! Keep an eye on
the #announcements channel, where I announce breaking updates and releases.
# Contribute
[](http://makeapullrequest.com)
[](https://github.com/bbatsov/emacs-lisp-style-guide)
[][liberapay]
[][paypal]
Doom is a labor of love and incurable madness, but I'm only one guy. Doom
wouldn't be where it is today without your help. I welcome contributions of any
kind!
+ I :heart: pull requests and bug reports (see the [Contributing
Guidelines][contribute])!
+ Don't hesitate to [tell me my Elisp-fu
sucks](https://github.com/doomemacs/doomemacs/issues/new/choose), but please
tell me why.
+ Hop on [our Discord server][discord] and say hi! Help others, hang out or talk
to me about Emacs, gamedev, programming, physics, pixel art, anime, gaming --
anything you like. Nourish this lonely soul.
+ If you'd like to support my work financially, buy me a drink through
[liberapay] or [paypal]. My work contends with studies, adventures in indie
gamedev and freelance work. Donations help me allocate more time to my Emacs
and OSS capers.
[contribute]: docs/contributing.org
[discord]: https://doomemacs.org/discord
[discuss]: https://doomemacs.org/discuss
[community-faq]: https://github.com/doomemacs/community?tab=readme-ov-file#frequently-asked-questions
[documentation]: docs/index.org
[faq]: https://github.com/doomemacs/doomemacs/blob/master/docs/faq.org
[getting-started]: docs/getting_started.org
[install]: docs/getting_started.org#install
[backtrace]: docs/getting_started.org#how-to-extract-a-backtrace-from-an-error
[configuration]: docs/getting_started.org#configuring-doom
[package-management]: docs/getting_started.org#package-management
[bin/doom]: docs/getting_started.org#the-bindoom-utility
[common-mistakes]: docs/getting_started.org#common-mistakes-when-configuring-doom-emacs
[change-theme]: docs/faq.org#how-do-i-change-the-theme
[change-font]: docs/faq.org#how-do-i-change-the-fonts
[modules]: docs/modules.org
[popup-system]: modules/ui/popup/README.org
[screenshots]: https://github.com/doomemacs/doomemacs/tree/screenshots#emacsd-screenshots
[bindings]: modules/config/default/+evil-bindings.el
[editorconfig]: http://editorconfig.org/
[evil-mode]: https://github.com/emacs-evil/evil
[fd]: https://github.com/sharkdp/fd
[gnu emacs]: https://www.gnu.org/software/emacs/
[helm]: https://github.com/emacs-helm/helm
[ivy]: https://github.com/abo-abo/swiper
[lsp-mode]: https://github.com/emacs-lsp/lsp-mode
[eglot]: https://github.com/joaotavora/eglot
[nix]: https://nixos.org
[ported-vim-plugins]: modules/editor/evil/README.org#ported-vim-plugins
[ripgrep]: https://github.com/BurntSushi/ripgrep
[straight.el]: https://github.com/radian-software/straight.el
[vim-easymotion]: https://github.com/easymotion/vim-easymotion
[vim-lion]: https://github.com/tommcdo/vim-lion
[vim-sneak]: https://github.com/justinmk/vim-sneak
[vim-unimpaired]: https://github.com/tpope/vim-unimpaired
[liberapay]: https://liberapay.com/hlissner/donate
[paypal]: https://paypal.me/hlissner/10
================================================
FILE: bin/doom
================================================
#!/usr/bin/env sh
:; # -*- mode: emacs-lisp; lexical-binding: t -*-
:; case "$EMACS" in *term*) EMACS=emacs ;; *) EMACS="${EMACS:-emacs}" ;; esac
:; [ "x$EMACS" = xemacs ] && { type emacs >/dev/null 2>&1 || err=1; }
:; [ "x$err" = x ] || { echo "Error: failed to run Emacs with command '$EMACS'"; echo; echo "Are you sure Emacs is installed and in your \$PATH?"; exit 1; } >&2
:; emacs="$EMACS ${DEBUG:+--debug-init} -q --no-site-file --batch"
:; export EMACS_PLUS_NO_PATH_INJECTION=1
:; export __DOOMPID="${__DOOMPID:-$$}"
:; export __DOOMSTEP="${__DOOMSTEP:-0}"
:; export __DOOMGEOM="${__DOOMGEOM:-`tput cols 2>/dev/null`x`tput lines 2>/dev/null`}"
:; export __DOOMGPIPE=${__DOOMGPIPE:-$__DOOMPIPE}
:; export __DOOMPIPE=; [ -t 0 ] || __DOOMPIPE="${__DOOMPIPE}0"; [ -t 1 ] || __DOOMPIPE="${__DOOMPIPE}1"
:; eval "$emacs --eval \"(setq warning-inhibit-types '((files missing-lexbind-cookie)))\" --load" "$0" -- "$@" || exit=$?
:; [ "${exit:-0}" -eq 254 ] && { export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-`eval "$emacs -Q --eval '(princ temporary-file-directory)'" 2>/dev/null`}}}"; sh "${TMPDIR}/doom.${__DOOMPID}.${__DOOMSTEP}.sh" "$0" "$@" && true; exit="$?"; }
:; exit $exit
;; This magical mess of a shebang is necessary for any script that relies on
;; Doom's CLI framework, because Emacs' tty libraries and capabilities are too
;; immature (borderline non-existent) at the time of writing (28.1). This
;; shebang sets out to accomplish these three goals:
;;
;; 1. To produce a more helpful error if Emacs isn't installed or broken. It
;; must do so without assuming whether $EMACS is a shell command (e.g. 'snap
;; run emacs') or an absolute path (to an emacs executable). I've avoided
;; 'command -v $EMACS' for this reason.
;;
;; 2. To allow this Emacs session to "exit into" a child process (since Elisp
;; lacks an analogue for exec system calls) by calling an auto-generated and
;; self-destructing "exit script" if the parent Emacs process exits with code
;; 254. It takes care to prevent nested child instances from clobbering the
;; exit script.
;;
;; 3. To expose some information about the terminal and session:
;; - $__DOOMGEOM holds the dimensions of the terminal (W . H).
;; - $__DOOMPIPE indicates whether the script has been piped (in and/or out).
;; - $__DOOMGPIPE indicates whether one of this process' parent has been
;; piped to/from.
;; - $__DOOMPID is a unique identifier for the parent script, so
;; child processes can identify which persistent data files (like logs) it
;; has access to.
;; - $__DOOMSTEP counts how many levels deep we are in the dream (appending
;; this to the exit script's filename avoids child processes clobbering the
;; same exit script and causing read errors).
;; - $TMPDIR (or $TEMP and $TMP on Windows) aren't guaranteed to have values,
;; and mktemp isn't available on all systems, but you know what is? Emacs!
;; So I use it to print `temporary-file-directory'. And it seconds as a
;; quick sanity check for Emacs' existence (for goal #1).
;;
;; Other weird facts about this shebang line:
;;
;; - The :; hack exploits properties of : and ; in shell scripting and elisp to
;; allow shell script and elisp to coexist in the same file without either's
;; interpreter throwing foreign syntax errors:
;;
;; - In elisp, ":" is a valid keyword symbol literal; it evaluates to itself
;; and has no side-effect.
;; - In the shell, ":" is a valid command that does nothing and ignores its
;; arguments.
;; - In elisp, ";" begins a comment. I.e. the interpreter ignores everything
;; after it.
;; - In the shell, ";" is a command separator.
;;
;; Put together, plus a strategically placed exit call, the shell will read
;; one part of this file and ignore the rest, while the elisp interpreter will
;; do the opposite.
;; - I intentionally suppress loading site files (must be done with '-q
;; --no-site-file' NOT '-Q', as the latter omits the site-lisp dir from
;; `load-path' too), so lisp/doom-cli.el can load them manually later (early
;; in lisp/doom-cli.el). Look there for an explanation why I do this.
;; - POSIX-compliancy is paramount: there's no guarantee what /bin/sh will be
;; symlinked to in the esoteric OSes/distros Emacs users use.
;; - The user may have mounted /tmp with a noexec flag, so pass the exit script
;; to /bin/sh rather than executing them directly.
;; Doom's core sets up everything we need; including `doom-*-dir' variables,
;; universal defaults, and autoloads for doom-*-initialize functions.
(condition-case e
(let* ((bin-dir (file-name-directory (file-truename load-file-name)))
(init-file (expand-file-name "../early-init.el" bin-dir)))
(or (and (load init-file nil 'nomessage 'nosuffix)
(featurep 'doom))
(user-error "Failed to load Doom from %s" init-file)))
;; Prevent ugly backtraces for trivial errors
(user-error (message "Error: %s" (cadr e))
(kill-emacs 2)))
;; 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
(concat
"Error: this script was executed as root, which is likely not what you want.\n"
"It will cause file permissions errors later, when you run Doom as another\n"
"user.\n\n"
"If this really *is* what you want, then change the owner of your Emacs\n"
"config to root:\n\n"
;; TODO Add cmd.exe/powershell commands
" chown root:root -R " (abbreviate-file-name doom-emacs-dir) "\n\n"
"Aborting..."))
(kill-emacs 2)))
;;
;;; Entry point
(defcli! doom (&args _command)
"A command line interface to Doom Emacs.
Includes package management, diagnostics, unit tests, and byte-compilation.
This tool also makes it trivial to launch Emacs out of a different folder or
with a different private module.
ENVIRONMENT VARIABLES:
`$EMACS'
The Emacs executable or command to use for any Emacs operations in this or
other Doom CLI shell scripts (default: first emacs found in `$PATH').
`$EMACSDIR'
The location of your Doom Emacs installation (defaults to ~/.config/emacs or
~/.emacs.d; whichever is found first). This is *not* your private Doom
configuration. The `--emacsdir' option also sets this variable.
`$DOOMDIR'
The location of your private configuration for Doom Emacs (defaults to
~/.config/doom or ~/.doom.d; whichever it finds first). This is *not* the
place you've cloned doomemacs/doomemacs to. The `--doomdir' option also sets
this variable.
`$DOOMPAGER'
The pager to invoke for large output (default: \"less +g\"). The `--pager'
option also sets this variable.
`$DOOMPROFILE'
Which Doom profile to activate (default: \"_@0\"). The `--profile' option
also sets this variable.
`$DOOMPROFILELOADFILE'
Doom generates a profile loader script on 'doom sync' or 'doom profile
sync'. By default, this file is written to and loaded from
$EMACSDIR/profiles/load.el. Set this envvar to change that. Note that this
envvar must be in scope for both interactive and non-interactive sessions
for it to be effective. This is especially useful for folks on Nix/Guix, who
have deployed Doom to a read-only directory.
Note: this file *must* end with a .el extension. It will be byte-compiled
after it is generated.
`$DOOMPROFILELOADPATH'
A colon-delimited (semi-colon on Windows) list of profile config files or
directories under which Doom will search for implicit profiles. See
`var:doom-profile-load-path' for its default value.
EXIT CODES:
0 Successful run
1 No error occurred, but the command couldn't complete
2 General internal error
3 Error with Emacs/Doom install or execution context
4 Unrecognized user input error
5 Command not found, or is incorrect/deprecated
6 Invalid, missing, or extra options/arguments
7-15 Reserved for Doom
16-192 Reserved for the user's extensions
254 Successful run (then execute the dynamically generated after-script)
255 Uncaught critical errors
SEE ALSO:
https://doomemacs.org Homepage
https://docs.doomemacs.org Official documentation
https://wiki.doomemacs.org Community wiki
https://doomemacs.org/discuss Github discussions & user support board
https://doomemacs.org/discord Discord chat server"
:partial t)
(defcli! :before
((force? ("-!" "--force") "Suppress prompts by auto-accepting their consequences")
(debug? ("-D" "--debug") "Enable debug output")
(verbose? ("-v" "--verbose") "Enable verbose output")
(doomdir ("--doomdir" dir) "Use Doom config living in `DIR' (e.g. ~/.doom.d)")
(emacsdir ("--emacsdir" dir) "Use Doom install living in `DIR' (e.g. ~/.emacs.d)")
(pager ("--pager" cmd) "Pager command to use for large output")
(profile ("--profile" name) "Use profile named NAME")
(bench? ("--benchmark") "Always display the benchmark")
&flags
(color? ("--color") "Whether or not to show ANSI color codes")
&multiple
(loads ("-L" "--load" "--strict-load" file) "Load elisp `FILE' before executing `COMMAND'")
(evals ("-E" "--eval" form) "Evaluate `FORM' before executing commands")
&input input
&context context
&args _)
"OPTIONS:
-E, -eval
Can be used multiple times.
-L, --load, --strict-load
Can be used multiple times to load multiple files. Both -L and --load will
silently fail on missing files, but --strict-load won't.
Warning: files loaded this way load too late to define new commands. To
define commands, do so from `$DOOMDIR'/cli.el, `$DOOMDIR'/init.el, or a
.doomrc file in the current project tree."
(when bench?
(setq doom-cli-benchmark-threshold 'always))
(unless init-file-debug ; debug-mode implies verbose
(when verbose?
(setq doom-print-minimum-level 'info)))
(when color?
(setq doom-print-backend (if (eq color? :yes) 'ansi)))
(when pager
(setq doom-cli-pager pager))
(when force?
(setf (doom-cli-context-suppress-prompts-p context) t))
;; For these settings to take full effect, the script must be restarted:
(when (or debug?
profile
emacsdir
doomdir)
(let (omit)
(when debug?
(setenv "DEBUG" "1")
(setq init-file-debug t)
(push "--debug" omit)
(push "-D" omit))
(when profile
(setenv "DOOMPROFILE" profile)
(push "--profile=" omit))
(when emacsdir
(setenv "EMACSDIR" emacsdir)
(push "--emacsdir=" omit))
(when doomdir
(setenv "DOOMDIR" doomdir)
(push "--doomdir=" omit))
(exit! :restart :omit omit)))
;; Load extra files and forms, as per given options.
(dolist (file loads)
(load (doom-path (cdr file))
(not (equal (car file) "--strict-load"))
(not init-file-debug) t))
(dolist (form evals)
(eval (read (cdr form)) t)))
;;
;;; Load user config + commands
;; Load $DOOMDIR/init.el, to read the user's `doom!' block and give users an
;; opportunity to customize the CLI environment, if they like. Otherwise, they
;; can do so in .doomrc or .doomproject.
(doom-modules-initialize)
;; There are a lot of CLIs, and some have expensive initialization, so best we
;; load them lazily.
(defcli-group!
:prefix 'doom
(defcli-alias! ((version v)) (:root :version))
;; Import this for implicit 'X help' commands for your script:
(defcli-alias! ((help h)) (:root :help))
;; And suggest its use when errors occur.
(add-to-list 'doom-help-commands "%p h[elp] %c")
(defcli-autoload! ((doctor doc)))
(defcli-autoload! (info))
(defcli-group! "Config Management"
:docs "Commands for maintaining your Doom Emacs configuration."
(defcli-autoload! ((sync s)))
(defcli-autoload! ((profile pf)))
(defcli-autoload! ((upgrade up)))
(defcli-autoload! (env))
(defcli-autoload! (gc))
(defcli-autoload! (install))
(defcli-obsolete! (profiles sync) (profile sync "--all") "3.0.0")
(defcli-obsolete! ((build b)) (sync "--rebuild") "3.0.0")
(defcli-obsolete! ((purge p)) (gc) "3.0.0")
;; TODO Post-3.0 commands
(defcli-stub! module)
(defcli-stub! nuke)
(defcli-stub! package)
(defcli-stub! rollback))
(defcli-group! "Development"
:docs "Commands for developing or launching Doom."
(defcli-autoload! (ci))
(defcli-autoload! (make))
(defcli-autoload! (emacs))
(defcli-obsolete! (run) (emacs) "3.0.0")
;; TODO Post-3.0 commands
(defcli-stub! test))
(let ((cli-file "cli.el"))
(defcli-group! "Module commands"
(with-doom-context 'module
(dolist (key (doom-module-list))
(when-let* ((path (doom-module-locate-path key cli-file)))
(defcli-group! :prefix (if (cdr key) (format "+%s" (cdr key)))
(doom-load (file-name-sans-extension path))))))))
;; Execute arbitrary CLI configuration in a local .doom.el file
(let (doomrc)
(cond
((setq doomrc (getenv "DOOMRC"))
(load! doomrc default-directory))
((setq doomrc (locate-dominating-file default-directory ".doom.el"))
(load! ".doom.el" doomrc)))))
;;
;;; Let 'er rip
(run! "doom" (cdr (member "--" argv)))
;;; doom ends here, unless...
================================================
FILE: bin/doom.ps1
================================================
# bin/doom.ps1
# TODO: Use magic shebang (polyglot)?
function Executable-Find {
foreach ($exe in $args) {
if ($exe) {
$path = Get-Command $exe -ErrorAction SilentlyContinue
if ($path) { return $path.Path; }
}
}
throw "Could not find in PATH: $($args -join ', ')"
}
$emacs = if ($env:EMACS) { $env:EMACS } else { Executable-Find "emacs.exe" }
$pwsh = Executable-Find "pwsh.exe" "powershell.exe"
$doom = "$PSScriptRoot/doom"
$oldemacsdir = $env:EMACSDIR
try {
if (-not $env:EMACSDIR) { $env:EMACSDIR = (get-item $PSScriptRoot).parent.FullName; }
if (-not $env:__DOOMSH) { $env:__DOOMSH = "ps1"; }
if (-not $env:__DOOMPID) { $env:__DOOMPID = $PID; }
if (-not $env:__DOOMSTEP) { $env:__DOOMSTEP = 0; }
if (-not $env:__DOOMGEOM) {
$cols = (Get-Host).UI.RawUI.WindowSize.Width
$lines = (Get-Host).UI.RawUI.WindowSize.Height
$env:__DOOMGEOM = "$($cols)x$($lines)"
}
# $env:__DOOMGPIPE = if (-not $env:__DOOMGPIPE) { $env:__DOOMPIPE } else { $env:__DOOMGPIPE }
# $env:__DOOMPIPE = ""
& $emacs -q --no-site-file --batch --load "$doom" -- --no-color $args
if ($LASTEXITCODE -eq 254) {
# TODO: Use Invoke-Command instead?
& $pwsh "$($env:temp)\doom.$($env:__DOOMPID).$($env:__DOOMSTEP).ps1" $PSCommandPath $args
$exit = $LASTEXITCODE
}
exit $exit
} finally {
# Only clear the env at top-level
if ($env:__DOOMSTEP -eq 0) {
$env:EMACSDIR = $oldemacsdir
Remove-Item Env:\__DOOMSH
Remove-Item Env:\__DOOMPID
Remove-Item Env:\__DOOMSTEP
Remove-Item Env:\__DOOMGEOM
}
}
================================================
FILE: bin/doom.sh
================================================
#!/bin/bash
#
# On Android (and possibly other Linux distros), /usr/bin/env does not exist.
# This script exists as a workaround for those users.
"$(dirname -- "${BASH_SOURCE:-$0}")/doom" "$@"
================================================
FILE: bin/doomscript
================================================
#!/usr/bin/env sh
# -*- coding: utf-8-unix -*-
# This is a shebang interpreter for launching Emacs Lisp scripts with Doom's CLI
# framework preloaded, plus any environment variables it needs. Use it like so:
#
# #!/usr/bin/env doomscript
# (print! "Hello world!")
#
# For this to work (and to avoid an absolute path in your shebang line), this
# file must be in your $PATH:
#
# export PATH="$HOME/.config/emacs/bin:$PATH"
#
# This isn't used for bin/doom because of this $PATH/absolute path requirement
# (and using $BASH_SOURCE to locate it would reduce its POSIX compliance), but
# this should be less of an issue for folks writing their own doomscripts.
if [ "$#" -eq 0 ]; then
>&2 echo "Error: missing required file argument"
exit 1
fi
case "$EMACS" in
*term*) EMACS=emacs ;; # in {ansi-,v}term
*\ *) ;;
*) EMACS="${EMACS:-emacs}"
# Only sanity-check $EMACS if it's a path or executable, beacuse it might
# be a full command.
if ! type "$EMACS" >/dev/null 2>&1; then
echo "Error: failed to run Emacs with command '$EMACS'"
echo
echo "Are you sure Emacs is installed and in your \$PATH?"
exit 1
fi >&2
;;
esac
# Careful not to use -Q! It implies --no-site-lisp; it omits the site-lisp
# directory from `load-path' which prevent Doom from manually loading the site
# files later. Site files are important on some systems or deployment methods
# (like Snap or NixOS).
emacs="$EMACS -q --no-site-file --batch"
# Doom respects $EMACSDIR to tell it where Doom lives. If it fails, then this is
# either isn't bash, or it's a posix shell being directly sourced with sh, which
# is unsupported.
export EMACSDIR="${EMACSDIR:-$(CDPATH='' cd -- "$(dirname -- "${BASH_SOURCE:-$0}")/.." && pwd)}"
if [ ! -f "$EMACSDIR/early-init.el" ]; then
echo "Error: failed to load $EMACSDIR/early-init.el."
echo
echo "Either the file doesn't exist (indicating a broken or missing Doom install)"
echo "or that this script is being sourced directly (which is unsupported)."
echo
echo "Set \$EMACSDIR to the path of an existing Doom installation."
exit 1
fi >&2
# Inform Doom's CLI about the characteristics of the current terminal and how
# bin/doom's been invoked. Read the shebang of bin/doom for explanations.
export __DOOMSH="${__DOOMSH:-sh}"
export __DOOMPID="${__DOOMPID:-$$}"
export __DOOMSTEP="${__DOOMSTEP:-0}"
export __DOOMGEOM="${__DOOMGEOM:-$(tput cols 2>/dev/null)x$(tput lines 2>/dev/null)}"
export __DOOMGPIPE="${__DOOMGPIPE:-$__DOOMPIPE}"
export __DOOMPIPE=
[ -t 0 ] || __DOOMPIPE="${__DOOMPIPE}0"
[ -t 1 ] || __DOOMPIPE="${__DOOMPIPE}1"
# Now we're ready to execute the given script. $EMACSDIR/early-init.el is Doom's
# universal bootstrapper (and will only load the bare minimum), so it must be
# loaded first.
script="$1"
shift
$emacs --load "$EMACSDIR/early-init" \
--load "$script" \
-- "$@"
exit=$?
# bin/doom can request the caller emulate an execve syscall by returning a 254
# exit code and generating a (temporary) exit script to be executed afterwards.
if [ "${exit:-0}" -eq 254 ]; then
# $TMPDIR (or $TEMP and $TMP on Windows) aren't guaranteed to have values,
# and mktemp isn't available on all systems, but you know what is? Emacs! So
# I rely on it to provide TMPDIR.
export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-$($emacs -Q --eval '(princ (temporary-file-directory))' 2>/dev/null)}}}"
# /tmp may be mounted with the noexec flag, so the exit-script can't be
# executed directly.
sh "${TMPDIR}/doom.${__DOOMPID}.${__DOOMSTEP}.sh" "$0" "$@"
exit="$?"
fi
exit $exit
# doomscript ends here... Unless...?
================================================
FILE: bin/org-capture
================================================
#!/usr/bin/env sh
# Open an org-capture popup frame from the shell. This opens a temporary emacs
# daemon if emacs isn't already running.
#
# Usage: org-capture [-k KEY] [MESSAGE]
# Examples:
# org-capture -k n "To the mind that is still, the whole universe surrenders."
set -e
cleanup() {
emacsclient --eval '(let (kill-emacs-hook) (kill-emacs))'
}
# If emacs isn't running, we start a temporary daemon, solely for this window.
if ! emacsclient --suppress-output --eval nil 2>/dev/null; then
echo "No Emacs daemon/server is available! Starting one..."
emacs --daemon
trap cleanup EXIT INT TERM
fi
# org-capture key mapped to argument flags
# keys=$(emacsclient -e "(+org-capture-available-keys)" | cut -d '"' -f2)
while getopts "hk:" opt; do
key="\"$OPTARG\""
break
done
shift $((OPTIND-1))
# use remaining args, else read from stdin if passed a single dash
str="$*"
case "$str" in
-) str=$(cat) ;;
esac
# Fix incompatible terminals that cause odd 'not a valid terminal' errors
[ "$TERM" = "alacritty" ] && export TERM=xterm-256color
# Non-daemon servers flicker a lot if frames are created from terminal, so we do
# it internally instead.
emacsclient -a "" \
-e "(+org-capture/open-frame \"$str\" ${key:-nil})"
================================================
FILE: docs/appendix.org
================================================
:PROPERTIES:
:ID: ca20678f-0f1a-4462-a599-da03f0e16330
:END:
#+title: Appendix
#+subtitle: A glossary of (Doom) Emacs terms, acronyms, & concepts
#+startup: nonum show2levels*
* Glossary
** General :category:
- Calendar Version, Calendar Versioning :: See https://calver.org.
- Semantic Version, Semantic Versioning :: See https://semver.org.
** Vim/Evil :category:
- leader key :: TODO
- localleader key :: TODO
** Environment Variables :category:
- $DOOMDIR :: The location of the user's private configuration for Doom Emacs;
usually found in =~/.config/doom= or =~/.doom.d=.
- $EMACSDIR :: The location of your Emacs initfile. This is where Doom users
will have cloned Doom's core to (=~/.config/emacs= or =~/.emacs.d=).
** Doom Emacs :category:
- Doom module :: A toggle-able collection of configuration, packages, and
functions, made for Doom Emacs.
** Emacs :category:
- ELPA :: Emacs-Lisp Package Archive. Used either to refer to the
GNU package repository or to all ELPA repositories as an ecosystem (e.g.
MELPA, Marmalade, etc).
- MELPA :: ELPA
- GNU ELPA :: ELPA
*** Configurations :category:
- Emacs bankruptcy :: To reset your Emacs configuration from scratch, usually
because the old one has gotten too messy or complicated, and working backwards
would be too much hassle.
- Emacs framework :: A foundation for your own Emacs Lisp projects, offering
tools to make it easier to build on top of it.
- Starter kit :: A library of preconfiguration for Emacs, intended to spare you
the time and effort of configuring Emacs yourself.
*** User Interface :category:
- Emacs buffer :: A [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffers.html#Buffers][buffer]] is a space in Emacs memory containing text to be edited.
Buffers are used to hold the contents of files that are being edited or
opened; there may also be buffers that are not visiting files they display
other information like Dired that shows the content of a directory. Each
buffer, including the current buffer, may or may not be displayed in any
windows.
- Echo area :: The [[https://www.gnu.org/software/emacs/manual/html_node/elisp/The-Echo-Area.html#The-Echo-Area][echo area]] is the last line of the frame. Unless the
minibuffer is active, this is the zone that shows all the messages Emacs sends
to the user
#+begin_quote
The *echo area* is used for displaying error messages (see [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Errors.html#Errors][Errors]]), for
messages made with the `message` primitive, and for echoing keystrokes. It is
not the same as the minibuffer, despite the fact that the minibuffer appears
(when active) in the same place on the screen as the echo area.
#+end_quote
- Emacs frame :: What the rest of the world calls windows. [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Frames.html][Source]].
- Emacs fringe :: On graphical displays, Emacs draws [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Fringes.html][fringes]] next to each window: thin
vertical strips down the sides which can display bitmaps indicating
truncation, continuation, horizontal scrolling, and so on.
- Header line :: The [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Header-Lines.html][header line]] is like a modeline (extra information line
about Emacs current state), that is displayed at the top of each window
instead of the bottom of them.
Notable examples include N. Rougier displaying filename [[https://github.com/rougier/elegant-emacs][in the header line]],
and LSP-mode powered context information ([[https://emacs-lsp.github.io/lsp-mode/page/main-features/#breadcrumb-on-headerline]["breadcrumbs"]])
#+begin_quote
A window can have a *header line* at the top, just as it can have a mode line
at the bottom. The header line feature works just like the mode line
feature[…]
#+end_quote
- Display margins :: A buffer can have blank areas called [[https://emacsdocs.org/docs/elisp/Display-Margins][display margins]] on the
left and on the right. Ordinary text never appears in these areas, but you can
put things into the display margins using the `display` property.
Margins tend to be a lot larger than fringes, as margins are at least as wide
as characters that you'd want to display there. It is almost always disabled:
relevant information can be almost always also be shown in fringes, and
fringes take way less screen real estate.
- Minibuffer :: The [[https://emacsdocs.org/docs/emacs/Minibuffer][minibuffer]] is the buffer that takes over the last line of
your Emacs frame whenever Emacs prompts you (the user) for input.
#+begin_quote
A *minibuffer* is a special buffer that Emacs commands use to read arguments
more complicated than the single numeric prefix argument. These arguments
include file names, buffer names, and command names (as in <kbd>M-x</kbd>).
The minibuffer is displayed on the bottom line of the frame, in the same place
as the echo area (see [[https://emacsdocs.org/docs/elisp/The-Echo-Area][The Echo Area]]), but only while it is in use for reading
an argument.
#+end_quote
- The Mode line :: The Emacs [[https://emacsdocs.org/docs/emacs/Mode-Line][mode line]] is the status bar displayed under each
Emacs window. It's what vimmers know as the status line.
#+begin_quote
Each Emacs window (aside from minibuffer windows) typically has a mode line at
the bottom, which displays status information about the buffer displayed in
the window. The mode line contains information about the buffer, such as its
name, associated file, depth of recursive editing, and major and minor modes.
#+end_quote
- Emacs window :: A [[https://emacsdocs.org/docs/elisp/Windows][window]] is an area of the screen that is used to display a
buffer (see Emacs buffer).
*** Editing :category:
- Kill :: Cut (in the Cut/Copy/Paste sense)
#+begin_quote
*Kill functions* delete text like the deletion functions, but save it so that
the user can reinsert it by *yanking* . Most of these functions have ‘kill-'
in their name. […] Killed text is saved for later yanking in the *kill ring*.
#+end_quote
- Major mode :: A [[https://emacsdocs.org/docs/emacs/Major-Modes][major mode]] is akin to file types/modes to vimmers/others. They
specialize Emacs for editing or interacting with particular kinds of text.
Each buffer has exactly one major mode at a time.
- Minor mode :: A [[https://emacsdocs.org/docs/emacs/Minor-Modes][minor mode]] provides optional features that users may enable or
disable independently of the choice of major mode. Minor modes can be enabled
individually or in combination.
Most minor modes implement features that are independent of the major mode,
and can thus be used with most major modes. For example, Auto Fill mode works
with any major mode that permits text insertion.
- Yank :: Paste (contrary to vim). The most common pitfall to avoid when coming
from Vim, is that in Emacs, yanking_ is _pasting_.
#+begin_quote
Yanking means inserting text from the kill ring
#+end_quote
*** Emacs Lisp :category:
- Alist :: An [[https://emacsdocs.org/docs/elisp/Association-Lists][association list]] is one of the main datatype used in Emacs Lisp.
It's a list of key-value cons cells (essentially tuples).
- Association list :: Alist
- Interactive command :: https://emacsdocs.org/docs/elisp/Defining-Commands
- Doc string :: Short for [[https://emacsdocs.org/docs/elisp/Function-Documentation][documentation string]] is information that is embedded
in a variable or function. Their docstring can be read when looking up
functions with [[kbd:][C-h f]] or variables with [[kbd:][C-h v]].
*** Keybinds :category:
- Universal argument :: See
https://emacsdocs.org/docs/elisp/Prefix-Command-Arguments. This is a special
key you use to modify the command you invoke directly afterwards.
For example, if you take a command called ~delete-stuff~, bound to [[kbd:][C-c d]] that
tells you it will "delete the current line, or delete the whole buffer if
prefix argument is set"; then
- [[kbd:][C-c d]] will delete a line
- [[kbd:][M-x delete-stuff RET]] will delete a line
- [[kbd:][C-u C-c d]] will delete the whole buffer
- [[kbd:][C-u M-x delete-stuff RET]] will delete the whole buffer.
The goal of the universal/prefix argument is to get a slightly different
behaviour for known commands.
#+begin_quote
Doom users with evil enabled will find the universal argument on [[kbd:][SPC u]]
instead than [[kbd:][C-u]].
#+end_quote
- Prefix argument :: Universal argument
- Prefix key :: A "prefix" is a key that begins a key sequence. For instance,
the key sequence [[kbd:][C-x C-k b]] is comprised of three distinct input events. Both
[[kbd:][C-x]] and [[kbd:][C-x C-k]] can be considered prefixes.
Prefix keys allow to store and move keybindings in groups. For example by
default all [[doom-package:lsp-mode]] commands are under ~SPC c l ...~, but if you want to
change that prefix to ~SPC L ...~ for all [[doom-package:lsp-mode]] commands, it is a one liner
in your configuration; you do _not_ have to rebind each command manually to
its new ~SPC L ...~ variant.
** Repositories :category:
- doomemacs/core :: https://git.doomemacs.org/core
- doomemacs/modules :: https://git.doomemacs.org/modules
- doomemacs/contrib-modules :: https://git.doomemacs.org/contrib-modules
- doomemacs/themes :: https://git.doomemacs.org/themes
- doomemacs/snippets :: https://git.doomemacs.org/snippets
* Acronyms
- CD :: Continuous Delivery
- CI :: Continuous Integration
- CLI :: Command-Line Interface
- PR :: (Github) Pull Request
- PRed :: PR
- YMMV :: Your mileage may vary
* Text Substitutions
================================================
FILE: docs/contributing.org
================================================
#+TITLE: Contributing
#+STARTUP: nofold
Doom Emacs is an active and ongoing project, maintained mostly by a single
person, but includes the efforts of 200 contributors and growing. There is no
shortage of things that need doing; bugs that need stomping, features that need
implementing, and documentation that needs documenting. If Doom's been useful to
you, convert some caffiene into code; it'd be a huge help!
You are welcome to [[https://discord.gg/qvGgnVx][join us on our Discord server]], otherwise read on to learn how
to contribute to our fine corner of the interwebs.
* Table of Contents :TOC_3:
- [[#where-can-i-help][Where can I help?]]
- [[#reporting-issues][Reporting issues]]
- [[#acquire-a-backtrace-from-errors][Acquire a backtrace from errors]]
- [[#create-a-step-by-step-reproduction-guide][Create a step-by-step reproduction guide]]
- [[#include-information-about-your-doom-install][Include information about your Doom install]]
- [[#debugging-crashes-with-gdb][Debugging crashes with gdb]]
- [[#suggesting-features-keybinds-andor-enhancements][Suggesting features, keybinds and/or enhancements]]
- [[#contributing-code][Contributing code]]
- [[#conventions][Conventions]]
- [[#code-style][Code style]]
- [[#naming-conventions][Naming conventions]]
- [[#commits--prs][Commits & PRs]]
- [[#keybind-conventions][Keybind conventions]]
- [[#your-first-code-contribution][Your first code contribution]]
- [[#submitting-pull-requests][Submitting pull requests]]
- [[#contributing-to-doom-core][Contributing to Doom core]]
- [[#contributing-to-an-existing-module][Contributing to an existing module]]
- [[#contributing-a-new-module][Contributing a new module]]
- [[#contributing-documentation][Contributing documentation]]
- [[#contributing-to-dooms-manual][Contributing to Doom's manual]]
- [[#contributing-module-documentation][Contributing module documentation]]
- [[#help-keep-packages-up-to-date][Help keep packages up-to-date!]]
- [[#other-ways-to-support-doom-emacs][Other ways to support Doom Emacs]]
- [[#special-thanks][Special thanks]]
* Where can I help?
+ Our [[https://github.com/hlissner/doom-emacs/issues][issue tracker]] has many issues. If you find one that you have an answer to,
it would be a huge help!
+ Look for issues tagged [[https://github.com/hlissner/doom-emacs/labels/good%20first%20issue][good first issue]]. These were judged to have a low
barrier of entry.
+ Look for issues tagged [[https://github.com/hlissner/doom-emacs/labels/help%20wanted][help wanted]]. These tend to be a little (or a lot)
harder, and are issues outside my own expertise.
+ If you've encountered a bug, [[https://github.com/hlissner/doom-emacs/issues/new/choose][file a bug report]].
+ The [[https://github.com/hlissner/doom-emacs/projects/3][development roadmap board]] is a rough timeline of what is being worked on
and when. It will give you an idea of what will change and where you can
redirect your efforts.
+ The [[https://github.com/hlissner/doom-emacs/projects/2][plugins under review board]] lists third party plugins being considered (or
rejected) for inclusion in Doom Emacs. Approved and unclaimed packages are
open for you to implement yourself.
+ The [[https://github.com/hlissner/doom-emacs/projects/5][upstream bugs board]] lists known issues that have external causes, but
affect Doom. If you're feeling adventurous (or are better acquainted with the
cause) perhaps you can address them at the source.
* TODO Reporting issues
You've found a problem and you're ready to fire off that bug report. Hold up!
Before you do that, [[file:getting_started.org::*Troubleshoot][have a look at our Troubleshooting guide]]. If none of these
suggestions pan out, /then/ it is time to file a bug report.
An effective bug report is informative. Please try to provide:
+ A backtrace of all mentioned errors.
+ A step-by-step reproduction of the issue.
+ Information about your Doom config and system environment.
+ Screenshots/casts of the issue (if possible).
This section will show you how to collect this information.
** Acquire a backtrace from errors
See "[[file:getting_started.org::*How to extract a backtrace from an error][How to extract a backtrace from an error]]" in the [[file:getting_started.org][Getting Started]] guide.
** TODO Create a step-by-step reproduction guide
** TODO Include information about your Doom install
** TODO Debugging crashes with gdb
* TODO Suggesting features, keybinds and/or enhancements
* TODO Contributing code
There's much to be done around here! We need bugfixes, new features, and
documentation. If you'd like to convert some caffeine into Emacs Lisp, here are
a few considerations before starting that PR:
** TODO Conventions
*** TODO Code style
Doom conforms to [[https://github.com/bbatsov/emacs-lisp-style-guide][@bbatsov's emacs-lisp style guide]] with the following
exceptions:
+ Use ~mapc~ instead of ~seq-do~.
+ No hanging parentheses
+ We use =DEPRECATED= to indicate code that will eventually be removed.
*** Naming conventions
Doom has a number of naming conventions that it uses in addition to the standard
lisp conventions. Third party packages may use their own conventions as well.
**** Lisp Naming Conventions
The lisp conventions are simple. Symbols follow ~NAMESPACE-SYMBOLNAME~ for
public variables/functions (e.g. ~bookmark-default-file~ or
~electric-indent-mode~) and ~NAMESPACE--SYMBOLNAME~ for private ones (e.g.
~byte-compile--lexical-environment~ and ~yas--tables~).
~NAMESPACE~ is usually the name of the containing file or package. E.g. the
~company~ plugin prefixes all its variables/functions with ~company-~.
**** Doom Naming Conventions
+ ~doom/NAME~ or ~+MODULE/NAME~ :: Denotes a public command designed to be used
interactively, via =M-x= or a keybinding. e.g. ~doom/info~, ~+popup/other~,
~+ivy/rg~.
+ ~doom:NAME~ :: A public evil operator, motion or command. e.g. ~+evil:align~,
~+ivy:rg~.
+ ~doom-[-]NAME-h~ or ~+MODULE-[-]NAME-h~ :: A non-interactive function meant to
be used (exclusively) as a hook. e.g. ~+cc-fontify-constants-h~,
~+flycheck-buffer-h~.
+ ~doom-[-]NAME-a~ or ~+MODULE-[-]NAME-a~ :: Functions designed to be used as
advice for other functions. e.g. ~doom-set-jump-a~,
~doom--fix-broken-smie-modes-a~, ~+org--babel-lazy-load-library-a~
+ ~doom-[-]NAME-fn~ or ~+MODULE-[-]NAME-fn~ :: Indicates an [[https://en.wikipedia.org/wiki/Strategy_pattern][strategy]] function. A
good rule of thumb for what makes a strategy function is: is it
interchangeable? Can it be replaced with another function with a matching
signature? e.g. ~+lookup-dumb-jump-backend-fn~, ~+magit-display-buffer-fn~,
~+workspaces-set-project-action-fn~
+ ~abc!~ :: A public Doom "autodef" function or macro. An autodef should always
be defined, even if its containing module is disabled (i.e. they will not
throw a void-function error). The purpose of this is to avoid peppering module
configs with conditionals or `after!` blocks before using their APIs. They
should noop if their module is disabled, and should be zero-cost in the case
their module is disabled.
Autodefs usually serve to configure Doom or a module. e.g. ~after!~,
~set-company-backends!~, ~set-evil-initial-state!~
*** TODO Commits & PRs
- Target the correct branch:
- =rewrite-docs= for changes to =*.org= files.
- =master= for everything else.
- /Never/ =develop=. It's EOL.
- Consult [[https://gist.github.com/hlissner/bb6365626d825aeaf5e857b1c03c9837][our do-not-PR list]] for things we won't accept pull requests for.
*** TODO Keybind conventions
** TODO Your first code contribution
** TODO Submitting pull requests
** TODO Contributing to Doom core
** TODO Contributing to an existing module
** TODO Contributing a new module
* TODO Contributing documentation
Doom Emacs' documentation is an ongoing effort. If you have suggestions,
improvements, tutorials and/or articles to submit, don't hesitate to get in
contact via our [[https://discord.gg/bcZ6P3y][Discord server]] or [[mailto:henrik@lissner.net][email]]. I appreciate any help I can get!
** TODO Contributing to Doom's manual
** TODO Contributing module documentation
* TODO Help keep packages up-to-date!
Doom pins all its packages to reduce the likelihood of upstream breakage leaking
into Doom Emacs. However, we may miss when a package releases hotfixes for
critical issues. Let us know or PR a bump to our pinned packages.
* TODO Other ways to support Doom Emacs
* TODO Special thanks
================================================
FILE: docs/examples.org
================================================
:PROPERTIES:
:ID: e103c1bc-be8e-4451-8e43-a93d9e35e692
:END:
#+title: Examples
#+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
your own reference. They are divided into Emacs-specific and Doom-specific
examples; where the former can also be useful to users who don't use Doom.
Some of Doom's components will read this file to generate documentation for you,
for example:
- Doom's [[doom-module:][:lang emacs-lisp]] module installs the [[doom-package:elisp-demos]] package. This displays
usage examples alongside documentation in [[doom-package:help]] and [[doom-package:helpful]] buffers (produced
by =describe-*= and =helpful-*= commands; e.g. [[kbd:][<help> h f]]). Doom has extended
this package to search this file as well.
- [[id:1b8b8fa9-6233-4ed8-95c7-f46f8e4e2592][Some Doom's CLI commands]] will emit documentation informed by Doom's org files,
including this file.
If you're interested in adding to this document, read [[id:9ac0c15c-29e7-43f8-8926-5f0edb1098f0][the documentation section]]
of our contributing guide first.
* TODO Emacs
This section is dedicated to examples of concepts and libraries that can benefit
all Emacs users, whether or not they use Doom.
** TODO Templates
*** TODO Emacs package
*** TODO Dynamic module
* TODO Doom Emacs
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 Configuration files
*** =profiles.el=
:PROPERTIES:
:ID: f9bce7da-d155-4727-9b6f-b566b5b8d824
:END:
This file can live in any of:
- =$DOOMDIR/profiles.el=
- =$EMACSDIR/profiles.el=
- =~/.config/doom-profiles.el=
- =~/.doom-profiles.el=
Here is an exhaustive example of all its syntax and capabilities:
#+begin_src emacs-lisp
;; -*- mode: emacs-lisp; -*-
((profile1
;; The permitted formats of each entry:
(var . value)
("envvar" . value)
(var :directive values...)
;; `user-emacs-directory' is often the first variable you want to set, so
;; Emacs knows where this profile lives. If you don't, it'll use the config
;; living in the default locations (~/.config/emacs or ~/.emacs.d).
(user-emacs-directory . "~/another/emacs/config/")
;; If this is a Doom config, you'll also want to set `doom-user-dir', which
;; defaults to ~/.config/doom or ~/.doom.d:
(doom-user-dir . "~/another/doom/config/")
;; If a CAR is a string, it is assumed you want to set an environment
;; variable. (Side-note: setting DOOMDIR will be unnecessary if you're setting
;; `doom-user-dir' above).
("DOOMDIR" . "~/another/doom/config/")
;; Doom profiles support a number of special directives. They are:
;;
;; (VAR :path SEGMENTS...) -- set VAR to an exapnded path built from SEGMENTS,
;; relative to `user-emacs-directory', unless an absolute path is in SEGMENTS.
(doom-cache-dir :path doom-user-dir ".local/cache")
(doom-data-dir :path doom-user-dir ".local/data")
(doom-state-dir :path doom-user-dir ".local/state")
;; (VAR :plist VALUE) -- use VALUE as a literal plist; ignoring any profile
;; directives that may be in it.
(some-plist :plist (:foo bar :baz womp))
;; (VAR :eval FORMS...) -- use to evaluate arbitrary elisp forms. Note that
;; his runs early in early-init.el. It's wise to assume no APIs are available
;; or loaded, only the previous bindings in this profile.
(doom-theme :eval (if (equal (system-name) "foo") 'doom-one 'doom-dracula))
;; Though discouraged, you may evaluate forms without a binding by using `_'.
;; You really should be doing this in the profile though...
(_ :eval (message "Hello world!"))
(_ :eval (with-eval-after-load 'company (setq-default company-idle-delay 2.0)))
;; (VAR :prepend FORMS...) or (VAR :append FORMS...) -- prepend or append the
;; evaluated result of each form in FORMS to VAR (a list). If VAR is undefined
;; at startup, it will be deferred until the variable is available.
(load-path :prepend (expand-file-name "packages/" doom-user-dir))
(load-path :prepend (expand-file-name "lisp/" doom-user-dir))
(load-path :append (expand-file-name "fallback/" doom-user-dir))
(exec-path :prepend (expand-file-name "bin/" doom-user-dir))
(auto-mode-alist :prepend '("\\.el\\'" . lisp-mode)))
(profile2
...)
(profile3
...))
#+end_src
*** =.doomprofile=
:PROPERTIES:
:ID: ac37ac6f-6082-4c34-b98c-962bc1e528c9
:END:
This file takes after the second level of =profiles.el='s format (see a more
complete example in [[id:f9bce7da-d155-4727-9b6f-b566b5b8d824][the previous section]]). For example:
#+begin_src emacs-lisp
;;; -*- mode: emacs-lisp -*-
;; A .doomprofile can be placed under an implicit profile. Same rules as
;; .doom-profiles.el, but one level deeper.
((var . value)
("envvar" . value)
(var :directive values...))
#+end_src
*** TODO =.doom=
*** TODO =.doom.el=
*** TODO =.doommodule=
** TODO Templates
*** TODO User configuration
*** TODO Module
*** TODO Project
*** TODO Theme
*** TODO Command-line interface
**** Unix utilities, rewritten as Doom scripts
To show off the syntax and capabilities of Doom's CLI framework, here are some
popular scripts ported to doomscripts for reference. They will all operate under
these assumptions:
1. The script lives somewhere in your =$PATH=,
2. =$EMACSDIR/bin/doomscript= lives in your =$PATH=.
3. The script is executable,
4. The script's filename matches the first argument of ~run!~ (by convention,
not a requirement),
***** ~mkdir~
#+begin_src emacs-lisp :eval no
#!/usr/bin/env doomscript
(defcli! mkdir
((mode ("-m" "--mode" mode))
(parents? ("-p" "--parents"))
(verbose? ("-v" "--verbose"))
&args directories)
"Create the DIRECTORIES, if do not already exist.
Mandatory arguments to long options are mandatory for short options too.
OPTIONS:
-m, --mode
set file mode (as in chmod), not a=rwx - umask.
-p, --parents
no error if existing, make parent directories as needed, with their file
modes unaffected by any `-m' option.
-v, --verbose
print a message for each created directory
AUTHOR:
Original program by David MacKenzie. Doomscript port by Henrik Lissner.
SEE ALSO:
`mkdir(2)`
Full documentation <https://www.gnu.org/software/coreutils/mkdir>
or available locally via: info '(coreutils) mkdir invocation'
Packaged by https://nixos.org
Copyright © 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/li‐
censes/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law."
(dolist (dir directories)
(unless (file-directory-p dir)
(make-directory dir parents?)
(when mode
(set-file-modes dir mode))
(when verbose?
(print! "mkdir: created directory '%s'" dir)))))
#+end_src
****** Notes
- Docstrings for Doom CLIs recognize indented sections with a capitalized
heading followed by a colon (like ~SEE ALSO:~, ~OPTIONS:~, etc). They will be
appended to the --help output for this command. ~OPTIONS~ and ~ARGUMENTS~ are
special, in that they decorate pre-existing documentation for referenced
options/arguments.
- The options were documented in the CLI's docstring, instead of inline like so:
#+begin_src emacs-lisp
((mode ("-m" "--mode" mode) "set file modes (as in chmod), not a=rwx - umask.")
(parents? ("-p" "--parents") "no error if existing, make parent directories as needed, with their file modes unaffected by any `-m' option.")
(verbose? ("-v" "--verbose") "print a message for each created directory")
&args directories)
#+end_src
Either is acceptable, but for long docs like this, it's better suited to the
docstring. If both were present, Doom's help docs would have concatenated them
(separated by two newlines).
- The ~mode~ option takes one argument, a chmod mask. I indicate this with
~"`MODE'"~. This is a special syntax for highlighting arguments in the help
docs of this command. If I had used a symbol, instead (one of the predefined
types in [[var:][doom-cli-argument-value-types]]), I would've gotten free type-checking
and error handling, but there is no predefined type for chmod masks (yet), so
I'd have to do my own checks:
#+begin_src emacs-lisp :eval no
(defcli! mkdir
((mode ("-m" "--mode" "`MODE'"))
(parents? ("-p" "--parents"))
(verbose? ("-v" "--verbose"))
&args directories)
(unless (string-match-p "^[0-9]\\{3,4\\}$" mode)
(user-error "Invalid mode: %s" mode))
(setq mode (string-to-number mode 8))
(dolist (dir directories)
(unless (file-directory-p dir)
(make-directory dir parents?)
(when mode
(set-file-modes dir mode))
(when verbose?
(print! "mkdir: created directory '%s'" dir)))))
#+end_src
That said, set-file-modes will throw its own type error, but it likely won't
be as user friendly.
***** TODO ~say~
#+begin_src emacs-lisp :eval no
#!/usr/bin/env doomscript
(defcli! say
((name ("--speaker" name) "Who is speaking?")
&args args)
"This command repeats what you say to it.
It serves as an example of the bare minimum you need to write a Doom-based CLI.
Naturally, it could be more useful; it could process more complex options and
arguments, call other Doom CLIs, read/write data from files or over networks --
but that can wait for more complicated examples.
ARGUMENTS:
ARGS
The message to be repeated back at you.
OPTIONS:
--speaker
If not specified, it is assumed that Emacs is speaking."
(print! "%s says: %S"
(or name "Emacs")
(string-join args " ")))
(run! "say" (cdr (member "--" argv)))
#+end_src
#+begin_src bash :eval no
$ say hello world
Emacs says: "Hello world"
$ say --speaker Henrik "I've doomed us all"
Henrik says: "I've doomed us all"
$ say --help
TODO
#+end_src
***** emacs
This isn't useful, but it should hopefully demonstrate the full spectrum of
Doom's CLI, by reimplementing a subset of ~emacs~'s options and arguments (and
none of its documentation). It will simply forward them to the real program
afterwards.
Since I don't want to override the real ~emacs~ in the ~$PATH~, I'll just call
it ~demacs~:
#+begin_src emacs-lisp :eval no
#!/usr/bin/env doomscript
(defcli! demacs
((cd ("--chdir" dir))
(quick? ("-Q" "--quick"))
(no-init? ("-q" "--no-init-file"))
(no-slisp? ("-nsl" "--no-site-lisp"))
(no-sfile? ("--no-site-file"))
(initdir ("--init-directory" dir))
(batch? ("--batch"))
(batch (("-l" "--load" (file) ...))
(("-e" "--eval" (form) ...))
(("-f" "--funcall" (fn) ...))
(("-L" "--directory" (dir) ...))
(("--kill")))
(script ("--script" (file)))
&args (args (file linecol)))
"Demacs is a thin wrapper around Emacs, made to demo of Doom's CLI Framework.
Since documentation isn't the focus of this example, this is all you'll get!"
(cond (script (load script))
(batch?
(dolist (do batch)
(pcase do
(`(,(or "-l" "--load") . ,file) (load file))
(`(,(or "-e" "--eval") . ,form) (eval (read form) t))
(`(,(or "-f" "--funcall") . ,fn) (funcall (read fn)))
(`("--kill" . t) (kill-emacs 0)))))
((exit! :then (cons "emacs"
(append (if quick '("-Q"))
(if no-init? '("-q"))
(if no-slisp? '("-nsl"))
(if no-sfile? '("--no-site-file"))
(if initdir `("--init-directory" ,initdir))
args))))))
#+end_src
****** Notes
There's a lot of (intentional) redundancy here, for posterity. A *much* simpler
(and more reliable) version of this command would've looked like this:
#+begin_src emacs-lisp
(defcli! demacs (&rest args)
(exit! :then (cons "emacs" args)))
#+end_src
But that wouldn't demonstrate enough. Though, it wouldn't forward ~--version~ or
~--help~ either.
** TODO Use cases
*** TODO Note-taking
*** TODO Game development
*** TODO Web development
*** TODO Emacs as your terminal
================================================
FILE: docs/faq.org
================================================
:PROPERTIES:
:ID: 5fa8967a-532f-4e0c-8ae8-25cd802bf9a9
:END:
#+title: Frequently Asked Questions
#+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
:END:
This section is for general questions about the Doom Emacs project and its
author.
** Is Emacs (or Doom) for me?
:PROPERTIES:
:ID: 6f325ee8-228a-4b05-8ce9-4a997948d46a
:END:
These four sections of [[id:a3bf32ae-8218-48c1-a7d9-a6fd61e5734a][our user manual]] answer this question:
- [[id:fba3642f-b01e-405b-80ac-2900df22e978][Why Emacs?]]
- [[id:e3172459-abcb-45cb-9135-9692f320a836][Why /not/ Emacs?]]
- [[id:46d2058d-249e-45a7-a7a2-58bade48df65][Why Doom?]]
- [[id:da317a3c-1672-40e2-85d5-b4246482af2c][Why /not/ Doom?]]
** How does Doom compare to <insert starter kit>?
I've compiled comparisons to several starter kits in [[id:f2186c7b-9f48-4b0b-ac0b-d891b5b1e1b3][our migration guide]].
** Is Doom a fork of another starter kit?
No. I started Doom from scratch in 2013 to learn Emacs and Emacs Lisp, and to
write a private config for myself. Starter kits were brought to my attention
later, when early Doom users vocally compared them.
That's not to say I've taken no inspiration from them since. Doom's earliest
file structure was inspired by Prelude's, until it was replaced with a module
system. Other concepts (like [[kbd:][SPC]] as a leader key) came from Spacemacs or were
PRed from migrating users, and were accepted because they seemed sensible.
More similarities (and differences) will no doubt emerge as our userbase grows
and more starter kits appear.
** Doom claims to be an Emacs framework, not a starter kit. What's the difference?
I don't claim to own these terms, but I use them to distinguish [[https://git.doomemacs.org/core][Doom's core]] (a
framework) from [[https://git.doomemacs.org/modules][Doom's module library]] (a starter kit).
My premise is: starter kits and Emacs frameworks have different goals. Where
starter kits help you avoid work by doing it for you, an Emacs framework helps
you /do/ that work yourself, but more effectively (by providing extra tools,
APIs, or organizational systems for writing/debugging). Of course, there will be
some crossover.
** Who maintains Doom Emacs?
My name is [[https://github.com/hlissner][Henrik]], I'm this project's author and its sole maintainer, for the
moment. I plan to onboard co-maintainers once the project has:
- Proper technical documentation for users, contributors, and
maintainers. Many important organizational questions haven't been formally
answered or committed to paper: such as our versioning scheme, git
conventions, community policies, and code/documentation style guides. Even
Doom's goals aren't formally stated anywhere.
- More unit, integration, and package tests. Total coverage isn't required (or
desired), but Emacs issues are complex and esoteric, so /some/ measure of
automated sanity checks (and protocols for merges and releases) are needed to
spare future maintainers a stroll through a minefield.
- Resolved its stability, performance, and standardization issues that plague
its CLI. Issues too esoteric for me to unleash onto unsuspecting
co-maintainers in good conscience. I could live with them when Doom was my
private config, but that is no longer the case. It needs to be rewritten.
Most of these issues will be resolved in the final 3.0.0 release.
I am looking for [[id:29d9a145-8f2e-4d22-b4d0-de8a2c72698d][module maintainers]] though!
** Why is the project called "Doom"?
As a kid in the Cretaceous period (1999), the [[https://github.com/id-Software/DOOM][source code]] of idsoftware's
classic Doom was my first exposure to programming. Totally clueless about C and
compilers, all I could do was peek at it from time to time and hope I'd absorb
its secrets if I stared hard enough. It didn't work, but it sure jump-started by
gamedev addiction.
So "Doom Emacs" was what you got when you combined childhood, demon-carnage
nostalgia, [[https://www.youtube.com/user/n4sco][terrible]] [[https://github.com/hlissner/emacs-solaire-mode][naming]] [[https://github.com/hlissner/vim-forrestgump][sense]], and the sneaking suspicion that Emacs is the
unwritten tenth circle Dante censored for humanity's protection.
I've doomed us all.
** Why does Doom use straight.el and not package.el?
=package.el= simply doesn't cut it. Its flaws become apparent the more packages
you manage, the more complex your config becomes, and how often those packages
see updates:
- No disaster recovery ::
When things go wrong, we don't always have time to deal with it. Or we need to
wait for upstream to deploy a fix. While we wait, we still have work to do,
but now what? Emacs is broken! =package.el= doesn't give you any options to
roll back, so you /have/ to deal with it, and now. Or hope your old config was
backed up.
Though Doom doesn't have a 'doom rollback' command (yet), the ability to
quickly checkout an old commit of a problematic package (or Doom itself),
without the overhead of forking and/or maintaining a local copy, is priceless.
- Rolling release or bust ::
=package.el= installs the latest version of every package, or none at all.
There's no rollback, no pinning to a stable ref, and no git history to peek
into. It offers little reproducibility; wiping/losing/copying your config
becomes a gamble if you aren't constantly backing up your packages (then
recompiling them if you're up/downgrading Emacs).
=melpa-stable= was well intentioned, but it offers no guarantees or standards
on how/when maintainers tag their projects. I'd rather the user decide for
themselves, because they're the ones in the trenches.
- Can't install packages from superior sources ::
Often, a crucial fix sits in a pull request somewhere for too long, a package
becomes outdated through official channels, or a superior fork springs up
somewhere other than an ELPA. =package.el= cannot reach those sources.
- Slow at startup (by default) ::
Initializing =package.el= can be expensive, depending on the number (and
complexity) of installed packages -- especially for batch scripts.
~package-quickstart~ helps, up to a point, but Doom's package manager can do
better with the assumptions available to its monolithic ecosystem. All without
imposing =straight.el= or =package.el= on your runtime environments.
Package management needs to be easier, because Emacs is hard enough already.
Doom fills these gaps with =straight.el='s help, and beyond.
Granted, you /can/ get most of the above with a little Git know-how, but it
stops being convenient as you reach package 5 or 15, your tenacity permitting.
** Why is startup time important? Why not use the daemon?
It isn't, but it gets a disproportional amount of attention because it's the
first thing Doom's users notice. Doom is perfectly compatible with the daemon
and I don't intend to discourage its use. If I had to say something about it,
it's that I'm unhappy that a daemon is needed at all to get sane startup times
out of Emacs.
It's left to the user to know or care about optimal load paths, and to implement
them, but that's a lot to ask when the problem domain is so vast, esoteric, and
a moving target (with a high cost-to-benefit). Who has the time to inspect, much
less fix, all their packages? And maintain that effort across Emacs or package
updates? It's easier to use the daemon, so people do.
That said, there's no one to blame for that. I consider Doom's effort, the
daemon, even native compilation (though all excellent endeavors) stop-gap
measures for a deeper, underlying issue in Emacs that needs smarter people than
I to address.
Rather than startup time, runtime performance is a bigger priority, though the
two rarely stray far from each other.
** Where do I follow the development of the project?
:PROPERTIES:
:ID: 4af14dad-5b74-43a7-8c9a-153227eed4a9
:END:
Our development resources are listed [[id:a20e3feb-f1e4-4bd3-92a9-6dfb17bcb24b][in our manual]].
** Where do I report issues, request features, or get user support?
Check out [[id:2f277e96-654d-406f-8797-b9a7d2ccc218][our community resources]] for a complete list of communities and
platforms. I'd recommend [[https://discourse.doomemacs.org/get-help][our Discourse]].
** I don't like Discord. Can Doom move to IRC/Telegram/Matrix/other?
This is requested *a lot*--and not always so kindly. We have [[https://discourse.doomemacs.org][a Discourse]] and
[[https://discourse.doomemacs.org/t/a-matrix-space-for-doom-emacs/2664/12][there are plans for a Matrix space]], but that's as many platforms as I have
bandwidth for. Please do not ask me to reconsider.
** How do I add a question to the FAQ?
:PROPERTIES:
:ID: aa28b732-0512-49ed-a47b-f20586c0f051
:END:
There is no submission process for FAQs. Our community leaders select them from
our Discord, Discourse, and Github communities (sometimes elsewhere) based on
frequency (actual or anticipated). Ask your questions there. If they make the
cut they will naturally find their way here.
* How do I...
:PROPERTIES:
:ID: 9c81ab2a-7da9-4b8e-9f90-d4ebff8bebbb
:END:
For common how-to and configuration questions from Doom users. You'll find more
[[https://discourse.doomemacs.org/tags/faq][on our Discourse]].
** Find out what version of Doom am I running?
Use ~M-x doom/info~ or ~$ doom info~ to produce detailed information about your
installation and environment.
Alternatively, ~M-x doom/version~ or ~$ doom version~ will only list the
versions of installed Doom components.
The installed version of Doom core is also displayed in the Doom dashboard's
mode-line.
** Turn (Doom) Emacs into a <insert language here> IDE with LSP?
:PROPERTIES:
:ID: 4cec77b2-bb1c-4b35-8ad1-d6dd9fcc1dbb
:END:
This is frequently asked: how to transform Doom Emacs into an IDE for some
programming language. In almost all cases, it's recommended that you enable
Doom's LSP support and install a supported LSP client.
This provides code completion, lookup {definition,references,documentation}
functionality, and syntax checking, all in one:
1. Enable Doom's [[doom-module::tools lsp]] module. ([[id:01cffea4-3329-45e2-a892-95a384ab2338][How do I enable modules?]])
2. Enable the ~+lsp~ flag on the ~:lang~ module corresponding to the language
you want LSP support for. E.g. For python, enable [[doom-module::lang python +lsp]]. For
rust, enable [[doom-module::lang rust +lsp]]. ([[id:01cffea4-3329-45e2-a892-95a384ab2338][How do I enable module flags?]])
3. Install [[https://emacs-lsp.github.io/lsp-mode/page/languages/][a supported LSP client]] on your system using your OS package manager
OR from within Emacs using ~M-x lsp-install-server~ (warning: not all servers
can be installed this way).
4. Run ~$ doom sync~ on the command line.
5. Restart Emacs.
6. (Optional) If Emacs fails to find your LSP server, you may need to run ~$
doom env~ to regenerate your envvar file (which contains your =$PATH=, which
tells Emacs where to find programs on your system).
*** Potential issues
1. Some language modules lack LSP support (either because it doesn't exist or
I'm not aware of it -- let me know!). If you're certain a language is
supported by [[doom-package:lsp-mode]], simply adding [[fn:lsp!]] to that major mode's hook will be
enough to enable it:
#+begin_src elisp
;; Remember to replace MAJOR-MODE with the major mode that powers the language.
;; E.g. `ruby-mode-local-vars-hook' or `python-mode-local-vars-hook'
(add-hook 'MAJOR-MODE-local-vars-hook #'lsp! 'append)
;; For Elisp gurus: Doom provides MAJOR-MODE-local-vars-hook, and we use it
;; instead of MAJOR-MODE-hook because it runs later in the mode's startup
;; process (giving other functionality or packages -- like direnv -- time to
;; configure the LSP client).
#+end_src
2. Some languages have alternatives that are superior to the LSP offerings (such
as Cider for Clojure or Sly for Common Lisp).
When in doubt, check that language module's documentation! Look up a module's
documentation with [[kbd:][<help> d m]] (or ~M-x doom/help-modules~).
** Change my fonts
Doom exposes a couple variables for setting fonts. They are:
- [[var:doom-font]]: the primary font for Emacs to use.
- [[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-emoji-font]]: used for rendering emoji. Only needed if you want to use
a font other than your operating system’s 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.
Each of these variables accept one of:
- A font-spec object: ~(font-spec :family "FontName" :size 12.0 :weight 'light)~
- An xft font string:
- Short form: ~"JetBrainsMono-12"~
- Long form: ~"Terminus (TTF):pixelsize=12:antialias=off"~
- An XLFD string: ~"-*-Fira Code-regular-normal-normal-*-11-*-*-*-*-*-*-*"~
For example:
#+begin_src emacs-lisp
;; 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-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
up, or run ~$ fc-list~ to see all the available fonts on your system. *Font
issues are /rarely/ Doom issues!*
#+end_quote
*** To change fonts on the fly:
1. Select your ~setq~ statements,
2. Evaluate them with ~M-x eval-region~ (evil users can use the [[kbd:][gr]] operator to
evaluate regions of elisp, non-evil users can use [[kbd:][C-x C-e]]),
3. Then reload the fonts: ~M-x doom/reload-font~.
Your changes should take effect immediately.
** Change, customize, or make themes?
- To change themes, add ~(setq doom-theme 'name-of-theme)~ to
=$DOOMDIR/config.el=.
- To switch themes on-the-fly, type [[kbd:][<help> t]] or ~M-x load-theme~.
- To customize or write themes, see our guide on [[https://discourse.doomemacs.org/t/how-to-switch-customize-or-write-themes/37][the Discourse]].
** Properly update Doom?
You can update Doom one of two ways:
1. The correct way: by running ~$ doom upgrade~ in the shell and restarting
Emacs.
2. The manual way (if ~doom upgrade~ is broken for some reason):
#+begin_src bash
$ cd ~/.emacs.d
$ git pull # pull the latest version of Doom's source
$ doom sync -u # update Doom's packages and 'doom sync'
#+end_src
This may change in the future, so ~$ doom upgrade~ will always be the safest
option. That said, ~$ doom help upgrade~ will always document the correct
procedure for manual updates if you need it.
** Bind my own keys (or change existing ones)?
Emacs provides a couple functions to bind keys:
- ~define-key KEYMAP KEY DEF~
- ~global-set-key KEY DEF~
- ~local-set-key KEY DEF~
- ~evil-define-key STATES KEYMAP KEY DEF &rest ...~
However, Doom provides a more general ~map!~ macro, to conveniently wrap up the
above four into a more succinct syntax. Comprehensive examples of ~map!~'s usage
can be found in its documentation (keyboard shortcut: [[kbd:][<help> f map\!]]).
There are also live examples =map!='s usage in
=config/default/+evil-bindings.el=.
Unfortunately, binding keys in Emacs can be a complicated affair. A more
detailed guide on keys, keymaps, and keymap precedence can be found [[https://discourse.doomemacs.org/t/how-to-re-bind-keys/56][on our
Discourse]].
** Change or alias the leader or localleader key?
This is documented in more detail in our user manual:
- [[id:76df34eb-142c-4280-85e7-b231d8adafc5][How to change your leader keys]]
- [[id:58741e77-c44b-4292-b9c9-5eb7da36fa21][How to bind new keys under the leader prefix]]
- [[id:8e0d2c05-6028-4e68-a50d-b81851f3f258][How to bind aliases for your leader / localleader prefix]]
** Change the style of (or disable) line-numbers?
Doom uses the [[doom-package:display-line-numbers]] package, which is included with Emacs 26+.
*** To disable line numbers entirely
#+begin_src emacs-lisp
;;; in $DOOMDIR/config.el
(setq display-line-numbers-type nil)
;; or
(remove-hook! '(prog-mode-hook text-mode-hook conf-mode-hook)
#'display-line-numbers-mode)
#+end_src
*** To switch to relative line numbers
To change the style of line numbers, change the value of the
~display-line-numbers-type~ variable. It accepts the following values:
#+begin_example
t normal line numbers
'relative relative line numbers
'visual relative line numbers in screen space
nil no line numbers
#+end_example
For example:
#+begin_src emacs-lisp
;;; add to $DOOMDIR/config.el
(setq display-line-numbers-type 'relative)
#+end_src
You'll find more precise documentation on the variable through [[kbd:][<help> v
display-line-numbers-type]] ([[kbd:][<help>]] is [[kbd:][SPC h]] for [[doom-package:evil]] users, [[kbd:][C-h]] otherwise).
*** To cycle through different styles of line numbers
Use ~M-x doom/toggle-line-numbers~ (bound to [[kbd:][<leader> t l]] by default) to cycle
through the available line number styles in the current buffer.
E.g. ~normal -> relative -> visual -> disabled -> normal~
** Disable Evil (vim emulation)?
By disabling the [[doom-module::editor evil]] module ([[id:01cffea4-3329-45e2-a892-95a384ab2338][how to toggle modules]]).
Read the "[[id:f3925da6-5f0b-4d11-aa08-7bb58bea1982][Removing evil-mode]]" section in the module's documentation for precise
instructions.
** Know when to run ~$ doom sync~?
:PROPERTIES:
:ID: 594d2505-d3cb-4061-ab76-06e7c8a4e0b8
:END:
As a rule of thumb, run ~$ doom sync~ whenever you:
- Update Doom with ~$ git pull~ instead of ~$ doom upgrade~,
- Change your ~doom!~ block in =$DOOMDIR/init.el=,
- Change =autoload.el= or =autoload/*.el= files in any module (or =$DOOMDIR=),
- Change the =packages.el= file in any module (or =$DOOMDIR=).
- Install an Emacs package or dependency outside of Emacs (i.e. through your OS
package manager).
If anything is misbehaving, it's a good idea to run ~$ doom sync~ first, to rule
out any issues with missing packages or autoloads.
This command is never needed for changes to =$DOOMDIR/config.el=.
** Suppress confirmation prompts when executing a doom command?
~-!~ or ~--force~ are the universal "suppress all prompts" switch for most
=doom= commands.
** 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~ 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~ on the other end, once moved.
** Start over, in case something went terribly wrong?
Delete =$EMACSDIR/.local/straight= and run ~$ doom sync~.
** Restore the s and S keys to their default vim behavior ([[doom-ref:][#1307]])
[[kbd:][s]] and [[kbd:][S]] have been intentionally replaced with the [[doom-package:evil-snipe]] plugin, which
provides 2-character versions of the f/F/t/T motion keys, ala [[https://github.com/goldfeld/vim-seek][vim-seek]] or
[[https://github.com/justinmk/vim-sneak][vim-sneak]].
These keys were changed because they are redundant with [[kbd:][cl]] and [[kbd:][cc]] respectively
(and the new behavior was deemed more useful).
If you still want to restore the old behavior, simply disable evil-snipe-mode:
#+begin_src emacs-lisp
;; in $DOOMDIR/config.el
(remove-hook 'doom-first-input-hook #'evil-snipe-mode)
#+end_src
* Common issues
:PROPERTIES:
:ID: 9adcf3a0-add2-4135-b918-e1d7f406c80d
:END:
For problems that come up especially often. You'll find more [[https://discourse.doomemacs.org][on our Discourse]]
and [[https://github.com/doomemacs/doomemacs/issues][Github issue tracker]]. Consult [[id:14040b81-3dd3-422e-abce-245f4c03d1b4][our troubleshooting guide]] for help debugging
issues.
** Doom and/or Emacs is slow
:PROPERTIES:
:ID: 643acc75-9717-4739-9c52-3947491e827e
:END:
The answer changes from version to version (of Emacs), and is often updated with
new information, so [[https://discourse.doomemacs.org/t/why-is-emacs-doom-slow/83][this is answered on Discourse]] instead.
** Doom starts up with a vanilla splash screen
The most common cause for this is a =~/.emacs= file. If it exists, Emacs will
read this file instead of the =~/.emacs.d= directory, ignoring Doom altogether.
If this isn't the case, run ~$ doom doctor~. It can detect a variety of common
issues and may offer you clues.
** I see a scratch buffer at startup instead of the dashboard
The common explanations for this are:
- Emacs can't find your private doom config (in =~/.doom.d= or
=~/.config/doom=). Make sure only one of these two folders exist, and that it
has an =init.el= file with a ~doom!~ block. Running ~$ doom install~ will
create these files and directories for you.
- An error occurred while starting up Doom. Use [[kbd:][C-h e]] to inspect Emacs' log.
Search it for errors or warnings. If you find one, [[id:aa116c29-b7d5-488a-860f-bdb22c1f4e8e][producing a backtrace]] from
the error can shed more light on it (and will be required if you ask the
community for help debugging it).
- You have disabled the [[doom-module::ui doom-dashboard]] module. Read about
[[id:5e267107-81fa-45b4-8ff3-26d4b98e508e][what Doom modules are]] and [[id:01cffea4-3329-45e2-a892-95a384ab2338][how to
toggle them]].
If you're still stuck, run ~$ doom doctor~. It can detect a variety of common
issues and may give you some clues as to what is wrong.
** Doom fails to find executables (or inherit my shell's =$PATH=)
The three most common causes for =$PATH= issues in Doom are:
1. Your shell configuration doesn't configure =$PATH= correctly. Run ~$ which
<PROGRAM>~ in your shell. If it doesn't emit the path you expect (or any path
at all) then you need to modify you shell config to do so correctly.
2. Your app launcher (rofi, albert, docky, dmenu, sxhkd, etc) is launching Emacs
with the wrong shell, either because it defaults to a different shell from
the one you actively use or the app launcher itself inherits the wrong
environment because it is being launched from the wrong shell.
3. You're a Mac user launching Emacs from an =Emacs.app= file. MacOS launches
these apps from an isolated environment.
As long as your shell is properly configured, there is a simple solution to
issues #1 and #3: generate an envvar file by running ~$ doom env~. This scrapes
your shell environment into a file that is loaded when Doom Emacs starts up. Run
~$ doom help env~ for details on how this works.
For issue #2, you'll need to investigate your launcher. There are too many
launchers write a walkthrough for, you'll have better luck asking about it on
[[https://doomemacs.org/discord][our Discord]] or [[https://discourse.doomemacs.org][Discourse]].
** Changes to my config aren't taking effect
1. Make sure you don't have both =~/.doom.d= and =~/.config/doom= directories.
Doom will ignore the first if the second exists.
2. Remember to run ~$ doom sync~ after making [[id:594d2505-d3cb-4061-ab76-06e7c8a4e0b8][certain changes]] to your config.
Run ~$ doom help sync~ to know exactly when you should use it.
3. If you are reconfiguring a package, make sure you've deferred your settings
until the package loads with the ~with-eval-after-load~ macro:
#+begin_src emacs-lisp
(with-eval-after-load 'magit
(setq magit-repository-directories '(("~/projects" . 2))
magit-save-repository-buffers nil))
#+end_src
There are two exceptions to this rule:
#+begin_src emacs-lisp
;; Setting file/directory variables don't (and shouldn't be) deferred. e.g.
(setq org-directory "~/org")
;; Don't defer setting variables whose documentation explicitly say they must
;; be set *before* the package is loaded. e.g.
(setq evil-respect-visual-line-mode t)
#+end_src
If none of these solve your issue, try ~$ doom doctor~. It will detect a variety
of common issues, and may give you some clues as to what is wrong. Otherwise,
consult [[id:2f277e96-654d-406f-8797-b9a7d2ccc218][the community]].
** Doom crashes and/or freezes
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-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.
- On some systems (particularly MacOS), manipulating the fringes or window
margins can cause Emacs to crash. This is most prominent in Doom's Dashboard
(which uses the margins to center its contents), in org-mode buffers (which
uses ~org-indent-mode~ to create virtual indentation), or Magit (whose fringes
are adjusted on the fly).
There is currently no known fix for this, as it can't be reliably reproduced.
Your best bet is to reinstall/rebuild Emacs or disable the errant
plugins/modules.
E.g. To disable ~org-indent-mode~:
#+begin_src emacs-lisp
;; in $DOOMDIR/config.el
(with-eval-after-load 'org
(setq org-startup-indented nil))
#+end_src
Or disable the [[doom-module::ui doom-dashboard]] and [[doom-module::tools magit]] modules (see [[doom-ref:][#1170]]).
If these don't help, check our troubleshooting guides for [[id:f88eaf35-97c4-48de-85ef-2d53f8615d4a][hard crashes]] or
[[id:0b744192-c648-452d-ba62-1b4c76dc3aee][freezes/hangs]].
** TRAMP connections hang forever when connecting
You'll find solutions [[https://www.emacswiki.org/emacs/TrampMode#toc7][on the emacswiki]].
** Why do I see ugly indentation highlights for tabs?
[[https://github.com/doomemacs/doomemacs/blob/4eeb3c7a19c324f5a7839a2e3edb03fc87d23034/core/core-ui.el#L97-L116][Doom highlights non-standard indentation]]. i.e. Indentation that doesn't match
the indent style you've set for that file. Spaces are Doom's default style for
most languages (excluding languages where tabs are the norm, like Go).
There are a couple ways to address this:
1. Fix your indentation! If it's highlighted, you have tabs when you should have
spaces (or spaces when you should be using tabs).
Two easy commands for that:
- ~M-x tabify~
- ~M-x untabify~
2. Change ~indent-tabs-mode~ (~nil~ = spaces, ~t~ = tabs) in
=$DOOMDIR/config.el=:
#+begin_src emacs-lisp
;; use tab indentation everywhere
(setq-default indent-tabs-mode t)
;; or only in certain modes
(setq-hook! 'sh-mode-hook indent-tabs-mode t) ; shell scripts
(setq-hook! '(c-mode-hook c++-mode-hook) indent-tabs-mode t) ; C/C++
#+end_src
3. Use [[https://editorconfig.org/][editorconfig]] to configure code style on a per-project basis. If you
enable Doom's [[doom-module::tools editorconfig]] module, Doom will recognize
=.editorconfigrc= files.
4. Or trust in [[doom-package:dtrt-indent]]; a plugin Doom uses to analyze and detect indentation
when you open a file (that isn't in a project with an editorconfig file).
This isn't foolproof, and won't work for files that have no content in them,
but it can help in one-off scenarios.
** "The directory =~/.emacs.d/server= is unsafe" error at startup (Windows only)
If you're getting this error you must reset the owner of
=C:\Users\USERNAME\.emacs.d= to your own account:
1. Right-click the =~/.emacs.d/server= directory in Windows Explorer,
2. Click Properties,
3. Select the "Security" tab,
4. Click the "Advanced" button,
5. Select the "Owner" tab,
6. Change the owner to your account name.
([[https://stackoverflow.com/questions/885793/emacs-error-when-calling-server-start][source]])
** My new keybinds don't work
Emacs has a complex and hierarchical keybinding system. If a global keybind
doesn't take effect, it's likely that another keymap is in effect with higher
priority than the global keymap. For example, non-evil users may have tried
something like this, to rebind [[kbd:][C-left]] and [[kbd:][C-right]]:
#+begin_src emacs-lisp
(map! "<C-left>" #'something
"<C-right>" #'something)
#+end_src
Just to find that the rebinding had no effect (i.e. [[kbd:][C-h k C-left]] reports that
it's still bound to ~sp-backward-slurp-sexp~). That's because these keys are
bound in ~smartparens-mode-map~. They need to be unbound for your global
keybinds to work:
#+begin_src emacs-lisp
(map! :after smartparens
:map smartparens-mode-map
[C-right] nil
[C-left] nil)
#+end_src
#+begin_quote
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
If you see an error like:
#+begin_example
Error: error ("Recursive load"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/jka-compr.el.gz"
"/Applications/Emacs.app/Contents/Resources/lisp/obsolete/cl.el.gz")
#+end_example
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
=tar= and =gzip= installed by default. Emacs requires the GNU variants!
#+end_quote
- =tar= and/or =gzip= aren't in your =$PATH=, somehow. Once you've corrected
your shell config, run ~$ doom env~ to regenerate your envvar file (containing
the =$PATH= Doom will see), then restart Emacs.
- *(macOS users only)* You've installed Emacs from one of the sources I
recommend you avoid. For example, emacsformacosx.com. Our user manual outlines
where you should acquire Emacs from.
If none of the above help, then [[id:3f3ea085-dbba-4d28-a56f-852f386249c1][file a bug report]].
* Contributors
:PROPERTIES:
:ID: 1afe59e5-0c67-4b70-a5b6-e7978ccf4220
:END:
For folks who want to report bugs and submit pull requests.
** How can I contribute to the project?
Our contributor's manual covers [[id:94f1eee7-eb2d-4d03-9881-7e36fbd82e4f][a bunch of ways you can help or support the
project]].
** How do I get my pull request processed ASAP?
:PROPERTIES:
:ID: 1223f94f-7c3f-4870-8a58-b94e8d7cbbb3
:END:
The project does not have a dedicated support team -- only one overworked
[[doom-user:hlissner][meatball]] and a handful of busy volunteers -- so there may be delays processing
your PR. Sometimes this is unavoidable, but there are some measures you can take
to mitigate these delays:
- Ensure there are no open PRs that tackle the same issue. If yours is intended
to replace an existing one, please mention it.
- Include an explanation: why the PR is necessary, what it fixes, any gotchas I
should be aware of, and issues it affects.
- Be acquainted with our [[id:46442b23-a7ae-44ba-afdb-b7ba8bb76b6e][git commit conventions]]. Good commit etiquette is
required. Do not be afraid to rebase or force-push to tidy up your PR, once it
is ready for review.
- Adhere to our [[id:b3d85a53-a544-44e5-9353-06e413bd7f30][code]], [[id:9bb17259-0b07-45a8-ae7a-fc5e0b16244e][documentation]], and [[id:cc55968b-f430-45e4-9e05-4c6187871b9d][keybind]] conventions, where applicable.
- Ensure you've targeted the =master= branch.
- Keep your PR focused. It shouldn't do too much in too many places, if that can
be avoided.
- If your PR introduces new tools, dependencies, or packages, I'm going to test
them. It takes time to research them, acquire them, learn how to use them, and
finally test them in the context of your PR. You can speed this up by
including steps to set up an MVE with some mock inputs and expected results.
Extra points if you supply a =shell.nix= or =Dockerfile= to do so (if
applicable).
** My PR was approved but not merged, what gives?
I approve PRs in bulk, often days before merging them. This is done to:
- Allow me to merge them when I have time to respond to regressions they may
cause.
- Give me a second chance to catch issues,
- Give the submitter extra time to correct mistakes,
- Give users a change to test it themselves,
If your PR was approved, you only have to wait for Henrik to get off his
glorious Canadian behind and merge it. If it's been a week or so with no
progress, feel free to ping him in-thread or [[https://doomemacs.org/discord][on Discord]] (in the #contributing
channel).
** Why was my issue deleted or tagged "delete me"?
:PROPERTIES:
:ID: 33641f29-7ed5-4a8c-a494-98ff1693349b
:END:
Due to the sheer complexity of Emacs, our issue tracker receives many
false-positive, redundant, vague, or "support request"-type issues. This is a
problem because they pollute our search results, make it difficult for users and
maintainers to track real issues, and cost much effort to process; taking away
time from real issues or project development.
Since Doom's "support team" only consists of one overworked maintainer and a
handful of busy volunteers, we have to be strict; we don't have the capacity to
chase issues that aren't *actionable*, *immediately reproducible*, or *cannot be
investigated within a reasonable amount of time* (which includes issues that are
poorly researched, vague, or open-ended).
Posts that fall into these categories will be immediately closed, tagged for
deletion, and given a brief explanation why, including instructions to overturn
or contest the ruling if I've made a mistake.
Some examples:
- Performance issues without a clear, verifiable, or reproducible cause.
- Behavior that can't be reproduced in [[id:04f91253-a92a-4125-a576-44de226582bb][vanilla Doom]].
- Behavior that can be reproduced in vanilla Emacs.
- An open-ended request to improve something without concrete goals.
- An issue that consists solely of "X doesn't work" and little else.
- An issue that omits important information, like steps to reproduce or system
information.
- A post asking how to configure or use Emacs to achieve some effect (our issue
tracker is for bug reports, not support; ask on [[https://doomemacs.org/discord][Discord]] or [[https://discourse.doomemacs.org][Discourse]] instead).
- A convoluted and unfocused issue that present multiple issues in one.
- A rude user that won't meet us half way and/or expects us to do all the work
for them.
To ensure your issue makes the cut, please consult "[[id:1223f94f-7c3f-4870-8a58-b94e8d7cbbb3][How do I ensure my issue
gets processed ASAP?]]" above.
** How do I create and maintain a PR branch for Doom Emacs?
[[id:40f24cd4-8108-411d-bdcd-0a2ef945b1e3][Our contributing guide offers a few techniques]].
* Sponsors
:PROPERTIES:
:ID: 739da458-feb0-42c3-abbc-11cbe3aaa273
:END:
For the generous folks who want to sponsor the project and its author.
** How do I sponsor the project?
:PROPERTIES:
:ID: 0b737d2b-c13b-4562-9274-015bc226a53f
:END:
Consider becoming my [[https://github.com/sponsors/hlissner][Github sponsor]]. If you're not a fan of Github sponsorship,
my page lists a couple alternatives.
If you do decide to sponsor me, thank you for your support! It is a big help,
and directly translates to more hours on my Doom, Emacs-related, or open-source
capers.
** How do I claim my tier rewards?
Once you have sponsored, you'll receive an automated email telling you how, but
in case you didn't: email me at contact@henrik.io or DM me on Discord
(@Henrik#0666) with *your github username* and (optionally) *Discourse
username*, and I'll help sort you out!
** Are there other ways to support the project or get sponsorship perks?
:PROPERTIES:
:ID: 29d9a145-8f2e-4d22-b4d0-de8a2c72698d
:END:
Yes! By becoming a module maintainer, community moderator, or regular you get
the same perks as sponsors [[https://github.com/sponsors/hlissner][on the 25/mo tier]]. Here's what they do:
- *Module maintainers* look after one or more Doom modules. They become my
consultants for that module(s)' ecosystem, packages, and implementation, and
issues about them. Some Emacs Lisp expertise is helpful, but it's more
important that you are knowledgeable about your chosen module's ecosystem.
- *Moderators* look after our Github, Discord, and/or Discourse communities.
They keep our issue tracker, github projects, and repos organized, and they
keep the peace by warning/banning bad actors. They're held to a higher
standard, however, as they represent us.
- *Regulars* are pillars of our community; they're folks that frequent our
Discord and/or Discourse, are active, helpful, and friendly. This is the only
role you can't apply for, but we keep a eye out for folks to give it to!
If code, documentation, or bug reports are more your thing, visit [[id:eb67a668-20ac-43ec-880b-883b6949ca76][our
contributing manual]] for ideas.
** What is the difference between "first shake" and "first priority"?
Some of my Sponsor tier rewards offer "first shake" or "first priority" on open
issues/feature requests. To explain what these mean:
- Issues that get *first shake* get triaged and investigated before other
issues, and if it can be resolved in one sitting, I will.
- Issues that get *first priority* get entirely resolved before I move on to
anything else.
That said, the exception to these rules are issues that are extraordinarily
difficult, outside my expertise, or depend on other development efforts to
resolve.
Folks that depend on Doom for their work or businesses would benefit from
getting first priority, to ensure their issues are resolved ASAP. Or check out
[[https://github.com/sponsors/hlissner?frequency=one-time&sponsor=hlissner][my one-time tiers]] to hire me for dedicated support.
** I have a question, comment, or complaint about sponsorships...
Feel free to DM me (Henrik#0666) on [[https://doomemacs.org/discord][Discord]], ask on [[https://discourse.doomemacs.org][Discourse]], or email me at
contact@henrik.io.
* Technical
:PROPERTIES:
:ID: 8b6f6bd0-da2f-4744-95b2-843a6fd283b6
:END:
For questions regarding Doom's code design, defaults, or conventions.
** Why does Doom sharp-quote function symbols?
~#'symbol~ is short for ~(function symbol)~, the same way ~'symbol~ is short for
~(quote symbol)~.
I use it to indicate to the byte-compiler (or human readers) that a symbol will
be treated as a function rather than literal data.
However, at runtime, the sharp-quote serves no functional purpose like it does
in other lisps. ~(funcall 'some-function)~ will function identically to
~(funcall #'some-function)~. The sole difference is at compile-time: the
byte-compiler performs additional checks on function symbols and will warn if a
function isn't known to be defined where it's used.
There's more about quoting [[https://emacsdocs.org/docs/elisp/Quoting][in the Emacs manual]].
** 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
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!*
#+end_quote
** Why does Doom not use dash, f, s, or similar libraries?
=subr-x=, =seq=, =map=, =pcase=, and =cl-lib= are all built into Emacs and,
since Emacs 27.1 (the minimum version Doom supports), have made Dash and co
(mostly) redundant. One of Doom's goals is to prefer native functionality where
possible or trivial. That said, many third-party packages depend on them, so
chances are they are already installed on your system.
** Why does Doom discourage the use of ~M-x customize~?
=Customize= exists so that you don't need to be a Lisp programmer to configure
Emacs. It's helpful to beginners (with both configuration and discovery), but I
think it should only serve as a stopgap until you are comfortable writing and
navigating Emacs Lisp, then abandoned. Here's why:
- The way it applies its settings (through theme variables) defies conventional
load order, which is troublesome to support in middleware like Doom (or user
configuration) when lazy loading is involved.
- I don't see many instances in the wild where this load-order quirk is
accommodated. I think this is because those writing/offering that code are
Lisp programmers, who don't use =Customize= and may not be exposed to its
quirks, but for beginners this is frustration waiting to happen.
- =Customize= works flawlessly if it is the sole source of truth for your Emacs
configuration, but /all/ Emacs configs eventually take on Lisp. At this point
you acquire a second source of truth that =Customize= is happy to (quietly)
override.
- Without its /unparalleled/ extensibility, I believe Emacs isn't particularly
interesting or effective software. And =Customize= exposes only a superficial
portion of that extensibility. Learning Lisp is inevitable if you want to deal
with issues or tweak where =Customize= can't, and Doom wants to help you face
Lisp, rather than work around it. Otherwise, you may be happier using modern,
better polished, and less-DIY competitors.
- =Customize='s commands are safe for read-only use (e.g. to browse/search
settings), but I'm not convinced it can be compete with Emacs'
self-documentating facilities. For example, its library of ~describe-*~
commands already set the bar pretty high.
All that said, I take no steps to disable or cripple =Customize= in Doom
(besides a warning here and there, and hiding it in some menus where it is known
to cause issues). If used sparingly, you may not even run into these issues.
** Why no =expand-region= for evil users (by default)?
I believe [[doom-package:expand-region]] is redundant with and less precise than evil's text
objects and motions.
- There's a text object for every "step" of expansion that expand-region
provides (and more).
- To select the word at point = [[kbd:][v i w]]
- symbol at point = [[kbd:][v i o]]
- line at point = [[kbd:][V]]
- the block at point (by indentation) = [[kbd:][v i i]]
- the block at point (by braces) = [[kbd:][v i b]]
- sentence at point = [[kbd:][v i s]]
- paragraph = [[kbd:][v i p]]
- etc.
- Selection expansion can be emulated by using text objects consecutively: [[kbd:][v i w]]
to select a word, followed by [[kbd:][i o]] to expand to a symbol, then [[kbd:][i b]] expands to
the surrounding brackets/parentheses, etc. There is no reverse of this
however; you'd have to restart visual mode.
The [[doom-package:expand-region]] way dictates you start at some point and expand/contract until
you have what you want selected. The vim/evil way would rather you select
exactly what you want from the get go. In the rare event a text object fails
you, a combination of [[kbd:][o]] (swaps your cursor between the two ends of the region)
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
([[kbd:][a]]), angle brackets, and single/double quotes.
#+end_quote
This is certainly more to remember compared to a pair of expand and contract
commands, but text objects (and motions) are the bread and butter of vim's modal
editing paradigm. Vimmers will feel right at home. To everyone else: mastering
them will have a far-reaching effect on your effectiveness in vim environments.
I highly recommend putting in the time to learn them.
That said, if you aren't convinced, it is trivial to install [[doom-package:expand-region]] and
binds keys to it yourself:
#+begin_src emacs-lisp
;;; in $DOOMDIR/packages.el
(package! expand-region)
;;; in $DOOMDIR/config.el
(map! :nv "C-=" #'er/contract-region
:nv "C-+" #'er/expand-region)
#+end_src
** Why ~doom env~ instead of ~exec-path-from-shell~?
For some context: there are scenarios where Emacs launches in an isolated
environment where it cannot see your =$PATH= or other needed environment
variables. This affects macOS users (all =Emacs.app= bundles launch Emacs in an
isolated environment), Linux users who misconfigure their launchers to use the
wrong shell, or Windows users who may have no shell environment at all.
[[doom-package:exec-path-from-shell]] was written to mitigate this, by polling the shell at
startup for those environment variables. ~$ doom env~ was written as more
reliable (and slightly faster) substitute. Here's why it's better:
1. [[doom-package:exec-path-from-shell]] must spawn (at least) one process at startup to scrape
your shell environment. This can be slow depending on the user's shell
configuration and may fail on non-standard shells (like =fish=). A single
program (like =pyenv= or =nvm=) or config framework (like =oh-my-zsh=) could
all our startup optimizations in one fell swoop.
2. [[doom-package:exec-path-from-shell]] takes a whitelist approach and captures only =$PATH= and
=$MANPATH= by default. You must be proactive in order to capture all the
envvars relevant to your development environment and tools.
~$ doom env~ takes the blacklist approach and captures all of your shell
environment. This front loads the debugging process, which is nicer than
dealing with it later, while you're getting work done.
That said, if you still want [[var:exec-path-from-shell]], it is trivial to install
yourself:
#+begin_src emacs-lisp
;;; in $DOOMDIR/packages.el
(package! exec-path-from-shell)
;;; in $DOOMDIR/config.el
(require 'exec-path-from-shell)
(when (display-graphic-p)
(exec-path-from-shell-initialize))
#+end_src
** Why =ws-butler= over =whitespace-cleanup= or =delete-trailing-whitespace=?
I believe [[doom-package:ws-butler]] is less imposing on teammates/project maintainers; it only
cleans up whitespace on the lines you've touched.
You know the story: a PR with 99 whitespace adjustments around a one-line
contribution. Why? Because they added [[fn:delete-trailing-whitespace]] (or
[[fn:whitespace-cleanup]]) to [[var:before-save-hook]], which mutates entire buffers.
Automated processes that mutate entire files (or worse, whole projects) should
be deliberately invoked, and by someone privvy to the consequences, rather than
automated. =ws-butler= achieves that balance by only cleaning whitespace on
lines that you have modified since opening the file.
================================================
FILE: docs/getting_started.org
================================================
#+TITLE: Getting Started Guide
#+STARTUP: nofold
GNU Emacs is one grand ol' adventure, let alone Doom Emacs. Before you start
you'll need to set up Emacs, Doom, and its packages, then learn how to take care
of your new puppy/operating system. This guide will walk you through installing,
using, configuring and troubleshooting all of these things, to smooth you into
your Emacs journey.
This guide will gloss over many technicalities so you can get up and running as
soon as possible. A more technical user manual is in the works for aspiring
contributors who want a deeper understanding of how Doom Emacs works.
#+begin_quote
If you feel like we've missed something, [[https://discord.gg/qvGgnVx][join us on our Discord server]] and let
us know!
#+end_quote
* Table of Contents :TOC_4:
- [[#install][Install]]
- [[#emacs--dependencies][Emacs & dependencies]]
- [[#on-linux][On Linux]]
- [[#ubuntu][Ubuntu]]
- [[#fedora][Fedora]]
- [[#arch-linux][Arch Linux]]
- [[#nixos][NixOS]]
- [[#opensuse][openSUSE]]
- [[#gentoo-linux][Gentoo Linux]]
- [[#on-macos][On macOS]]
- [[#with-homebrew][With Homebrew]]
- [[#with-macports][With MacPorts]]
- [[#on-windows][On Windows]]
- [[#with-chocolatey--scoop][With chocolatey / scoop]]
- [[#with-a-precompiled-binary--git-bash][With a precompiled binary + Git Bash]]
- [[#with-wsl--ubuntu-1804-lts][With WSL + Ubuntu 18.04 LTS]]
- [[#doom-emacs][Doom Emacs]]
- [[#the-bindoom-utility][The ~bin/doom~ utility]]
- [[#install-doom-manually][Install Doom Manually]]
- [[#install-doom-alongside-other-configs-with-chemacs2][Install Doom alongside other configs (with Chemacs2)]]
- [[#externalsystem-dependencies][External/system dependencies]]
- [[#update--rollback][Update & Rollback]]
- [[#rollback][Rollback]]
- [[#updowngrading-emacs][Up/Downgrading Emacs]]
- [[#migrate][Migrate]]
- [[#from-vanilla-emacs][From vanilla Emacs]]
- [[#from-spacemacs][From Spacemacs]]
- [[#configure][Configure]]
- [[#modules][Modules]]
- [[#package-management][Package management]]
- [[#installing-packages][Installing packages]]
- [[#installing-packages-from-external-sources][Installing packages from external sources]]
- [[#pinning-packages-to-specific-commits][Pinning packages to specific commits]]
- [[#disabling-packages][Disabling packages]]
- [[#changing-a-recipe-for-an-included-package][Changing a recipe for an included package]]
- [[#usingloading-local-packages][Using/loading local packages]]
- [[#configuring-doom][Configuring Doom]]
- [[#configuring-packages][Configuring packages]]
- [[#reloading-your-config][Reloading your config]]
- [[#binding-keys][Binding keys]]
- [[#writing-your-own-modules][Writing your own modules]]
- [[#file-structure][File structure]]
- [[#initel][=init.el=]]
- [[#configel][=config.el=]]
- [[#packagesel][=packages.el=]]
- [[#autoloadel-or-autoloadel][=autoload/*.el= OR =autoload.el=]]
- [[#doctorel][=doctor.el=]]
- [[#cliel][=cli.el=]]
- [[#testtest-el][=test/**/test-*.el=]]
- [[#additional-files][Additional files]]
- [[#load-order][Load order]]
- [[#flags][Flags]]
- [[#doom-cookies][Doom cookies]]
- [[#if][~;;;###if~]]
- [[#package][~;;;###package~]]
- [[#autodef][~;;;###autodef~]]
- [[#common-mistakes-when-configuring-doom-emacs][Common mistakes when configuring Doom Emacs]]
- [[#packages-are-eagerly-loaded][Packages are eagerly loaded]]
- [[#manual-package-management][Manual package management]]
- [[#using-org-babel-do-load-languages-to-load-your-babel-packages][Using ~org-babel-do-load-languages~ to load your babel packages]]
- [[#using-delete-trailing-whitespaces-or-whitespace-cleanup-to-manage-leftover-whitespace][Using ~delete-trailing-whitespaces~ or ~whitespace-cleanup~ to manage leftover whitespace]]
- [[#troubleshoot][Troubleshoot]]
- [[#looking-up-documentation-and-state-from-within-emacs][Looking up documentation and state from within Emacs]]
- [[#variables-functions-faces-etc][Variables, functions, faces, etc.]]
- [[#for-doom-modules-packages-autodefs-etc][For Doom Modules, packages, autodefs, etc.]]
- [[#how-to-extract-a-backtrace-from-an-error][How to extract a backtrace from an error]]
- [[#enabling-debug-on-error][Enabling ~debug-on-error~]]
- [[#a-backtrace-from-bindoom][A backtrace from ~bin/doom~]]
- [[#evaluating-elisp-on-the-fly][Evaluating Elisp on-the-fly]]
- [[#how-to-determine-the-origin-of-a-bug][How to determine the origin of a bug]]
- [[#testing-in-dooms-sandbox][Testing in Doom's sandbox]]
- [[#opening-the-sandbox][Opening the sandbox]]
- [[#launching-the-sandbox][Launching the sandbox]]
- [[#testing-packages-in-the-sandbox][Testing packages in the sandbox]]
- [[#bisecting-your-private-config][Bisecting your private config]]
- [[#bisecting-doom-emacs][Bisecting Doom Emacs]]
* Install
This is what you'll have installed by the end of this section:
- Git 2.23+
- Emacs 27.1+ *(27.2 is recommended, or [[https://www.emacswiki.org/emacs/GccEmacs][native-comp]])*
- [[https://github.com/BurntSushi/ripgrep][ripgrep]] 11.0+
- GNU Find
- (Optional) [[https://github.com/sharkdp/fd][fd]] 7.3.0+ (known as ~fd-find~ on Debian, Ubuntu & derivatives) --
improves performance for many file indexing commands
These packages ought to be available through the package managers of your
operating system; i.e. homebrew & macports on macOS, scoop/chocolatey on
Windows, or pacman/aptitude/etc on the various Linux distributions.
** Emacs & dependencies
*** On Linux
Installation instructions for Emacs 27.1+ are listed below for many popular
Linux distributions. In the unusual case that 27.1 or newer is unavailable on
your system, you'll have to [[https://www.gnu.org/software/emacs/manual/html_node/efaq/Installing-Emacs.html][build it from source]] instead.
**** Ubuntu
Emacs 27.x is not available through Ubuntu's package manager out-of-the-box, but
is available through a PPA:
#+BEGIN_SRC bash
add-apt-repository ppa:kelleyk/emacs
apt-get update
apt-get install emacs27
#+END_SRC
Or through snap:
#+BEGIN_SRC bash
snap install emacs --classic
#+END_SRC
In some cases, you may need to delete old version of emacs and it's dependencies first, before installing emacs27:
#+BEGIN_SRC bash
sudo apt remove emacs
sudo apt autoremove
#+END_SRC
***** Other dependencies
Then install Doom's other dependencies:
#+BEGIN_SRC bash
apt-get install ripgrep fd-find
# On 18.04 or older, ripgrep and fd-find won't be available in
# official repos. You'll need to install them another way, e.g.
sudo dpkg -i fd_8.2.1_amd64.deb # adapt version number and architecture
sudo dpkg -i fd_8.2.1_amd64.deb # adapt version number and architecture
#+END_SRC
**** Fedora
#+BEGIN_SRC bash
# required dependencies
dnf install emacs git ripgrep
# optional dependencies
dnf install fd-find # is 'fd' in Fedora <28
#+END_SRC
**** Arch Linux
#+BEGIN_SRC bash
# required dependencies
pacman -S git emacs ripgrep
# optional dependencies
pacman -S fd
#+END_SRC
The above installs Emacs 27 (at the time of writing).
**** NixOS
On NixOS Emacs 27.2 can be installed via ~nix-env -Ai nixos.emacs~, or
permanently with the following added to ~etc/nixos/configuration.nix~:
#+BEGIN_SRC nix
environment.systemPackages = with pkgs; [
# required dependencies
git
emacs # Emacs 27.2
ripgrep
# optional dependencies
coreutils # basic GNU utilities
fd
clang
];
#+END_SRC
Installing Emacs 28+ will require [[https://github.com/nix-community/emacs-overlay/issues][nix-community/emacs-overlay]]:
#+BEGIN_SRC nix
nixpkgs.overlays = [
(import (builtins.fetchTarball https://github.com/nix-community/emacs-overlay/archive/master.tar.gz))
];
environment.systemPackages = [
pkgs.emacsGcc # Installs Emacs 28 + native-comp
];
#+END_SRC
**** openSUSE
***** Emacs 27.1
Emacs can be installed from the [[https://software.opensuse.org/download.html?project=editors&package=emacs][package list]], or manually via zypper.
For example, to install on openSUSE Leap 15.1 (requires root):
#+BEGIN_SRC bash
zypper addrepo https://download.opensuse.org/repositories/editors/openSUSE_Leap_15.1/editors.repo
zypper refresh
zypper install emacs
#+END_SRC
If you already have an older version of Emacs installed, you will be prompted to
install the update candidate (Emacs 27.1).
***** ripgrep
Download ripgrep 11.0.2 from [[https://software.opensuse.org/download/package?package=ripgrep&project=openSUSE%3AFactory][the package list]] or installed manually (requires
root).
#+BEGIN_SRC bash
zypper addrepo https://download.opensuse.org/repositories/openSUSE:Factory/standard/openSUSE:Factory.repo
zypper refresh
zypper install ripgrep
#+END_SRC
Only ripgrep 0.8.1 is officially available on Leap 15.1 and 15.2, so you will
need to install Rust to build ripgrep from source. Rust can be downloaded [[https://software.opensuse.org/package/rust][from
the package list]] or installed manually via zypper (requires root), e.g.
#+BEGIN_SRC bash
zypper addrepo https://download.opensuse.org/repositories/openSUSE:Leap:15.1:Update/standard/openSUSE:Leap:15.1:Update.repo
zypper refresh
zypper install rust
#+END_SRC
See the [[https://github.com/BurntSushi/ripgrep#building][ripgrep documentation]] for instructions on building from source.
**** Gentoo Linux
Everything you need is in Gentoo's official =::gentoo= repository.
***** Emacs
To use Emacs graphically, enable the =gui= USE flag. And enable the =xft= USE flag to render fonts correctly (see
[[https://github.com/hlissner/doom-emacs/issues/4876][issue #4876]])
#+begin_src sh
echo "app-editors/emacs gui xft" >> /etc/portage/package.use/emacs
#+end_src
To install the latest unmasked version compatible with Doom:
#+begin_src sh
emerge '>=app-editors/emacs-27.0'
#+end_src
Or, for GCCEmacs/Native Compilation, use the live ebuild for version 28.0 with the =jit= USE flag:
Unmask the desired ebuild by adding the following to =package.accept_keywords=:
#+begin_src
=app-editors/emacs-28.0.9999 **
#+end_src
Add the =jit= USE flag to =package.use=:
#+begin_src
=app-editors/emacs-28.0.9999 jit
#+end_src
And emerge:
#+begin_src sh
emerge =app-editors/emacs-28.0.9999
#+end_src
***** Other Dependencies
#+begin_src sh
# required
emerge '>=dev-vcs/git-2.23' '>=sys-apps/ripgrep-11.0' sys-apps/findutils
# optional
emerge '>=sys-apps/fd-7.3.0'
#+end_src
*** On macOS
MacOS users have many options for installing Emacs, but not all of them are well
suited to Doom. Before we get to that you'll need either the Homebrew or
MacPorts package manager installed (you only need one):
+ [[http://brew.sh/][How to install Homebrew]]
+ [[https://www.macports.org/install.php][How to install MacPorts]]
**** With Homebrew
First, Doom's dependencies:
#+BEGIN_SRC bash
# required dependencies
brew install git ripgrep
# optional dependencies
brew install coreutils fd
# Installs clang
xcode-select --install
#+END_SRC
For Emacs itself, these three formulas are the best options, ordered from most
to least recommended for Doom (based on compatibility).
- [[https://bitbucket.org/mituharu/emacs-mac/overview][emacs-mac]]. It offers good integration
with macOS, native emojis and better childframe support.
#+BEGIN_SRC bash
brew tap railwaycat/emacsmacport
brew install emacs-mac --with-modules
ln -s /usr/local/opt/emacs-mac/Emacs.app /Applications/Emacs.app
#+END_SRC
- [[https://github.com/d12frosted/homebrew-emacs-plus][emacs-plus]]. Some users have
experienced [flashing artifacts when scrolling](https://github.com/d12frosted/homebrew-emacs-plus/issues/314):
#+BEGIN_SRC bash
brew tap d12frosted/emacs-plus
brew install emacs-plus
ln -s /usr/local/opt/emacs-plus/Emacs.app /Applications/Emacs.app
#+END_SRC
- [[https://formulae.brew.sh/formula/emacs][emacs]] is another acceptable option, **but does not provide a Emacs.app**:
#+BEGIN_SRC bash
brew install emacs
#+END_SRC
***** Where *not* to install Emacs from
These builds/forks have known compatibility issues with Doom and are *very
likely* to cause issues later on. They are not recommended:
+ emacsformacosx.com
+ ~brew cask install emacs~ (installs from emacsformacosx.com)
+ AquaMacs
+ XEmacs
**** With MacPorts
There are four ports (at time of writing) available through MacPorts, and they
are all acceptable options:
+ [[https://ports.macports.org/port/emacs/summary][emacs]] (27.2) and [[https://ports.macports.org/port/emacs-devel/summary][emacs-devel]] (28) -- Installs terminal-only Emacs
+ [[https://ports.macports.org/port/emacs-app/summary][emacs-app]] (27.2), [[https://ports.macports.org/port/emacs-app-devel/summary][emacs-app-devel]] (28) -- Installs GUI Emacs
+ [[https://ports.macports.org/port/emacs-mac-app/summary][emacs-mac-app]] (27.2) -- the [[https://bitbucket.org/mituharu/emacs-mac][Mitsuharu Yamamoto mac port]]
Some of these ports do not add an =emacs= binary to your ~PATH~, which is
necessary for Doom's installation process. You'll have to do so yourself by
adding this to your shell config:
#+BEGIN_SRC sh
# Add this to ~/.zshrc or ~/.bash_profile
export PATH="/Applications/MacPorts/Emacs.app/Contents/MacOS:$PATH"
#+END_SRC
Or by replacing ~/usr/local/bin/emacs~ with a shim script containing:
#+BEGIN_SRC
#!/bin/sh
/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs "$@"
#+END_SRC
*** On Windows
#+begin_quote
*WARNING:* Emacs on Windows is much slower than its Linux or macOS counterparts.
There are some suggestions on how to speed it up later in this section.
#+end_quote
There are three methods for installing Emacs 27.x on Windows, each with their
pros and cons:
+ With chocolatey/scoop
+ With a precompiled binary + Git Bash
+ With WSL2 + Ubuntu
If you don't know which to choose, I highly recommend WSL; it produces the
fastest and most stable environment of the three, but has the most complex
installation process.
Before moving on to installing Emacs et co, a few steps to prepare Windows for
Emacs are necessary:
1. Create a ~HOME~ [[https://mywindowshub.com/how-to-edit-system-environment-variables-for-a-user-in-windows-10/][system environment variable]].
Set it to =C:\Users\USERNAME\=, otherwise Emacs will treat
=C:\Users\USERNAME\AppData\Roaming= as your ~HOME~, which will cause issues
later.
2. Add =C:\Users\USERNAME\.emacs.d\bin= to your ~PATH~.
This way, you don't have to type all of =C:\Users\USERNAME\.emacs.d\bin\doom=
every time you need to run this script (and you'll need to, often).
#+begin_quote
A pre-existing PATH variable should already exist among your system
variables. It contains a string of file paths separated by colons;
~pathA:pathB:pathC~. Prepend the path to bin/doom to that string, like so:
~C:\Users\username\.emacs.d\bin:pathA:pathB:pathC~
#+end_quote
3. Restart your system so your new values for ~HOME~ and ~PATH~ take effect.
Now we're ready to move on!
**** With [[https://chocolatey.org/][chocolatey]] / scoop
[[https://chocolatey.org/][Chocolatey]] is a package manager for Windows, and is the simplest way to install
Emacs and Doom's dependencies:
#+BEGIN_SRC sh
choco install git emacs ripgrep
# Optional dependencies
choco install fd llvm
#+END_SRC
Scoop will work too, but because Emacs is a GUI application you'll need to
enable the 'extras' Scoop bucket:
#+BEGIN_SRC sh
scoop bucket add extras
scoop install git emacs ripgrep
# Optional dependencies
scoop install fd llvm
#+END_SRC
**** With a precompiled binary + Git Bash
(Credit goes to @earvingad and [[https://earvingad.github.io/posts/doom_emacs_windows/][his fantastic tutorial]] for informing this guide)
1. Download and install Git from https://git-scm.com/download/win
2. Download and extract Emacs, ripgrep and fd where you want them, but in
different folders:
- Emacs 27.2 from http://ftp.wayne.edu/gnu/emacs/windows/emacs-27/
- Ripgrep from https://github.com/BurntSushi/ripgrep/releases
- (optional) fd from https://github.com/sharkdp/fd/releases
3. Add the three folders from step 2 to your ~PATH~
- Go to Control panel -> User Accounts -> Change my environment variables.
- Click "New", type HOME and set your C:\Users\USERNAME and OK.
- Select "Path", click "edit", prepend =C:\path\to\the\emacs\bin:= to it and
click OK.
- Select "Path", click "edit", prepend =C:\path\to\the\ripgrep:= to it and
click OK.
- Select "Path", click "edit", prepend =C:\path\to\the\fd:= to it and click
OK.
- Click Ok.
And done! Keep git-bash.exe open, you'll need it for the rest of this guide.
#+begin_quote
*IMPORTANT:* you'll need to open git-bash.exe whenever you want to run a
bin/doom command.
#+end_quote
**** With WSL + Ubuntu 18.04 LTS
(Credit goes to @lunias and [[https://ethanaa.com/blog/switching-to-doom-emacs/#installing-on-windows-10
][his fantastic tutorial]] for informing this guide)
1. Install Powershell as admin (Windows key + x) with:
#+BEGIN_SRC
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
#+END_SRC
2. Restart your Computer
3. Download and install Ubuntu 18.04 L>TS from the Microsoft Store
4. Launch Ubuntu 18.04 LTS
5. Update and upgrade Ubuntu
#+BEGIN_SRC
sudo apt update && sudo apt upgrade
#+END_SRC
6. Then install Emacs:
#+BEGIN_SRC sh
sudo add-apt-repository ppa:kelleyk/emacs
sudo apt update
sudo apt install emacs27
#+END_SRC
7. Then Doom's dependencies:
#+BEGIN_SRC sh
# required dependencies
sudo apt-get install git ripgrep
# optional dependencies
sudo apt-get install fd-find
#+END_SRC
And done! Keep Ubuntu open, you'll need it for the rest of this guide.
** Doom Emacs
With Emacs and Doom's dependencies installed, next is to install Doom Emacs
itself:
#+BEGIN_SRC bash
git clone https://github.com/hlissner/doom-emacs ~/.emacs.d
~/.emacs.d/bin/doom install
#+END_SRC
=doom install= will set up your =DOOMDIR= at =~/.doom.d= (if it doesn't already
exist) and will work you through the first-time setup of Doom Emacs. Carefully
follow any instructions it puts out.
If this is your first time, you should run ~doom doctor~. This will diagnose
common issues with your system or config.
#+BEGIN_QUOTE
If you'd like a more technical break down of ~doom install~, it's been
translated into shell commands below, in the "Install Doom Manually" section.
#+END_QUOTE
*** The ~bin/doom~ utility
This utility is your new best friend. It won't spot you a beer, but it'll
shoulder much of the work associated with managing and maintaining your Doom
Emacs configuration, and then some. Not least of which is installation of and
updating Doom and your installed packages.
It exposes a variety of commands. ~bin/doom help~ will list them all, but here
is a summary of the most important ones:
+ ~doom sync~: This synchronizes your config with Doom Emacs. It ensures that
needed packages are installed, orphaned packages are removed and necessary
metadata correctly generated. Run this whenever you modify your ~doom!~ block
or =packages.el= file. You'll need ~doom sync -u~ if you override the recipe
of package installed by another module.
+ ~doom upgrade~: Updates Doom Emacs (if available) and all its packages.
+ ~doom env~: (Re)generates an "envvar file", which is a snapshot of your
shell environment that Doom loads at startup. If your app launcher or OS
launches Emacs in the wrong environment you will need this. **This is required
for GUI Emacs users on MacOS.**
+ ~doom doctor~: If Doom misbehaves, the doc will diagnose common issues with
your installation, system and environment.
+ ~doom purge~: Over time, the repositories for Doom's plugins will accumulate.
Run this command from time to time to delete old, orphaned packages, and with
the ~-g~ switch to compact existing package repos.
Use ~doom help~ to see an overview of the available commands that =doom=
provides, and ~doom help COMMAND~ to display documentation for a particular
~COMMAND~.
#+begin_quote
I recommend you add =~/.emacs.d/bin= to your ~PATH~ so you can call =doom=
directly and from anywhere. Accomplish this by adding this to your .bashrc or
.zshrc file: ~export PATH="$HOME/.emacs.d/bin:$PATH"~
#+end_quote
*** Install Doom Manually
If you'd rather install Doom yourself, instead of rely on the magic of =doom
install=, here is its equivalent in bash shell commands (assuming
=hlissner/doom-emacs= has been cloned to =~/.emacs.d=):
#+BEGIN_SRC bash
# So we don't have to write ~/.emacs.d/bin/doom every time
PATH="$HOME/.emacs.d/bin:$PATH"
# Create a directory for our private config
mkdir ~/.doom.d # or ~/.config/doom
# The init.example.el file contains an example doom! call, which tells Doom what
# modules to load and in what order.
cp ~/.emacs.d/init.example.el ~/.doom.d/init.el
cp ~/.emacs.d/core/templates/config.example.el ~/.doom.d/config.el
cp ~/.emacs.d/core/templates/packages.example.el ~/.doom.d/packages.el
# You might want to edit ~/.doom.d/init.el here and make sure you only have the
# modules you want enabled.
# Then synchronize Doom with your config:
doom sync
# If you know Emacs won't be launched from your shell environment (e.g. you're
# on macOS or use an app launcher that doesn't launch programs with the correct
# shell) then create an envvar file to ensure Doom correctly inherits your shell
# environment.
#
# If you don't know whether you need this or not, there's no harm in doing it
# anyway. `doom install` will have prompted you to generate one. If you
# responded no, you can generate it later with the following command:
doom env
# Lastly, install the icon fonts Doom uses:
emacs --batch -f nerd-icons-install-fonts
#+END_SRC
To understand the purpose of the =~/.doom.d= directory and =~/.doom.d/init.el=
file, see the [[#configure][Configure]] section further below.
*** Install Doom alongside other configs (with Chemacs2)
[[https://github.com/plexus/chemacs2][Chemacs2]] is a bootloader for Emacs. It allows you to switch between multiple
Emacs configurations. Here is a quick guide for setting it up with Doom Emacs as
the default config:
1. First, install Doom somewhere:
#+BEGIN_SRC sh :eval no
git clone https://github.com/hlissner/doom-emacs ~/doom-emacs
~/doom-emacs/bin/doom install
#+END_SRC
2. Move aside any existing config and install Chemacs2 as your new =~/.emacs.d=:
#+BEGIN_SRC bash :eval no
[ -f ~/.emacs ] && mv ~/.emacs ~/.emacs.bak
[ -d ~/.emacs.d ] && mv ~/.emacs.d ~/.emacs.legacy
git clone https://github.com/plexus/chemacs2.git ~/.emacs.d
#+END_SRC
3. Create =~/.emacs-profiles.el= with a list of your Emacs profiles. This file
is structured like a =.dir-locals.el= file. Here is an example with Doom (as
the default), Spacemacs, and Prelude:
#+BEGIN_SRC emacs-lisp :eval no
(("default" . ((user-emacs-directory . "~/doom-emacs")))
("legacy" . ((user-emacs-directory . "~/.emacs.legacy")))
("spacemacs" . ((user-emacs-directory . "~/spacemacs"))))
#+END_SRC
To start Emacs with a specific config, use the =--with-profile= option:
#+BEGIN_SRC bash
emacs --with-profile spacemacs
#+END_SRC
If no profile is specified, the =default= profile is used.
** External/system dependencies
Doom is comprised of approximately 160 modules which provide its features,
language support and integration with external tools. Many of these have
external dependencies that you must install yourself. You'll find what a module
needs and how to install them in that module's README.org file or by running
~bin/doom doctor~.
The [[file:modules.org][Module Index]] lists all Doom's available modules, with links to their
documentation. Documentation is a work-in-progrees; some modules may not have
README.org files yet!
#+begin_quote
Use ~M-x doom/help-modules~ (bound to =SPC h d m= or =C-h d m=) to jump to a
module's documentation from within Doom, otherwise, place your cursor on a
module in your ~doom!~ block (in =~/.doom.d/init.el=) and press =K= to jump to
its documentation (or =gd= to jump to its source code). =C-c g k= and =C-c g d=
for non-evil users, respectively.
#+end_quote
* Update & Rollback
Doom is an active project and many of its 300+ packages are in active
development as well. It is wise to occasionally update:
#+BEGIN_SRC bash
doom upgrade # or 'doom up'
#+END_SRC
If you want to update Doom manually, ~doom upgrade~ is equivalent to:
#+BEGIN_SRC bash
cd ~/.emacs.d
git pull # updates Doom
doom clean # Ensure your config isn't byte-compiled
doom sync # synchronizes your config with Doom Emacs
doom update # updates installed packages
#+END_SRC
To upgrade only your packages (and not Doom itself):
#+BEGIN_SRC bash
doom upgrade --packages
#+END_SRC
#+begin_quote
To minimize issues while upgrading, avoid modifying Doom's source files in
=~/.emacs.d=. All your customization should be kept in your =DOOMDIR= (e.g.
=~/.doom.d=). Read the [[#Configure][Configure]] section for more on configuring Doom.
#+end_quote
** TODO Rollback
The =bin/doom= script doesn't currently offer rollback support for Doom or its
packages (yet).
** Up/Downgrading Emacs
*You may encounter errors after up/downgrading Emacs.* Run ~doom sync~ on the
command line after changing the installed version of Emacs. If you've changed
the major version (e.g. 27 -> 28 or vice versa) run ~doom build~ too.
+ ~doom sync~ will re-index any built-in/site loaddef files. This is especially
necessary if paths to built-in libraries have changed.
+ ~doom build~ will recompile all your installed packages, which is necessary
because Emacs bytecode not generally forward compatible across major releases
(e.g. 27 -> 28). Alternatively, reinstall all your packages by deleting
=~/.emacs.d/.local=, then run ~doom sync~.
* TODO Migrate
If you're here from another Emacs distribution (or your own), here are a few
things to be aware of while you convert your old config to Doom:
+ Doom does not use =package.el= to manage its packages, but ~use-package~ does!
You will see errors if you have ~:ensure ...~ properties in your ~use-package~
blocks. Remove these and, instead, add ~package!~ declarations to
=~/.doom.d/packages.el= to install your packages.
See [[#package-management]["Package Management"]], further in this guide.
(This section is incomplete)
** TODO From vanilla Emacs
#+begin_quote
Have you migrated from your own config? Help me flesh out this section by
letting me know what kind of hurdles you faced in doing so. You'll find me [[https://discord.gg/qvGgnVx][on
our Discord server]].
#+end_quote
** TODO From Spacemacs
#+begin_quote
Have you migrated from Spacemacs? Help me flesh out this section by letting me
know what kind of hurdles you faced in doing so. You'll find me [[https://discord.gg/qvGgnVx][on our Discord
server]].
#+end_quote
* Configure
You can configure Doom by tweaking the files found in your =DOOMDIR=. Doom
expects this directory to be found in one of:
1. =~/.config/doom= (respects ~$XDG_CONFIG_HOME~)
2. or =~/.doom.d=
This directory is referred to as your =DOOMDIR=. Only one of these directories
should exist (Doom will only recognize one).
#+begin_quote
Change the =DOOMDIR= environment variable to change where Doom looks for this
directory. Symlinks will work as well.
#+end_quote
When you ran ~doom install~, it deployed a simple Doom configuration to your
=DOOMDIR=, comprised of these three files:
+ init.el :: Where you'll find your ~doom!~ block, which controls what Doom
modules are enabled and in what order they will be loaded.
This file is evaluated early when Emacs is starting up; before any other
module has loaded. You generally shouldn't add code to this file unless you're
targeting Doom's CLI or something that needs to be configured very early in
the startup process.
+ config.el :: Here is where 99.99% of your private configuration should go.
Anything in here is evaluated /after/ all other modules have loaded, when
starting up Emacs.
+ packages.el :: Package management is done from this file; where you'll declare
what packages to install and where from.
#+begin_quote
Note: do not use ~M-x customize~ or the customize API in general. Doom is
designed to be configured programmatically from your config.el, which can
conflict with Customize's way of modifying variables.
If you're concerned about ~defcustom~ setters, Doom has a ~setq!~ macro that
will trigger them.
#+end_quote
** Modules
Doom consists of around 160 modules and growing. A Doom module is a bundle of
packages, configuration and commands, organized into a unit that can be toggled
easily by tweaking your ~doom!~ block (found in =$DOOMDIR/init.el=).
#+begin_quote
If =$DOOMDIR/init.el= doesn't exist, you haven't run ~doom install~ yet. See [[#install][the
"Install" section]] above.
#+end_quote
Your ~doom!~ block should look something like this:
#+BEGIN_SRC emacs-lisp
;; To comment something out, you insert at least one semicolon before it and the
;; Emacs Lisp interpreter will ignore everything until the end of the line.
(doom! :lang
python ; this module is not commented, therefore enabled
;;javascript ; this module is commented out, therefore disabled
;;lua ; this module is disabled
ruby ; this module is enabled
php) ; this module is enabled
#+END_SRC
It controls what modules are enabled and in what order they are loaded. Some
modules have *optional features* that can be enabled by passing them flags,
denoted by a plus prefix:
#+BEGIN_SRC emacs-lisp
(doom! :completion
(company +childframe)
:lang
(csharp +unity)
(org +brain +dragndrop +gnuplot +hugo +jupyter)
(sh +fish))
#+END_SRC
Different modules support different flags. You'll find a comprehensive list of
available modules and their supported flags in [[file:modules.org][Module Index]]. Flags that a
module does not recognize will be silently ignored.
#+begin_quote
*IMPORTANT:* any changes to your ~doom!~ block won't take effect until you run
~doom sync~ on the command line.
#+end_quote
#+begin_quote
~doom doctor~ will detect issues with your ~doom!~ block, such as duplicate or
misspelled modules and flags.
#+end_quote
** Package management
**Doom Emacs does not use package.el** (the package manager built into Emacs).
Instead, it uses its own declarative package manager built on top of
[[https://github.com/raxod502/straight.el][straight.el]].
Packages are declared in ~packages.el~ files. You'll find one in your =DOOMDIR=
and in many of Doom's modules. Read on to learn how to use this system to
install your own packages.
#+begin_quote
*WARNING:* Do not install packages directly (with ~M-x package-install~ or ~M-x
straight-use-package~). Without an accompanying ~package!~ declaration somewhere
these packages will be forgotten when you restart Emacs and uninstalled the next
time you run ~doom sync~ or ~doom purge~.
#+end_quote
#+begin_quote
*WARNING:* If you're here from another Emacs distro (or vanilla Emacs), be wary
of the ~:ensure~ property in ~use-package~ blocks, because it will attempt (and
fail) to install packages through package.el. Tutorials will recommend you
install packages this way too!
#+end_quote
*** Installing packages
To install a package, add a ~package!~ declaration for it to
=DOOMDIR/packages.el=:
#+BEGIN_SRC emacs-lisp
;; Install a package named "example" from ELPA, MELPA, or Emacsmirror
(package! example)
#+END_SRC
If a package could not be found in any known repo you will get an error like:
#+begin_quote
Could not find package X in recipe repositories: (org-elpa melpa gnu-elpa-mirror
emacsmirror-mirror)
#+end_quote
The most likely cause for this is either:
- You've misspelled the package's name.
- Or the package really doesn't exist on ELPA, MELPA, or EmacsMirror and you'll
need to [[*Installing packages from external sources][specify a recipe for it]].
~package!~ will return non-nil if the package is cleared for install and hasn't
been disabled elsewhere. Use this fact to chain package dependencies together.
e.g.
#+BEGIN_SRC elisp
(when (package! example)
(package! plugin-that-example-depends-on))
#+END_SRC
#+begin_quote
*IMPORTANT:* New packages won't be installed until you run ~doom sync~.
#+end_quote
*** Installing packages from external sources
To install a package straight from an external source (like github, gitlab,
etc), you'll need to specify a [[https://github.com/raxod502/straight.el#the-recipe-format][MELPA-style straight recipe]]:
Here are a few examples:
#+BEGIN_SRC elisp
;; Install it directly from a github repository. For this to work, the package
;; must have an appropriate PACKAGENAME.el file which must contain at least a
;; Package-Version or Version line in its header.
(package! example
:recipe (:host github :repo "username/my-example-fork"))
;; If the source files for a package are in a subdirectory in said repo, use
;; `:files' to target them.
(package! example :recipe
(:host github
:repo "username/my-example-fork"
:files ("*.el" "src/lisp/*.el")))
;; To grab a particular branch or tag:
(package! example :recipe
(:host gitlab
:repo "username/my-example-fork"
:branch "develop"))
;; If a package has a default recipe on MELPA or emacsmirror, you may omit
;; keywords and the recipe will inherit the rest of the recipe from their
;; original.
(package! example :recipe (:branch "develop"))
;; If the repo pulls in many unneeded submodules, you can disable recursive cloning
(package! example :recipe (:nonrecursive t))
;; A package can be installed straight from a git repo by setting :host to nil:
(package! example
:recipe (:host nil :repo "https://some/git/repo"))
#+END_SRC
The specification for the ~package!~ macro's ~:recipe~ is laid out [[https://github.com/raxod502/straight.el#the-recipe-format][in
Straight.el's README]].
#+begin_quote
*IMPORTANT:* Run ~bin/doom sync~ whenever you modify packages.el files to
ensure your changes take effect.
#+end_quote
*** Pinning packages to specific commits
All of Doom's packages are pinned by default. A pinned package is a package
locked to a specific commit, like so:
#+BEGIN_SRC elisp
(package! evil :pin "e00626d9fd")
#+END_SRC
To unpin a package, use the ~unpin!~ macro:
#+BEGIN_SRC elisp
(unpin! evil)
;; It can be used to unpin multiple packages at once
(unpin! evil helm org-mode)
;; Or to unpin all packages in modules
(unpin! (:lang python ruby rust) (:tools docker))
;; Or to unpin an entire category of modules
(unpin! :completion :lang :tools)
;; This will work too, if you prefer the syntax, but it provides no concise
;; syntax for unpinning multiple packages:
(package! helm :pin nil)
#+END_SRC
Though it is *highly* discouraged, you may unpin all packages and make Doom
Emacs rolling release:
#+BEGIN_SRC elisp
(unpin! t)
#+END_SRC
#+begin_quote
Unpinning all packages is discouraged because Doom's modules are designed
against the pinned versions of its packages. More volatile packages (like
lsp-mode, ein and org) change rapidly, and are likely to cause breakages if
unpinned.
Instead, it's a better to selectively unpin packages, or repin them to the exact
commit you want.
#+end_quote
*** Disabling packages
The ~package!~ macro possesses a ~:disable~ property:
#+BEGIN_SRC emacs-lisp
(package! irony :disable t)
(package! rtags :disable t)
#+END_SRC
Once a package is disabled, ~use-package!~ and ~after!~ blocks for it will be
ignored, and the package is removed the next time you run ~bin/doom sync~. Use
this to disable Doom's packages that you don't want or need.
There is also the ~disable-packages!~ macro for conveniently disabling multiple
packages:
#+BEGIN_SRC elisp
(disable-packages! irony rtags)
#+END_SRC
#+begin_quote
*IMPORTANT:* Run ~bin/doom sync~ whenever you modify packages.el files to
ensure your changes take effect.
#+end_quote
*** Changing a recipe for an included package
If a Doom module installs package X from one place, but you'd like to install it
from another (say, a superior fork), add a ~package!~ declaration for it in your
=DOOMDIR/packages.el=. Your private declarations always have precedence over
modules (even your own).
#+BEGIN_SRC elisp
;; in modules/editor/evil/packages.el
(package! evil) ; installs from MELPA
;; in DOOMDIR/packages.el
(package! evil :recipe (:host github :repo "username/my-evil-fork"))
#+END_SRC
To install a package only if a built-in package doesn't exist, use ~:built-in
'prefer~:
#+BEGIN_SRC elisp
(package! so-long :built-in 'prefer)
#+END_SRC
#+begin_quote
*IMPORTANT:* Remember to run ~doom sync -u~ after changing recipes for existing
packages. At the time of writing, ~doom sync~ alone will not pick up on recipe
changes.
#+end_quote
*** Using/loading local packages
Say you are developing an Emacs package locally and want to "install" it for
live testing. To do this specify a ~:local-repo~ in that package's recipe:
#+BEGIN_SRC elisp
(package! my-package
:recipe (:local-repo "/path/to/my/package"))
;; Relative paths are expanded to ~/.emacs.d/.local/straight/repos/{local-repo}
;; or ~/.doom.d/{local-repo} -- the first that is found.
(package! my-package
:recipe (:local-repo "my/package")) ; looks for ~/.doom.d/my/package/my-package.el
(package! my-package
:recipe (:local-repo "/path/to/my/package"
;; By default, the package manager grabs all *.el files at the root
;; of the project and nothing else. To include other files, or
;; accommodate unconventional project structures, specify what :files
;; you want:
:files ("*.el" "src/lisp/*.el")
;; With this you can avoid having to run 'doom sync' every time you
;; change the package.
:build (:not compile)))
#+END_SRC
Alternatively, add the package's location to Emacs' ~load-path~. Do this if you
don't need/care for autoload cookies or byte-compilation:
#+BEGIN_SRC elisp
;; Doom has modified `use-package's `:load-path' to expand relative paths from
;; your DOOMDIR. e.g. ~/.doom.d/lisp/package
(use-package my-package
:load-path "lisp/package")
;; or
(add-load-path! "lisp/package")
#+END_SRC
#+begin_quote
*IMPORTANT:* Remember to run ~doom sync~ to rebuild your package after you've
changed it, and to re-index any autoloads in it.
#+end_quote
** Configuring Doom
*** Configuring packages
If your configuration needs are simple, the ~use-package!~, ~after!~,
~add-hook!~ and ~setq-hook!~ macros are your bread and butter.
#+BEGIN_SRC emacs-lisp
;;; ~/.doom.d/config.el (example)
(setq doom-font (font-spec :family "Fira Mono" :size 12))
;; Takes a feature symbol or a library name (string)
(after! evil
(setq evil-magic nil))
;; Takes a major-mode, a quoted hook function or a list of either
(add-hook! python-mode
(setq python-shell-interpreter "bpython"))
;; These are equivalent
(setq-hook! 'python-mode-hook python-indent-offset 2)
(setq-hook! python-mode python-indent-offset 2)
(use-package! hl-todo
;; if you omit :defer, :hook, :commands, or :after, then the package is loaded
;; immediately. By using :hook here, the `hl-todo` package won't be loaded
;; until prog-mode-hook is triggered (by activating a major mode derived from
;; it, e.g. python-mode)
:hook (prog-mode . hl-todo-mode)
:init
;; code here will run immediately
:config
;; code here will run after the package is loaded
(setq hl-todo-highlight-punctuation ":"))
#+END_SRC
For more flexibility, the ~use-package-hook!~ is another option, but should be
considered a last resort (because there is usually a better way). It allows you
to disable, append/prepend to and/or overwrite Doom's ~use-package!~ blocks.
These are powered by ~use-package~'s inject-hooks under the hood.
~use-package-hook!~ *must be used before that package's ~use-package!~ block*.
Therefore it must be used from your private init.el file.
#+BEGIN_SRC emacs-lisp
;;; ~/.doom.d/init.el (example)
;; If a :pre-init / :pre-config hook returns nil, it overwrites that package's
;; original :init / :config block. Exploit this to overwrite Doom's config.
(use-package-hook! doom-themes
:pre-config
(setq doom-neotree-file-icons t)
nil)
;; ...otherwise, make sure they always return non-nil!
(use-package-hook! evil
:pre-init
(setq evil-magic nil)
t)
;; `use-package-hook' also has :post-init and :post-config hooks
#+END_SRC
*** Reloading your config
You may find it helpful to have your changes take effect immediately. For things
that don't require a complete restart of Doom Emacs (like changing your enabled
modules or installed packages), you can evaluate Emacs Lisp code on-the-fly.
+ Evil users can use the =gr= operator to evaluate a segment of code. The return
value is displayed in the minibuffer or in a popup (if the result is large
enough to warrant one).
=gr= works for most languages, but using it on Elisp is a special case; it's
executed within your current session of Emacs. You can use this to modify
Emacs' state on the fly.
+ Non-evil users can use =C-x C-e= to run ~eval-last-sexp~, as well as ~M-x
+eval/buffer-or-region~ (on =SPC c e=).
+ Another option is to open a scratch buffer with =SPC x=, change its major mode
(~M-x emacs-lisp-mode~), and use the above keys to evaluate your code.
+ An ielm REPL is available by pressing =SPC o r=
(~+eval/open-repl-other-window~).
+ There's also =M-:= or =SPC ;=, which invokes ~eval-expression~, which you can
use to run elisp code inline.
While all this is helpful for reconfiguring your running Emacs session, it can
also be helpful for debugging.
*** TODO Binding keys
+ define-key
+ global-set-key
+ map!
+ undefine-key!
+ define-key!
** Writing your own modules
To create your own module you need only create a directory for it in
=~/.doom.d/modules/abc/xyz=, then add =:abc xyz= to your ~doom!~ block in
=~/.doom.d/init.el= to enable it.
#+begin_quote
In this example, =:abc= is called the category and =xyz= is the name of the
module. Doom refers to modules in one of two formats: =:abc xyz= and =abc/xyz=.
#+end_quote
If a private module possesses the same name as a built-in Doom module (say,
=:lang org=), it replaces the built-in module. Use this fact to rewrite modules
you don't agree with.
Of course, an empty module isn't terribly useful, but it goes to show that nothing in a module is required. The typical module will have:
+ A =packages.el= to declare all the packages it will install,
+ A =config.el= to configure and load those packages,
+ And, sometimes, an =autoload.el= to store that module's functions, to be
loaded when they are used.
These are a few exceptional examples of a well-rounded module:
+ [[file:../modules/completion/company/README.org][:completion company]]
The remainder of this guide will go over the technical details of a Doom module.
*** File structure
Doom recognizes a handful of special file names, none of which are required for
a module to function. They are:
#+begin_example
category/
module/
test/*.el
autoload/*.el
autoload.el
init.el
cli.el
config.el
packages.el
doctor.el
#+end_example
**** =init.el=
This file is loaded early, before anything else, but after Doom core is loaded.
It is loaded in both interactive and non-interactive sessions (it's the only
file, besides =cli.el= that is loaded when the =bin/doom= starts up).
Do:
+ Configure Emacs or perform setup/teardown operations that must be set early;
before other modules are (or this module is) loaded.
+ Reconfigure packages defined in Doom modules with ~use-package-hook!~ (as a
last resort, when ~after!~ and hooks aren't enough).
+ Configure behavior of =bin/doom= in a way that must also apply in
interactive sessions.
Don't:
+ Configure packages with ~use-package!~ or ~after!~ from here
+ Preform expensive or error-prone operations; these files are evaluated
whenever =bin/doom= is used; a fatal error in this file can make Doom
unbootable (but not irreversibly).
+ Define new =bin/doom= commands here. That's what =cli.el= is for.
**** =config.el=
The heart of every module. Code in this file should expect dependencies (in
=packages.el=) to be installed and available. Use it to load and configure its
packages.
Do:
+ Use ~after!~ or ~use-package!~ to configure packages.
#+BEGIN_SRC emacs-lisp
;; from modules/completion/company/config.el
(use-package! company ; `use-package!' is a thin wrapper around `use-package'
; it is required that you use this in Doom's modules,
; but not required to be used in your private config.
:commands (company-mode global-company-mode company-complete
company-complete-common company-manual-begin company-grab-line)
:config
(setq company-idle-delay nil
company-tooltip-limit 10
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil)
[...])
#+END_SRC
+ Lazy load packages with ~use-package~'s ~:defer~ property.
+ Use the ~featurep!~ macro to make some configuration conditional based on the
state of another module or the presence of a flag.
Don't:
+ Use ~package!~
+ Install packages with =package.el= or ~use-package~'s ~:ensure~ property. Doom
has its own package manager. That's what =packages.el= is for.
**** =packages.el=
This file is where package declarations belong. It's also a good place to look
if you want to see what packages a module manages (and where they are installed
from).
Do:
+ Declare packages with the ~package!~ macro
+ Disable single packages with ~package!~'s ~:disable~ property or multiple
packages with the ~disable-packages!~ macro.
+ Use the ~featurep!~ macro to make packages conditional based on the state of
another module or the presence of a flag.
Don't:
+ Configure packages here (definitely no ~use-package!~ or ~after!~ in here!).
This file is read in an isolated environment and will have no lasting effect.
The only exception is configuration targeting =straight.el=.
+ Perform expensive calculations. These files are read often and sometimes
multiple times.
+ Produce any side-effects, for the same reason.
#+begin_quote
The "[[#package-management][Package Management]]" section goes over the ~package!~ macro and how to deal
with packages.
#+end_quote
**** =autoload/*.el= OR =autoload.el=
These files are where you'll store functions that shouldn't be loaded until
they're needed and logic that should be autoloaded (evaluated very, very early
at startup).
This is all made possible thanks to these autoload cookie: ~;;;###autoload~.
Placing this on top of a lisp form will do one of two things:
1. Add a ~autoload~ call to Doom's autoload file (found in
=~/.emacs.d/.local/autoloads.el=, which is read very early in the startup
process).
2. Or copy that lisp form to Doom's autoload file verbatim (usually the case for
anything other than ~def*~ forms, like ~defun~ or ~defmacro~).
Doom's autoload file is generated by scanning these files when you execute ~doom
sync~.
For example:
#+BEGIN_SRC emacs-lisp
;; from modules/lang/org/autoload/org.el
;;;###autoload
(defun +org/toggle-checkbox ()
(interactive)
[...])
;; from modules/lang/org/autoload/evil.el
;;;###autoload (autoload '+org:attach "lang/org/autoload/evil" nil t)
(evil-define-command +org:attach (&optional uri)
(interactive "<a>")
[...])
#+END_SRC
**** =doctor.el=
When you execute ~doom doctor~, this file defines a series of tests for the
module. These should perform sanity checks on the environment, such as:
+ Check if the module's dependencies are satisfied,
+ Warn if any of the enabled flags are incompatible,
+ Check if the system has any issues that may interfere with the operation of
this module.
Use the ~warn!~, ~error!~ and ~explain!~ macros to communicate issues to the
user and, ideally, explain how to fix them.
For example, the ~:lang cc~ module's doctor checks to see if the irony server is
installed:
#+BEGIN_SRC emacs-lisp
;; from lang/cc/doctor.el
(require 'irony)
(unless (file-directory-p irony-server-install-prefix)
(warn! "Irony server isn't installed. Run M-x irony-install-server"))
#+END_SRC
**** TODO =cli.el=
This file is read when =bin/doom= starts up. Use it to define your own CLI
commands or reconfigure existing ones.
**** TODO =test/**/test-*.el=
Doom's unit tests go here. More information on them to come...
**** Additional files
Any files beyond the ones I have already named are not given special treatment.
They must be loaded manually to be loaded at all. In this way modules can be
organized in any way you wish. Still, there is one convention that has emerged
in Doom's community that you may choose to adopt: extra files in the root of the
module are prefixed with a plus, e.g. =+extra.el=. There is no syntactical or
functional significance to this convention.
These can be loaded with the ~load!~ macro, which will load an elisp file
relative to the file it's used from. e.g.
#+BEGIN_SRC emacs-lisp
;; Omitting the file extension allows Emacs to load the byte-compiled version,
;; if it is available:
(load! "+git") ; loads ./+git.el
#+END_SRC
This can be useful for splitting up your configuration into multiple files,
saving you the hassle of creating multiple modules.
*** Load order
A module's files have a precise load-order, which differs slightly depending on
what kind of session it is. Doom has three types of sessions:
+ Interactive session :: the typical session you open when you intend to use
Emacs (e.g. for text editing). This loads the most, because you will likely be
using a lot of it.
+ Batch session :: this is a non-interactive session, loaded when you execute
Emacs commands on the command line with no UI, e.g. ~emacs --batch --eval
'(message "Hello world")'~.
The expectation for these sessions is that it should quickly spin up, run the
command then quit, therefore very little is loaded in this session.
+ CLI session :: this is the same as a batch session /except/ it is what starts
up when you run any =bin/doom= command.
With that out of the way, here is the load order of Doom's most important files:
| File | Interactive | Batch | CLI |
|---------------------------------------------+-------------+-------+-----|
| ~/.emacs.d/early-init.el (Emacs 27+ only) | yes | no | no |
| ~/.emacs.d/init.el | yes | no | no |
| $DOOMDIR/init.el | yes | yes | yes |
| {~/.emacs.d,$DOOMDIR}/modules/*/*/init.el | yes | yes | yes |
| $DOOMDIR/cli.el | no | no | yes |
| {~/.emacs.d,$DOOMDIR}/modules/*/*/cli.el | no | no | yes |
| {~/.emacs.d,$DOOMDIR}/modules/*/*/config.el | yes | no | no |
| $DOOMDIR/config.el | yes | no | no |
*** Flags
A module's flag is an arbitrary symbol. By convention, these symbols are
prefixed with a ~+~ or a ~-~ to denote the addition or removal of a feature,
respectively. There is no functional significance to this notation.
A module may choose to interpret flags however it wishes, and can be tested for
using the ~featurep!~ macro:
#+BEGIN_SRC elisp
;; Has the current module been enabled with the +my-feature flag?
(when (featurep! +my-feature) ...)
;; It can be used to check the presence of flags in other modules:
(when (featurep! :lang python +lsp) ...)
#+END_SRC
Use this fact to make aspects of a module conditional. e.g. Prevent company
plugins from loading if the =:completion company= module isn't enabled.
*** Doom cookies
Autoload cookies were mentioned [[*=autoload/*.el= OR =autoload.el=][earlier]]. A couple more exist that are specific
to Doom Emacs. This section will go over what they do and how to use them.
**** ~;;;###if~
Any file in a module can have a ~;;;###if FORM~ cookie at or near the top of the
file (must be within the first 256 bytes of the file). =FORM= is evaluated to
determine whether or not to include this file for autoloads scanning (on ~doom
sync~) or byte-compilation (on ~doom compile~).
i.e. if =FORM= returns ~nil~, Doom will neither index its ~;;;###autoload~
cookies nor byte-compile the file.
Use this to prevent errors that would occur if certain conditions aren't met.
For example, say =file.el= is using a certain function that won't be available
if the containing module wasn't enabled with a particular flag. We could safe
guard against this with:
#+BEGIN_SRC emacs-lisp
;;;###if (featurep! +particular-flag)
#+END_SRC
This will prevent errors at compile time or if/when that file is loaded.
Another example, this time contingent on =so-long= *not* being present:
#+BEGIN_SRC emacs-lisp
;;;###if (not (locate-library "so-long"))
#+END_SRC
#+begin_quote
Keep in mind that =FORM= runs in a limited, non-interactive sub-session. I don't
recommend doing anything expensive or especially complicated in them.
#+end_quote
**** ~;;;###package~
This cookie exists solely to assist the ~doom/help-packages~ command. This
command shows you documentation about packages in the Emacs ecosystem, including
the ones that are installed. It also lists a) all the modules that install said
package and b) all the places it is configured.
It accomplishes A by scanning for at ~package!~ declarations for that package,
but it accomplishes B by scanning for:
+ ~after!~ calls
+ ~use-package!~ or ~use-package~ calls
+ and ~;;;###package X~ cookies, where X is the name of the package
Use it to let ~doom/help-packages~ know where to find config for packages where
no ~after!~ or ~use-package!~ call is involved.
**** ~;;;###autodef~
An autodef is a special kind of autoloaded function (or macro) which Doom
guarantees will /always/ be defined, whether or not its containing module is
enabled (but will no-op if it is disabled).
#+begin_quote
If the containing module is disabled the definition is replaced with a macro
that does not process its arguments, so it is a zero-cost abstraction.
#+end_quote
You can browse the available autodefs in your current session with ~M-x
doom/help-autodefs~ (=SPC h d u= or =C-h d u=).
An autodef cookie is used in exactly the same way as the autoload cookie:
#+BEGIN_SRC elisp
;;;###autodef
(defun set-something! (value)
...)
#+END_SRC
An example would be the ~set-company-backend!~ function that the =:completion
company= module exposes. It lets you register company completion backends with
certain major modes. For instance:
#+BEGIN_SRC emacs-lisp
(set-company-backend! 'python-mode '(company-anaconda))
#+END_SRC
And if =:completion company= is disabled, this call and its arguments are left
unprocessed and ignored.
** Common mistakes when configuring Doom Emacs
Having helped many users configure Doom, I've spotted a few recurring oversights
that I will list here, in the hopes that it will help you avoid the same
mistakes:
*** Packages are eagerly loaded
Using ~use-package!~ without a deferring keyword (one of: ~:defer :after
:commands :defer-incrementally :after-call~) will load the package immediately.
This causes other packages to be pulled in and loaded, which will compromise
many of Doom's startup optimizations.
This is usually by accident. Choosing which keyword to use depends on the
needs of the package, so there is no simple answer to this.
*** Manual package management
A lot of Emacs documentation and help will contain advice to install packages
with package.el's API (e.g. ~package-install~) or with use-package's ~:ensure~
keyword). You are free to do this, if it is your preference, but otherwise, Doom
has its own package management system.
Migrating ~use-package~ code to Doom is usually a case of removing the ~:ensure~
keyword and adding a ~(package! PACKAGENAME)~ to =~/.doom.d/packages.el= (and
running ~doom sync~ to sync your config).
*** Using ~org-babel-do-load-languages~ to load your babel packages
You don't need ~org-babel-do-load-languages~. Doom lazy loads babel packages
based on the language name in ~#+BEGIN_SRC~ blocks needed. As long as the babel
plugin is installed and the plugin is named after its language (e.g.
~#+BEGIN_SRC rust~ will load ~ob-rust~), you don't need to do anything else.
There may be some special cases, however. Doom tries to handle a couple of them
(e.g. with ob-jupyter, ob-ipython and ob-async). If you are experiencing errors
while trying to use a certain language in org src blocks, check out the [[file:../modules/lang/org/README.org][:lang
org module documentation]] for details on how to add support for it.
*** Using ~delete-trailing-whitespaces~ or ~whitespace-cleanup~ to manage leftover whitespace
#+BEGIN_SRC elisp
(add-hook 'after-save-hook #'delete-trailing-whitespace)
;; or
(add-hook 'after-save-hook #'whitespace-cleanup)
#+END_SRC
These two lines are a common sight in Emacs configs, but they are unnecessary
for Doom Emacs. We already use the more sophisticated =ws-butler= to manage
extraneous whitespace. However, you might have the impression that it isn't
working. That's because =ws-butler= works in two unusual ways, meant to be less
imposing than its alternatives:
1. It only cleans up trailing whitespace /on lines that you've touched/ (but
always strips newlines at EOF).
Why do this? Because I believe file-wide reformatting should be a deliberate
act (and not blindly automated). If it is necessary, chances are you're
working on somebody else's project -- or with other people, but here, large
scale whitespace changes could cause problems or simply be rude. We don't
endorse PRs that are 1% contribution and 99% whitespace!
However, if it's truly deliberate, ~M-x delete-trailing-whitespaces~ and ~M-x
whitespace-cleanup~ are available to be called =deliberately=, instead.
2. =ws-butler= replaces trailing whitespace and newlines with *virtual*
whitespace. This is whitespace that only exists in the Emacs buffer, but
isn't actually written to the file.
Why do this? Because you might have wanted to use that space for something in
your current editing session, and it would be inconvenient for the editor to
delete it before you got to it.
If you use it, it's there. If you don't, it isn't written to the file.
* Troubleshoot
When problems arise, you should be prepared to collect information in order to
solve them, or for the bug report you're about to write. Both Emacs and Doom
provide tools to make this easier. Here are a few things you can try, first:
+ Investigate the =*Messages*= log for warnings or error messages. This log can
be opened with =SPC h e=, =C-h e= or =M-x view-echo-area-messages=.
+ Look up errors/warnings [[file:faq.org::Common Issues][on the FAQ]] and [[https://github.com/hlissner/doom-emacs/issues][Doom's issue tracker]]. It is possible
that a solution for your issue already exists. The FAQ can be searched from
inside Doom with =SPC h d f= (or =C-h d f= for non-evil users).
+ Run ~bin/doom doctor~ on the command line to diagnose common issues with your
environment and config. It will suggest solutions for them as well.
+ ~bin/doom clean~ will ensure the problem isn't stale bytecode in your private
config or Doom core. If you haven't used ~bin/doom compile~, there's no need
to do this.
+ ~bin/doom sync~ will ensure the problem isn't missing packages or outdated
autoloads files
+ ~bin/doom build~ will ensure the problem isn't stale package bytecode or
broken symlinks.
+ ~bin/doom update~ will ensure that your packages are up-to-date, eliminating
issues that originate from upstream.
+ If you happen to know what module(s) are relevant to your issue, check their
documentation (press =<leader> h d m= to jump to a module's documentation). Your
issue may be documented.
+ If possible, see if the issue can be reproduced in vanilla Emacs (Emacs
without Doom) and/or vanilla Doom (Doom without your private config). [[#testing-in-dooms-sandbox][Doom's
sandbox can help you check]].
+ Ask for help on [[https://discord.gg/qvGgnVx][our Discord server]]. It is the quickest way to get help,
sometimes straight from Doom's maintainer, who is very active there.
If none of these things have helped you, then it's time to open a bug report.
See "[[file:contributing.org::*Reporting issues][Reporting Issues]]" in the [[file:contributing.org][contributing guidelines]] on how to file an
effective bug report.
** Looking up documentation and state from within Emacs
...
*** Variables, functions, faces, etc.
Emacs is a Lisp interpreter whose state you can access on-the-fly with tools
provided to you by Emacs itself. They're available on the =SPC h= prefix by
default. Use them to debug your sessions.
Here are some of the more important ones:
+ ~describe-variable~ (=SPC h v=)
+ ~describe-function~ (=SPC h f=)
+ ~describe-face~ (=SPC h F=)
+ ~describe-bindings~ (=SPC h b=)
+ ~describe-key~ (=SPC h k=)
+ ~describe-char~ (=SPC h '=)
+ ~find-library~ (=SPC h P=)
You can also evaluate code with ~eval-expression~ (=M-;= or =SPC ;=).
*** TODO For Doom Modules, packages, autodefs, etc.
+ ~doom/open-news~ (=SPC h n=) ::
...
+ ~doom/help~ (=SPC h d h=) ::
Open the index of Doom's manual.
+ ~doom/help-modules~ (=SPC h d m=) ::
Jumps to a module's documentation.
+ ~doom/help-autodefs~ (=SPC h u=) ::
Jumps to the documentation for an autodef function/macro. These are special
functions that are always defined, whether or not their containing modules
are enabled.
+ ~doom/help-packages~ (=SPC h p=) ::
Look up packages that are installed, by whom (what modules) and where jump
to all the places it is being configured.
+ ~doom/info~ ::
...
** How to extract a backtrace from an error
If you encounter an error while using Doom Emacs, you're probably about to head
off and file a bug report (or request help on [[https://discord.gg/qvGgnVx][our Discord server]]). Before you
do, please generate a backtrace to include with it.
To do so you must enable ~debug-on-error~ then recreate the error.
*** Enabling ~debug-on-error~
There are three ways to enable ~debug-on-error~:
1. Start Emacs with ~emacs --debug-init~. Use this for errors that occur at
startup.
2. Evil users can press =SPC h d d= and non-evil users can press =C-h d d=.
3. If the above don't work, there's always: ~M-x toggle-debug-on-error~
Now that ~debug-on-error~ is on, recreate the error. A window should pop up with
a backtrace.
*** A backtrace from ~bin/doom~
If the error you've encountered is emitted from ~bin/doom~, you can re-run the
same command with the ~-d~ or ~--debug~ switches to force it to emit a backtrace
when an error occurs. The ~DEBUG~ environment variable will work to.
#+BEGIN_SRC sh
doom -d sync
doom --debug install
DEBUG=1 doom update
#+END_SRC
#+BEGIN_QUOTE
Note: switch order is important. ~-d~ / ~--debug~ /must/ come right after ~doom~
and before the subcommand. This will be fixed eventually.
#+END_QUOTE
** Evaluating Elisp on-the-fly
Often, you may find it helpful for debugging to evaluate some Emacs Lisp. Here
are couple things you can do:
+ Use =M-:= (bound to ~eval-expression~),
+ =SPC x= will open a scratch buffer. ~M-x emacs-lisp-mode~ will change it to
the appropriate major mode, then use ~+eval:region~ (=gr=) and ~+eval/buffer~
(=gR=) to evaluate code,
**
gitextract_iw40yntc/
├── .doom
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ └── config.yml
│ └── workflows/
│ ├── lint-commits.yml
│ └── triage.yml
├── .gitignore
├── LICENSE
├── README.md
├── bin/
│ ├── doom
│ ├── doom.ps1
│ ├── doom.sh
│ ├── doomscript
│ └── org-capture
├── docs/
│ ├── appendix.org
│ ├── contributing.org
│ ├── examples.org
│ ├── faq.org
│ ├── getting_started.org
│ └── index.org
├── early-init.el
├── lisp/
│ ├── .doommodule
│ ├── cli/
│ │ ├── ci.el
│ │ ├── doctor.el
│ │ ├── emacs.el
│ │ ├── env.el
│ │ ├── gc.el
│ │ ├── info.el
│ │ ├── install.el
│ │ ├── make/
│ │ │ └── completions.el
│ │ ├── make.el
│ │ ├── profile.el
│ │ ├── run.el
│ │ ├── sync.el
│ │ ├── test.el
│ │ └── upgrade.el
│ ├── demos.org
│ ├── doom-cli.el
│ ├── doom-compat.el
│ ├── doom-editor.el
│ ├── doom-elpaca.el
│ ├── doom-keybinds.el
│ ├── doom-lib.el
│ ├── doom-projects.el
│ ├── doom-start.el
│ ├── doom-straight.el
│ ├── doom-ui.el
│ ├── doom.el
│ ├── init.el
│ ├── lib/
│ │ ├── autoloads.el
│ │ ├── buffers.el
│ │ ├── config.el
│ │ ├── debug.el
│ │ ├── docs.el
│ │ ├── files.el
│ │ ├── fonts.el
│ │ ├── git.el
│ │ ├── help.el
│ │ ├── indent.el
│ │ ├── modules.el
│ │ ├── packages.el
│ │ ├── plist.el
│ │ ├── print.el
│ │ ├── process.el
│ │ ├── profiles.el
│ │ ├── projects.el
│ │ ├── sandbox.el
│ │ ├── scratch.el
│ │ ├── sessions.el
│ │ ├── store.el
│ │ ├── strings.el
│ │ ├── system.el
│ │ ├── text.el
│ │ ├── themes.el
│ │ └── ui.el
│ ├── modules/
│ │ ├── .doommodule
│ │ ├── cli/
│ │ │ └── .doommodule
│ │ ├── compat/
│ │ │ └── .doommodule
│ │ └── emacs/
│ │ └── .doommodule
│ └── packages.el
├── modules/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.org
│ ├── app/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── calendar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── emms/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── everywhere/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── cli.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── irc/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── irc.el
│ │ │ │ ├── ivy.el
│ │ │ │ ├── settings.el
│ │ │ │ └── vertico.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── rss/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── checkers/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── grammar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── spell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── +flyspell.el
│ │ │ │ └── +spell-fu.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── syntax/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── completion/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── company/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── corfu/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── helm/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ └── helm.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ido/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ivy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ ├── ivy.el
│ │ │ │ └── posframe.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── vertico/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── evil.el
│ │ │ ├── magit.el
│ │ │ ├── vertico.el
│ │ │ └── workspaces.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── config/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── default/
│ │ │ ├── +emacs-bindings.el
│ │ │ ├── +evil-bindings.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── default.el
│ │ │ │ ├── deferred.el
│ │ │ │ ├── files.el
│ │ │ │ ├── search.el
│ │ │ │ └── text.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── literate/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── cli.el
│ │ └── use-package/
│ │ ├── .doommodule
│ │ ├── init.el
│ │ └── packages.el
│ ├── editor/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── evil/
│ │ │ ├── +commands.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ ├── embrace.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── ex.el
│ │ │ │ ├── files.el
│ │ │ │ ├── textobjects.el
│ │ │ │ └── unimpaired.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── file-templates/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── packages.el
│ │ │ └── templates/
│ │ │ ├── android-mode/
│ │ │ │ └── __build.gradle
│ │ │ ├── c++-mode/
│ │ │ │ ├── __cpp
│ │ │ │ ├── __hpp
│ │ │ │ ├── __main.cpp
│ │ │ │ └── __winmain.cpp
│ │ │ ├── c-mode/
│ │ │ │ ├── __c
│ │ │ │ ├── __h
│ │ │ │ └── __main.c
│ │ │ ├── direnv-envrc-mode/
│ │ │ │ └── __envrc
│ │ │ ├── dockerfile-mode/
│ │ │ │ └── __
│ │ │ ├── emacs-ert-mode/
│ │ │ │ └── __
│ │ │ ├── emacs-lisp-mode/
│ │ │ │ ├── __doom-doctor
│ │ │ │ ├── __doom-module
│ │ │ │ ├── __doom-packages
│ │ │ │ ├── __doom-test
│ │ │ │ ├── __doommodulerc
│ │ │ │ ├── __doomrc
│ │ │ │ ├── __doomrc_el
│ │ │ │ └── __package
│ │ │ ├── fish-mode/
│ │ │ │ └── __
│ │ │ ├── gitignore-mode/
│ │ │ │ └── __
│ │ │ ├── go-mode/
│ │ │ │ ├── __.go
│ │ │ │ └── __main.go
│ │ │ ├── java-mode/
│ │ │ │ ├── __annotation-type
│ │ │ │ ├── __class
│ │ │ │ ├── __enum
│ │ │ │ ├── __interface
│ │ │ │ ├── __main
│ │ │ │ └── __record
│ │ │ ├── js-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __gulpfile.js
│ │ │ │ ├── __node
│ │ │ │ └── __webpack.config.js
│ │ │ ├── json-mode/
│ │ │ │ ├── __bower.json
│ │ │ │ └── __package.json
│ │ │ ├── love-mode/
│ │ │ │ ├── __conf.lua
│ │ │ │ └── __main.lua
│ │ │ ├── makefile-gmake-mode/
│ │ │ │ ├── __
│ │ │ │ └── __cpp
│ │ │ ├── markdown-mode/
│ │ │ │ ├── __
│ │ │ │ └── __jekyll-post
│ │ │ ├── nix-mode/
│ │ │ │ ├── __
│ │ │ │ └── __shell.nix
│ │ │ ├── nose-mode/
│ │ │ │ └── __
│ │ │ ├── nxml-mode/
│ │ │ │ └── __
│ │ │ ├── org-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __contact.org
│ │ │ │ ├── __doom-category-readme
│ │ │ │ ├── __doom-docs
│ │ │ │ ├── __doom-readme
│ │ │ │ ├── __invoice.org
│ │ │ │ └── __project.org
│ │ │ ├── php-mode/
│ │ │ │ ├── __
│ │ │ │ └── __.class.php
│ │ │ ├── python-mode/
│ │ │ │ ├── __
│ │ │ │ └── __setup.py
│ │ │ ├── rspec-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __.rspec
│ │ │ │ └── __helper
│ │ │ ├── ruby-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __.gemspec
│ │ │ │ ├── __Gemfile
│ │ │ │ ├── __Rakefile
│ │ │ │ └── __module
│ │ │ ├── rust-mode/
│ │ │ │ ├── __Cargo.toml
│ │ │ │ └── __main.rs
│ │ │ ├── scss-mode/
│ │ │ │ ├── __
│ │ │ │ ├── __master.scss
│ │ │ │ └── __normalize.scss
│ │ │ ├── sh-mode/
│ │ │ │ ├── __
│ │ │ │ └── __zunit
│ │ │ ├── slim-mode/
│ │ │ │ └── __
│ │ │ ├── snippet-mode/
│ │ │ │ └── __
│ │ │ ├── solidity-mode/
│ │ │ │ └── __sol
│ │ │ ├── text-mode/
│ │ │ │ ├── __license
│ │ │ │ ├── __license-apache
│ │ │ │ ├── __license-apache-bp
│ │ │ │ ├── __license-bsd2
│ │ │ │ ├── __license-bsd3
│ │ │ │ ├── __license-gpl3
│ │ │ │ ├── __license-gpl3-bp
│ │ │ │ ├── __license-lgpl3
│ │ │ │ ├── __license-mit
│ │ │ │ ├── __license-mozilla
│ │ │ │ ├── __license-mozilla-bp
│ │ │ │ └── __license-unlicense
│ │ │ ├── web-mode/
│ │ │ │ ├── __.html
│ │ │ │ └── __jekyll-layout.html
│ │ │ └── yaml-mode/
│ │ │ └── __docker-compose.yml
│ │ ├── fold/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── fold.el
│ │ │ │ └── hideshow.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── format/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── evil.el
│ │ │ │ ├── format.el
│ │ │ │ ├── lsp.el
│ │ │ │ ├── org.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── god/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lispy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── multiple-cursors/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── evil-mc.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── objed/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── parinfer/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── rotate-text/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── packages.el
│ │ ├── snippets/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── settings.el
│ │ │ │ └── snippets.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── whitespace/
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── word-wrap/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── emacs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── dired/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── electric/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── config.el
│ │ ├── eww/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── ibuffer/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── workspaces.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── tramp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── config.el
│ │ ├── undo/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── vc/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── vc.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── email/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── mu4e/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ ├── email.el
│ │ │ │ ├── evil.el
│ │ │ │ └── mu-lock.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── notmuch/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── wanderlust/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── input/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── bidi/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── config.el
│ │ ├── chinese/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── japanese/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── layout/
│ │ ├── +azerty.el
│ │ ├── +bepo.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── bepo.el
│ │ └── config.el
│ ├── lang/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── ada/
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── agda/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── beancount/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── advice.el
│ │ │ │ └── beancount.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── cc/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── clojure/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── common-lisp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── common-lisp.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── coq/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── crystal/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── csharp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── dart/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── data/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── dhall/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── elixir/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── elm/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── emacs-lisp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── emacs-lisp.el
│ │ │ │ └── helpful.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── erlang/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ess/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── factor/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── faust/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── fortran/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── doctor.el
│ │ ├── fsharp/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── fstar/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── gdscript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── go/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── graphql/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── graphviz/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── haskell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── hy/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── idris/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── janet/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── java/
│ │ │ ├── +lsp.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── java.el
│ │ │ │ └── lsp.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── javascript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── json/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── julia/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── kotlin/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── latex/
│ │ │ ├── +fontification.el
│ │ │ ├── +ref.el
│ │ │ ├── +viewers.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── lean/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ledger/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lua/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── lua.el
│ │ │ │ └── moonscript.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── markdown/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── nim/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── nix/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ocaml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── org/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── contrib-present.el
│ │ │ │ ├── contrib-roam.el
│ │ │ │ ├── org-attach.el
│ │ │ │ ├── org-avy.el
│ │ │ │ ├── org-babel.el
│ │ │ │ ├── org-capture.el
│ │ │ │ ├── org-export.el
│ │ │ │ ├── org-link.el
│ │ │ │ ├── org-refile.el
│ │ │ │ ├── org-tables.el
│ │ │ │ └── org.el
│ │ │ ├── cli.el
│ │ │ ├── config.el
│ │ │ ├── contrib/
│ │ │ │ ├── dragndrop.el
│ │ │ │ ├── journal.el
│ │ │ │ ├── jupyter.el
│ │ │ │ ├── noter.el
│ │ │ │ ├── present.el
│ │ │ │ ├── pretty.el
│ │ │ │ └── roam.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── php/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── plantuml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── purescript/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── python/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat-28.1.el
│ │ │ │ ├── conda.el
│ │ │ │ ├── pyenv.el
│ │ │ │ ├── python.el
│ │ │ │ └── uv.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── qt/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── racket/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── raku/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── rest/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── rst/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── ruby/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── rust/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat.el
│ │ │ │ └── rust.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── scala/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── scheme/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── sh/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── sml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── solidity/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── swift/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── terra/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── web/
│ │ │ ├── +css.el
│ │ │ ├── +html.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── css.el
│ │ │ │ ├── evil.el
│ │ │ │ └── html.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── yaml/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── zig/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── os/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── macos/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── tty/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── term/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── eshell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── commands.el
│ │ │ │ ├── company.el
│ │ │ │ ├── eshell.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── prompts.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── shell/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── term/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ └── vterm/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── themes/
│ │ ├── .doommodule
│ │ └── doom/
│ │ └── .doommodule
│ ├── tools/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── ansible/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── biblio/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── collab/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── debugger/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ └── debugger.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── direnv/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── docker/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── editorconfig/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── ein/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── eval/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── eval.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── repl.el
│ │ │ │ └── settings.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── llm/
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── lookup/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── docsets.el
│ │ │ │ ├── evil.el
│ │ │ │ ├── lookup.el
│ │ │ │ ├── online.el
│ │ │ │ └── xwidget.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── lsp/
│ │ │ ├── +eglot.el
│ │ │ ├── +lsp.el
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── common.el
│ │ │ │ ├── eglot.el
│ │ │ │ └── lsp-mode.el
│ │ │ ├── config.el
│ │ │ ├── demos.org
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── magit/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── make/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload.el
│ │ │ └── packages.el
│ │ ├── pass/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── consult.el
│ │ │ │ ├── ivy.el
│ │ │ │ └── pass.el
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── pdf/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ └── packages.el
│ │ ├── terraform/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ ├── tmux/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ └── autoload/
│ │ │ ├── evil.el
│ │ │ └── tmux.el
│ │ ├── tree-sitter/
│ │ │ ├── .doommodule
│ │ │ ├── README.org
│ │ │ ├── autoload/
│ │ │ │ ├── compat-30.el
│ │ │ │ └── tree-sitter.el
│ │ │ ├── config.el
│ │ │ ├── doctor.el
│ │ │ └── packages.el
│ │ └── upload/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ └── ui/
│ ├── .doommodule
│ ├── README.org
│ ├── dashboard/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── config.el
│ ├── deft/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── doom/
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── doom-dashboard/
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── config.el
│ ├── doom-quit/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ └── config.el
│ ├── emoji/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── hl-todo/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── indent-guides/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── ligatures/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── ligatures.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── minimap/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── modeline/
│ │ ├── +light.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── nav-flash/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── neotree/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── ophints/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── popup/
│ │ ├── +hacks.el
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── popup.el
│ │ │ └── settings.el
│ │ └── config.el
│ ├── smooth-scroll/
│ │ ├── README.org
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── tabs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── treemacs/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ ├── config.el
│ │ ├── doctor.el
│ │ └── packages.el
│ ├── unicode/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── packages.el
│ ├── vc-gutter/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ └── diff-hl.el
│ │ ├── config.el
│ │ └── packages.el
│ ├── vi-tilde-fringe/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload.el
│ │ └── packages.el
│ ├── window-select/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── config.el
│ │ └── packages.el
│ ├── workspaces/
│ │ ├── .doommodule
│ │ ├── README.org
│ │ ├── autoload/
│ │ │ ├── evil.el
│ │ │ └── workspaces.el
│ │ ├── config.el
│ │ └── packages.el
│ └── zen/
│ ├── .doommodule
│ ├── README.org
│ ├── autoload.el
│ ├── config.el
│ └── packages.el
├── profiles/
│ ├── README.org
│ └── safe-mode/
│ └── init.el
├── shell.nix
└── static/
├── BUG_REPORT
├── QUICKSTART_INTRO
├── VANILLA_SANDBOX
├── config.example.el
├── init.example.el
└── packages.example.el
SYMBOL INDEX (5 symbols across 5 files)
FILE: modules/editor/file-templates/templates/c++-mode/__main.cpp
function main (line 7) | auto main(int argc, char *argv[]) -> int {
FILE: modules/editor/file-templates/templates/c++-mode/__winmain.cpp
function WinMain (line 7) | int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR...
FILE: modules/editor/file-templates/templates/c-mode/__main.c
function main (line 7) | int main(int argc, char *argv[]) {
FILE: modules/editor/file-templates/templates/go-mode/__main.go
function main (line 7) | func main() {
FILE: modules/editor/file-templates/templates/rust-mode/__main.rs
function main (line 1) | fn main() {
Condensed preview — 1095 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,778K chars).
[
{
"path": ".doom",
"chars": 4840,
"preview": "\"3.0.0-pre\"\n((name . doom)\n (version . \"3.0.0-pre\")\n (homepage . \"https://doomemacs.org\")\n\n (commit\n (preset doom-conve"
},
{
"path": ".github/CODEOWNERS",
"chars": 9700,
"preview": "# -*- mode: conf -*-\n# Auto-generated by 'doom make .github/CODEOWNERS', do not edit it by hand.\n\n* @doomemacs/maintaine"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 3930,
"preview": "---\nname: 📝 Bug Report\ndescription: Report something that isn't working as intended\nlabels: [\"is:bug\", \"needs-triage\"]\np"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 1675,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: 📝 Feature Request\n url: https://doomemacs.org/discuss/new?catego"
},
{
"path": ".github/workflows/lint-commits.yml",
"chars": 131,
"preview": "name: Lint commits\non: [push, pull_request]\njobs:\n lint-commits:\n uses: doomemacs/ci/.github/workflows/lint-commits."
},
{
"path": ".github/workflows/triage.yml",
"chars": 181,
"preview": "name: Mark stale issues and lock closed threads\non:\n schedule:\n - cron: '0 */12 * * *' # twice, daily\njobs:\n triag"
},
{
"path": ".gitignore",
"chars": 526,
"preview": "# project dotfiles\n.*\n!.doom*\n!.dir-locals.el\n!.gitignore\n!/.github\n\n# generated by doom\n/profiles/*.el\n/.local*/\n\n# pos"
},
{
"path": "LICENSE",
"chars": 1087,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014-2026 Henrik Lissner.\n\nPermission is hereby granted, free of charge, to any per"
},
{
"path": "README.md",
"chars": 13050,
"preview": "<div align=\"center\">\n\n# Doom Emacs\n\n[Install](#install) • [Documentation] • [FAQ] • [Screenshots] • [Contribute](#contri"
},
{
"path": "bin/doom",
"chars": 13677,
"preview": "#!/usr/bin/env sh\n:; # -*- mode: emacs-lisp; lexical-binding: t -*-\n:; case \"$EMACS\" in *term*) EMACS=emacs ;; *) EMACS="
},
{
"path": "bin/doom.ps1",
"chars": 1662,
"preview": "# bin/doom.ps1\n# TODO: Use magic shebang (polyglot)?\n\nfunction Executable-Find {\n foreach ($exe in $args) {\n i"
},
{
"path": "bin/doom.sh",
"chars": 194,
"preview": "#!/bin/bash\n#\n# On Android (and possibly other Linux distros), /usr/bin/env does not exist.\n# This script exists as a wo"
},
{
"path": "bin/doomscript",
"chars": 3692,
"preview": "#!/usr/bin/env sh\n# -*- coding: utf-8-unix -*-\n# This is a shebang interpreter for launching Emacs Lisp scripts with Doo"
},
{
"path": "bin/org-capture",
"chars": 1239,
"preview": "#!/usr/bin/env sh\n\n# Open an org-capture popup frame from the shell. This opens a temporary emacs\n# daemon if emacs isn'"
},
{
"path": "docs/appendix.org",
"chars": 9805,
"preview": ":PROPERTIES:\n:ID: ca20678f-0f1a-4462-a599-da03f0e16330\n:END:\n#+title: Appendix\n#+subtitle: A glossary of (Doom)"
},
{
"path": "docs/contributing.org",
"chars": 8546,
"preview": "#+TITLE: Contributing\n#+STARTUP: nofold\n\nDoom Emacs is an active and ongoing project, maintained mostly by a single\npers"
},
{
"path": "docs/examples.org",
"chars": 12809,
"preview": ":PROPERTIES:\n:ID: e103c1bc-be8e-4451-8e43-a93d9e35e692\n:END:\n#+title: Examples\n#+subtitle: Samples of Emacs/Doo"
},
{
"path": "docs/faq.org",
"chars": 47341,
"preview": ":PROPERTIES:\n:ID: 5fa8967a-532f-4e0c-8ae8-25cd802bf9a9\n:END:\n#+title: Frequently Asked Questions\n#+subtitle: An"
},
{
"path": "docs/getting_started.org",
"chars": 66035,
"preview": "#+TITLE: Getting Started Guide\n#+STARTUP: nofold\n\nGNU Emacs is one grand ol' adventure, let alone Doom Emacs. Before you"
},
{
"path": "docs/index.org",
"chars": 5247,
"preview": "#+TITLE: Doom Emacs Documentation\n#+STARTUP: nofold\n\nDoom is a configuration framework for [[https://www.gnu.org/softwar"
},
{
"path": "early-init.el",
"chars": 8737,
"preview": ";;; early-init.el --- Doom's universal bootstrapper -*- lexical-binding: t -*-\n;;; Commentary:\n;;\n;; This file, in summa"
},
{
"path": "lisp/.doommodule",
"chars": 300,
"preview": "(3 0 0)\n((name . :doom)\n (depth . -110)\n ;; (packages\n ;; (elpaca :host github\n ;; :repo \"progfolio/elpaca\"\n ;"
},
{
"path": "lisp/cli/ci.el",
"chars": 21131,
"preview": ";;; lisp/cli/ci.el -*- lexical-binding: t; -*-\n\n;;\n;;; Variables\n\n(defvar doom-ci-commit-trailer-keys\n '((\"Fix\" ref has"
},
{
"path": "lisp/cli/doctor.el",
"chars": 21653,
"preview": ";;; lisp/cli/doctor.el --- userland heuristics and Emacs diagnostics -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Cod"
},
{
"path": "lisp/cli/emacs.el",
"chars": 5019,
"preview": ";;; lisp/cli/emacs.el --- launching Emacs and sandboxes -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(require "
},
{
"path": "lisp/cli/env.el",
"chars": 6794,
"preview": ";;; lisp/cli/env.el --- envvar file generator -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;; Variables\n\n;"
},
{
"path": "lisp/cli/gc.el",
"chars": 7977,
"preview": ";;; lisp/cli/gc.el --- clean up after profiles, packages, and logs -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:"
},
{
"path": "lisp/cli/info.el",
"chars": 816,
"preview": ";;; lisp/cli/info.el --- information about your Doom install -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;"
},
{
"path": "lisp/cli/install.el",
"chars": 5286,
"preview": ";;; lisp/cli/install.el --- Doom Emacs install wizard -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(doom-requi"
},
{
"path": "lisp/cli/make/completions.el",
"chars": 6284,
"preview": ";;; lisp/cli/make/completions.el --- generate shell completion scripts -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; C"
},
{
"path": "lisp/cli/make.el",
"chars": 1757,
"preview": ";;; lisp/cli/make.el --- file generation commands -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(load! \"make/co"
},
{
"path": "lisp/cli/profile.el",
"chars": 2902,
"preview": ";;; lisp/cli/profile.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(doom-require 'doom-lib 'profiles)\n\n\n;;\n;"
},
{
"path": "lisp/cli/run.el",
"chars": 339,
"preview": ";;; lisp/cli/run.el --- launching project and CI/CD tasks -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;; "
},
{
"path": "lisp/cli/sync.el",
"chars": 6349,
"preview": ";;; lisp/cli/sync.el --- synchronize config command -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(doom-require"
},
{
"path": "lisp/cli/test.el",
"chars": 1141,
"preview": ";;; lisp/cli/test.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; The heart of Doom's test DSL and framework. Power"
},
{
"path": "lisp/cli/upgrade.el",
"chars": 7710,
"preview": ";;; lisp/cli/upgrade.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(doom-require 'doom-lib 'packages)\n\n\n;;\n;"
},
{
"path": "lisp/demos.org",
"chars": 19197,
"preview": "#+title: Doom Emacs API Demos\n#+property: header-args:elisp :results pp :exports both :eval never-export\n\nThis module in"
},
{
"path": "lisp/doom-cli.el",
"chars": 111747,
"preview": ";;; lisp/doom-cli.el --- API+DSL for Doom's CLI framework -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; The heart of"
},
{
"path": "lisp/doom-compat.el",
"chars": 9382,
"preview": ";;; lisp/doom-compat.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; This file backports functions and variables fr"
},
{
"path": "lisp/doom-editor.el",
"chars": 26528,
"preview": ";;; doom-editor.el --- defaults for text editing in Doom -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(defvar "
},
{
"path": "lisp/doom-elpaca.el",
"chars": 247,
"preview": ";;; lisp/doom-elpaca.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; In the near future, Doom will replace Straight"
},
{
"path": "lisp/doom-keybinds.el",
"chars": 19088,
"preview": ";;; doom-keybinds.el --- defaults for Doom's keybinds -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; A centralized ke"
},
{
"path": "lisp/doom-lib.el",
"chars": 72707,
"preview": ";;; doom-lib.el --- Doom's core standard library -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;; Custom error"
},
{
"path": "lisp/doom-projects.el",
"chars": 14718,
"preview": ";;; doom-projects.el --- defaults for project management in Doom -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n"
},
{
"path": "lisp/doom-start.el",
"chars": 17009,
"preview": ";;; lisp/doom-start.el --- bootstraps interactive sessions -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;;"
},
{
"path": "lisp/doom-straight.el",
"chars": 16889,
"preview": ";;; lisp/doom-straight.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; Emacs package management is opinionated, and"
},
{
"path": "lisp/doom-ui.el",
"chars": 34814,
"preview": ";;; doom-ui.el --- defaults for Doom's aesthetics -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;; Variable"
},
{
"path": "lisp/doom.el",
"chars": 43544,
"preview": ";;; doom.el --- the heart of the beast -*- lexical-binding: t; -*-\n;;\n;; Author: Henrik Lissner <contact@henrik.io>\n;; "
},
{
"path": "lisp/init.el",
"chars": 811,
"preview": ";;; lisp/init.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; :doom is now treated like a normal module, and this i"
},
{
"path": "lisp/lib/autoloads.el",
"chars": 9585,
"preview": ";;; lisp/lib/autoloads.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(defvar doom-autoloads-excluded-package"
},
{
"path": "lisp/lib/buffers.el",
"chars": 14537,
"preview": ";;; lisp/lib/buffers.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defvar doom-real-buffer-functions ()\n \"A list of p"
},
{
"path": "lisp/lib/config.el",
"chars": 5283,
"preview": ";;; lisp/lib/config.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defvar doom-after-reload-hook '(doom-kill-childframe"
},
{
"path": "lisp/lib/debug.el",
"chars": 18596,
"preview": ";;; lisp/lib/debug.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;; Doom's debug mode\n\n;;;###autoload\n(d"
},
{
"path": "lisp/lib/docs.el",
"chars": 23972,
"preview": ";;; core/lib/docs.el -- a reader mode for Doom's Org docs -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; This file de"
},
{
"path": "lisp/lib/files.el",
"chars": 27311,
"preview": ";;; lisp/lib/files.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(defun doom-files--build-checks (spec &opti"
},
{
"path": "lisp/lib/fonts.el",
"chars": 7018,
"preview": ";;; lisp/lib/fonts.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defvar doom-font-increment 2\n \"How many steps to inc"
},
{
"path": "lisp/lib/git.el",
"chars": 505,
"preview": ";;; lisp/lib/git.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;;###autoload\n(defun doom-git-toplevel (&res"
},
{
"path": "lisp/lib/help.el",
"chars": 31102,
"preview": ";;; lisp/lib/help.el -*- lexical-binding: t; -*-\n\n(defvar doom--help-major-mode-module-alist\n '((dockerfile-mode :tools"
},
{
"path": "lisp/lib/indent.el",
"chars": 4699,
"preview": ";;; lisp/lib/indent.el -*- lexical-binding: t; -*-\n\n;; REVIEW: Move this out of autoloads in v3\n;;;###autoload\n(progn\n "
},
{
"path": "lisp/lib/modules.el",
"chars": 8822,
"preview": ";;; lib/modules.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n(defvar doom-modules nil\n \"A table of enabled"
},
{
"path": "lisp/lib/packages.el",
"chars": 57178,
"preview": ";;; lisp/lib/packages.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; Emacs package management is opinionated, and "
},
{
"path": "lisp/lib/plist.el",
"chars": 2575,
"preview": ";;; lisp/lib/plist.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;\n;;; Macros\n\n;;; DEPRECATED: In favor of "
},
{
"path": "lisp/lib/print.el",
"chars": 19254,
"preview": ";;; lisp/lib/print.el -*- lexical-binding: t; -*-\n;;; Commentary\n;;\n;; This is Doom's output library, for controlling wh"
},
{
"path": "lisp/lib/process.el",
"chars": 1780,
"preview": ";;; lisp/lib/process.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;;###autoload\n(defun doom-call-process ("
},
{
"path": "lisp/lib/profiles.el",
"chars": 23711,
"preview": ";;; lisp/lib/profiles.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;; Code:\n\n;;; File/directory variables\n(defvar doo"
},
{
"path": "lisp/lib/projects.el",
"chars": 8020,
"preview": ";;; lisp/lib/projects.el -*- lexical-binding: t; -*-\n\n;; HACK: We forward declare these variables because they are let-b"
},
{
"path": "lisp/lib/sandbox.el",
"chars": 8150,
"preview": ";;; lisp/lib/sandbox.el -*- lexical-binding: t; -*-\n\n(defvar doom-sandbox-buffer-name \"*doom:sandbox*\"\n \"Name of the Do"
},
{
"path": "lisp/lib/scratch.el",
"chars": 8566,
"preview": ";;; lisp/lib/scratch.el -*- lexical-binding: t; -*-\n\n(defvar doom-scratch-default-file \"__default\"\n \"The default file n"
},
{
"path": "lisp/lib/sessions.el",
"chars": 5562,
"preview": ";;; lisp/lib/sessions.el -*- lexical-binding: t; -*-\n\n(defvar desktop-base-file-name)\n(defvar desktop-dirname)\n(defvar d"
},
{
"path": "lisp/lib/store.el",
"chars": 6399,
"preview": ";;; lisp/lib/cache.el -*- lexical-binding: t; -*-\n\n;; This little library abstracts the process of writing arbitrary eli"
},
{
"path": "lisp/lib/strings.el",
"chars": 441,
"preview": ";;; lisp/lib/strings.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun doom-pcre-quote (str)\n \"Like `reqexp-quote',"
},
{
"path": "lisp/lib/system.el",
"chars": 5069,
"preview": ";;; lisp/lib/system.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun doom-system-distro ()\n \"Return a symbol repre"
},
{
"path": "lisp/lib/text.el",
"chars": 12362,
"preview": ";;; lisp/lib/text.el -*- lexical-binding: t; -*-\n\n(defvar-local doom--sppss-memo-last-point nil)\n(defvar-local doom--spp"
},
{
"path": "lisp/lib/themes.el",
"chars": 4673,
"preview": ";;; lisp/lib/themes.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defconst doom-customize-theme-hook nil)\n\n;;;###autol"
},
{
"path": "lisp/lib/ui.el",
"chars": 9718,
"preview": ";;; lisp/lib/ui.el -*- lexical-binding: t; -*-\n\n;;\n;;; Public library\n\n;;;###autoload\n(defun doom-resize-window (window "
},
{
"path": "lisp/modules/.doommodule",
"chars": 45,
"preview": "\"3.0.0-pre\"\n((name . :doom)\n (depth . -110))\n"
},
{
"path": "lisp/modules/cli/.doommodule",
"chars": 47,
"preview": "\"3.0.0-pre\"\n((name :doom cli)\n (depth . -100))\n"
},
{
"path": "lisp/modules/compat/.doommodule",
"chars": 53,
"preview": "\"3.0.0-pre\"\n((name :doom compat)\n (depth -115 -101))\n"
},
{
"path": "lisp/modules/emacs/.doommodule",
"chars": 51,
"preview": "\"3.0.0-pre\"\n((name :doom emacs)\n (depth -100 100))\n"
},
{
"path": "lisp/packages.el",
"chars": 1277,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; lisp/packages.el\n\n;; doom.el\n(package! auto-minor-mode\n :pin \"17cfa1b54800fdef2975c0"
},
{
"path": "modules/.gitignore",
"chars": 133,
"preview": ".DS_Store\n.idea\n*.log\ntmp/\n*~\n*.*~\n\\#*\n.\\#*\n*.cache*\n*.log\ntest/.local*/\ntest/result\n\n# compiled files\n*.elc\n*.lib\n*.fas"
},
{
"path": "modules/LICENSE",
"chars": 1081,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2021 Henrik Lissner\n\nPermission is hereby granted, free of charge, to any person ob"
},
{
"path": "modules/README.org",
"chars": 74329,
"preview": ":PROPERTIES:\n:ID: 12d2de30-c569-4b8e-bbc7-85dd5ccc4afa\n:END:\n#+title: Official modules\n#+subtitle: Doom Emacs' "
},
{
"path": "modules/app/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/README.org",
"chars": 390,
"preview": "#+title: :app\n#+created: February 19, 2017\n#+since: 21.12.0\n\n* Description\nApplication modules are complex and opini"
},
{
"path": "modules/app/calendar/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/calendar/README.org",
"chars": 2614,
"preview": "#+title: :app calendar\n#+subtitle: Watch your missed deadlines in real time\n#+created: January 13, 2018\n#+since: "
},
{
"path": "modules/app/calendar/autoload.el",
"chars": 2098,
"preview": ";;; app/calendar/autoload.el -*- lexical-binding: t; -*-\n\n(defvar +calendar--wconf nil)\n(defvar +calendar-workspace-name"
},
{
"path": "modules/app/calendar/config.el",
"chars": 3687,
"preview": ";;; app/calendar/config.el -*- lexical-binding: t; -*-\n\n(defvar +calendar-open-function #'+calendar/open-calendar\n \"TOD"
},
{
"path": "modules/app/calendar/packages.el",
"chars": 402,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; app/calendar/packages.el\n\n(package! calfw :pin \"36846cdca91794cf38fa171d5a3ac291d3ebc"
},
{
"path": "modules/app/emms/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/emms/README.org",
"chars": 2473,
"preview": "#+title: :app emms\n#+subtitle: A media player for music no one's heard of\n#+created: March 06, 2021\n#+since: 21.1"
},
{
"path": "modules/app/emms/autoload.el",
"chars": 748,
"preview": ";;; app/emms/autoload.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +emms/mpd-start-music-daemon ()\n (interacti"
},
{
"path": "modules/app/emms/config.el",
"chars": 549,
"preview": ";;; app/emms/config.el -*- lexical-binding: t; -*-\n\n(use-package! emms\n :defer t\n :init\n (setq emms-directory (file-n"
},
{
"path": "modules/app/emms/packages.el",
"chars": 121,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; app/emms/packages.el\n\n(package! emms :pin \"002a8db0913c1780149eb4a9306e6f582efe8974\")"
},
{
"path": "modules/app/everywhere/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/everywhere/README.org",
"chars": 2290,
"preview": "#+title: :app everywhere\n#+subtitle: *leave* Emacs!? You must be joking\n#+created: February 07, 2021\n#+since: 21."
},
{
"path": "modules/app/everywhere/cli.el",
"chars": 172,
"preview": ";;; app/everywhere/cli.el -*- lexical-binding: t; -*-\n\n(defcli! () ()\n \"Spawn an emacsclient window for quick edits.\"\n "
},
{
"path": "modules/app/everywhere/config.el",
"chars": 2134,
"preview": ";;; app/everywhere/config.el -*- lexical-binding: t; -*-\n\n(use-package! emacs-everywhere\n ;; Entry points into this pac"
},
{
"path": "modules/app/everywhere/doctor.el",
"chars": 430,
"preview": ";;; app/everywhere/doctor.el -*- lexical-binding: t; -*-\n\n(when (featurep :system 'windows)\n (error! \"emacs-everywhere "
},
{
"path": "modules/app/everywhere/packages.el",
"chars": 139,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; app/everywhere/packages.el\n\n(package! emacs-everywhere :pin \"09a6a64dd07a712aad8ef1d0"
},
{
"path": "modules/app/irc/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/irc/README.org",
"chars": 5394,
"preview": "#+title: :app irc\n#+subtitle: How neckbeards socialize\n#+created: June 11, 2017\n#+since: 2.0.3\n\n* Description :un"
},
{
"path": "modules/app/irc/autoload/irc.el",
"chars": 3955,
"preview": ";;; app/irc/autoload/email.el -*- lexical-binding: t; -*-\n\n(defvar +irc--workspace-name \"*IRC*\")\n\n(defun +irc-setup-wcon"
},
{
"path": "modules/app/irc/autoload/ivy.el",
"chars": 1502,
"preview": ";;; app/irc/autoload/ivy.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :completion ivy)\n\n;;;###autoload\n(defun +irc/"
},
{
"path": "modules/app/irc/autoload/settings.el",
"chars": 592,
"preview": ";;; app/irc/autoload/settings.el -*- lexical-binding: t; -*-\n\n;;;###autodef\n(defun set-irc-server! (server plist)\n \"Reg"
},
{
"path": "modules/app/irc/autoload/vertico.el",
"chars": 790,
"preview": ";;; app/irc/autoload/vertico.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :completion vertico)\n\n;;;###autoload\n(def"
},
{
"path": "modules/app/irc/config.el",
"chars": 9385,
"preview": ";;; app/irc/config.el -*- lexical-binding: t; -*-\n\n(defvar +irc-left-padding 13\n \"By how much spaces the left hand side"
},
{
"path": "modules/app/irc/doctor.el",
"chars": 245,
"preview": ";; -*- lexical-binding: t; no-byte-compile: t; -*-\n;;; app/irc/doctor.el\n\n(when (memq 'circe-notifications doom-disabled"
},
{
"path": "modules/app/irc/packages.el",
"chars": 200,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; app/irc/packages.el\n\n(package! circe :pin \"e909ff49e59c396b19564855a3f282684a4e716e\")"
},
{
"path": "modules/app/rss/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/app/rss/README.org",
"chars": 4613,
"preview": "#+title: :app rss\n#+subtitle: An RSS reader that Google can't shut down\n#+created: May 12, 2020\n#+since: 2.0.9\n\n*"
},
{
"path": "modules/app/rss/autoload.el",
"chars": 5093,
"preview": ";;; app/rss/autoload.el -*- lexical-binding: t; -*-\n\n(defvar +rss--wconf nil)\n\n;;;###autoload\n(defun =rss ()\n \"Activate"
},
{
"path": "modules/app/rss/config.el",
"chars": 3640,
"preview": ";;; app/rss/config.el -*- lexical-binding: t; -*-\n\n;; This is an opinionated workflow that turns Emacs into an RSS reade"
},
{
"path": "modules/app/rss/doctor.el",
"chars": 426,
"preview": ";;; app/rss/doctor.el -*- lexical-binding: t; -*-\n\n(when (modulep! +youtube)\n (unless (executable-find \"mpv\")\n (warn"
},
{
"path": "modules/app/rss/packages.el",
"chars": 391,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; app/rss/packages.el\n\n(package! elfeed :pin \"bbb3cac27b0412d80b327b5cfaab83683c96a2a1\""
},
{
"path": "modules/checkers/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/checkers/README.org",
"chars": 249,
"preview": "#+title: :checkers\n#+created: August 01, 2021\n#+since: 21.12.0\n\n* Description\nFor modules dedicated to linting plain"
},
{
"path": "modules/checkers/grammar/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/checkers/grammar/README.org",
"chars": 2423,
"preview": "#+title: :checkers grammar\n#+subtitle: Tasing grammar mistake every you make\n#+created: January 09, 2020\n#+since: "
},
{
"path": "modules/checkers/grammar/config.el",
"chars": 1722,
"preview": ";;; checkers/grammar/config.el -*- lexical-binding: t; -*-\n\n(use-package! langtool\n :commands (langtool-check\n "
},
{
"path": "modules/checkers/grammar/packages.el",
"chars": 207,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; checkers/grammar/packages.el\n\n(package! langtool :pin \"6605f26f56b7da1499a32885236c02"
},
{
"path": "modules/checkers/spell/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/checkers/spell/README.org",
"chars": 8697,
"preview": "#+title: :checkers spell\n#+subtitle: Tasing you for misspelling mispelling\n#+created: February 20, 2017\n#+since: "
},
{
"path": "modules/checkers/spell/autoload/+flyspell.el",
"chars": 2733,
"preview": ";;; checkers/spell/autoload/+flyspell.el -*- lexical-binding: t; -*-\n;;;###if (modulep! +flyspell)\n\n;;;###autodef\n(defal"
},
{
"path": "modules/checkers/spell/autoload/+spell-fu.el",
"chars": 4933,
"preview": ";;; checkers/spell/autoload/+spell-fu.el -*- lexical-binding: t; -*-\n;;;###if (modulep! -flyspell)\n\n(defun +spell--corre"
},
{
"path": "modules/checkers/spell/config.el",
"chars": 8683,
"preview": ";;; checkers/spell/config.el -*- lexical-binding: t; -*-\n\n;;\n;;; Ispell\n\n;; `elisp-mode' is loaded at startup. In order "
},
{
"path": "modules/checkers/spell/doctor.el",
"chars": 379,
"preview": ";;; checkers/spell/doctor.el -*- lexical-binding: t; -*-\n\n(when (or (modulep! -flyspell)\n (modulep! +aspell))\n "
},
{
"path": "modules/checkers/spell/packages.el",
"chars": 627,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; checkers/spell/packages.el\n\n(if (modulep! -flyspell)\n (package! spell-fu\n :re"
},
{
"path": "modules/checkers/syntax/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/checkers/syntax/README.org",
"chars": 3317,
"preview": "#+title: :checkers syntax\n#+subtitle: Tasing you for every semicolon you forget\n#+created: February 20, 2017\n#+since"
},
{
"path": "modules/checkers/syntax/autoload.el",
"chars": 1029,
"preview": ";;; checkers/syntax/autoload.el -*- lexical-binding: t; -*-\n\n;;;###autodef\n(defun set-next-checker! (mode checker next &"
},
{
"path": "modules/checkers/syntax/config.el",
"chars": 6192,
"preview": ";;; checkers/syntax/config.el -*- lexical-binding: t; -*-\n\n;;\n;;; Flycheck\n\n(use-package! flycheck\n :unless (modulep! +"
},
{
"path": "modules/checkers/syntax/packages.el",
"chars": 521,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; checkers/syntax/packages.el\n\n(unless (modulep! +flymake)\n (package! flycheck :pin \"5"
},
{
"path": "modules/completion/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/README.org",
"chars": 628,
"preview": "#+title: :completion\n#+created: July 29, 2021\n#+since: 21.12.0\n\n* Description\nThese modules provide interfaces and f"
},
{
"path": "modules/completion/company/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/company/README.org",
"chars": 6371,
"preview": "#+title: :completion company\n#+subtitle: The ultimate code completion backend\n#+created: February 19, 2017\n#+since: "
},
{
"path": "modules/completion/company/autoload.el",
"chars": 5574,
"preview": ";;; completion/company/autoload.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defvar +company-backend-alist\n '((text-"
},
{
"path": "modules/completion/company/config.el",
"chars": 9892,
"preview": ";;; completion/company/config.el -*- lexical-binding: t; -*-\n\n(use-package! company\n :commands (company-complete-common"
},
{
"path": "modules/completion/company/packages.el",
"chars": 309,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/company/packages.el\n\n(package! company :pin \"42d3897308a992cd2268ba2d4e2ec"
},
{
"path": "modules/completion/corfu/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/corfu/README.org",
"chars": 14791,
"preview": "#+title: :completion corfu\n#+subtitle: Complete with cap(f), cape, and a flying feather\n#+created: September 9, 2022"
},
{
"path": "modules/completion/corfu/autoload.el",
"chars": 3909,
"preview": ";;; completion/corfu/autoload.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +corfu-dabbrev-friend-buffer-p (othe"
},
{
"path": "modules/completion/corfu/config.el",
"chars": 10127,
"preview": ";;; completion/corfu/config.el -*- lexical-binding: t; -*-\n\n(defvar +corfu-want-ret-to-confirm t\n \"Configure how the us"
},
{
"path": "modules/completion/corfu/packages.el",
"chars": 852,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/corfu/packages.el\n\n(package! corfu :pin \"abfe0003d71b61ffdcf23fc6e54664348"
},
{
"path": "modules/completion/helm/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/helm/README.org",
"chars": 10088,
"preview": "#+title: :completion helm\n#+subtitle: A bazooka for hunting house flies\n#+created: February 20, 2017\n#+since: 2.0"
},
{
"path": "modules/completion/helm/autoload/evil.el",
"chars": 1706,
"preview": ";;; completion/helm/autoload/evil.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :editor evil)\n\n;;;###autoload (autol"
},
{
"path": "modules/completion/helm/autoload/helm.el",
"chars": 3341,
"preview": ";;; completion/helm/autoload/helm.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +helm/projectile-find-file ()\n "
},
{
"path": "modules/completion/helm/config.el",
"chars": 7424,
"preview": ";;; completion/helm/config.el -*- lexical-binding: t; -*-\n\n;; Posframe (requires +childframe)\n(defvar +helm-posframe-han"
},
{
"path": "modules/completion/helm/doctor.el",
"chars": 278,
"preview": ";; -*- lexical-binding: t; no-byte-compile: t; -*-\n;;; completion/helm/doctor.el\n\n(dolist (module '(ivy ido vertico))\n "
},
{
"path": "modules/completion/helm/packages.el",
"chars": 1038,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/helm/packages.el\n\n(package! helm :pin \"9d8de1e0810ef5a5e1f3a46c9461b78b9e8"
},
{
"path": "modules/completion/ido/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/ido/README.org",
"chars": 1516,
"preview": "#+title: :completion ido\n#+subtitle: A foil for other search engines\n#+created: February 20, 2017\n#+since: 2.0.0\n"
},
{
"path": "modules/completion/ido/config.el",
"chars": 2012,
"preview": ";;; completion/ido/config.el -*- lexical-binding: t; -*-\n\n(defvar ido-mode-hook nil\n \"List of hooks to run when `ido-mo"
},
{
"path": "modules/completion/ido/doctor.el",
"chars": 278,
"preview": ";; -*- lexical-binding: t; no-byte-compile: t; -*-\n;;; completion/ido/doctor.el\n\n(dolist (module '(helm ivy vertico))\n "
},
{
"path": "modules/completion/ido/packages.el",
"chars": 431,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/ido/packages.el\n\n(package! flx-ido :pin \"4b1346eb9a8a76ee9c9dede69738c63ad"
},
{
"path": "modules/completion/ivy/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/ivy/README.org",
"chars": 8669,
"preview": "#+title: :completion ivy\n#+subtitle: Yesterday's lightest search engine\n#+created: February 20, 2017\n#+since: 2.0"
},
{
"path": "modules/completion/ivy/autoload/evil.el",
"chars": 670,
"preview": ";; completion/ivy/autoload/evil.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :editor evil)\n\n;;;###autoload (autoloa"
},
{
"path": "modules/completion/ivy/autoload/ivy.el",
"chars": 14459,
"preview": ";;; completion/ivy/autoload/ivy.el -*- lexical-binding: t; -*-\n\n(defun +ivy--is-workspace-buffer-p (buffer)\n (let ((buf"
},
{
"path": "modules/completion/ivy/autoload/posframe.el",
"chars": 536,
"preview": ";;; completion/ivy/autoload/posframe.el -*- lexical-binding: t; -*-\n;;;###if (modulep! +childframe)\n\n;;;###autoload\n(def"
},
{
"path": "modules/completion/ivy/config.el",
"chars": 17267,
"preview": ";;; completion/ivy/config.el -*- lexical-binding: t; -*-\n\n(defvar +ivy-buffer-preview nil\n \"If non-nil, preview buffers"
},
{
"path": "modules/completion/ivy/doctor.el",
"chars": 278,
"preview": ";; -*- lexical-binding: t; no-byte-compile: t; -*-\n;;; completion/ivy/doctor.el\n\n(dolist (module '(helm ido vertico))\n "
},
{
"path": "modules/completion/ivy/packages.el",
"chars": 868,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/ivy/packages.el\n\n(package! swiper :pin \"ee79f68215ae7e2b8a38ba6bf7f82b3fe5"
},
{
"path": "modules/completion/vertico/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/completion/vertico/README.org",
"chars": 14983,
"preview": "#+title: :completion vertico\n#+subtitle: Tomorrow's search engine\n#+created: July 25, 2021\n#+since: 21.12.0 (#466"
},
{
"path": "modules/completion/vertico/autoload/evil.el",
"chars": 737,
"preview": ";; completion/vertico/autoload/evil.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :editor evil)\n\n;;;###autoload (aut"
},
{
"path": "modules/completion/vertico/autoload/magit.el",
"chars": 327,
"preview": ";;; completion/vertico/autoload/magit.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :tools magit)\n\n;;;###autoload\n(d"
},
{
"path": "modules/completion/vertico/autoload/vertico.el",
"chars": 12150,
"preview": ";;; completion/vertico/autoload/vertico.el -*- lexical-binding: t; -*-\n\n(defvar consult-ripgrep-args)\n(defvar embark-qui"
},
{
"path": "modules/completion/vertico/autoload/workspaces.el",
"chars": 4517,
"preview": ";;; completion/vertico/autoload/workspaces.el -*- lexical-binding: t; -*-\n;;;###if (modulep! :ui workspaces)\n\n(defun +ve"
},
{
"path": "modules/completion/vertico/config.el",
"chars": 15898,
"preview": ";;; completion/vertico/config.el -*- lexical-binding: t; -*-\n\n(defvar +vertico-company-completion-styles '(basic partial"
},
{
"path": "modules/completion/vertico/doctor.el",
"chars": 1090,
"preview": ";; -*- lexical-binding: t; no-byte-compile: t; -*-\n;;; completion/vertico/doctor.el\n\n(dolist (module '(ivy helm ido))\n "
},
{
"path": "modules/completion/vertico/packages.el",
"chars": 1139,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; completion/vertico/packages.el\n\n(package! vertico :pin \"93f15873d7d6244d72202c5dd7724"
},
{
"path": "modules/config/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/config/README.org",
"chars": 295,
"preview": "#+title: :config\n#+created: July 29, 2021\n#+since: 21.12.0\n\n* Description\nModules in this category provide sane defa"
},
{
"path": "modules/config/default/+emacs-bindings.el",
"chars": 33476,
"preview": ";;; config/default/+emacs-bindings.el -*- lexical-binding: t; -*-\n\n;; Sensible default key bindings for non-evil users\n("
},
{
"path": "modules/config/default/+evil-bindings.el",
"chars": 46835,
"preview": ";;; config/default/+bindings.el -*- lexical-binding: t; -*-\n\n(when (modulep! :editor evil +everywhere)\n ;; NOTE: SPC u "
},
{
"path": "modules/config/default/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/config/default/README.org",
"chars": 2278,
"preview": "#+title: :config default\n#+subtitle: Reasonable defaults for reasonable people\n#+created: February 14, 2018\n#+since:"
},
{
"path": "modules/config/default/autoload/default.el",
"chars": 2421,
"preview": ";; config/default/autoload/default.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +default/compile (arg)\n \"Runs "
},
{
"path": "modules/config/default/autoload/deferred.el",
"chars": 836,
"preview": ";;; config/default/autoload/deferred.el -*- lexical-binding: t; -*-\n\n;; REVIEW: Generalize this\n;;;###autoload\n(defun +d"
},
{
"path": "modules/config/default/autoload/files.el",
"chars": 2615,
"preview": ";;; config/default/autoload/files.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +default/browse-project ()\n \"Br"
},
{
"path": "modules/config/default/autoload/search.el",
"chars": 5523,
"preview": ";;; config/default/autoload/search.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +default/search-cwd (&optional "
},
{
"path": "modules/config/default/autoload/text.el",
"chars": 7007,
"preview": ";;; config/default/autoload/text.el -*- lexical-binding: t; -*-\n\n;;;###autoload\n(defun +default/newline-above ()\n \"Inse"
},
{
"path": "modules/config/default/config.el",
"chars": 26047,
"preview": ";;; config/default/config.el -*- lexical-binding: t; -*-\n\n(defvar +default-want-RET-continue-comments t\n \"If non-nil, R"
},
{
"path": "modules/config/default/packages.el",
"chars": 376,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; config/default/packages.el\n\n(package! avy :pin \"933d1f36cca0f71e4acb5fac707e9ae26c536"
},
{
"path": "modules/config/literate/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/config/literate/README.org",
"chars": 4418,
"preview": "#+title: :config literate\n#+subtitle: Disguise your config as poor documentation\n#+created: May 28, 2020\n#+since: "
},
{
"path": "modules/config/literate/autoload.el",
"chars": 8411,
"preview": ";;; config/literate/autoload.el -*- lexical-binding: t; -*-\n\n;;;###autoload (add-hook 'org-mode-hook #'+literate-enable-"
},
{
"path": "modules/config/literate/cli.el",
"chars": 785,
"preview": ";;; config/literate/cli.el -*- lexical-binding: t; -*-\n\n(load! \"autoload\")\n\n(defun +literate-add-installed-org-to-load-p"
},
{
"path": "modules/config/use-package/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/config/use-package/init.el",
"chars": 8972,
"preview": ";;; config/use-package/init.el -*- lexical-binding: t; -*-\n;;; Commentary:\n;;\n;; In the near future, Doom will stop usin"
},
{
"path": "modules/config/use-package/packages.el",
"chars": 482,
"preview": ";; -*- no-byte-compile: t; -*-\n;;; core/use-package/packages.el\n\n(package! bind-key\n ;; HACK: bind-key-pkg.el in the em"
},
{
"path": "modules/editor/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/editor/README.org",
"chars": 241,
"preview": "#+title: :editor\n#+created: July 30, 2021\n#+since: 21.12.0\n\n* Description\nFor modules concerned with the insertion a"
},
{
"path": "modules/editor/evil/+commands.el",
"chars": 4957,
"preview": ";;; editor/evil/+commands.el -*- lexical-binding: t; -*-\n\n;;\n;;; Custom commands\n;; Editing\n(evil-ex-define-cmd \"@\" "
},
{
"path": "modules/editor/evil/.doommodule",
"chars": 0,
"preview": ""
},
{
"path": "modules/editor/evil/README.org",
"chars": 11953,
"preview": "#+title: :editor evil\n#+subtitle: The text editor Emacs was missing\n#+created: April 08, 2020\n#+since: 2.0.0\n\n* D"
}
]
// ... and 895 more files (download for full content)
About this extraction
This page contains the full source code of the doomemacs/doomemacs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1095 files (3.4 MB), approximately 948.8k tokens, and a symbol index with 5 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.