Merge branch 'develop' into add-keymap-description-for-ruby

This commit is contained in:
Henrik Lissner 2020-05-18 02:46:15 -04:00 committed by GitHub
commit 896cefb579
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
87 changed files with 2183 additions and 1611 deletions

View file

@ -23,7 +23,7 @@
- [Install](#install) - [Install](#install)
- [Roadmap](#roadmap) - [Roadmap](#roadmap)
- [Getting help](#getting-help) - [Getting help](#getting-help)
- [Contributing](#contributing) - [Contribute](#contribute)
# Introduction # Introduction

119
bin/doom
View file

@ -5,25 +5,28 @@
:; case "$VERSION" in *\ 2[0-5].[0-9]) echo "Detected Emacs $VERSION"; echo "Doom only supports Emacs 26.1 and newer"; echo; exit 2 ;; esac :; case "$VERSION" in *\ 2[0-5].[0-9]) echo "Detected Emacs $VERSION"; echo "Doom only supports Emacs 26.1 and newer"; echo; exit 2 ;; esac
:; DOOMBASE="$(dirname "$0")/.." :; DOOMBASE="$(dirname "$0")/.."
:; [ "$1" = -d ] || [ "$1" = --debug ] && { shift; export DEBUG=1; } :; [ "$1" = -d ] || [ "$1" = --debug ] && { shift; export DEBUG=1; }
:; [ "$1" = run ] && { cd "$DOOMBASE"; shift; exec $EMACS -q --no-splash -l bin/doom "$@"; exit 0; } :; [ "$1" = run ] && { cd "$DOOMBASE"; shift; exec $EMACS -q --no-splash -l init.el -f doom-run-all-startup-hooks-h "$@"; exit 0; }
:; exec $EMACS --no-site-file --script "$0" -- "$@" :; exec $EMACS --no-site-file --script "$0" -- "$@"
:; exit 0 :; exit 0
(let* ((load-prefer-newer t) (let* ((loaddir (file-name-directory (file-truename load-file-name)))
(loaddir (file-name-directory (file-truename load-file-name)))
(emacsdir (getenv "EMACSDIR")) (emacsdir (getenv "EMACSDIR"))
(user-emacs-directory (user-emacs-directory
(abbreviate-file-name (or emacsdir (expand-file-name "../" loaddir))))) (abbreviate-file-name
(if emacsdir
(file-name-as-directory emacsdir)
(expand-file-name "../" loaddir)))))
;;
(load (expand-file-name "core/core.el" user-emacs-directory) nil t)
;; HACK Load `cl' and site files manually so we can stop them from polluting ;; HACK Load `cl' and site files manually so we can stop them from polluting
;; CLI logs with deprecation and file load messages. ;; CLI logs with deprecation and file load messages.
(let ((inhibit-message t)) (quiet! (when (> emacs-major-version 26)
(when (> emacs-major-version 26) (require 'cl))
(require 'cl)) (load "site-start" t t))
(load "site-start" t t))
(push (expand-file-name "core" user-emacs-directory) load-path) (doom-log "Initializing Doom CLI")
(require 'core)
(require 'core-cli) (require 'core-cli)
(defcli! :main (defcli! :main
@ -45,10 +48,10 @@ with a different private module."
(setq user-emacs-directory (file-name-as-directory emacsdir)) (setq user-emacs-directory (file-name-as-directory emacsdir))
(print! (info "EMACSDIR=%s") localdir)) (print! (info "EMACSDIR=%s") localdir))
(when doomdir (when doomdir
(setenv "DOOMDIR" doomdir) (setenv "DOOMDIR" (file-name-as-directory doomdir))
(print! (info "DOOMDIR=%s") localdir)) (print! (info "DOOMDIR=%s") localdir))
(when localdir (when localdir
(setenv "DOOMLOCALDIR" localdir) (setenv "DOOMLOCALDIR" (file-name-as-directory localdir))
(print! (info "DOOMLOCALDIR=%s") localdir)) (print! (info "DOOMLOCALDIR=%s") localdir))
(when debug-p (when debug-p
(setenv "DEBUG" "1") (setenv "DEBUG" "1")
@ -75,54 +78,50 @@ with a different private module."
(when (or emacsdir doomdir localdir) (when (or emacsdir doomdir localdir)
(load! "core/core.el" user-emacs-directory)) (load! "core/core.el" user-emacs-directory))
(cond ((not noninteractive) (let (print-level print-gensym print-length)
(print! "Doom launched out of %s (test mode)" (path user-emacs-directory)) (condition-case e
(load! "init.el" user-emacs-directory) (if (null command)
(doom-run-all-startup-hooks-h)) (doom-cli-execute "help")
(let ((start-time (current-time)))
((null command) (and (doom-cli-execute command args)
(doom-cli-execute "help")) (print! (success "Finished! (%.4fs)")
(float-time
((condition-case e (time-subtract (current-time)
(let ((start-time (current-time))) start-time))))))
(and (doom-cli-execute command args) (user-error
(print! (success "Finished! (%.4fs)") (print! (error "%s\n") (error-message-string e))
(float-time (print! (yellow "See 'doom help %s' for documentation on this command.") (car args))
(time-subtract (current-time) (error "")) ; Ensure non-zero exit code
start-time))))) ((debug error)
(user-error (print! (error "There was an unexpected error:"))
(print! (error "%s\n") (error-message-string e)) (print-group!
(print! (yellow "See 'doom help %s' for documentation on this command.") (car args)) (print! "%s %s" (bold "Type:") (car e))
(error "")) ; Ensure non-zero exit code (print! (bold "Message:"))
((debug error) (print-group!
(print! (error "There was an unexpected error:")) (print! "%s" (get (car e) 'error-message)))
(print-group! (print! (bold "Data:"))
(print! "%s %s" (bold "Type:") (car e)) (print-group!
(print! (bold "Message:")) (if (cdr e)
(print-group! (dolist (item (cdr e))
(print! "%s" (get (car e) 'error-message))) (print! "%S" item))
(print! (bold "Data:")) (print! "n/a")))
(print-group! (when (and (bound-and-true-p straight-process-buffer)
(if (cdr e) (string-match-p (regexp-quote straight-process-buffer)
(dolist (item (cdr e)) (error-message-string e)))
(print! "%S" item)) (print! (bold "Straight output:"))
(print! "n/a"))) (print-group! (print! "%s" (straight--process-get-output)))))
(when (featurep 'straight) (unless debug-on-error
(when (string-match-p (regexp-quote straight-process-buffer) (terpri)
(error-message-string e)) (print!
(print! (bold "Straight output:")) (concat "Run the command again with the -d (or --debug) switch to enable debug\n"
(print-group! (print! "%s" (straight--process-get-output)))))) "mode and (hopefully) generate a backtrace from this error:\n"
(unless debug-on-error "\n %s\n\n"
(terpri) "If you file a bug report, please include it!")
(print! (string-join (append (list (file-name-nondirectory load-file-name) "-d" command)
(concat "Run the command again with the -d (or --debug) switch to enable debug\n" args)
"mode and (hopefully) generate a backtrace from this error:\n" " "))
"\n %s\n\n" ;; Ensure non-zero exit code
"If you file a bug report, please include it!") (error ""))))))
(string-join (append (list (file-name-nondirectory load-file-name) "-d" command)
args)
" "))
(error ""))))))) ; Ensure non-zero exit code
(doom-cli-execute :main (cdr (member "--" argv))) (doom-cli-execute :main (cdr (member "--" argv)))
(setq argv nil)) (setq argv nil))

View file

@ -55,14 +55,19 @@ And jumps to your `doom!' block."
(defmacro doom--if-compile (command on-success &optional on-failure) (defmacro doom--if-compile (command on-success &optional on-failure)
(declare (indent 2)) (declare (indent 2))
`(with-current-buffer (compile ,command) (let ((windowsym (make-symbol "doom-sync-window")))
(add-hook `(with-current-buffer (compile ,command t)
'compilation-finish-functions (let ((,windowsym (get-buffer-window (current-buffer))))
(lambda (_buf status) (select-window ,windowsym)
(if (equal status "finished\n") (add-hook
,on-success 'compilation-finish-functions
,on-failure)) (lambda (_buf status)
nil 'local))) (if (equal status "finished\n")
(progn
(delete-window ,windowsym)
,on-success)
,on-failure))
nil 'local)))))
;;;###autoload ;;;###autoload
(defun doom/reload () (defun doom/reload ()
@ -89,7 +94,7 @@ Runs `doom-reload-hook' afterwards."
(doom-initialize-modules 'force) (doom-initialize-modules 'force)
(general-auto-unbind-keys t))) (general-auto-unbind-keys t)))
(run-hook-wrapped 'doom-reload-hook #'doom-try-run-hook) (run-hook-wrapped 'doom-reload-hook #'doom-try-run-hook)
(print! (success "Config successfully reloaded!"))) (message "Config successfully reloaded!"))
(user-error "Failed to reload your config"))) (user-error "Failed to reload your config")))
;;;###autoload ;;;###autoload

View file

@ -1,5 +1,36 @@
;;; core/autoload/debug.el -*- lexical-binding: t; -*- ;;; core/autoload/debug.el -*- lexical-binding: t; -*-
;;
;;; Doom's debug mode
;;;###autoload
(defvar doom-debug-variables
'(doom-debug-mode
init-file-debug
debug-on-error
garbage-collection-messages
use-package-verbose
jka-compr-verbose
lsp-log-io
gcmh-verbose
magit-refresh-verbose
url-debug)
"A list of variable to toggle on `doom/toggle-debug-mode'.")
;;;###autoload
(defun doom/toggle-debug-mode (&optional arg)
"Toggle `debug-on-error' and `doom-debug-mode' for verbose logging."
(interactive (list (or current-prefix-arg 'toggle)))
(let ((value
(cond ((eq arg 'toggle) (not doom-debug-mode))
((> (prefix-numeric-value arg) 0)))))
(mapc (doom-rpartial #'set value) doom-debug-variables)
(message "Debug mode %s" (if value "on" "off"))))
;;
;;; Hooks
;;;###autoload ;;;###autoload
(defun doom-run-all-startup-hooks-h () (defun doom-run-all-startup-hooks-h ()
"Run all startup Emacs hooks. Meant to be executed after starting Emacs with "Run all startup Emacs hooks. Meant to be executed after starting Emacs with
@ -17,18 +48,12 @@
;; ;;
;;; Helpers ;;; Helpers
(defun doom-template-insert (template)
"TODO"
(let ((file (expand-file-name (format "templates/%s" template) doom-core-dir)))
(when (file-exists-p file)
(insert-file-contents file))))
(defsubst doom--collect-forms-in (file form) (defsubst doom--collect-forms-in (file form)
(when (file-readable-p file) (when (file-readable-p file)
(let (forms) (let (forms)
(with-temp-buffer (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(delay-mode-hooks (emacs-lisp-mode)) (let (emacs-lisp-mode) (emacs-lisp-mode))
(while (re-search-forward (format "(%s " (regexp-quote form)) nil t) (while (re-search-forward (format "(%s " (regexp-quote form)) nil t)
(let ((ppss (syntax-ppss))) (let ((ppss (syntax-ppss)))
(unless (or (nth 4 ppss) (unless (or (nth 4 ppss)
@ -45,7 +70,7 @@ ready to be pasted in a bug report on github."
(require 'vc-git) (require 'vc-git)
(require 'core-packages) (require 'core-packages)
(let ((default-directory doom-emacs-dir) (let ((default-directory doom-emacs-dir)
(doom-modules (doom-modules))) (doom-modules (doom-module-list)))
(letf! (defun sh (&rest args) (cdr (apply #'doom-call-process args))) (letf! (defun sh (&rest args) (cdr (apply #'doom-call-process args)))
`((emacs `((emacs
(version . ,emacs-version) (version . ,emacs-version)
@ -243,48 +268,62 @@ Some items are not supported by the `nsm.el' module."
(file (make-temp-file "doom-sandbox-"))) (file (make-temp-file "doom-sandbox-")))
(require 'package) (require 'package)
(with-temp-file file (with-temp-file file
(insert (prin1 `(progn
(prin1-to-string (setq noninteractive nil
(macroexp-progn process-environment ',doom--initial-process-environment
(append `((setq noninteractive nil exec-path ',doom--initial-exec-path
init-file-debug t init-file-debug t
load-path ',load-path load-path ',load-path
package--init-file-ensured t package--init-file-ensured t
package-user-dir ,package-user-dir package-user-dir ,package-user-dir
package-archives ',package-archives package-archives ',package-archives
user-emacs-directory ,doom-emacs-dir) user-emacs-directory ,doom-emacs-dir)
(with-eval-after-load 'undo-tree (with-eval-after-load 'undo-tree
;; undo-tree throws errors because `buffer-undo-tree' isn't ;; undo-tree throws errors because `buffer-undo-tree' isn't
;; corrrectly initialized ;; correctly initialized
(setq-default buffer-undo-tree (make-undo-tree)))) (setq-default buffer-undo-tree (make-undo-tree)))
(pcase mode (ignore-errors
(`vanilla-doom+ ; Doom core + modules - private config (delete-directory ,(expand-file-name "auto-save-list" doom-emacs-dir) 'parents)))
`((load-file ,(expand-file-name "core.el" doom-core-dir)) (current-buffer))
(doom-initialize) (prin1 `(unwind-protect
(doom-initialize-core) (defun --run-- () ,(read (concat "(progn\n" contents "\n)")))
(add-hook 'window-setup-hook #'doom-display-benchmark-h) (delete-file ,file))
(setq doom-modules ',doom-modules) (current-buffer))
(maphash (lambda (key plist) (prin1 (pcase mode
(let ((doom--current-module key) (`vanilla-doom+ ; Doom core + modules - private config
(doom--current-flags (plist-get plist :flags))) `(progn
(load! "init" (doom-module-locate-path (car key) (cdr key)) t))) (load-file ,(expand-file-name "core.el" doom-core-dir))
doom-modules) (setq doom-modules-dirs (list doom-modules-dir))
(maphash (lambda (key plist) (let ((doom-init-modules-p t))
(let ((doom--current-module key) (doom-initialize)
(doom--current-flags (plist-get plist :flags))) (doom-initialize-core-modules))
(load! "config" (doom-module-locate-path (car key) (cdr key)) t))) (setq doom-modules ',doom-modules)
doom-modules) (--run--)
(run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook) (maphash (lambda (key plist)
(doom-run-all-startup-hooks-h))) (let ((doom--current-module key)
(`vanilla-doom ; only Doom core (doom--current-flags (plist-get plist :flags)))
`((load-file ,(expand-file-name "core.el" doom-core-dir)) (load! "init" (doom-module-locate-path (car key) (cdr key)) t)))
(doom-initialize) doom-modules)
(doom-initialize-core) (maphash (lambda (key plist)
(doom-run-all-startup-hooks-h))) (let ((doom--current-module key)
(`vanilla ; nothing loaded (doom--current-flags (plist-get plist :flags)))
`((package-initialize))))))) (load! "config" (doom-module-locate-path (car key) (cdr key)) t)))
"\n(unwind-protect (progn\n" contents "\n)\n" doom-modules)
(format "(delete-file %S))" file))) (run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook)
(doom-run-all-startup-hooks-h)))
(`vanilla-doom ; only Doom core
`(progn
(load-file ,(expand-file-name "core.el" doom-core-dir))
(let ((doom-init-modules-p t))
(doom-initialize)
(doom-initialize-core-modules))
(--run--)
(doom-run-all-startup-hooks-h)))
(`vanilla ; nothing loaded
`(progn
(package-initialize)
(--run--))))
(current-buffer)))
(let ((args (if (eq mode 'doom) (let ((args (if (eq mode 'doom)
(list "-l" file) (list "-l" file)
(list "-Q" "-l" file)))) (list "-Q" "-l" file))))
@ -343,7 +382,7 @@ to reproduce bugs and determine if Doom is to blame."
(doom-sandbox-emacs-lisp-mode) (doom-sandbox-emacs-lisp-mode)
(setq-local default-directory doom-emacs-dir) (setq-local default-directory doom-emacs-dir)
(unless (buffer-live-p exists) (unless (buffer-live-p exists)
(doom-template-insert "VANILLA_SANDBOX") (insert-file-contents (doom-glob doom-core-dir "templates/VANILLA_SANDBOX"))
(let ((contents (substitute-command-keys (buffer-string)))) (let ((contents (substitute-command-keys (buffer-string))))
(erase-buffer) (erase-buffer)
(insert contents "\n"))) (insert contents "\n")))
@ -378,20 +417,3 @@ will be automatically appended to the result."
(profiler-report) (profiler-report)
(profiler-stop)) (profiler-stop))
(setq doom--profiler (not doom--profiler))) (setq doom--profiler (not doom--profiler)))
;;;###autoload
(defun doom/toggle-debug-mode (&optional arg)
"Toggle `debug-on-error' and `doom-debug-mode' for verbose logging."
(interactive (list (or current-prefix-arg 'toggle)))
(let ((value
(cond ((eq arg 'toggle) (not doom-debug-mode))
((> (prefix-numeric-value arg) 0)))))
(setq doom-debug-mode value
debug-on-error value
garbage-collection-messages value
use-package-verbose value
jka-compr-verbose value
lsp-log-io value
gcmh-verbose value
magit-refresh-verbose value)
(message "Debug mode %s" (if value "on" "off"))))

View file

@ -115,7 +115,8 @@ selection of all minor-modes, active or not."
(require 'org) (require 'org)
(let* ((default-directory doom-docs-dir) (let* ((default-directory doom-docs-dir)
(org-agenda-files (mapcar #'expand-file-name (doom-enlist files))) (org-agenda-files (mapcar #'expand-file-name (doom-enlist files)))
(depth (if (integerp depth) depth))) (depth (if (integerp depth) depth))
(org-inhibit-startup t))
(message "Loading search results...") (message "Loading search results...")
(unwind-protect (unwind-protect
(delq (delq
@ -218,7 +219,7 @@ selection of all minor-modes, active or not."
:prompt "Search documentation for: ")) :prompt "Search documentation for: "))
;;;###autoload ;;;###autoload
(defun doom/help-news-search (&optional initial-input) (defun doom/help-search-news (&optional initial-input)
"Search headlines in Doom's newsletters." "Search headlines in Doom's newsletters."
(interactive) (interactive)
(doom-completing-read-org-headings (doom-completing-read-org-headings
@ -427,8 +428,8 @@ If prefix arg is present, refresh the cache."
(let ((guess (or (function-called-at-point) (let ((guess (or (function-called-at-point)
(symbol-at-point)))) (symbol-at-point))))
(require 'finder-inf nil t) (require 'finder-inf nil t)
(require 'core-packages) (require 'package)
(doom-initialize-packages) (require 'straight)
(let ((packages (delete-dups (let ((packages (delete-dups
(append (mapcar #'car package-alist) (append (mapcar #'car package-alist)
(mapcar #'car package--builtins) (mapcar #'car package--builtins)
@ -503,7 +504,7 @@ If prefix arg is present, refresh the cache."
(modules (modules
(if (gethash (symbol-name package) straight--build-cache) (if (gethash (symbol-name package) straight--build-cache)
(doom-package-get package :modules) (doom-package-get package :modules)
(plist-get (cdr (assq package (doom-packages-list 'all))) (plist-get (cdr (assq package (doom-package-list 'all)))
:modules))) :modules)))
(package--print-help-section "Modules") (package--print-help-section "Modules")
(insert "Declared by the following Doom modules:\n") (insert "Declared by the following Doom modules:\n")

View file

@ -1,276 +1,5 @@
;;; core/autoload/packages.el -*- lexical-binding: t; -*- ;;; core/autoload/packages.el -*- lexical-binding: t; -*-
;;
;;; Package metadata
;;;###autoload
(defun doom-package-get (package &optional prop nil-value)
"Returns PACKAGE's `package!' recipe from `doom-packages'."
(let ((plist (cdr (assq package doom-packages))))
(if prop
(if (plist-member plist prop)
(plist-get plist prop)
nil-value)
plist)))
;;;###autoload
(defun doom-package-set (package prop value)
"Set PROPERTY in PACKAGE's recipe to VALUE."
(setf (alist-get package doom-packages)
(plist-put (alist-get package doom-packages)
prop value)))
;;;###autoload
(defun doom-package-recipe (package &optional prop nil-value)
"Returns the `straight' recipe PACKAGE was registered with."
(let ((plist (gethash (symbol-name package) straight--recipe-cache)))
(if prop
(if (plist-member plist prop)
(plist-get plist prop)
nil-value)
plist)))
;;;###autoload
(defun doom-package-recipe-repo (package)
"Resolve and return PACKAGE's (symbol) local-repo property."
(if-let* ((recipe (cdr (straight-recipes-retrieve package)))
(repo (straight-vc-local-repo-name recipe)))
repo
(symbol-name package)))
;;;###autoload
(defun doom-package-build-recipe (package &optional prop nil-value)
"Returns the `straight' recipe PACKAGE was installed with."
(let ((plist (nth 2 (gethash (symbol-name package) straight--build-cache))))
(if prop
(if (plist-member plist prop)
(plist-get plist prop)
nil-value)
plist)))
;;;###autoload
(defun doom-package-build-time (package)
"TODO"
(car (gethash (symbol-name package) straight--build-cache)))
;;;###autoload
(defun doom-package-dependencies (package &optional recursive _noerror)
"Return a list of dependencies for a package."
(let ((deps (nth 1 (gethash (symbol-name package) straight--build-cache))))
(if recursive
(nconc deps (mapcan (lambda (dep) (doom-package-dependencies dep t t))
deps))
deps)))
;;;###autoload
(defun doom-package-depending-on (package &optional noerror)
"Return a list of packages that depend on the package named NAME."
(cl-check-type name symbol)
;; can't get dependencies for built-in packages
(unless (or (doom-package-build-recipe name)
noerror)
(error "Couldn't find %s, is it installed?" name))
(cl-loop for pkg in (hash-table-keys straight--build-cache)
for deps = (doom-package-dependencies pkg)
if (memq package deps)
collect pkg
and append (doom-package-depending-on pkg t)))
;;
;;; Predicate functions
;;;###autoload
(defun doom-package-built-in-p (package)
"Return non-nil if PACKAGE (a symbol) is built-in."
(eq (doom-package-build-recipe package :type)
'built-in))
;;;###autoload
(defun doom-package-installed-p (package)
"Return non-nil if PACKAGE (a symbol) is installed."
(file-directory-p (straight--build-dir (symbol-name package))))
;;;###autoload
(defun doom-package-registered-p (package)
"Return non-nil if PACKAGE (a symbol) has been registered with `package!'.
Excludes packages that have a non-nil :built-in property."
(when-let (plist (doom-package-get package))
(not (plist-get plist :ignore))))
;;;###autoload
(defun doom-package-private-p (package)
"Return non-nil if PACKAGE was installed by the user's private config."
(assq :private (doom-package-get package :modules)))
;;;###autoload
(defun doom-package-protected-p (package)
"Return non-nil if PACKAGE is protected.
A protected package cannot be deleted and will be auto-installed if missing."
(memq package doom-core-packages))
;;;###autoload
(defun doom-package-core-p (package)
"Return non-nil if PACKAGE is a core Doom package."
(or (doom-package-protected-p package)
(assq :core (doom-package-get package :modules))))
;;;###autoload
(defun doom-package-backend (package)
"Return 'straight, 'builtin, 'elpa or 'other, depending on how PACKAGE is
installed."
(cond ((gethash (symbol-name package) straight--build-cache)
'straight)
((or (doom-package-built-in-p package)
(assq package package--builtins))
'builtin)
((assq package package-alist)
'elpa)
((locate-library (symbol-name package))
'other)))
;;;###autoload
(defun doom-package-different-recipe-p (name)
"Return t if a package named NAME (a symbol) has a different recipe than it
was installed with."
(cl-check-type name symbol)
;; TODO
;; (when (doom-package-installed-p name)
;; (when-let* ((doom-recipe (assq name doom-packages))
;; (install-recipe (doom-package-recipe)))
;; (not (equal (cdr quelpa-recipe)
;; (cdr (plist-get (cdr doom-recipe) :recipe))))))
)
;;
;;; Package list getters
(defun doom--read-module-packages-file (file &optional noeval noerror)
(with-temp-buffer ; prevent buffer-local settings from propagating
(condition-case e
(if (not noeval)
(load file noerror t t)
(when (file-readable-p file)
(insert-file-contents file)
(delay-mode-hooks (emacs-lisp-mode))
(while (search-forward "(package! " nil t)
(save-excursion
(goto-char (match-beginning 0))
(unless (let ((ppss (syntax-ppss)))
(or (nth 3 ppss)
(nth 4 ppss)))
(cl-destructuring-bind (name . plist)
(cdr (sexp-at-point))
(push (cons
name (plist-put
plist :modules
(list (doom-module-from-path file))))
doom-packages)))))))
((debug error)
(signal 'doom-package-error
(list (doom-module-from-path file)
file
e))))))
;;;###autoload
(defun doom-package-list (&optional all-p)
"Retrieve a list of explicitly declared packages from enabled modules.
This excludes core packages listed in `doom-core-packages'.
If ALL-P, gather packages unconditionally across all modules, including disabled
ones."
(let ((doom-interactive-mode t)
(doom-modules (doom-modules))
doom-packages)
(doom--read-module-packages-file
(doom-path doom-core-dir "packages.el") all-p t)
(let ((private-packages (doom-path doom-private-dir "packages.el")))
(unless all-p
;; We load the private packages file twice to ensure disabled packages
;; are seen ASAP, and a second time to ensure privately overridden
;; packages are properly overwritten.
(doom--read-module-packages-file private-packages nil t))
(if all-p
(mapc #'doom--read-module-packages-file
(doom-files-in doom-modules-dir
:depth 2
:match "/packages\\.el$"))
(cl-loop for key being the hash-keys of doom-modules
for path = (doom-module-path (car key) (cdr key) "packages.el")
for doom--current-module = key
do (doom--read-module-packages-file path nil t)))
(doom--read-module-packages-file private-packages all-p t))
(nreverse doom-packages)))
;;;###autoload
(defun doom-package-pinned-list ()
"Return an alist mapping package names (strings) to pinned commits (strings)."
(let (alist)
(dolist (package doom-packages alist)
(cl-destructuring-bind (name &key disable ignore pin unpin &allow-other-keys)
package
(when (and (not ignore)
(not disable)
(or pin unpin))
(setf (alist-get (doom-package-recipe-repo name) alist
nil 'remove #'equal)
(unless unpin pin)))))))
;;;###autoload
(defun doom-package-unpinned-list ()
"Return an alist mapping package names (strings) to pinned commits (strings)."
(let (alist)
(dolist (package doom-packages alist)
(cl-destructuring-bind
(_ &key recipe disable ignore pin unpin &allow-other-keys)
package
(when (and (not ignore)
(not disable)
(or unpin
(and (plist-member recipe :pin)
(null pin))))
(cl-pushnew (doom-package-recipe-repo (car package)) alist
:test #'equal))))))
;;;###autoload
(defun doom-package-recipe-list ()
"Return straight recipes for non-builtin packages with a local-repo."
(let (recipes)
(dolist (recipe (hash-table-values straight--recipe-cache))
(cl-destructuring-bind (&key local-repo type no-build &allow-other-keys)
recipe
(unless (or (null local-repo)
(eq type 'built-in)
no-build)
(push recipe recipes))))
(nreverse recipes)))
;;;###autoload
(defmacro doom-with-package-recipes (recipes binds &rest body)
"TODO"
(declare (indent 2))
(let ((recipe-var (make-symbol "recipe"))
(recipes-var (make-symbol "recipes")))
`(let* ((,recipes-var ,recipes)
(built ())
(straight-use-package-pre-build-functions
(cons (lambda (pkg) (cl-pushnew pkg built :test #'equal))
straight-use-package-pre-build-functions)))
(dolist (,recipe-var ,recipes-var)
(cl-block nil
(straight--with-plist (append (list :recipe ,recipe-var) ,recipe-var)
,(doom-enlist binds)
,@body)))
(nreverse built))))
;;
;;; Main functions
;;;###autoload ;;;###autoload
(defun doom/reload-packages () (defun doom/reload-packages ()
"Reload `doom-packages', `package' and `quelpa'." "Reload `doom-packages', `package' and `quelpa'."
@ -280,47 +9,192 @@ ones."
(doom-initialize-packages t) (doom-initialize-packages t)
(message "Reloading packages...DONE")) (message "Reloading packages...DONE"))
;;;###autoload
(defun doom/update-pinned-package-form (&optional select)
"Inserts or updates a `:pin' for the `package!' statement at point.
;;
;;; Bump commands
(defun doom--package-full-recipe (package plist)
(doom-plist-merge
(plist-get plist :recipe)
(or (cdr (straight-recipes-retrieve package))
(plist-get (cdr (assq package doom-packages))
:recipe))))
(defun doom--package-to-bump-string (package plist)
"Return a PACKAGE and its PLIST in 'username/repo@commit' format."
(format "%s@%s"
(plist-get (doom--package-full-recipe package plist) :repo)
(substring-no-properties (plist-get plist :pin) 0 7)))
(defun doom--package-at-point (&optional point)
"Return the package and plist from the (package! PACKAGE PLIST...) at point."
(save-match-data
(save-excursion
(and point (goto-char point))
(if (eq (sexp-at-point) 'package!)
(progn
(backward-sexp)
(backward-char)
t)
(while (and (search-backward "(package!" nil t)
(doom-point-in-string-or-comment-p))))
(unless (or (doom-point-in-string-or-comment-p)
(not (eq (car-safe (sexp-at-point)) 'package!)))
(cl-destructuring-bind (beg . end)
(bounds-of-thing-at-point 'sexp)
(let ((package (let (doom-packages)
(eval (sexp-at-point) t))))
(list :beg beg
:end end
:package (car package)
:plist (cdr package))))))))
;;;###autoload
(defun doom/bumpify-package-at-point ()
"Convert `package!' call at point to a bump string."
(interactive)
(cl-destructuring-bind (&key package plist beg end)
(doom--package-at-point)
(when-let (str (doom--package-to-bump-string package plist))
(goto-char beg)
(delete-region beg end)
(insert str))))
;;;###autoload
(defun doom/bumpify-packages-in-buffer ()
"Convert all `package!' calls in buffer into bump strings."
(interactive)
(save-excursion
(goto-char (point-min))
(while (search-forward "(package!" nil t)
(unless (doom-point-in-string-or-comment-p)
(doom/bumpify-package-at-point)))))
;;;###autoload
(defun doom/bump-package-at-point (&optional select)
"Inserts or updates a `:pin' for the `package!' statement at point.
Grabs the latest commit id of the package using 'git'."
(interactive "P")
(doom-initialize-packages)
(cl-destructuring-bind (&key package plist beg end)
(or (doom--package-at-point)
(user-error "Not on a `package!' call"))
(let* ((recipe (doom--package-full-recipe package plist))
(branch (or (plist-get recipe :branch)
straight-vc-git-default-branch))
(oldid (or (plist-get plist :pin)
(doom-package-get package :pin)))
id url)
(when (or (eq (plist-get plist :built-in) t)
(and (eq (plist-get plist :built-in) 'prefer)
(locate-library (symbol-name package))))
(user-error "%s: skipping built-in package" package))
(setq url (straight-vc-git--destructure recipe (upstream-repo upstream-host)
(straight-vc-git--encode-url upstream-repo upstream-host))
id (when url
(cdr (doom-call-process
"git" "ls-remote" url
(unless select
(or branch straight-vc-git-default-branch))))))
(unless id
(user-error "%s: no id from %s" package url))
(let* ((id (car (split-string
(if select
(completing-read "Commit: " (split-string id "\n" t))
id)))))
(when (and oldid (equal oldid id))
(user-error "%s: no update necessary" package))
(save-excursion
(if (re-search-forward ":pin +\"\\([^\"]+\\)\"" end t)
(replace-match id t t nil 1)
(thing-at-point--end-of-sexp)
(backward-char)
(insert " :pin " (prin1-to-string id))))
(message "Updated %S: %s -> %s"
package
(substring oldid 0 10)
(substring id 0 10))))))
;;;###autoload
(defun doom/bump-packages-in-buffer (&optional select)
"Inserts or updates a `:pin' for the `package!' statement at point.
Grabs the latest commit id of the package using 'git'." Grabs the latest commit id of the package using 'git'."
(interactive "P") (interactive "P")
;; REVIEW Better error handling
;; TODO Insert a new `package!' if no `package!' at poin
(require 'straight)
(ignore-errors
(while (and (atom (sexp-at-point))
(not (bolp)))
(forward-sexp -1)))
(save-excursion (save-excursion
(if (not (eq (sexp-at-point) 'package!)) (goto-char (point-min))
(user-error "Not on a `package!' call") (doom-initialize-packages)
(backward-char) (let (packages)
(let* ((recipe (cdr (sexp-at-point))) (while (search-forward "(package! " nil t)
(package (car recipe)) (unless (let ((ppss (syntax-ppss)))
(oldid (doom-package-get package :pin)) (or (nth 4 ppss)
(id (nth 3 ppss)
(cdr (doom-call-process (save-excursion
"git" "ls-remote" (and (goto-char (match-beginning 0))
(straight-vc-git--destructure (not (plist-member (sexp-at-point) :pin))))))
(doom-plist-merge (condition-case e
(plist-get (cdr recipe) :recipe) (push (doom/bump-package-at-point) packages)
(or (cdr (straight-recipes-retrieve package)) (user-error (message "%s" (error-message-string e))))))
(plist-get (cdr (assq package doom-packages)) :recipe))) (if packages
(upstream-repo upstream-host) (message "Updated %d packages\n- %s" (length packages) (string-join packages "\n- "))
(straight-vc-git--encode-url upstream-repo upstream-host)))))) (message "No packages to update")))))
(unless id
(user-error "No id for %S package" package)) ;;;###autoload
(let* ((id (if select (defun doom/bump-module (category &optional module select)
(car (split-string (completing-read "Commit: " (split-string id "\n" t)))) "Bump packages in CATEGORY MODULE.
(car (split-string id)))) If SELECT (prefix arg) is non-nil, prompt you to choose a specific commit for
(id (substring id 0 10))) each package."
(if (and oldid (string-match-p (concat "^" oldid) id)) (interactive
(user-error "No update necessary") (let* ((module (completing-read
(if (re-search-forward ":pin +\"\\([^\"]+\\)\"" (cdr (bounds-of-thing-at-point 'sexp)) t) "Bump module: "
(replace-match id t t nil 1) (let ((modules (cons (list :core) (doom-module-list 'all))))
(thing-at-point--end-of-sexp) (mapcar (lambda (m)
(backward-char) (if (listp m)
(insert " :pin " (prin1-to-string id))) (format "%s %s" (car m) (cdr m))
(message "Updated %S: %s -> %s" package oldid id))))))) (format "%s" m)))
(append (list ":private")
(delete-dups (mapcar #'car modules))
modules)))
nil t nil nil))
(module (split-string module " " t)))
(list (intern (car module))
(ignore-errors (intern (cadr module)))
current-prefix-arg)))
(mapc (lambda (module)
(if-let (packages-file
(pcase category
(:private (doom-glob doom-private-dir "packages.el"))
(:core (doom-glob doom-core-dir "packages.el"))
(_ (doom-module-locate-path category module "packages.el"))))
(with-current-buffer
(or (get-file-buffer packages-file)
(find-file-noselect packages-file))
(doom/bump-packages-in-buffer select)
(save-buffer))
(message "Module %s has no packages.el file" (cons category module))))
(if module
(list (cons category module))
(cl-remove-if-not (lambda (m) (eq (car m) category))
(cons (list :core) (doom-module-list 'all))))))
;;;###autoload
(defun doom/bump-package (package)
"Bump PACKAGE in all modules that install it."
(interactive
(list (completing-read "Bump package: "
(mapcar #'car (doom-package-list 'all)))))
(let* ((packages (doom-package-list 'all))
(modules (plist-get (alist-get package packages) :modules)))
(unless modules
(user-error "This package isn't installed by any Doom module"))
(dolist (module modules)
(when-let (packages-file (doom-module-locate-path (car module) (cdr module)))
(doom/bump-module (car module) (cdr module))))))
;;
;;; Bump commits
;;;###autoload
(defun doom/commit-bumps ()
(interactive))

View file

@ -35,24 +35,6 @@ list, the pair is destructured into (CAR . CDR)."
"Delete PROP from PLIST in-place." "Delete PROP from PLIST in-place."
`(setq ,plist (doom-plist-delete ,plist ,prop))) `(setq ,plist (doom-plist-delete ,plist ,prop)))
;;;###autoload
(defmacro with-plist! (plist props &rest body)
"With props bound from PLIST to PROPS, evaluate BODY.
PROPS is a list of symbols. Each one is converted to a keyword and then its
value is looked up in the PLIST and bound to the symbol for the duration of
BODY."
(declare (indent 2))
(let ((plist-sym (make-symbol "plist")))
`(let* ((,plist-sym ,plist)
,@(cl-loop for prop in props
collect
`(,prop
(plist-get
,plist-sym
,(doom-keyword-intern (symbol-name prop))))))
,@body)))
;; ;;
;;; Library ;;; Library

View file

@ -1,7 +1,4 @@
;;; core/autoload/cli.el -*- lexical-binding: t; -*- ;;; core/autoload/process.el -*- lexical-binding: t; -*-
;;
;;; Library
;;;###autoload ;;;###autoload
(defun doom-call-process (command &rest args) (defun doom-call-process (command &rest args)
@ -10,7 +7,7 @@
Returns (STATUS . OUTPUT) when it is done, where STATUS is the returned error Returns (STATUS . OUTPUT) when it is done, where STATUS is the returned error
code of the process and OUTPUT is its stdout output." code of the process and OUTPUT is its stdout output."
(with-temp-buffer (with-temp-buffer
(cons (or (apply #'call-process command nil t nil args) (cons (or (apply #'call-process command nil t nil (remq nil args))
-1) -1)
(string-trim (buffer-string))))) (string-trim (buffer-string)))))
@ -28,7 +25,7 @@ Warning: freezes indefinitely on any stdin prompt."
(cons (let ((process (cons (let ((process
(make-process :name "doom-sh" (make-process :name "doom-sh"
:buffer (current-buffer) :buffer (current-buffer)
:command (cons command args) :command (cons command (remq nil args))
:connection-type 'pipe)) :connection-type 'pipe))
done-p) done-p)
(set-process-filter (set-process-filter

View file

@ -71,6 +71,9 @@
"TODO" "TODO"
(add-hook 'window-setup-hook #'doom-load-session 'append)) (add-hook 'window-setup-hook #'doom-load-session 'append))
;;;###autoload
(add-to-list 'command-switch-alist (cons "--restore" #'doom-restore-session-handler))
;; ;;
;;; Commands ;;; Commands

View file

@ -2,7 +2,9 @@
(defcli! (compile c) (defcli! (compile c)
((recompile-p ["-r" "--recompile"]) ((recompile-p ["-r" "--recompile"])
&rest targets) (core-p ["-c" "--core"])
(private-p ["-p" "--private"])
(verbose-p ["-v" "--verbose"]))
"Byte-compiles your config or selected modules. "Byte-compiles your config or selected modules.
compile [TARGETS...] compile [TARGETS...]
@ -11,8 +13,23 @@
Accepts :core and :private as special arguments, which target Doom's core files Accepts :core and :private as special arguments, which target Doom's core files
and your private config files, respectively. To recompile your packages, use and your private config files, respectively. To recompile your packages, use
'doom rebuild' instead." 'doom build' instead."
(doom-cli-byte-compile targets recompile-p)) (doom-cli-byte-compile
(if (or core-p private-p)
(append (when core-p
(list (doom-glob doom-emacs-dir "init.el")
doom-core-dir))
(when private-p
(list doom-private-dir)))
(append (list (doom-glob doom-emacs-dir "init.el")
doom-core-dir)
(cl-remove-if-not
;; Only compile Doom's modules
(lambda (path) (file-in-directory-p path doom-emacs-dir))
;; Omit `doom-private-dir', which is always first
(cdr (doom-module-load-path)))))
recompile-p
verbose-p))
(defcli! clean () (defcli! clean ()
"Delete all *.elc files." "Delete all *.elc files."
@ -25,17 +42,20 @@ and your private config files, respectively. To recompile your packages, use
(defun doom--byte-compile-ignore-file-p (path) (defun doom--byte-compile-ignore-file-p (path)
(let ((filename (file-name-nondirectory path))) (let ((filename (file-name-nondirectory path)))
(or (string-prefix-p "." filename) (or (not (equal (file-name-extension path) "el"))
(member filename (list "packages.el" "doctor.el"))
(string-prefix-p "." filename)
(string-prefix-p "test-" filename) (string-prefix-p "test-" filename)
(string-suffix-p ".example.el" filename) (string-prefix-p "flycheck_" filename)
(not (equal (file-name-extension path) "el")) (string-suffix-p ".example.el" filename))))
(member filename (list "packages.el" "doctor.el")))))
(cl-defun doom-cli-byte-compile (&optional modules recompile-p) (cl-defun doom-cli-byte-compile (&optional targets recompile-p verbose-p)
"Byte compiles your emacs configuration. "Byte compiles your emacs configuration.
init.el is always byte-compiled by this. init.el is always byte-compiled by this.
If TARGETS is specified, as a list of direcotries
If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are
byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom
core. It always ignores unit tests and files with `no-byte-compile' enabled. core. It always ignores unit tests and files with `no-byte-compile' enabled.
@ -48,138 +68,109 @@ Use `doom-clean-byte-compiled-files' or `make clean' to reverse
byte-compilation. byte-compilation.
If RECOMPILE-P is non-nil, only recompile out-of-date files." If RECOMPILE-P is non-nil, only recompile out-of-date files."
(let ((default-directory doom-emacs-dir) (let* ((default-directory doom-emacs-dir)
(doom-modules (doom-modules)) (targets (nreverse (delete-dups targets)))
(byte-compile-verbose doom-debug-mode) ;; In case it is changed during compile-time
(byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) (auto-mode-alist auto-mode-alist)
kill-emacs-hook kill-buffer-query-functions)
;; In case it is changed during compile-time
(auto-mode-alist auto-mode-alist)
(noninteractive t)
targets)
(let (target-dirs)
(dolist (module (delete-dups modules))
(pcase module
(":core"
(push (doom-glob doom-emacs-dir "init.el") targets)
(push doom-core-dir target-dirs))
(":private"
(push doom-private-dir target-dirs))
((pred file-directory-p)
(push module target-dirs))
((pred (string-match "^\\([^/]+\\)/\\([^/]+\\)$"))
(push (doom-module-locate-path
(doom-keyword-intern (match-string 1 module))
(intern (match-string 2 module)))
target-dirs))
(_ (user-error "%S is not a valid target" module))))
(and (or (null modules) (member ":private" modules))
(not recompile-p)
(not (or doom-auto-accept
(y-or-n-p
(concat "Warning: byte compiling is for advanced users. It will interfere with your\n"
"efforts to debug issues. It is not recommended you do it if you frequently\n"
"tinker with your Emacs config.\n\n"
"Alternatively, use `bin/doom compile :core` instead to byte-compile only the\n"
"Doom core files, as these don't change often.\n\n"
"If you have issues, please make sure byte-compilation isn't the cause by using\n"
"`bin/doom clean` to clear out your *.elc files.\n\n"
"Byte-compile anyway?"))))
(user-error "Aborting"))
(let ((after-load-functions
(if (null targets)
after-load-functions
;; Assemble el files we want to compile, and preserve in the order
;; they are loaded in, so we don't run into any scary catch-22s
;; while byte-compiling, like missing macros.
(cons (let ((target-dirs (cl-remove-if-not #'file-directory-p targets)))
(lambda (path)
(and (not (doom--byte-compile-ignore-file-p path))
(cl-find-if (doom-partial #'file-in-directory-p path)
target-dirs)
(cl-pushnew path targets))))
after-load-functions))))
(doom-log "Reloading Doom in preparation for byte-compilation")
;; But first we must be sure that Doom and your private config have been ;; But first we must be sure that Doom and your private config have been
;; fully loaded. Which usually aren't so in an noninteractive session. ;; fully loaded. Which usually aren't so in an noninteractive session.
(let ((doom-interactive-mode 'byte-compile)) (let ((load-prefer-newer t)
(doom-initialize) (noninteractive t)
(doom-initialize-packages) doom-interactive-mode)
(doom-initialize-core)) (doom-initialize 'force)
(quiet! (doom-initialize-packages))))
;; (if (null targets)
(unless target-dirs (print! (info "No targets to %scompile" (if recompile-p "re" "")))
(push (doom-glob doom-emacs-dir "init.el") targets) (print! (start "%scompiling your config...")
;; If no targets were supplied, then we use your module list. (if recompile-p "Re" "Byte-"))
(appendq! target-dirs
(list doom-core-dir)
(nreverse
(cl-remove-if-not
(lambda (path) (file-in-directory-p path doom-emacs-dir))
;; Omit `doom-private-dir', which is always first
(cdr (doom-module-load-path))))))
;; Assemble el files we want to compile; taking into account that MODULES (dolist (dir
;; may be a list of MODULE/SUBMODULE strings from the command line. (cl-remove-if-not #'file-directory-p targets)
(appendq! targets (setq targets (cl-remove-if #'file-directory-p targets)))
(doom-files-in target-dirs (prependq! targets
:match "\\.el$" (doom-files-in
:filter #'doom--byte-compile-ignore-file-p))) dir :match "\\.el" :filter #'doom--byte-compile-ignore-file-p)))
(unless targets (print-group!
(print! (require 'use-package)
(if targets (condition-case-unless-debug e
(warn "Couldn't find any valid targets") (let* ((total-ok 0)
(info "No targets to %scompile" (if recompile-p "re" "")))) (total-fail 0)
(cl-return nil)) (total-noop 0)
(byte-compile-verbose nil)
(print! (byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local))
(start (if recompile-p (byte-compile-dynamic-docstrings t)
"Recompiling stale elc files..." (use-package-compute-statistics nil)
"Byte-compiling your config (may take a while)..."))) (use-package-defaults use-package-defaults)
(print-group! (use-package-expand-minimally t)
(require 'use-package) (targets (delete-dups targets))
(condition-case e (modules (seq-group-by #'doom-module-from-path targets))
(let ((total-ok 0) (total-files (length targets))
(total-fail 0) (total-modules (length modules))
(total-noop 0) (i 0)
(use-package-defaults use-package-defaults) last-module)
(use-package-expand-minimally t) ;; Prevent packages from being loaded at compile time if they
kill-emacs-hook kill-buffer-query-functions) ;; don't meet their own predicates.
;; Prevent packages from being loaded at compile time if they (push (list :no-require t
;; don't meet their own predicates. (lambda (_name args)
(push (list :no-require t (or (when-let (pred (or (plist-get args :if)
(lambda (_name args) (plist-get args :when)))
(or (when-let (pred (or (plist-get args :if) (not (eval pred t)))
(plist-get args :when))) (when-let (pred (plist-get args :unless))
(not (eval pred t))) (eval pred t)))))
(when-let (pred (plist-get args :unless)) use-package-defaults)
(eval pred t))))) (dolist (module-files modules)
use-package-defaults) (cl-incf i)
(dolist (target (cdr module-files))
(unless recompile-p (let ((elc-file (byte-compile-dest-file target)))
(doom-clean-byte-compiled-files)) (cl-incf
(if (and recompile-p (not (file-newer-than-file-p target elc-file)))
(dolist (target (delete-dups (delq nil targets))) total-noop
(cl-incf (pcase (if (not (doom-file-cookie-p target "if" t))
(if (not (or (not recompile-p) 'no-byte-compile
(let ((elc-file (byte-compile-dest-file target))) (unless (equal last-module (car module-files))
(and (file-exists-p elc-file) (print! (success "(% 3d/%d) Compiling %s %s module...")
(file-newer-than-file-p target elc-file))))) i total-modules (caar module-files) (cdar module-files))
total-noop (setq last-module (car module-files)))
(pcase (if (doom-file-cookie-p target "if" t) (if verbose-p
(byte-compile-file target) (byte-compile-file target)
'no-byte-compile) (quiet! (byte-compile-file target))))
(`no-byte-compile (`no-byte-compile
(print! (info "Ignored %s") (relpath target)) (print! (debug "(% 3d/%d) Ignored %s")
total-noop) i total-modules (relpath target))
(`nil total-noop)
(print! (error "Failed to compile %s") (relpath target)) (`nil
total-fail) (print! (error "(% 3d/%d) Failed to compile %s")
(_ i total-modules (relpath target))
(print! (success "Compiled %s") (relpath target)) total-fail)
(load target t t) (_ total-ok)))))))
total-ok))))) (print! (class (if (= total-fail 0) 'success 'warn)
(print! (class (if (= total-fail 0) 'success 'error) "%s %d/%d file(s) (%d ignored)")
"%s %d/%d file(s) (%d ignored)") (if recompile-p "Recompiled" "Byte-compiled")
(if recompile-p "Recompiled" "Compiled") total-ok total-files
total-ok (- (length targets) total-noop) total-noop)
total-noop) (= total-fail 0))
t) ((debug error)
((debug error) (print! (error "There were breaking errors.\n\n%s")
(print! (error "\nThere were breaking errors.\n\n%s") "Reverting changes...")
"Reverting changes...") (signal 'doom-error (list 'byte-compile e))))))))
(signal 'doom-error (list 'byte-compile e)))))))
(defun doom-clean-byte-compiled-files () (defun doom-clean-byte-compiled-files ()
"Delete all the compiled elc files in your Emacs configuration and private "Delete all the compiled elc files in your Emacs configuration and private
@ -188,7 +179,8 @@ module. This does not include your byte-compiled, third party packages.'"
(print! (start "Cleaning .elc files")) (print! (start "Cleaning .elc files"))
(print-group! (print-group!
(cl-loop with default-directory = doom-emacs-dir (cl-loop with default-directory = doom-emacs-dir
with success = nil with success = 0
with esc = (if doom-debug-mode "" "\033[1A")
for path for path
in (append (doom-glob doom-emacs-dir "*.elc") in (append (doom-glob doom-emacs-dir "*.elc")
(doom-files-in doom-private-dir :match "\\.elc$" :depth 1) (doom-files-in doom-private-dir :match "\\.elc$" :depth 1)
@ -196,10 +188,10 @@ module. This does not include your byte-compiled, third party packages.'"
(doom-files-in doom-modules-dirs :match "\\.elc$" :depth 4)) (doom-files-in doom-modules-dirs :match "\\.elc$" :depth 4))
if (file-exists-p path) if (file-exists-p path)
do (delete-file path) do (delete-file path)
and do (print! (success "Deleted %s") (relpath path)) and do (print! (success "\033[KDeleted %s%s") (relpath path) esc)
and do (setq success t) and do (cl-incf success)
finally do finally do
(print! (if success (print! (if (> success 0)
(success "All elc files deleted") (success "\033[K%d elc files deleted" success)
(info "No elc files to clean")))) (info "\033[KNo elc files to clean"))))
t)) t))

View file

@ -1,10 +1,12 @@
;;; core/cli/debug.el -*- lexical-binding: t; -*- ;;; core/cli/debug.el -*- lexical-binding: t; -*-
(load! "autoload/debug" doom-core-dir)
;; ;;
;;; Commands ;;; Commands
(defcli! info (defcli! info
((format ["--json" "--md" "--lisp"] "What format to dump info into")) ((format ["--json" "--md" "--lisp"] "What format to dump info into"))
"Output system info in markdown for bug reports." "Output system info in markdown for bug reports."
(pcase format (pcase format
("--json" ("--json"
@ -24,6 +26,5 @@
(defcli! (version v) () (defcli! (version v) ()
"Show version information for Doom & Emacs." "Show version information for Doom & Emacs."
:bare t
(doom/version) (doom/version)
nil) nil)

View file

@ -48,8 +48,8 @@ in."
;; REVIEW Refactor me ;; REVIEW Refactor me
(print! (start "Checking your Emacs version...")) (print! (start "Checking your Emacs version..."))
(when EMACS27+ (when EMACS28+
(warn! "Emacs %s detected. Emacs HEAD is unstable and may cause errors." (warn! "Emacs %s detected. Doom doesn't support Emacs 28/HEAD. It is unstable and may cause errors."
emacs-version)) emacs-version))
(print! (start "Checking for Emacs config conflicts...")) (print! (start "Checking for Emacs config conflicts..."))
@ -81,7 +81,6 @@ in."
(print-group! (print-group!
(let ((doom-interactive-mode 'doctor)) (let ((doom-interactive-mode 'doctor))
(doom-initialize 'force) (doom-initialize 'force)
(doom-initialize-core)
(doom-initialize-modules)) (doom-initialize-modules))
(print! (success "Initialized Doom Emacs %s") doom-version) (print! (success "Initialized Doom Emacs %s") doom-version)
@ -133,14 +132,21 @@ in."
(`darwin "~/Library/Fonts/")) (`darwin "~/Library/Fonts/"))
(require 'all-the-icons nil t)) (require 'all-the-icons nil t))
(with-temp-buffer (with-temp-buffer
(insert (cdr (doom-call-process "fc-list" "" "file"))) (let ((errors 0))
(dolist (font all-the-icons-font-names) (cl-destructuring-bind (status . output)
(if (save-excursion (re-search-backward font nil t)) (doom-call-process "fc-list" "" "file")
(success! "Found font %s" font) (if (not (zerop status))
(print! (warn "Warning: couldn't find %S font") font) (print! (error "There was an error running `fc-list'. Is fontconfig installed correctly?"))
(explain! "You can install it by running `M-x all-the-icons-install-fonts' within Emacs.\n\n" (insert (cdr (doom-call-process "fc-list" "" "file")))
"This could also mean you've installed them in non-standard locations, in which " (dolist (font all-the-icons-font-names)
"case feel free to ignore this warning."))))))) (if (save-excursion (re-search-backward font nil t))
(success! "Found font %s" font)
(print! (warn "Warning: couldn't find %S font") font)))
(when (> errors 0)
(explain! "Some all-the-icons fonts were missing.\n\n"
"You can install them by running `M-x all-the-icons-install-fonts' within Emacs.\n"
"This could also mean you've installed them in non-standard locations, in which "
"case feel free to ignore this warning.")))))))))
(print! (start "Checking for stale elc files in your DOOMDIR...")) (print! (start "Checking for stale elc files in your DOOMDIR..."))
(when (file-directory-p doom-private-dir) (when (file-directory-p doom-private-dir)
@ -158,15 +164,17 @@ in."
(condition-case-unless-debug ex (condition-case-unless-debug ex
(let ((doctor-file (doom-module-path (car key) (cdr key) "doctor.el")) (let ((doctor-file (doom-module-path (car key) (cdr key) "doctor.el"))
(packages-file (doom-module-path (car key) (cdr key) "packages.el"))) (packages-file (doom-module-path (car key) (cdr key) "packages.el")))
(cl-loop for name in (let (doom-packages (cl-loop with doom-format-indent = 6
for name in (let (doom-packages
doom-disabled-packages) doom-disabled-packages)
(load packages-file 'noerror 'nomessage) (load packages-file 'noerror 'nomessage)
(mapcar #'car doom-packages)) (mapcar #'car doom-packages))
unless (or (doom-package-get name :disable) unless (or (doom-package-get name :disable)
(eval (doom-package-get name :ignore)) (eval (doom-package-get name :ignore))
(plist-member (doom-package-get name :recipe) :local-repo)
(doom-package-built-in-p name) (doom-package-built-in-p name)
(doom-package-installed-p name)) (doom-package-installed-p name))
do (print! (error "%s is not installed") name)) do (print! (error "Missing emacs package: %S") name))
(let ((inhibit-message t)) (let ((inhibit-message t))
(load doctor-file 'noerror 'nomessage))) (load doctor-file 'noerror 'nomessage)))
(file-missing (error! "%s" (error-message-string ex))) (file-missing (error! "%s" (error-message-string ex)))

View file

@ -1,8 +1,10 @@
;;; core/cli/env.el -*- lexical-binding: t; -*- ;;; core/cli/env.el -*- lexical-binding: t; -*-
(defcli! env (defcli! env
((clear-p ["-c" "--clear"] "Clear and delete your envvar file") ((allow ["-a" "--allow" regexp] "An envvar whitelist regexp")
(outputfile ["-o" PATH] (reject ["-r" "--reject" regexp] "An envvar blacklist regexp")
(clear-p ["-c" "--clear"] "Clear and delete your envvar file")
(outputfile ["-o" PATH]
"Generate the envvar file at PATH. Envvar files that aren't in "Generate the envvar file at PATH. Envvar files that aren't in
`doom-env-file' won't be loaded automatically at startup. You will need to load `doom-env-file' won't be loaded automatically at startup. You will need to load
them manually from your private config with the `doom-load-envvars-file' them manually from your private config with the `doom-load-envvars-file'
@ -46,86 +48,86 @@ Why this over exec-path-from-shell?
(print! (success "Successfully deleted %S") (print! (success "Successfully deleted %S")
(path env-file))) (path env-file)))
(args ((and args (not (or allow reject)))
(user-error "I don't understand 'doom env %s'" (user-error "I don't understand 'doom env %s'"
(string-join args " "))) (string-join args " ")))
((doom-cli-reload-env-file 'force env-file))))) ((doom-cli-reload-env-file
'force env-file (list allow) (list reject))))))
;; ;;
;; Helpers ;; Helpers
(defvar doom-env-ignored-vars (defvar doom-env-blacklist
'("^DBUS_SESSION_BUS_ADDRESS$" '("^DBUS_SESSION_BUS_ADDRESS$"
"^GPG_AGENT_INFO$" "^GPG_AGENT_INFO$" "^\\(SSH\\|GPG\\)_TTY$"
"^\\(SSH\\|GPG\\)_TTY$" "^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$"
"^HOME$" "^HOME$" "^PWD$" "^PS1$" "^R?PROMPT$" "^TERM$"
"^PS1$"
"^PWD$"
"^R?PROMPT$"
"^SSH_AGENT_PID$"
"^SSH_AUTH_SOCK$"
"^TERM$"
;; Doom envvars ;; Doom envvars
"^DEBUG$" "^DEBUG$" "^INSECURE$" "^YES$" "^__")
"^INSECURE$"
"^YES$"
"^__")
"Environment variables to not save in `doom-env-file'. "Environment variables to not save in `doom-env-file'.
Each string is a regexp, matched against variable names to omit from Each string is a regexp, matched against variable names to omit from
`doom-env-file'.") `doom-env-file'.")
(defun doom-cli-reload-env-file (&optional force-p env-file) (defvar doom-env-whitelist '()
"A whitelist for envvars to save in `doom-env-file'.
This overrules `doom-env-ignored-vars'. Each string is a regexp, matched against
variable names to omit from `doom-env-file'.")
(defun doom-cli-reload-env-file (&optional force-p env-file whitelist blacklist)
"Generates `doom-env-file', if it doesn't exist (or if FORCE-P). "Generates `doom-env-file', if it doesn't exist (or if FORCE-P).
This scrapes the variables from your shell environment by running This scrapes the variables from your shell environment by running
`doom-env-executable' through `shell-file-name' with `doom-env-switches'. By `doom-env-executable' through `shell-file-name' with `doom-env-switches'. By
default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in default, on Linux, this is '$SHELL -ic /usr/bin/env'. Variables in
`doom-env-ignored-vars' are removed." `doom-env-ignored-vars' are removed."
(let ((env-file (if env-file (let ((env-file (if env-file (expand-file-name env-file) doom-env-file))
(expand-file-name env-file) (process-environment doom--initial-process-environment))
doom-env-file)))
(when (or force-p (not (file-exists-p env-file))) (when (or force-p (not (file-exists-p env-file)))
(with-temp-file env-file (with-temp-file env-file
(setq-local coding-system-for-write 'utf-8)
(print! (start "%s envvars file at %S") (print! (start "%s envvars file at %S")
(if (file-exists-p env-file) (if (file-exists-p env-file)
"Regenerating" "Regenerating"
"Generating") "Generating")
(path env-file)) (path env-file))
(let ((process-environment doom--initial-process-environment)) (print-group!
(print! (info "Scraping shell environment")) (when doom-interactive-mode
(print-group! (user-error "'doom env' must be run on the command line, not an interactive session"))
(when doom-interactive-mode (goto-char (point-min))
(user-error "'doom env' must be run on the command line, not an interactive session")) (insert
(goto-char (point-min)) (concat
(insert "# -*- mode: sh -*-\n"
(concat "# ---------------------------------------------------------------------------\n"
"# -*- mode: sh -*-\n" "# This file was auto-generated by `doom env'. It contains a list of environment\n"
"# ---------------------------------------------------------------------------\n" "# variables scraped from your default shell (excluding variables blacklisted\n"
"# This file was auto-generated by `doom env'. It contains a list of environment\n" "# in doom-env-ignored-vars).\n"
"# variables scraped from your default shell (excluding variables blacklisted\n" "#\n"
"# in doom-env-ignored-vars).\n" (if (file-equal-p env-file doom-env-file)
"#\n" (concat "# It is NOT safe to edit this file. Changes will be overwritten next time you\n"
(if (file-equal-p env-file doom-env-file) "# run 'doom sync'. To create a safe-to-edit envvar file use:\n#\n"
(concat "# It is NOT safe to edit this file. Changes will be overwritten next time you\n" "# doom env -o ~/.doom.d/myenv\n#\n"
"# run 'doom sync'. To create a safe-to-edit envvar file use:\n#\n" "# And load it with (doom-load-envvars-file \"~/.doom.d/myenv\").\n")
"# doom env -o ~/.doom.d/myenv\n#\n" (concat "# This file is safe to edit by hand, but remember to preserve the null bytes at\n"
"# And load it with (doom-load-envvars-file \"~/.doom.d/myenv\").\n") "# the end of each line! needs to be loaded manually with:\n#\n"
(concat "# This file is safe to edit by hand, but remember to preserve the null bytes at\n" "# (doom-load-envvars-file \"path/to/this/file\")\n#\n"
"# the end of each line! needs to be loaded manually with:\n#\n" "# Use 'doom env -o path/to/this/file' to regenerate it."))
"# (doom-load-envvars-file \"path/to/this/file\")\n#\n" "# ---------------------------------------------------------------------------\n\0\n"))
"# Use 'doom env -o path/to/this/file' to regenerate it.")) ;; We assume that this noninteractive session was spawned from the
"# ---------------------------------------------------------------------------\n\0\n")) ;; user's interactive shell, therefore we just dump
;; We assume that this noninteractive session was spawned from the ;; `process-environment' to a file.
;; user's interactive shell, therefore we just dump (dolist (env process-environment)
;; `process-environment' to a file. (if (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "=")))
(dolist (env process-environment) (remq nil (append blacklist doom-env-blacklist)))
(if (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "="))) (if (not (cl-find-if (doom-rpartial #'string-match-p (car (split-string env "=")))
doom-env-ignored-vars) (remq nil (append whitelist doom-env-whitelist))))
(print! (info "Ignoring %s") env) (print! (info "Ignoring %s") env)
(insert env "\0\n"))) (print! (info "Whitelisted %s") env)
(print! (success "Successfully generated %S") (insert env "\0\n"))
(path env-file)) (insert env "\0\n")))
t)))))) (print! (success "Successfully generated %S")
(path env-file))
t)))))

View file

@ -24,7 +24,6 @@ DOOMDIR environment variable. e.g.
doom -p ~/.config/doom install doom -p ~/.config/doom install
DOOMDIR=~/.config/doom doom install" DOOMDIR=~/.config/doom doom install"
:bare t
(print! (green "Installing Doom Emacs!\n")) (print! (green "Installing Doom Emacs!\n"))
(let ((default-directory (doom-path "~"))) (let ((default-directory (doom-path "~")))
;; Create `doom-private-dir' ;; Create `doom-private-dir'
@ -59,8 +58,14 @@ DOOMDIR environment variable. e.g.
;; In case no init.el was present the first time `doom-initialize-modules' was ;; In case no init.el was present the first time `doom-initialize-modules' was
;; called in core.el (e.g. on first install) ;; called in core.el (e.g. on first install)
(doom-initialize 'force 'noerror) (ignore-errors
(doom-initialize-modules) (load! "init" doom-private-dir t))
(when doom-modules
(maphash (lambda (key plist)
(let ((doom--current-module key)
(doom--current-flags (plist-get plist :flags)))
(ignore-errors (load! "init" (plist-get plist :path) t))))
doom-modules))
;; Ask if user would like an envvar file generated ;; Ask if user would like an envvar file generated
(if noenv-p (if noenv-p
@ -79,28 +84,28 @@ DOOMDIR environment variable. e.g.
(print! "Regenerating autoloads files") (print! "Regenerating autoloads files")
(doom-cli-reload-autoloads) (doom-cli-reload-autoloads)
(cond (nofonts-p) (cond (nofonts-p)
(IS-WINDOWS (IS-WINDOWS
(print! (warn "Doom cannot install all-the-icons' fonts on Windows!\n")) (print! (warn "Doom cannot install all-the-icons' fonts on Windows!\n"))
(print-group! (print-group!
(print! (print!
(concat "You'll have to do so manually:\n\n" (concat "You'll have to do so manually:\n\n"
" 1. Launch Doom Emacs\n" " 1. Launch Doom Emacs\n"
" 2. Execute 'M-x all-the-icons-install-fonts' to download the fonts\n" " 2. Execute 'M-x all-the-icons-install-fonts' to download the fonts\n"
" 3. Open the download location in windows explorer\n" " 3. Open the download location in windows explorer\n"
" 4. Open each font file to install them")))) " 4. Open each font file to install them"))))
((or doom-auto-accept ((or doom-auto-accept
(y-or-n-p "Download and install all-the-icon's fonts?")) (y-or-n-p "Download and install all-the-icon's fonts?"))
(require 'all-the-icons) (require 'all-the-icons)
(let ((window-system (cond (IS-MAC 'ns) (let ((window-system (cond (IS-MAC 'ns)
(IS-LINUX 'x)))) (IS-LINUX 'x))))
(all-the-icons-install-fonts 'yes)))) (all-the-icons-install-fonts 'yes))))
(when (file-exists-p "~/.emacs") (when (file-exists-p "~/.emacs")
(print! (warn "A ~/.emacs file was detected. This conflicts with Doom and should be deleted!"))) (print! (warn "A ~/.emacs file was detected. This conflicts with Doom and should be deleted!")))
(print! (success "\nFinished! Doom is ready to go!\n")) (print! (success "\nFinished! Doom is ready to go!\n"))
(with-temp-buffer (with-temp-buffer
(doom-template-insert "QUICKSTART_INTRO") (insert-file-contents (doom-glob doom-core-dir "templates/QUICKSTART_INTRO"))
(print! (buffer-string))))) (print! "%s" (buffer-string)))))

View file

@ -2,7 +2,7 @@
;;; core/cli/packages.el ;;; core/cli/packages.el
(defcli! (update u) (defcli! (update u)
((discard-p ["--discard"] "All local changes to packages are discarded")) ((discard-p ["--discard"] "All local changes to packages are discarded"))
"Updates packages. "Updates packages.
This works by fetching all installed package repos and checking the distance This works by fetching all installed package repos and checking the distance
@ -74,23 +74,79 @@ list remains lean."
"-n" "25" end-ref (concat "^" (regexp-quote start-ref))) "-n" "25" end-ref (concat "^" (regexp-quote start-ref)))
(straight--process-get-output))) (straight--process-get-output)))
(defun doom--barf-if-incomplete-packages ()
(let ((straight-safe-mode t))
(condition-case _ (straight-check-all)
(error (user-error "Package state is incomplete. Run 'doom sync' first")))))
(defmacro doom--with-package-recipes (recipes binds &rest body)
(declare (indent 2))
(let ((recipe-var (make-symbol "recipe"))
(recipes-var (make-symbol "recipes")))
`(let* ((,recipes-var ,recipes)
(built ())
(straight-use-package-pre-build-functions
(cons (lambda (pkg &rest _) (cl-pushnew pkg built :test #'equal))
straight-use-package-pre-build-functions)))
(dolist (,recipe-var ,recipes-var (nreverse built))
(cl-block nil
(straight--with-plist (append (list :recipe ,recipe-var) ,recipe-var)
,(doom-enlist binds)
,@body))))))
(defvar doom--cli-updated-recipes nil)
(defun doom--cli-recipes-update ()
"Updates straight and recipe repos."
(unless doom--cli-updated-recipes
(straight--make-build-cache-available)
(print! (start "Updating recipe repos..."))
(print-group!
(doom--with-package-recipes
(delq
nil (mapcar (doom-rpartial #'gethash straight--repo-cache)
(mapcar #'symbol-name straight-recipe-repositories)))
(recipe package type local-repo)
(let ((esc (unless doom-debug-mode "\033[1A"))
(ref (straight-vc-get-commit type local-repo))
newref output)
(print! (start "\033[KUpdating recipes for %s...%s") package esc)
(when (straight-vc-fetch-from-remote recipe)
(setq output (straight--process-get-output))
(straight-merge-package package)
(unless (equal ref (setq newref (straight-vc-get-commit type local-repo)))
(print! (success "\033[K%s updated (%s -> %s)")
package
(doom--abbrev-commit ref)
(doom--abbrev-commit newref))
(unless (string-empty-p output)
(print-group! (print! (info "%s" output)))))))))
(setq straight--recipe-lookup-cache (make-hash-table :test #'eq)
doom--cli-updated-recipes t)))
(defun doom-cli-packages-install () (defun doom-cli-packages-install ()
"Installs missing packages. "Installs missing packages.
This function will install any primary package (i.e. a package with a `package!' This function will install any primary package (i.e. a package with a `package!'
declaration) or dependency thereof that hasn't already been." declaration) or dependency thereof that hasn't already been."
(straight--transaction-finalize) (doom-initialize-packages)
(print! (start "Installing packages...")) (print! (start "Installing packages..."))
(let ((pinned (doom-package-pinned-list))) (let ((pinned (doom-package-pinned-list)))
(print-group! (print-group!
(if-let (built (if-let (built
(doom-with-package-recipes (doom-package-recipe-list) (doom--with-package-recipes (doom-package-recipe-list)
(recipe package type local-repo) (recipe package type local-repo)
(unless (file-directory-p (straight--repos-dir local-repo))
(doom--cli-recipes-update))
(condition-case-unless-debug e (condition-case-unless-debug e
(straight-use-package (intern package)) (let ((straight-use-package-pre-build-functions
(cons (lambda (pkg &rest _)
(when-let (commit (cdr (assoc pkg pinned)))
(print! (info "Checked out %s") commit)))
straight-use-package-pre-build-functions)))
(straight-use-package (intern package)))
(error (error
(signal 'doom-package-error (signal 'doom-package-error (list package e))))))
(list package e (straight--process-get-output)))))))
(print! (success "Installed %d packages") (print! (success "Installed %d packages")
(length built)) (length built))
(print! (info "No packages need to be installed")) (print! (info "No packages need to be installed"))
@ -99,7 +155,7 @@ declaration) or dependency thereof that hasn't already been."
(defun doom-cli-packages-build (&optional force-p) (defun doom-cli-packages-build (&optional force-p)
"(Re)build all packages." "(Re)build all packages."
(straight--transaction-finalize) (doom-initialize-packages)
(print! (start "(Re)building %spackages...") (if force-p "all " "")) (print! (start "(Re)building %spackages...") (if force-p "all " ""))
(print-group! (print-group!
(let ((straight-check-for-modifications (let ((straight-check-for-modifications
@ -118,7 +174,7 @@ declaration) or dependency thereof that hasn't already been."
(unless force-p (unless force-p
(straight--make-build-cache-available)) (straight--make-build-cache-available))
(if-let (built (if-let (built
(doom-with-package-recipes recipes (package local-repo) (doom--with-package-recipes recipes (package local-repo)
(unless force-p (unless force-p
;; Ensure packages with outdated files/bytecode are rebuilt ;; Ensure packages with outdated files/bytecode are rebuilt
(let ((build-dir (straight--build-dir package)) (let ((build-dir (straight--build-dir package))
@ -143,18 +199,21 @@ declaration) or dependency thereof that hasn't already been."
(defun doom-cli-packages-update () (defun doom-cli-packages-update ()
"Updates packages." "Updates packages."
(straight--transaction-finalize) (doom-initialize-packages)
(print! (start "Updating packages (this may take a while)...")) (doom--barf-if-incomplete-packages)
(let* ((repo-dir (straight--repos-dir)) (let* ((repo-dir (straight--repos-dir))
(pinned (doom-package-pinned-list)) (pinned (doom-package-pinned-list))
(recipes (doom-package-recipe-list))
(packages-to-rebuild (make-hash-table :test 'equal)) (packages-to-rebuild (make-hash-table :test 'equal))
(repos-to-rebuild (make-hash-table :test 'equal)) (repos-to-rebuild (make-hash-table :test 'equal))
(recipes (doom-package-recipe-list))
(total (length recipes)) (total (length recipes))
(esc (unless doom-debug-mode "\033[1A")) (esc (unless doom-debug-mode "\033[1A"))
(i 0) (i 0)
errors) errors)
(doom-with-package-recipes recipes (recipe package type local-repo) (when recipes
(doom--cli-recipes-update))
(print! (start "Updating packages (this may take a while)..."))
(doom--with-package-recipes recipes (recipe package type local-repo)
(cl-incf i) (cl-incf i)
(print-group! (print-group!
(unless (straight--repository-is-available-p recipe) (unless (straight--repository-is-available-p recipe)
@ -173,7 +232,9 @@ declaration) or dependency thereof that hasn't already been."
(error "%S is not a valid repository" package))) (error "%S is not a valid repository" package)))
(condition-case-unless-debug e (condition-case-unless-debug e
(let ((ref (straight-vc-get-commit type local-repo)) (let ((ref (straight-vc-get-commit type local-repo))
(target-ref (cdr (assoc local-repo pinned))) (target-ref
(cdr (or (assoc local-repo pinned)
(assoc package pinned))))
output) output)
(or (cond (or (cond
((not (stringp target-ref)) ((not (stringp target-ref))
@ -201,9 +262,9 @@ declaration) or dependency thereof that hasn't already been."
(doom--same-commit-p target-ref (straight-vc-get-commit type local-repo))) (doom--same-commit-p target-ref (straight-vc-get-commit type local-repo)))
((print! (start "\033[K(%d/%d) Re-cloning %s...") i total local-repo esc) ((print! (start "\033[K(%d/%d) Re-cloning %s...") i total local-repo esc)
(let ((repo (straight--repos-dir local-repo))) (let ((repo (straight--repos-dir local-repo))
(ignore-errors (straight-vc-git-default-clone-depth 'full))
(delete-directory repo 'recursive)) (delete-directory repo 'recursive)
(print-group! (print-group!
(straight-use-package (intern package) nil 'no-build)) (straight-use-package (intern package) nil 'no-build))
(prog1 (file-directory-p repo) (prog1 (file-directory-p repo)
@ -219,7 +280,7 @@ declaration) or dependency thereof that hasn't already been."
(puthash package t packages-to-rebuild) (puthash package t packages-to-rebuild)
(unless (string-empty-p output) (unless (string-empty-p output)
(print! (start "\033[K(%d/%d) Updating %s...") i total local-repo) (print! (start "\033[K(%d/%d) Updating %s...") i total local-repo)
(print-group! (print! (indent 2 output)))) (print-group! (print! "%s" (indent 2 output))))
(print! (success "\033[K(%d/%d) %s updated (%s -> %s)") (print! (success "\033[K(%d/%d) %s updated (%s -> %s)")
i total local-repo i total local-repo
(doom--abbrev-commit ref) (doom--abbrev-commit ref)
@ -227,24 +288,19 @@ declaration) or dependency thereof that hasn't already been."
(user-error (user-error
(signal 'user-error (error-message-string e))) (signal 'user-error (error-message-string e)))
(error (error
(print! (warn "\033[K(%d/%d) Encountered error with %s" i total package)) (signal 'doom-package-error (list package e)))))))
(print-group! (print-group!
(print! (error "%s") e) (princ "\033[K")
(print-group! (print! (info "%s" (straight--process-get-output))))) (if (hash-table-empty-p packages-to-rebuild)
(push package errors)))))) (ignore (print! (success "All %d packages are up-to-date") total))
(princ "\033[K") (straight--transaction-finalize)
(when errors (let ((default-directory (straight--build-dir)))
(print! (error "Encountered %d error(s), the offending packages: %s") (mapc (doom-rpartial #'delete-directory 'recursive)
(length errors) (string-join errors ", "))) (hash-table-keys packages-to-rebuild)))
(if (hash-table-empty-p packages-to-rebuild) (print! (success "Updated %d package(s)")
(ignore (print! (success "All %d packages are up-to-date") total)) (hash-table-count packages-to-rebuild))
(let ((default-directory (straight--build-dir))) (doom-cli-packages-build)
(mapc (doom-rpartial #'delete-directory 'recursive) t))))
(hash-table-keys packages-to-rebuild)))
(print! (success "Updated %d package(s)")
(hash-table-count packages-to-rebuild))
(doom-cli-packages-build)
t)))
;;; PURGE (for the emperor) ;;; PURGE (for the emperor)
@ -258,8 +314,8 @@ declaration) or dependency thereof that hasn't already been."
(defun doom--cli-packages-purge-builds (builds) (defun doom--cli-packages-purge-builds (builds)
(if (not builds) (if (not builds)
(progn (print! (info "No builds to purge")) (prog1 0
0) (print! (info "No builds to purge")))
(print! (start "Purging straight builds..." (length builds))) (print! (start "Purging straight builds..." (length builds)))
(print-group! (print-group!
(length (length
@ -287,8 +343,8 @@ declaration) or dependency thereof that hasn't already been."
(defun doom--cli-packages-regraft-repos (repos) (defun doom--cli-packages-regraft-repos (repos)
(if (not repos) (if (not repos)
(progn (print! (info "No repos to regraft")) (prog1 0
0) (print! (info "No repos to regraft")))
(print! (start "Regrafting %d repos..." (length repos))) (print! (start "Regrafting %d repos..." (length repos)))
(let ((before-size (doom-directory-size (straight--repos-dir)))) (let ((before-size (doom-directory-size (straight--repos-dir))))
(print-group! (print-group!
@ -302,8 +358,7 @@ declaration) or dependency thereof that hasn't already been."
(defun doom--cli-packages-purge-repo (repo) (defun doom--cli-packages-purge-repo (repo)
(let ((repo-dir (straight--repos-dir repo))) (let ((repo-dir (straight--repos-dir repo)))
(delete-directory repo-dir 'recursive) (delete-directory repo-dir 'recursive)
(ignore-errors (delete-file (straight--modified-file repo))
(delete-file (straight--modified-file repo)))
(if (file-directory-p repo-dir) (if (file-directory-p repo-dir)
(ignore (print! (error "Failed to purge repos/%s" repo))) (ignore (print! (error "Failed to purge repos/%s" repo)))
(print! (success "Purged repos/%s" repo)) (print! (success "Purged repos/%s" repo))
@ -311,8 +366,8 @@ declaration) or dependency thereof that hasn't already been."
(defun doom--cli-packages-purge-repos (repos) (defun doom--cli-packages-purge-repos (repos)
(if (not repos) (if (not repos)
(progn (print! (info "No repos to purge")) (prog1 0
0) (print! (info "No repos to purge")))
(print! (start "Purging straight repositories...")) (print! (start "Purging straight repositories..."))
(print-group! (print-group!
(length (length
@ -322,8 +377,8 @@ declaration) or dependency thereof that hasn't already been."
(require 'core-packages) (require 'core-packages)
(let ((dirs (doom-files-in package-user-dir :type t :depth 0))) (let ((dirs (doom-files-in package-user-dir :type t :depth 0)))
(if (not dirs) (if (not dirs)
(progn (print! (info "No ELPA packages to purge")) (prog1 0
0) (print! (info "No ELPA packages to purge")))
(print! (start "Purging ELPA packages...")) (print! (start "Purging ELPA packages..."))
(dolist (path dirs (length dirs)) (dolist (path dirs (length dirs))
(condition-case e (condition-case e
@ -346,16 +401,18 @@ a `package!' declaration) or isn't depended on by another primary package.
If BUILDS-P, include straight package builds. If BUILDS-P, include straight package builds.
If REPOS-P, include straight repos. If REPOS-P, include straight repos.
If ELPA-P, include packages installed with package.el (M-x package-install)." If ELPA-P, include packages installed with package.el (M-x package-install)."
(doom-initialize-packages)
(doom--barf-if-incomplete-packages)
(print! (start "Purging orphaned packages (for the emperor)...")) (print! (start "Purging orphaned packages (for the emperor)..."))
(cl-destructuring-bind (&optional builds-to-purge repos-to-purge repos-to-regraft) (cl-destructuring-bind (&optional builds-to-purge repos-to-purge repos-to-regraft)
(let ((rdirs (straight--directory-files (straight--repos-dir) nil nil 'sort)) (let ((rdirs (straight--directory-files (straight--repos-dir) nil nil 'sort))
(bdirs (straight--directory-files (straight--build-dir) nil nil 'sort))) (bdirs (straight--directory-files (straight--build-dir) nil nil 'sort)))
(list (cl-remove-if (doom-rpartial #'gethash straight--profile-cache) (list (seq-remove (doom-rpartial #'gethash straight--profile-cache)
bdirs) bdirs)
(cl-remove-if (doom-rpartial #'straight--checkhash straight--repo-cache) (seq-remove (doom-rpartial #'straight--checkhash straight--repo-cache)
rdirs) rdirs)
(cl-remove-if-not (doom-rpartial #'straight--checkhash straight--repo-cache) (seq-filter (doom-rpartial #'straight--checkhash straight--repo-cache)
rdirs))) rdirs)))
(let (success) (let (success)
(print-group! (print-group!
(if (not builds-p) (if (not builds-p)

View file

@ -1,8 +1,8 @@
;;; core/cli/upgrade.el -*- lexical-binding: t; -*- ;;; core/cli/upgrade.el -*- lexical-binding: t; -*-
(defcli! (upgrade up) (defcli! (upgrade up)
((force-p ["-f" "--force"] "Discard local changes to Doom and packages, and upgrade anyway") ((force-p ["-f" "--force"] "Discard local changes to Doom and packages, and upgrade anyway")
(packages-only-p ["-p" "--packages"] "Only upgrade packages, not Doom")) (packages-only-p ["-p" "--packages"] "Only upgrade packages, not Doom"))
"Updates Doom and packages. "Updates Doom and packages.
This requires that ~/.emacs.d is a git repo, and is the equivalent of the This requires that ~/.emacs.d is a git repo, and is the equivalent of the
@ -19,7 +19,7 @@ following shell commands:
nil (list nil (list
(unless packages-only-p (unless packages-only-p
(doom-cli-upgrade doom-auto-accept doom-auto-discard)) (doom-cli-upgrade doom-auto-accept doom-auto-discard))
(doom-cli-execute "refresh") (doom-cli-execute "sync")
(when (doom-cli-packages-update) (when (doom-cli-packages-update)
(doom-cli-reload-package-autoloads) (doom-cli-reload-package-autoloads)
t))) t)))
@ -110,6 +110,24 @@ following shell commands:
(equal (vc-git--rev-parse "HEAD") new-rev)) (equal (vc-git--rev-parse "HEAD") new-rev))
(print! (info "%s") (cdr result)) (print! (info "%s") (cdr result))
(error "Failed to check out %s" (substring new-rev 0 10))) (error "Failed to check out %s" (substring new-rev 0 10)))
;; Reload Doom's CLI & libraries, in case there were any
;; upstream changes. Major changes will still break, however
(condition-case-unless-debug e
(progn
(mapc (doom-rpartial #'unload-feature t)
'(core core-lib
core-cli
core-modules
core-packages))
(require 'core)
(setq doom-init-p nil
doom-init-modules-p nil)
(doom-initialize))
(error
(signal 'doom-error (list "Could not upgrade Doom without issues"
e))))
(print! (success "Finished upgrading Doom Emacs"))) (print! (success "Finished upgrading Doom Emacs")))
t))))) t)))))
(ignore-errors (ignore-errors

View file

@ -1,5 +1,24 @@
;;; -*- lexical-binding: t; no-byte-compile: t; -*- ;;; -*- lexical-binding: t; no-byte-compile: t; -*-
(require 'seq)
(load! "autoload/process")
(load! "autoload/plist")
(load! "autoload/files")
(load! "autoload/format")
;; Create all our core directories to quell file errors
(mapc (doom-rpartial #'make-directory 'parents)
(list doom-local-dir
doom-etc-dir
doom-cache-dir))
;; Ensure straight and the bare minimum is ready to go
(require 'core-modules)
(require 'core-packages)
(doom-initialize-core-packages)
;; ;;
;;; Variables ;;; Variables
@ -11,7 +30,6 @@ commands like `doom-cli-packages-install', `doom-cli-packages-update' and
(defvar doom-auto-discard (getenv "FORCE") (defvar doom-auto-discard (getenv "FORCE")
"If non-nil, discard all local changes while updating.") "If non-nil, discard all local changes while updating.")
(defvar doom--cli-p nil)
(defvar doom--cli-commands (make-hash-table :test 'equal)) (defvar doom--cli-commands (make-hash-table :test 'equal))
(defvar doom--cli-groups (make-hash-table :test 'equal)) (defvar doom--cli-groups (make-hash-table :test 'equal))
(defvar doom--cli-group nil) (defvar doom--cli-group nil)
@ -54,9 +72,10 @@ commands like `doom-cli-packages-install', `doom-cli-packages-update' and
(defun doom--cli-process (cli args) (defun doom--cli-process (cli args)
(let* ((args (copy-sequence args)) (let* ((args (copy-sequence args))
(arglist (copy-sequence (doom-cli-arglist cli))) (arglist (copy-sequence (doom-cli-arglist cli)))
(expected (or (cl-position-if (doom-rpartial #'memq cl--lambda-list-keywords) (expected
arglist) (or (cl-position-if (doom-rpartial #'memq cl--lambda-list-keywords)
(length arglist))) arglist)
(length arglist)))
(got 0) (got 0)
restvar restvar
rest rest
@ -137,7 +156,7 @@ Executes a cli defined with `defcli!' with the name or alias specified by
COMMAND, and passes ARGS to it." COMMAND, and passes ARGS to it."
(if-let (cli (doom-cli-get command)) (if-let (cli (doom-cli-get command))
(funcall (doom-cli-fn cli) (funcall (doom-cli-fn cli)
(doom--cli-process cli args)) (doom--cli-process cli (remq nil args)))
(user-error "Couldn't find any %S command" command))) (user-error "Couldn't find any %S command" command)))
(defmacro defcli! (name speclist &optional docstring &rest body) (defmacro defcli! (name speclist &optional docstring &rest body)
@ -186,10 +205,6 @@ BODY will be run when this dispatcher is called."
for optsym = (if (listp opt) (car opt) opt) for optsym = (if (listp opt) (car opt) opt)
unless (memq optsym cl--lambda-list-keywords) unless (memq optsym cl--lambda-list-keywords)
collect (list optsym `(cdr (assq ',optsym --alist--)))) collect (list optsym `(cdr (assq ',optsym --alist--))))
,@(unless (plist-get plist :bare)
'((unless doom-init-p
(doom-initialize 'force 'noerror)
(doom-initialize-modules))))
,@body))) ,@body)))
doom--cli-commands) doom--cli-commands)
(when aliases (when aliases
@ -208,10 +223,25 @@ BODY will be run when this dispatcher is called."
;;; Straight hacks ;;; Straight hacks
(defvar doom--cli-straight-discard-options (defvar doom--cli-straight-discard-options
'("^Delete remote \"[^\"]+\", re-create it with correct " '(("has diverged from"
"^Reset branch " . "^Reset [^ ]+ to branch")
"^Abort merge$" ("but recipe specifies a URL of"
"^Discard changes$")) . "re-create it with correct URL")
("has a merge conflict:"
. "^Abort merge$")
("has a dirty worktree:"
. "^Discard changes$")
("^In repository "
. "^Reset branch \\|^Delete remote [^,]+, re-create it with correct URL"))
"A list of regexps, mapped to regexps.
Their CAR is tested against the prompt, and CDR is tested against the presented
option, and is used by `straight-vc-git--popup-raw' to select which option to
recommend.
It may not be obvious to users what they should do for some straight prompts,
so Doom will recommend the one that reverts a package back to its (or target)
original state.")
;; HACK Remove dired & magit options from prompt, since they're inaccessible in ;; HACK Remove dired & magit options from prompt, since they're inaccessible in
;; noninteractive sessions. ;; noninteractive sessions.
@ -222,63 +252,69 @@ BODY will be run when this dispatcher is called."
(defadvice! doom--straight-fallback-to-y-or-n-prompt-a (orig-fn &optional prompt) (defadvice! doom--straight-fallback-to-y-or-n-prompt-a (orig-fn &optional prompt)
:around #'straight-are-you-sure :around #'straight-are-you-sure
(or doom-auto-accept (or doom-auto-accept
(if noninteractive (if doom-interactive-mode
(y-or-n-p (format! "%s" (or prompt ""))) (funcall orig-fn prompt)
(funcall orig-fn prompt)))) (y-or-n-p (format! "%s" (or prompt ""))))))
(defun doom--straight-recommended-option-p (prompt option)
(cl-loop for (prompt-re . opt-re) in doom--cli-straight-discard-options
if (string-match-p prompt-re prompt)
return (string-match-p opt-re option)))
(defadvice! doom--straight-fallback-to-tty-prompt-a (orig-fn prompt actions) (defadvice! doom--straight-fallback-to-tty-prompt-a (orig-fn prompt actions)
"Modifies straight to prompt on the terminal when in noninteractive sessions." "Modifies straight to prompt on the terminal when in noninteractive sessions."
:around #'straight--popup-raw :around #'straight--popup-raw
(if (not noninteractive) (if doom-interactive-mode
(funcall orig-fn prompt actions) (funcall orig-fn prompt actions)
;; We can't intercept C-g, so no point displaying any options for this key (let ((doom--cli-straight-discard-options doom--cli-straight-discard-options))
;; when C-c is the proper way to abort batch Emacs. ;; We can't intercept C-g, so no point displaying any options for this key
(delq! "C-g" actions 'assoc) ;; when C-c is the proper way to abort batch Emacs.
;; HACK These are associated with opening dired or magit, which isn't (delq! "C-g" actions 'assoc)
;; possible in tty Emacs, so... ;; HACK These are associated with opening dired or magit, which isn't
(delq! "e" actions 'assoc) ;; possible in tty Emacs, so...
(delq! "g" actions 'assoc) (delq! "e" actions 'assoc)
(if doom-auto-discard (delq! "g" actions 'assoc)
(cl-loop with doom-auto-accept = t (if doom-auto-discard
for (_key desc func) in actions (cl-loop with doom-auto-accept = t
when desc for (_key desc func) in actions
when (cl-find-if (doom-rpartial #'string-match-p desc)
doom--cli-straight-discard-options)
return (funcall func))
(print! (start "%s") (red prompt))
(print-group!
(terpri)
(let (options)
(print-group!
(print! " 1) Abort")
(cl-loop for (_key desc func) in actions
when desc when desc
do (push func options) when (doom--straight-recommended-option-p prompt desc)
and do return (funcall func))
(print! "%2s) %s" (1+ (length options)) (print! (start "%s") (red prompt))
(if (cl-find-if (doom-rpartial #'string-match-p desc) (print-group!
doom--cli-straight-discard-options)
(green (concat desc " (Recommended)"))
desc))))
(terpri) (terpri)
(let* ((options (let (options)
(cons (lambda () (print-group!
(let ((doom-format-indent 0)) (print! " 1) Abort")
(terpri) (cl-loop for (_key desc func) in actions
(print! (warn "Aborted"))) when desc
(kill-emacs 1)) do (push func options)
(nreverse options))) and do
(prompt (print! "%2s) %s" (1+ (length options))
(format! "How to proceed? (%s) " (if (doom--straight-recommended-option-p prompt desc)
(mapconcat #'number-to-string (progn
(number-sequence 1 (length options)) (setq doom--cli-straight-discard-options nil)
", "))) (green (concat desc " (Recommended)")))
answer fn) desc))))
(while (null (nth (setq answer (1- (read-number prompt))) (terpri)
options)) (let* ((options
(print! (warn "%s is not a valid answer, try again.") (cons (lambda ()
answer)) (let ((doom-format-indent 0))
(funcall (nth answer options)))))))) (terpri)
(print! (warn "Aborted")))
(kill-emacs 1))
(nreverse options)))
(prompt
(format! "How to proceed? (%s) "
(mapconcat #'number-to-string
(number-sequence 1 (length options))
", ")))
answer fn)
(while (null (nth (setq answer (1- (read-number prompt)))
options))
(print! (warn "%s is not a valid answer, try again.")
answer))
(funcall (nth answer options)))))))))
(defadvice! doom--straight-respect-print-indent-a (args) (defadvice! doom--straight-respect-print-indent-a (args)
"Indent straight progress messages to respect `doom-format-indent', so we "Indent straight progress messages to respect `doom-format-indent', so we
@ -297,34 +333,18 @@ everywhere we use it (and internally)."
interactive))) interactive)))
;;
;;; Dependencies
(require 'seq)
;; Eagerly load these libraries because we may be in a session that hasn't been
;; fully initialized (e.g. where autoloads files haven't been generated or
;; `load-path' populated).
(load! "autoload/cli")
(load! "autoload/debug")
(load! "autoload/files")
(load! "autoload/format")
(load! "autoload/plist")
;; ;;
;;; CLI Commands ;;; CLI Commands
(load! "cli/help") (load! "cli/help")
(load! "cli/install") (load! "cli/install")
(defcligroup! "Maintenance" (defcli! (sync s refresh re)
"For managing your config and packages" ((inhibit-envvar-p ["-e"] "Don't regenerate the envvar file")
(defcli! (sync s refresh re) (inhibit-elc-p ["-c"] "Don't recompile config")
((if-necessary-p ["-n" "--if-necessary"] "Only regenerate autoloads files if necessary") (update-p ["-u"] "...")
(inhibit-envvar-p ["-e"] "Don't regenerate the envvar file")
(prune-p ["-p" "--prune"] "Purge orphaned packages & regraft repos")) (prune-p ["-p" "--prune"] "Purge orphaned packages & regraft repos"))
"Synchronize your config with Doom Emacs. "Synchronize your config with Doom Emacs.
This is the equivalent of running autoremove, install, autoloads, then This is the equivalent of running autoremove, install, autoloads, then
recompile. Run this whenever you: recompile. Run this whenever you:
@ -337,48 +357,44 @@ recompile. Run this whenever you:
It will ensure that unneeded packages are removed, all needed packages are It will ensure that unneeded packages are removed, all needed packages are
installed, autoloads files are up-to-date and no byte-compiled files have gone installed, autoloads files are up-to-date and no byte-compiled files have gone
stale." stale."
:bare t (print! (start "Synchronizing your config with Doom Emacs..."))
(let (success) (print-group!
;; Ensures that no pre-existing state pollutes the generation of the new (and (not inhibit-envvar-p)
;; autoloads files. (file-exists-p doom-env-file)
(dolist (file (list doom-autoload-file doom-package-autoload-file)) (doom-cli-reload-env-file 'force))
(delete-file file) (doom-cli-reload-core-autoloads)
(delete-file (byte-compile-dest-file file))) (doom-cli-packages-install)
(doom-cli-packages-build)
(when update-p
(doom-cli-packages-update))
(doom-cli-packages-purge prune-p 'builds-p prune-p prune-p)
(doom-cli-reload-package-autoloads)
t))
(doom-initialize 'force 'noerror) (load! "cli/env")
(doom-initialize-modules) (load! "cli/upgrade")
(load! "cli/packages")
(print! (start "Synchronizing your config with Doom Emacs...")) (load! "cli/autoloads")
(print-group!
(when (and (not inhibit-envvar-p)
(file-exists-p doom-env-file))
(doom-cli-reload-env-file 'force))
(doom-cli-reload-core-autoloads)
(doom-cli-packages-install)
(doom-cli-packages-build)
(doom-cli-packages-purge prune-p 'builds-p prune-p prune-p)
(doom-cli-reload-package-autoloads)
t)))
(load! "cli/env")
(load! "cli/upgrade")
(load! "cli/packages")
(load! "cli/autoloads"))
(defcligroup! "Diagnostics" (defcligroup! "Diagnostics"
"For troubleshooting and diagnostics" "For troubleshooting and diagnostics"
(load! "cli/doctor") (load! "cli/doctor")
(load! "cli/debug") (load! "cli/debug")
(load! "cli/test"))
;; Our tests are broken at the moment. Working on fixing them, but for now we
;; disable them:
;; (load! "cli/test")
)
(defcligroup! "Compilation" (defcligroup! "Compilation"
"For compiling Doom and your config" "For compiling Doom and your config"
(load! "cli/byte-compile")) (load! "cli/byte-compile"))
(defcligroup! "Utilities" (defcligroup! "Utilities"
"Conveniences for interacting with Doom externally" "Conveniences for interacting with Doom externally"
(defcli! run () (defcli! run (&rest args)
"Run Doom Emacs from bin/doom's parent directory. "Run Doom Emacs from bin/doom's parent directory.
All arguments are passed on to Emacs. All arguments are passed on to Emacs.
@ -388,11 +404,16 @@ All arguments are passed on to Emacs.
WARNING: this command exists for convenience and testing. Doom will suffer WARNING: this command exists for convenience and testing. Doom will suffer
additional overhead by being started this way. For the best performance, it is additional overhead by being started this way. For the best performance, it is
best to run Doom out of ~/.emacs.d and ~/.doom.d.") best to run Doom out of ~/.emacs.d and ~/.doom.d."))
;; (load! "cli/batch")
;; (load! "cli/org") ;;
) ;;; Load user config
(condition-case-unless-debug e
(load! "init" doom-private-dir t)
(error
(signal 'doom-private-error (list "init.el" e))))
(provide 'core-cli) (provide 'core-cli)
;;; core-cli.el ends here ;;; core-cli.el ends here

View file

@ -79,8 +79,8 @@ possible."
t)))))) t))))))
;; Don't autosave files or create lock/history/backup files. We don't want ;; Don't autosave files or create lock/history/backup files. We don't want
;; copies of potentially sensitive material floating around, and we'll rely on ;; copies of potentially sensitive material floating around or polluting our
;; git and our own good fortune instead. Fingers crossed! ;; filesystem. We rely on git and our own good fortune instead. Fingers crossed!
(setq auto-save-default nil (setq auto-save-default nil
create-lockfiles nil create-lockfiles nil
make-backup-files nil make-backup-files nil
@ -216,7 +216,7 @@ possible."
(use-package! recentf (use-package! recentf
;; Keep track of recently opened files ;; Keep track of recently opened files
:defer-incrementally easymenu tree-widget timer :defer-incrementally easymenu tree-widget timer
:after-call after-find-file :hook (doom-first-file . recentf-mode)
:commands recentf-open-files :commands recentf-open-files
:config :config
(defun doom--recent-file-truename (file) (defun doom--recent-file-truename (file)
@ -246,22 +246,20 @@ possible."
"Add dired directory to recentf file list." "Add dired directory to recentf file list."
(recentf-add-file default-directory))) (recentf-add-file default-directory)))
(when doom-interactive-mode (add-hook 'kill-emacs-hook #'recentf-cleanup)
(add-hook 'kill-emacs-hook #'recentf-cleanup) (advice-add #'recentf-load-list :around #'doom-shut-up-a))
(quiet! (recentf-mode +1))))
(use-package! savehist (use-package! savehist
;; persist variables across sessions ;; persist variables across sessions
:defer-incrementally custom :defer-incrementally custom
:after-call post-command-hook :hook (doom-first-input . savehist-mode)
:init
(setq savehist-file (concat doom-cache-dir "savehist"))
:config :config
(setq savehist-file (concat doom-cache-dir "savehist") (setq savehist-save-minibuffer-history t
savehist-save-minibuffer-history t
savehist-autosave-interval nil ; save on kill only savehist-autosave-interval nil ; save on kill only
savehist-additional-variables '(kill-ring search-ring regexp-search-ring)) savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
(savehist-mode +1)
(add-hook! 'kill-emacs-hook (add-hook! 'kill-emacs-hook
(defun doom-unpropertize-kill-ring-h () (defun doom-unpropertize-kill-ring-h ()
"Remove text properties from `kill-ring' for a smaller savehist file." "Remove text properties from `kill-ring' for a smaller savehist file."
@ -273,11 +271,11 @@ possible."
(use-package! saveplace (use-package! saveplace
;; persistent point location in buffers ;; persistent point location in buffers
:after-call after-find-file dired-initial-position-hook :hook (doom-first-file . save-place-mode)
:config :init
(setq save-place-file (concat doom-cache-dir "saveplace") (setq save-place-file (concat doom-cache-dir "saveplace")
save-place-limit 100) save-place-limit 100)
:config
(defadvice! doom--recenter-on-load-saveplace-a (&rest _) (defadvice! doom--recenter-on-load-saveplace-a (&rest _)
"Recenter on cursor when loading a saved place." "Recenter on cursor when loading a saved place."
:after-while #'save-place-find-file-hook :after-while #'save-place-find-file-hook
@ -312,7 +310,8 @@ files, so we replace calls to `pp' with the much faster `prin1'."
;;; Packages ;;; Packages
(use-package! better-jumper (use-package! better-jumper
:after-call pre-command-hook :hook (doom-first-input . better-jumper-mode)
:hook (better-jumper-post-jump . recenter)
:preface :preface
;; REVIEW Suppress byte-compiler warning spawning a *Compile-Log* buffer at ;; REVIEW Suppress byte-compiler warning spawning a *Compile-Log* buffer at
;; startup. This can be removed once gilbertw1/better-jumper#2 is merged. ;; startup. This can be removed once gilbertw1/better-jumper#2 is merged.
@ -322,17 +321,14 @@ files, so we replace calls to `pp' with the much faster `prin1'."
(global-set-key [remap evil-jump-backward] #'better-jumper-jump-backward) (global-set-key [remap evil-jump-backward] #'better-jumper-jump-backward)
(global-set-key [remap xref-pop-marker-stack] #'better-jumper-jump-backward) (global-set-key [remap xref-pop-marker-stack] #'better-jumper-jump-backward)
:config :config
(better-jumper-mode +1) (defun doom-set-jump-a (orig-fn &rest args)
(add-hook 'better-jumper-post-jump-hook #'recenter)
(defadvice! doom-set-jump-a (orig-fn &rest args)
"Set a jump point and ensure ORIG-FN doesn't set any new jump points." "Set a jump point and ensure ORIG-FN doesn't set any new jump points."
(better-jumper-set-jump (if (markerp (car args)) (car args))) (better-jumper-set-jump (if (markerp (car args)) (car args)))
(let ((evil--jumps-jumping t) (let ((evil--jumps-jumping t)
(better-jumper--jumping t)) (better-jumper--jumping t))
(apply orig-fn args))) (apply orig-fn args)))
(defadvice! doom-set-jump-maybe-a (orig-fn &rest args) (defun doom-set-jump-maybe-a (orig-fn &rest args)
"Set a jump point if ORIG-FN returns non-nil." "Set a jump point if ORIG-FN returns non-nil."
(let ((origin (point-marker)) (let ((origin (point-marker))
(result (result
@ -439,7 +435,7 @@ files, so we replace calls to `pp' with the much faster `prin1'."
(use-package! smartparens (use-package! smartparens
;; Auto-close delimiters and blocks as you type. It's more powerful than that, ;; Auto-close delimiters and blocks as you type. It's more powerful than that,
;; but that is all Doom uses it for. ;; but that is all Doom uses it for.
:after-call doom-switch-buffer-hook after-find-file :hook (doom-first-buffer . smartparens-global-mode)
:commands sp-pair sp-local-pair sp-with-modes sp-point-in-comment sp-point-in-string :commands sp-pair sp-local-pair sp-with-modes sp-point-in-comment sp-point-in-string
:config :config
;; smartparens recognizes `slime-mrepl-mode', but not `sly-mrepl-mode', so... ;; smartparens recognizes `slime-mrepl-mode', but not `sly-mrepl-mode', so...
@ -499,16 +495,12 @@ files, so we replace calls to `pp' with the much faster `prin1'."
(defun doom-disable-smartparens-mode-maybe-h () (defun doom-disable-smartparens-mode-maybe-h ()
(when smartparens-mode (when smartparens-mode
(setq-local doom-buffer-smartparens-mode t) (setq-local doom-buffer-smartparens-mode t)
(turn-off-smartparens-mode)))) (turn-off-smartparens-mode)))))
(smartparens-global-mode +1))
(use-package! so-long (use-package! so-long
:after-call after-find-file :hook (doom-first-file . global-so-long-mode)
:config :config
(when doom-interactive-mode
(global-so-long-mode +1))
(setq so-long-threshold 400) ; reduce false positives w/ larger threshold (setq so-long-threshold 400) ; reduce false positives w/ larger threshold
;; Don't disable syntax highlighting and line numbers, or make the buffer ;; Don't disable syntax highlighting and line numbers, or make the buffer
;; read-only, in `so-long-minor-mode', so we can have a basic editing ;; read-only, in `so-long-minor-mode', so we can have a basic editing
@ -528,6 +520,7 @@ files, so we replace calls to `pp' with the much faster `prin1'."
(appendq! so-long-minor-modes (appendq! so-long-minor-modes
'(flycheck-mode '(flycheck-mode
flyspell-mode flyspell-mode
spell-fu-mode
eldoc-mode eldoc-mode
smartparens-mode smartparens-mode
highlight-numbers-mode highlight-numbers-mode
@ -558,8 +551,7 @@ files, so we replace calls to `pp' with the much faster `prin1'."
(use-package! ws-butler (use-package! ws-butler
;; a less intrusive `delete-trailing-whitespaces' on save ;; a less intrusive `delete-trailing-whitespaces' on save
:after-call after-find-file :hook (doom-first-buffer . ws-butler-global-mode))
:config (ws-butler-global-mode +1))
(provide 'core-editor) (provide 'core-editor)
;;; core-editor.el ends here ;;; core-editor.el ends here

View file

@ -26,9 +26,12 @@ and Emacs states, and for non-evil users.")
;; ;;
;;; Keybind settings ;;; Keybind settings
(when IS-MAC (cond (IS-MAC
(setq mac-command-modifier 'super (setq mac-command-modifier 'super
mac-option-modifier 'meta)) mac-option-modifier 'meta))
(IS-WINDOWS
(setq w32-lwindow-modifier 'super
w32-rwindow-modifier 'super)))
;; ;;
@ -176,8 +179,7 @@ localleader prefix."
;;; Packages ;;; Packages
(use-package! which-key (use-package! which-key
:defer 1 :hook (doom-first-input . which-key-mode)
:after-call pre-command-hook
:init :init
(setq which-key-sort-order #'which-key-prefix-then-key-order (setq which-key-sort-order #'which-key-prefix-then-key-order
which-key-sort-uppercase-first nil which-key-sort-uppercase-first nil
@ -192,9 +194,7 @@ localleader prefix."
(setq-hook! 'which-key-init-buffer-hook line-spacing 3) (setq-hook! 'which-key-init-buffer-hook line-spacing 3)
(which-key-add-key-based-replacements doom-leader-key "<leader>") (which-key-add-key-based-replacements doom-leader-key "<leader>")
(which-key-add-key-based-replacements doom-localleader-key "<localleader>") (which-key-add-key-based-replacements doom-localleader-key "<localleader>"))
(which-key-mode +1))
;; ;;

View file

@ -118,6 +118,7 @@ unreadable. Returns the names of envvars that were changed."
(env (env
(with-temp-buffer (with-temp-buffer
(save-excursion (save-excursion
(setq-local coding-system-for-read 'utf-8)
(insert "\0\n") ; to prevent off-by-one (insert "\0\n") ; to prevent off-by-one
(insert-file-contents file)) (insert-file-contents file))
(save-match-data (save-match-data
@ -157,7 +158,7 @@ at the values with which this function was called."
A factory for quickly producing interaction commands, particularly for keybinds A factory for quickly producing interaction commands, particularly for keybinds
or aliases." or aliases."
(declare (doc-string 1) (pure t) (side-effect-free t)) (declare (doc-string 1) (pure t) (side-effect-free t))
`(lambda () (interactive) ,@body)) `(lambda (&rest _) (interactive) ,@body))
(defalias 'lambda! 'λ!) (defalias 'lambda! 'λ!)
(defun λ!! (command &optional arg) (defun λ!! (command &optional arg)
@ -165,7 +166,7 @@ or aliases."
A factory for quickly producing interactive, prefixed commands for keybinds or A factory for quickly producing interactive, prefixed commands for keybinds or
aliases." aliases."
(declare (doc-string 1) (pure t) (side-effect-free t)) (declare (doc-string 1) (pure t) (side-effect-free t))
(lambda () (interactive) (lambda (&rest _) (interactive)
(let ((current-prefix-arg arg)) (let ((current-prefix-arg arg))
(call-interactively command)))) (call-interactively command))))
(defalias 'lambda!! 'λ!!) (defalias 'lambda!! 'λ!!)
@ -209,38 +210,41 @@ the same name, for use with `funcall' or `apply'. ARGLIST and BODY are as in
(setq body (macroexp-progn body)) (setq body (macroexp-progn body))
(when (memq (car bindings) '(defun defmacro)) (when (memq (car bindings) '(defun defmacro))
(setq bindings (list bindings))) (setq bindings (list bindings)))
(dolist (binding (nreverse bindings) body) (dolist (binding (reverse bindings) (macroexpand body))
(let ((type (car binding)) (let ((type (car binding))
(rest (cdr binding))) (rest (cdr binding)))
(setq (setq
body (pcase type body (pcase type
(`defmacro `(cl-macrolet ((,(car rest) ,(cadr rest) ,@(cddr rest))) ,body)) (`defmacro `(cl-macrolet ((,(car rest) ,(cadr rest) ,@(cddr rest))) ,body))
(`defun `(cl-letf* ((,(car rest) (symbol-function #',(car rest))) (`defun `(cl-letf* ((,(car rest) (symbol-function #',(car rest)))
((symbol-function #',(car rest)) ((symbol-function #',(car rest))
(lambda ,(cadr rest) ,@(cddr rest)))) (lambda ,(cadr rest) ,@(cddr rest))))
,body)) (ignore ,(car rest))
,body))
(_ (_
(when (eq (car-safe type) 'function) (when (eq (car-safe type) 'function)
(setq type `(symbol-function ,type))) (setq type (list 'symbol-function type)))
`(cl-letf ((,type ,@rest)) ,body))))))) (list 'cl-letf (list (cons type rest)) body)))))))
(defmacro quiet! (&rest forms) (defmacro quiet! (&rest forms)
"Run FORMS without generating any output. "Run FORMS without generating any output.
This silences calls to `message', `load-file', `write-region' and anything that This silences calls to `message', `load', `write-region' and anything that
writes to `standard-output'." writes to `standard-output'."
`(cond (doom-debug-mode ,@forms) `(if doom-debug-mode
((not doom-interactive-mode) (progn ,@forms)
(letf! ((standard-output (lambda (&rest _))) ,(if doom-interactive-mode
(defun load-file (file) (load-file nil t)) `(let ((inhibit-message t)
(defun message (&rest _)) (save-silently t))
(defun write-region (start end filename &optional append visit lockname mustbenew) (prog1 ,@forms (message "")))
(unless visit (setq visit 'no-message)) `(letf! ((standard-output (lambda (&rest _)))
(funcall write-region start end filename append visit lockname mustbenew))) (defun message (&rest _))
,@forms)) (defun load (file &optional noerror nomessage nosuffix must-suffix)
((let ((inhibit-message t) (funcall load file noerror t nosuffix must-suffix))
(save-silently t)) (defun write-region (start end filename &optional append visit lockname mustbenew)
(prog1 ,@forms (message "")))))) (unless visit (setq visit 'no-message))
(funcall write-region start end filename append visit lockname mustbenew)))
,@forms))))
(defmacro if! (cond then &rest body) (defmacro if! (cond then &rest body)
"Expands to THEN if COND is non-nil, to BODY otherwise. "Expands to THEN if COND is non-nil, to BODY otherwise.
@ -466,11 +470,19 @@ advised)."
(put ',fn 'permanent-local-hook t) (put ',fn 'permanent-local-hook t)
(add-hook sym #',fn ,append)))))) (add-hook sym #',fn ,append))))))
(defmacro add-hook-trigger! (hook-var &rest targets)
"TODO"
`(let ((fn (intern (format "%s-h" ,hook-var))))
(fset fn (lambda (&rest _) (run-hooks ,hook-var) (set ,hook-var nil)))
(put ,hook-var 'permanent-local t)
(dolist (on (list ,@targets))
(if (functionp on)
(advice-add on :before fn)
(add-hook on fn)))))
(defmacro add-hook! (hooks &rest rest) (defmacro add-hook! (hooks &rest rest)
"A convenience macro for adding N functions to M hooks. "A convenience macro for adding N functions to M hooks.
If N and M = 1, there's no benefit to using this macro over `add-hook'.
This macro accepts, in order: This macro accepts, in order:
1. The mode(s) or hook(s) to add to. This is either an unquoted mode, an 1. The mode(s) or hook(s) to add to. This is either an unquoted mode, an

View file

@ -71,6 +71,13 @@ before the user's private module.")
;; ;;
;;; Bootstrap API ;;; Bootstrap API
(defun doom-initialize-core-modules ()
"Load Doom's core files for an interactive session."
(require 'core-keybinds)
(require 'core-ui)
(require 'core-projects)
(require 'core-editor))
(defun doom-initialize-modules (&optional force-p) (defun doom-initialize-modules (&optional force-p)
"Loads the init.el in `doom-private-dir' and sets up hooks for a healthy "Loads the init.el in `doom-private-dir' and sets up hooks for a healthy
session of Dooming. Will noop if used more than once, unless FORCE-P is session of Dooming. Will noop if used more than once, unless FORCE-P is
@ -78,16 +85,18 @@ non-nil."
(when (or force-p (not doom-init-modules-p)) (when (or force-p (not doom-init-modules-p))
(setq doom-init-modules-p t (setq doom-init-modules-p t
doom-modules nil) doom-modules nil)
(load custom-file 'noerror 'nomessage) (with-temp-buffer
(when (load! "init" doom-private-dir t) (doom-log "Initializing core modules")
(when doom-modules (doom-initialize-core-modules)
(maphash (lambda (key plist) (when-let (init-p (load! "init" doom-private-dir t))
(let ((doom--current-module key) (doom-log "Initializing user config")
(doom--current-flags (plist-get plist :flags))) (when doom-modules
(load! "init" (plist-get plist :path) t))) (maphash (lambda (key plist)
doom-modules)) (let ((doom--current-module key)
(run-hook-wrapped 'doom-before-init-modules-hook #'doom-try-run-hook) (doom--current-flags (plist-get plist :flags)))
(when doom-interactive-mode (load! "init" (plist-get plist :path) t)))
doom-modules))
(run-hook-wrapped 'doom-before-init-modules-hook #'doom-try-run-hook)
(when doom-modules (when doom-modules
(maphash (lambda (key plist) (maphash (lambda (key plist)
(let ((doom--current-module key) (let ((doom--current-module key)
@ -95,7 +104,8 @@ non-nil."
(load! "config" (plist-get plist :path) t))) (load! "config" (plist-get plist :path) t)))
doom-modules)) doom-modules))
(run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook) (run-hook-wrapped 'doom-init-modules-hook #'doom-try-run-hook)
(load! "config" doom-private-dir t))))) (load! "config" doom-private-dir t)
(load custom-file 'noerror (not doom-debug-mode))))))
;; ;;
@ -122,15 +132,17 @@ non-nil."
of PROPERTY and VALUEs. of PROPERTY and VALUEs.
\(fn CATEGORY MODULE PROPERTY VALUE &rest [PROPERTY VALUE [...]])" \(fn CATEGORY MODULE PROPERTY VALUE &rest [PROPERTY VALUE [...]])"
(if-let (old-plist (doom-module-get category module)) (puthash (cons category module)
(progn (if-let (old-plist (doom-module-get category module))
(when plist (if (null plist)
(when (cl-oddp (length plist)) old-plist
(signal 'wrong-number-of-arguments (list (length plist)))) (when (cl-oddp (length plist))
(while plist (signal 'wrong-number-of-arguments (list (length plist))))
(plist-put old-plist (pop plist) (pop plist)))) (while plist
(puthash (cons category module) old-plist doom-modules)) (plist-put old-plist (pop plist) (pop plist)))
(puthash (cons category module) plist doom-modules))) old-plist)
plist)
doom-modules))
(defun doom-module-set (category module &rest plist) (defun doom-module-set (category module &rest plist)
"Enables a module by adding it to `doom-modules'. "Enables a module by adding it to `doom-modules'.
@ -223,18 +235,21 @@ those directories. The first returned path is always `doom-private-dir'."
collect (plist-get plist :path))) collect (plist-get plist :path)))
nil)) nil))
(defun doom-modules (&optional refresh-p) (defun doom-module-list (&optional all-p)
"Minimally initialize `doom-modules' (a hash table) and return it. "Minimally initialize `doom-modules' (a hash table) and return it.
This value is cached. If REFRESH-P, then don't use the cached value." This value is cached. If REFRESH-P, then don't use the cached value."
(or (unless refresh-p doom-modules) (if all-p
(let (doom-interactive-mode (cl-loop for path in (cdr (doom-module-load-path 'all))
doom-modules collect (doom-module-from-path path))
doom-init-modules-p) (or doom-modules
(load! "init" doom-private-dir t) (let (doom-interactive-mode
(or doom-modules doom-modules
(make-hash-table :test 'equal doom-init-modules-p)
:size 20 (load! "init" doom-private-dir t)
:rehash-threshold 1.0))))) (or doom-modules
(make-hash-table :test 'equal
:size 20
:rehash-threshold 1.0))))))
;; ;;
@ -254,6 +269,17 @@ This value is cached. If REFRESH-P, then don't use the cached value."
;; Macros are already fontified, no need for this ;; Macros are already fontified, no need for this
(font-lock-remove-keywords 'emacs-lisp-mode use-package-font-lock-keywords) (font-lock-remove-keywords 'emacs-lisp-mode use-package-font-lock-keywords)
;; A common mistake for new users is that they inadvertantly try to install
;; their packages with package.el, by copying over old `use-package'
;; declarations with an :ensure t property. Doom doesn't use package.el, so
;; this will throw an error that will confuse beginners.
(setq use-package-ensure-function #'ignore)
;; ...On the other hand, if the user has loaded `package', then we should
;; assume they know what they're doing and restore the old behavior:
(add-transient-hook! 'package-initialize
(when (eq use-package-ensure-function #'ignore)
(setq use-package-ensure-function #'use-package-ensure-elpa)))
;; We define :minor and :magic-minor from the `auto-minor-mode' package here ;; We define :minor and :magic-minor from the `auto-minor-mode' package here
;; so we don't have to load `auto-minor-mode' so early. ;; so we don't have to load `auto-minor-mode' so early.
(dolist (keyword '(:minor :magic-minor)) (dolist (keyword '(:minor :magic-minor))
@ -364,8 +390,8 @@ for a list of all recognized module trees. Order defines precedence (from most
to least)." to least)."
`(let ((modules `(let ((modules
,@(if (keywordp (car modules)) ,@(if (keywordp (car modules))
(list (list 'quote modules)) (list (list 'quote modules))
modules))) modules)))
(unless doom-modules (unless doom-modules
(setq doom-modules (setq doom-modules
(make-hash-table :test 'equal (make-hash-table :test 'equal

View file

@ -30,43 +30,20 @@
;; `doom-core-dir'. These contain `package!' declarations that tell DOOM what ;; `doom-core-dir'. These contain `package!' declarations that tell DOOM what
;; plugins to install and where from. ;; plugins to install and where from.
;; ;;
;; All that said, you can still use package.el's commands, but 'bin/doom ;; All that said, you can still use package.el's commands, but 'bin/doom sync'
;; refresh' will purge ELPA packages. ;; will purge ELPA packages.
(defvar doom-init-packages-p nil
"If non-nil, Doom's package management system has been initialized.")
(defvar doom-packages () (defvar doom-packages ()
"A list of enabled packages. Each element is a sublist, whose CAR is the "A list of enabled packages. Each element is a sublist, whose CAR is the
package's name as a symbol, and whose CDR is the plist supplied to its package's name as a symbol, and whose CDR is the plist supplied to its
`package!' declaration. Set by `doom-initialize-packages'.") `package!' declaration. Set by `doom-initialize-packages'.")
(defvar doom-core-packages '(straight use-package)
"A list of packages that must be installed (and will be auto-installed if
missing) and shouldn't be deleted.")
(defvar doom-core-package-sources
'((org-elpa :local-repo nil)
(melpa
:type git :host github
:repo "melpa/melpa"
:no-build t)
(gnu-elpa-mirror
:type git :host github
:repo "emacs-straight/gnu-elpa-mirror"
:no-build t)
(emacsmirror-mirror
:type git :host github
:repo "emacs-straight/emacsmirror-mirror"
:no-build t))
"A list of recipes for straight's recipe repos.")
(defvar doom-disabled-packages () (defvar doom-disabled-packages ()
"A list of packages that should be ignored by `use-package!' and `after!'.") "A list of packages that should be ignored by `use-package!' and `after!'.")
;; ;;
;;; Package managers ;;; package.el
;; Ensure that, if we do need package.el, it is configured correctly. You really ;; Ensure that, if we do need package.el, it is configured correctly. You really
;; shouldn't be using it, but it may be convenient for quick package testing. ;; shouldn't be using it, but it may be convenient for quick package testing.
@ -94,7 +71,7 @@ missing) and shouldn't be deleted.")
;;; Straight ;;; Straight
(setq straight-base-dir doom-local-dir (setq straight-base-dir doom-local-dir
straight-repository-branch "master" straight-repository-branch "develop"
straight-cache-autoloads nil ; we already do this, and better. straight-cache-autoloads nil ; we already do this, and better.
;; Doom doesn't encourage you to modify packages in place. Disabling this ;; Doom doesn't encourage you to modify packages in place. Disabling this
;; makes 'doom sync' instant (once everything set up), which is much nicer ;; makes 'doom sync' instant (once everything set up), which is much nicer
@ -123,88 +100,327 @@ missing) and shouldn't be deleted.")
;; ;;
;;; Bootstrapper ;;; Bootstrappers
(defun doom--ensure-straight ()
(cl-destructuring-bind (&key pin recipe &allow-other-keys)
(doom-package-get 'straight)
(let ((repo-dir (doom-path straight-base-dir "straight/repos/straight.el"))
(repo-url (concat "http" (if gnutls-verify-error "s")
"://github.com/"
(or (plist-get recipe :repo) "raxod502/straight.el")))
(branch (or (plist-get recipe :branch) straight-repository-branch))
(call (if doom-debug-mode #'doom-exec-process #'doom-call-process)))
(if (not (file-directory-p repo-dir))
(message "Installing straight...")
;; TODO Rethink this clumsy workaround
(let ((default-directory repo-dir))
(unless (equal (cdr (doom-call-process "git" "rev-parse" "HEAD")) pin)
(delete-directory repo-dir 'recursive)
(message "Updating straight..."))))
(unless (file-directory-p repo-dir)
(cond
((eq straight-vc-git-default-clone-depth 'full)
(funcall call "git" "clone" "--origin" "origin" repo-url repo-dir))
((null pin)
(funcall call "git" "clone" "--origin" "origin" repo-url repo-dir
"--depth" (number-to-string straight-vc-git-default-clone-depth)
"--branch" straight-repository-branch))
((integerp straight-vc-git-default-clone-depth)
(make-directory repo-dir t)
(let ((default-directory repo-dir))
(funcall call "git" "init")
(funcall call "git" "checkout" "-b" straight-repository-branch)
(funcall call "git" "remote" "add" "origin" repo-url)
(funcall call "git" "fetch" "origin" pin
"--depth" (number-to-string straight-vc-git-default-clone-depth))
(funcall call "git" "checkout" "--detach" pin)))))
(require 'straight (concat repo-dir "/straight.el"))
(doom-log "Initializing recipes")
(with-temp-buffer
(insert-file-contents (doom-path repo-dir "bootstrap.el"))
;; Don't install straight for us -- we've already done that -- only set
;; up its recipe repos for us.
(eval-region (search-forward "(require 'straight)")
(point-max))))))
(defun doom-initialize-core-packages (&optional force-p)
"Ensure `straight' is installed and was compiled with this version of Emacs."
(when (or force-p (null (bound-and-true-p straight-recipe-repositories)))
(doom-log "Initializing straight")
(let ((doom-disabled-packages nil)
(doom-packages (doom-package-list nil 'core-only)))
(doom--ensure-straight)
(doom-log "Installing core packages")
(dolist (package doom-packages)
(cl-destructuring-bind (name &key recipe &allow-other-keys)
package
(when recipe
(straight-override-recipe (cons name recipe)))
(straight-use-package name))))))
(defun doom-initialize-packages (&optional force-p) (defun doom-initialize-packages (&optional force-p)
"Ensures that Doom's package system and straight.el are initialized. "Process all packages, essential and otherwise, if they haven't already been.
If FORCE-P is non-nil, do it anyway. If FORCE-P is non-nil, do it anyway.
This ensure `doom-packages' is populated, if isn't aren't already. Use this This ensures `doom-packages' is populated and `straight' recipes are properly
before any of straight's or Doom's package management's API to ensure all the processed."
necessary package metadata is initialized and available for them." (doom-initialize-core-packages force-p)
(unless doom-init-packages-p
(setq force-p t))
(when (or force-p (not (bound-and-true-p package--initialized))) (when (or force-p (not (bound-and-true-p package--initialized)))
(doom-log "Initializing package.el") (doom-log "Initializing package.el")
(require 'package) (require 'package)
(package-initialize)) (package-initialize)
(when (or force-p (not doom-packages)) (unless package--initialized
(doom-log "Initializing straight") (error "Failed to initialize package.el")))
(setq doom-init-packages-p t) (when (or force-p (null doom-packages))
(doom-ensure-straight) (doom-log "Initializing straight.el")
(mapc #'straight-use-package doom-core-packages) (or (setq doom-disabled-packages nil
(doom-log "Initializing doom-packages") doom-packages (doom-package-list))
(setq doom-disabled-packages nil (error "Failed to read any packages"))
doom-pinned-packages nil
doom-packages (doom-package-list))
(dolist (package doom-packages) (dolist (package doom-packages)
(let ((name (car package))) (cl-destructuring-bind
(with-plist! (cdr package) (recipe modules disable ignore pin) (name &key recipe disable ignore &allow-other-keys) package
(if ignore (unless ignore
(doom-log "Ignoring package %S" name) (if disable
(if (not disable)
(with-demoted-errors "Package error: %s"
(when recipe
(straight-override-recipe (cons name recipe)))
(straight-register-package name))
(doom-log "Disabling package %S" name)
(cl-pushnew name doom-disabled-packages) (cl-pushnew name doom-disabled-packages)
;; Warn about disabled core packages (when recipe
(when (cl-find :core modules :key #'car) (straight-override-recipe (cons name recipe)))
(print! (warn "%s\n%s") (straight-register-package name)))))))
(format "You've disabled %S" name)
(indent 2 (concat "This is a core package. Disabling it will cause errors, as Doom assumes\n"
"core packages are always available. Disable their minor-modes or hooks instead.")))))))))))
(defun doom-ensure-straight ()
"Ensure `straight' is installed and was compiled with this version of Emacs." ;;
(unless (fboundp 'straight--reset-caches) ;;; Package management API
(defvar bootstrap-version)
(let* (;; Force straight to install into ~/.emacs.d/.local/straight instead of (defun doom-package-get (package &optional prop nil-value)
;; ~/.emacs.d/straight by pretending `doom-local-dir' is our .emacs.d. "Returns PACKAGE's `package!' recipe from `doom-packages'."
(user-emacs-directory straight-base-dir) (let ((plist (cdr (assq package doom-packages))))
(bootstrap-file (doom-path straight-base-dir "straight/repos/straight.el/straight.el")) (if prop
(bootstrap-version 5)) (if (plist-member plist prop)
(make-directory (doom-path straight-base-dir "straight/build") 'parents) (plist-get plist prop)
(or (require 'straight nil t) nil-value)
(file-readable-p bootstrap-file) plist)))
(with-current-buffer
(url-retrieve-synchronously (defun doom-package-set (package prop value)
(format "https://raw.githubusercontent.com/raxod502/straight.el/%s/install.el" "Set PROPERTY in PACKAGE's recipe to VALUE."
straight-repository-branch) (setf (alist-get package doom-packages)
'silent 'inhibit-cookies) (plist-put (alist-get package doom-packages)
(goto-char (point-max)) prop value)))
(eval-print-last-sexp)))
(load bootstrap-file nil t)) (defun doom-package-recipe (package &optional prop nil-value)
(require 'straight)) "Returns the `straight' recipe PACKAGE was registered with."
(straight--reset-caches) (let ((plist (gethash (symbol-name package) straight--recipe-cache)))
(setq straight-recipe-repositories nil (if prop
straight-recipe-overrides nil) (if (plist-member plist prop)
(mapc #'straight-use-recipes doom-core-package-sources) (plist-get plist prop)
(straight-register-package nil-value)
`(straight :type git :host github plist)))
:repo ,(format "%s/straight.el" straight-repository-user)
:files ("straight*.el") (defun doom-package-recipe-repo (package)
:branch ,straight-repository-branch "Resolve and return PACKAGE's (symbol) local-repo property."
:no-byte-compile t))) (if-let* ((recipe (cdr (straight-recipes-retrieve package)))
(repo (straight-vc-local-repo-name recipe)))
repo
(symbol-name package)))
(defun doom-package-build-recipe (package &optional prop nil-value)
"Returns the `straight' recipe PACKAGE was installed with."
(let ((plist (nth 2 (gethash (symbol-name package) straight--build-cache))))
(if prop
(if (plist-member plist prop)
(plist-get plist prop)
nil-value)
plist)))
(defun doom-package-build-time (package)
"TODO"
(car (gethash (symbol-name package) straight--build-cache)))
(defun doom-package-dependencies (package &optional recursive _noerror)
"Return a list of dependencies for a package."
(let ((deps (nth 1 (gethash (symbol-name package) straight--build-cache))))
(if recursive
(append deps (mapcan (lambda (dep) (doom-package-dependencies dep t t))
(copy-sequence deps)))
(copy-sequence deps))))
(defun doom-package-depending-on (package &optional noerror)
"Return a list of packages that depend on the package named NAME."
(cl-check-type name symbol)
;; can't get dependencies for built-in packages
(unless (or (doom-package-build-recipe name)
noerror)
(error "Couldn't find %s, is it installed?" name))
(cl-loop for pkg in (hash-table-keys straight--build-cache)
for deps = (doom-package-dependencies pkg)
if (memq package deps)
collect pkg
and append (doom-package-depending-on pkg t)))
;;; Predicate functions
(defun doom-package-built-in-p (package)
"Return non-nil if PACKAGE (a symbol) is built-in."
(eq (doom-package-build-recipe package :type)
'built-in))
(defun doom-package-installed-p (package)
"Return non-nil if PACKAGE (a symbol) is installed."
(file-directory-p (straight--build-dir (symbol-name package))))
(defun doom-package-is-type-p (package type)
"TODO"
(memq type (doom-enlist (doom-package-get package :type))))
(defun doom-package-in-module-p (package category &optional module)
"Return non-nil if PACKAGE was installed by the user's private config."
(when-let (modules (doom-package-get package :modules))
(or (and (not module) (assq :private modules))
(member (cons category module) modules))))
(defun doom-package-backend (package)
"Return 'straight, 'builtin, 'elpa or 'other, depending on how PACKAGE is
installed."
(cond ((gethash (symbol-name package) straight--build-cache)
'straight)
((or (doom-package-built-in-p package)
(assq package package--builtins))
'builtin)
((assq package package-alist)
'elpa)
((locate-library (symbol-name package))
'other)))
(defun doom-package-changed-recipe-p (name)
"Return t if a package named NAME (a symbol) has a different recipe than it
was installed with."
(cl-check-type name symbol)
;; TODO
;; (when (doom-package-installed-p name)
;; (when-let* ((doom-recipe (assq name doom-packages))
;; (install-recipe (doom-package-recipe)))
;; (not (equal (cdr quelpa-recipe)
;; (cdr (plist-get (cdr doom-recipe) :recipe))))))
)
;;; Package getters
(defun doom--read-packages (file &optional noeval noerror)
(condition-case-unless-debug e
(with-temp-buffer ; prevent buffer-local state from propagating
(if (not noeval)
(load file noerror 'nomessage 'nosuffix)
(when (file-exists-p file)
(insert-file-contents file)
(let (emacs-lisp-mode) (emacs-lisp-mode))
;; Scrape `package!' blocks from FILE for a comprehensive listing of
;; packages used by this module.
(while (search-forward "(package!" nil t)
(let ((ppss (save-excursion (syntax-ppss))))
;; Don't collect packages in comments or strings
(unless (or (nth 3 ppss)
(nth 4 ppss))
(goto-char (match-beginning 0))
(cl-destructuring-bind (_ name . plist)
(read (current-buffer))
(push (cons
name (plist-put
plist :modules
(list (doom-module-from-path file))))
doom-packages))))))))
(error
(signal 'doom-package-error
(list (doom-module-from-path file)
file e)))))
(defun doom-package-list (&optional all-p core-only-p)
"Retrieve a list of explicitly declared packages from enabled modules.
If ALL-P, gather packages unconditionally across all modules, including disabled
ones."
(let ((doom-interactive-mode t)
doom-packages)
(doom--read-packages
(doom-path doom-core-dir "packages.el") all-p 'noerror)
(unless core-only-p
(let ((private-packages (doom-path doom-private-dir "packages.el"))
(doom-modules (doom-module-list)))
(if all-p
(mapc #'doom--read-packages
(doom-files-in doom-modules-dir
:depth 2
:match "/packages\\.el$"))
;; We load the private packages file twice to ensure disabled packages
;; are seen ASAP, and a second time to ensure privately overridden
;; packages are properly overwritten.
(doom--read-packages private-packages nil 'noerror)
(cl-loop for key being the hash-keys of doom-modules
for path = (doom-module-path (car key) (cdr key) "packages.el")
for doom--current-module = key
do (doom--read-packages path nil 'noerror)))
(doom--read-packages private-packages all-p 'noerror)))
(cl-remove-if-not
(if core-only-p
(lambda (pkg) (eq (plist-get (cdr pkg) :type) 'core))
#'identity)
(nreverse doom-packages))))
(defun doom-package-pinned-list ()
"Return an alist mapping package names (strings) to pinned commits (strings)."
(let (alist)
(dolist (package doom-packages alist)
(cl-destructuring-bind (name &key disable ignore pin unpin &allow-other-keys)
package
(when (and (not ignore)
(not disable)
(or pin unpin))
(setf (alist-get (doom-package-recipe-repo name) alist
nil 'remove #'equal)
(unless unpin pin)))))))
(defun doom-package-unpinned-list ()
"Return an alist mapping package names (strings) to pinned commits (strings)."
(let (alist)
(dolist (package doom-packages alist)
(cl-destructuring-bind
(_ &key recipe disable ignore pin unpin &allow-other-keys)
package
(when (and (not ignore)
(not disable)
(or unpin
(and (plist-member recipe :pin)
(null pin))))
(cl-pushnew (doom-package-recipe-repo (car package)) alist
:test #'equal))))))
(defun doom-package-recipe-list ()
"Return straight recipes for non-builtin packages with a local-repo."
(let (recipes)
(dolist (recipe (hash-table-values straight--recipe-cache))
(cl-destructuring-bind (&key local-repo type no-build &allow-other-keys)
recipe
(unless (or (null local-repo)
(eq type 'built-in)
no-build)
(push recipe recipes))))
(nreverse recipes)))
(defun doom-package-state-list ()
"TODO"
(let (alist)
(dolist (recipe (hash-table-values straight--repo-cache) alist)
(cl-destructuring-bind (&key local-repo type &allow-other-keys)
recipe
(when (and local-repo (not (eq type 'built-in)))
(setf (alist-get local-repo alist nil nil #'equal)
(straight-vc-get-commit type local-repo)))))))
;; ;;
;;; Module package macros ;;; Module package macros
(cl-defmacro package! (cl-defmacro package!
(name &rest plist &key built-in recipe ignore _pin _disable) (name &rest plist &key built-in recipe ignore _type _pin _disable)
"Declares a package and how to install it (if applicable). "Declares a package and how to install it (if applicable).
This macro is declarative and does not load nor install packages. It is used to This macro is declarative and does not load nor install packages. It is used to
@ -215,6 +431,15 @@ Only use this macro in a module's packages.el file.
Accepts the following properties: Accepts the following properties:
:type core|local|built-in|virtual
Specifies what kind of package this is. Can be a symbol or a list thereof.
`core' = this is a protected package and cannot be disabled!
`local' = this package is being modified in-place. This package's repo is
unshallowed and will be skipped when you update packages.
`built-in' = this package is already built-in (otherwise, will be
installed)
`virtual' = this package is not tracked by Doom's package manager. It won't
be installed or uninstalled. Use this to pin 2nd order dependencies.
:recipe RECIPE :recipe RECIPE
Specifies a straight.el recipe to allow you to acquire packages from external Specifies a straight.el recipe to allow you to acquire packages from external
sources. See https://github.com/raxod502/straight.el#the-recipe-format for sources. See https://github.com/raxod502/straight.el#the-recipe-format for
@ -254,6 +479,8 @@ elsewhere."
(plist-put! plist :modules (plist-put! plist :modules
(append module-list (append module-list
(list module) (list module)
(when (file-in-directory-p ,(dir!) doom-private-dir)
'((:private . modules)))
nil)))) nil))))
;; Merge given plist with pre-existing one ;; Merge given plist with pre-existing one
(doplist! ((prop val) (list ,@plist) plist) (doplist! ((prop val) (list ,@plist) plist)
@ -282,8 +509,9 @@ elsewhere."
(error-message-string e))))) (error-message-string e)))))
;; This is the only side-effect of this macro! ;; This is the only side-effect of this macro!
(setf (alist-get name doom-packages) plist) (setf (alist-get name doom-packages) plist)
(with-no-warnings (unless (plist-get plist :disable)
(not (plist-get plist :disable))))) (with-no-warnings
(cons name plist)))))
(defmacro disable-packages! (&rest packages) (defmacro disable-packages! (&rest packages)
"A convenience macro for disabling packages in bulk. "A convenience macro for disabling packages in bulk.
@ -311,24 +539,26 @@ should use it!"
(if (memq t targets) (if (memq t targets)
`(mapc (doom-rpartial #'doom-package-set :unpin t) `(mapc (doom-rpartial #'doom-package-set :unpin t)
(mapcar #'car doom-packages)) (mapcar #'car doom-packages))
(let (forms) (macroexp-progn
(dolist (target targets) (mapcar
(cl-check-type target (or symbol keyword list)) (lambda (target)
(cond (when target
((symbolp target) `(doom-package-set ',target :unpin t)))
(push `(doom-package-set ',target :unpin t) forms)) (cl-loop for target in targets
((or (keywordp target) if (or (keywordp target) (listp target))
(listp target)) append
(cl-destructuring-bind (category . modules) (doom-enlist target) (cl-loop with (category . modules) = (doom-enlist target)
(dolist (pkg doom-packages) for (name . plist) in doom-packages
(let ((pkg-modules (plist-get (cdr pkg) :modules))) for pkg-modules = (plist-get plist :modules)
(and (assq category pkg-modules) if (and (assq category pkg-modules)
(or (null modules) (or (null modules)
(cl-loop for module in modules (cl-loop for module in modules
if (member (cons category module) pkg-modules) if (member (cons category module) pkg-modules)
return t)) return t))
(push `(doom-package-set ',(car pkg) :unpin t) forms)))))))) name)
(macroexp-progn forms)))) collect it)
else if (symbolp target)
collect target)))))
(provide 'core-packages) (provide 'core-packages)
;;; core-packages.el ends here ;;; core-packages.el ends here

View file

@ -20,7 +20,6 @@ Emacs.")
;;; Packages ;;; Packages
(use-package! projectile (use-package! projectile
:after-call after-find-file dired-before-readin-hook minibuffer-setup-hook
:commands (projectile-project-root :commands (projectile-project-root
projectile-project-name projectile-project-name
projectile-project-p projectile-project-p
@ -146,8 +145,9 @@ c) are not valid projectile projects."
;; .gitignore. This is recommended in the projectile docs. ;; .gitignore. This is recommended in the projectile docs.
((executable-find doom-projectile-fd-binary) ((executable-find doom-projectile-fd-binary)
(setq projectile-generic-command (setq projectile-generic-command
(format "%s . -0 -H -E .git --color=never --type file --type symlink --follow" (concat (format "%s . -0 -H -E .git --color=never --type file --type symlink --follow"
doom-projectile-fd-binary) doom-projectile-fd-binary)
(if IS-WINDOWS " --path-separator=/"))
projectile-git-command projectile-generic-command projectile-git-command projectile-generic-command
projectile-git-submodule-command nil projectile-git-submodule-command nil
;; ensure Windows users get fd's benefits ;; ensure Windows users get fd's benefits

View file

@ -443,9 +443,10 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
(use-package! winner (use-package! winner
;; undo/redo changes to Emacs' window layout ;; undo/redo changes to Emacs' window layout
:after-call after-find-file doom-switch-window-hook :hook (window-configuration-change . winner-mode)
:preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself :preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
:config (winner-mode +1) :config
(remove-hook 'window-configuration-change #'winner-mode)
(appendq! winner-boring-buffers (appendq! winner-boring-buffers
'("*Compile-Log*" "*inferior-lisp*" "*Fuzzy Completions*" '("*Compile-Log*" "*inferior-lisp*" "*Fuzzy Completions*"
"*Apropos*" "*Help*" "*cvs*" "*Buffer List*" "*Ibuffer*" "*Apropos*" "*Help*" "*cvs*" "*Buffer List*" "*Ibuffer*"
@ -454,13 +455,12 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
(use-package! paren (use-package! paren
;; highlight matching delimiters ;; highlight matching delimiters
:after-call after-find-file doom-switch-buffer-hook :hook (doom-first-buffer . show-paren-mode)
:config :config
(setq show-paren-delay 0.1 (setq show-paren-delay 0.1
show-paren-highlight-openparen t show-paren-highlight-openparen t
show-paren-when-point-inside-paren t show-paren-when-point-inside-paren t
show-paren-when-point-in-periphery t) show-paren-when-point-in-periphery t))
(show-paren-mode +1))
;;;###package whitespace ;;;###package whitespace

View file

@ -1,8 +1,9 @@
;;; core.el --- the heart of the beast -*- lexical-binding: t; -*- ;;; core.el --- the heart of the beast -*- lexical-binding: t; -*-
(when (version< emacs-version "26.1") (eval-when-compile
(error "Detected Emacs %s. Doom only supports Emacs 26.1 and higher" (when (< emacs-major-version 26)
emacs-version)) (error "Detected Emacs v%s. Doom only supports Emacs 26 and newer"
emacs-version)))
(defconst doom-version "2.0.9" (defconst doom-version "2.0.9"
"Current version of Doom Emacs.") "Current version of Doom Emacs.")
@ -195,7 +196,7 @@ users).")
;; Emacs "updates" its ui more often than it needs to, so we slow it down ;; Emacs "updates" its ui more often than it needs to, so we slow it down
;; slightly from 0.5s: ;; slightly from 0.5s:
(setq idle-update-delay 1) (setq idle-update-delay 1.0)
;; Emacs is essentially one huge security vulnerability, what with all the ;; Emacs is essentially one huge security vulnerability, what with all the
;; dependencies it pulls in from all corners of the globe. Let's try to be at ;; dependencies it pulls in from all corners of the globe. Let's try to be at
@ -291,7 +292,9 @@ users).")
;; Performance on Windows is considerably worse than elsewhere, especially if ;; Performance on Windows is considerably worse than elsewhere, especially if
;; WSL is involved. We'll need everything we can get. ;; WSL is involved. We'll need everything we can get.
(when IS-WINDOWS (when IS-WINDOWS
(setq w32-get-true-file-attributes nil)) ; slightly faster IO (setq w32-get-true-file-attributes nil ; slightly faster IO
w32-pipe-read-delay 0 ; faster ipc
w32-pipe-buffer-size (* 64 1024))) ; read more at a time (was 4K)
;; Remove command line options that aren't relevant to our current OS; means ;; Remove command line options that aren't relevant to our current OS; means
;; slightly less to process at startup. ;; slightly less to process at startup.
@ -304,15 +307,13 @@ users).")
;; Adopt a sneaky garbage collection strategy of waiting until idle time to ;; Adopt a sneaky garbage collection strategy of waiting until idle time to
;; collect; staving off the collector while the user is working. ;; collect; staving off the collector while the user is working.
(when doom-interactive-mode (setq gcmh-idle-delay 5
(setq gc-cons-percentage 0.6) gcmh-high-cons-threshold 16777216 ; 16mb
(add-transient-hook! 'pre-command-hook (gcmh-mode +1)) gcmh-verbose doom-debug-mode
(with-eval-after-load 'gcmh gc-cons-percentage 0.6)
(setq gcmh-idle-delay 10 (with-eval-after-load 'gcmh
gcmh-high-cons-threshold 16777216 ;; But restore this later, otherwise we risk freezing and stuttering!
gcmh-verbose doom-debug-mode ; 16mb (setq gc-cons-percentage 0.1))
gc-cons-percentage 0.1)
(add-hook 'focus-out-hook #'gcmh-idle-garbage-collect)))
;; HACK `tty-run-terminal-initialization' is *tremendously* slow for some ;; HACK `tty-run-terminal-initialization' is *tremendously* slow for some
;; reason. Disabling it completely could have many side-effects, so we ;; reason. Disabling it completely could have many side-effects, so we
@ -335,18 +336,14 @@ users).")
"Run MODE-local-vars-hook after local variables are initialized." "Run MODE-local-vars-hook after local variables are initialized."
(run-hook-wrapped (intern-soft (format "%s-local-vars-hook" major-mode)) (run-hook-wrapped (intern-soft (format "%s-local-vars-hook" major-mode))
#'doom-try-run-hook)) #'doom-try-run-hook))
(add-hook 'hack-local-variables-hook #'doom-run-local-var-hooks-h)
;; If the user has disabled `enable-local-variables', then ;; If the user has disabled `enable-local-variables', then
;; `hack-local-variables-hook' is never triggered, so we trigger it at the end ;; `hack-local-variables-hook' is never triggered, so we trigger it at the end
;; of `after-change-major-mode-hook': ;; of `after-change-major-mode-hook':
(defun doom-run-local-var-hooks-if-necessary-h () (defun doom-run-local-var-hooks-maybe-h ()
"Run `doom-run-local-var-hooks-h' if `enable-local-variables' is disabled." "Run `doom-run-local-var-hooks-h' if `enable-local-variables' is disabled."
(unless enable-local-variables (unless enable-local-variables
(doom-run-local-var-hooks-h))) (doom-run-local-var-hooks-h)))
(add-hook 'after-change-major-mode-hook
#'doom-run-local-var-hooks-if-necessary-h
'append)
;; ;;
@ -425,7 +422,18 @@ If this is a daemon session, load them all immediately instead."
nil #'doom-load-packages-incrementally nil #'doom-load-packages-incrementally
(cdr doom-incremental-packages) t)))) (cdr doom-incremental-packages) t))))
(add-hook 'emacs-startup-hook #'doom-load-packages-incrementally-h)
;;
;;; Custom hooks
(defvar doom-first-input-hook nil
"Transient hooks run before the first user input.")
(defvar doom-first-file-hook nil
"Transient hooks run before the first interactively opened file.")
(defvar doom-first-buffer-hook nil
"Transient hooks run before the first interactively opened buffer.")
;; ;;
@ -443,7 +451,7 @@ If RETURN-P, return the message as a string instead of displaying it."
(setq doom-init-time (setq doom-init-time
(float-time (time-subtract (current-time) before-init-time)))))) (float-time (time-subtract (current-time) before-init-time))))))
(defun doom-initialize (&optional force-p noerror) (defun doom-initialize (&optional force-p)
"Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil). "Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil).
The bootstrap process ensures that the essential directories exist, all core The bootstrap process ensures that the essential directories exist, all core
@ -471,6 +479,7 @@ for a list of all recognized module trees. Order defines precedence (from most
to least)." to least)."
(when (or force-p (not doom-init-p)) (when (or force-p (not doom-init-p))
(setq doom-init-p t) (setq doom-init-p t)
(doom-log "Initializing Doom")
;; Reset as much state as possible, so `doom-initialize' can be treated like ;; Reset as much state as possible, so `doom-initialize' can be treated like
;; a reset function. e.g. when reloading the config. ;; a reset function. e.g. when reloading the config.
@ -478,70 +487,55 @@ to least)."
load-path doom--initial-load-path load-path doom--initial-load-path
process-environment doom--initial-process-environment) process-environment doom--initial-process-environment)
;; Load shell environment, optionally generated from 'doom env'. No need to (or (and
;; do so if we're in terminal Emacs, because Emacs will correctly inherit ;; `doom-autoload-file' tells Emacs where to load all its functions
;; from. This includes everything in core/autoload/*.el and
;; autoload files in enabled modules.
(or (doom-load-autoloads-file doom-autoload-file)
(ignore (warn "Doom's core autoloads file is missing")))
;; Loads `doom-package-autoload-file', which loads a concatenated
;; package autoloads file which caches `load-path',
;; `auto-mode-alist', `Info-directory-list', and
;; `doom-disabled-packages'. A big reduction in startup time.
(or (doom-load-autoloads-file doom-package-autoload-file)
(ignore (warn "Doom's package autoloads file is missing"))))
;; If neither autoloads file loads, then the user forgot to sync, or
;; aborted a doom command midway!
(signal 'doom-error
(list "Doom is in an incomplete state"
"run 'bin/doom sync' on the command line to repair it")))
;; Load shell environment, optionally generated from 'doom env'. No need
;; to do so if we're in terminal Emacs, where Emacs correctly inherits
;; your shell environment there. ;; your shell environment there.
(when (and (or (display-graphic-p) (and (or (display-graphic-p)
(daemonp)) (daemonp))
(file-exists-p doom-env-file)) (doom-load-envvars-file doom-env-file 'noerror))
(doom-load-envvars-file doom-env-file))
;; Loads `use-package' and our module helper library
(require 'core-modules) (require 'core-modules)
(let (;; `doom-autoload-file' tells Emacs where to load all its functions
;; from. This includes everything in core/autoload/*.el and autoload
;; files in enabled modules.
(core-autoloads-p (doom-load-autoloads-file doom-autoload-file noerror))
;; Loads `doom-package-autoload-file', which loads a concatenated
;; package autoloads file which caches `load-path', `auto-mode-alist',
;; `Info-directory-list', and `doom-disabled-packages'. A big
;; reduction in startup time.
(pkg-autoloads-p (doom-load-autoloads-file doom-package-autoload-file noerror)))
(if (and core-autoloads-p pkg-autoloads-p (not force-p)) ;; In case we want to use package.el or straight via M-x later
;; In case we want to use package.el or straight via M-x (autoload 'doom-initialize-packages "core-packages")
(progn (autoload 'doom-initialize-core-packages "core-packages")
(with-eval-after-load 'package (with-eval-after-load 'package (require 'core-packages))
(require 'core-packages)) (with-eval-after-load 'straight (doom-initialize-packages))
(with-eval-after-load 'straight
(require 'core-packages)
(doom-initialize-packages)))
;; Eagerly load these libraries because we may be in a session that hasn't been ;; Bootstrap the interactive session
;; fully initialized (e.g. where autoloads files haven't been generated or (add-hook! 'window-setup-hook
;; `load-path' populated). (add-hook 'hack-local-variables-hook #'doom-run-local-var-hooks-h)
(mapc (doom-rpartial #'load nil (not doom-debug-mode) 'nosuffix) (add-hook 'after-change-major-mode-hook #'doom-run-local-var-hooks-maybe-h 'append)
(file-expand-wildcards (concat doom-core-dir "autoload/*.el"))) (add-hook 'doom-first-input-hook #'gcmh-mode)
(add-hook-trigger! 'doom-first-input-hook 'pre-command-hook)
(add-hook-trigger! 'doom-first-file-hook 'after-find-hook 'dired-initial-position-hook)
(add-hook-trigger! 'doom-first-buffer-hook 'after-find-hook 'doom-switch-buffer-hook))
(add-hook 'emacs-startup-hook #'doom-load-packages-incrementally-h)
(add-hook 'window-setup-hook #'doom-display-benchmark-h 'append)
;; Create all our core directories to quell file errors ;; Load core/core-*.el, the user's private init.el and their config.el
(mapc (doom-rpartial #'make-directory 'parents) (doom-initialize-modules force-p))
(list doom-local-dir
doom-etc-dir
doom-cache-dir))
;; Ensure the package management system (and straight) are ready for doom-init-p)
;; action (and all core packages/repos are installed)
(require 'core-packages)
(doom-initialize-packages force-p))
(unless (or (and core-autoloads-p pkg-autoloads-p)
noerror)
(unless core-autoloads-p
(warn "Your Doom core autoloads file is missing"))
(unless pkg-autoloads-p
(warn "Your package autoloads file is missing"))
(signal 'doom-autoload-error (list "Run `bin/doom refresh' to generate them")))
(when doom-interactive-mode
(add-hook 'window-setup-hook #'doom-display-benchmark-h 'append)
(add-to-list 'command-switch-alist (cons "--restore" #'doom-restore-session-handler))))
t))
(defun doom-initialize-core ()
"Load Doom's core files for an interactive session."
(require 'core-keybinds)
(require 'core-ui)
(require 'core-projects)
(require 'core-editor))
(provide 'core) (provide 'core)
;;; core.el ends here ;;; core.el ends here

View file

@ -5,8 +5,24 @@
(package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065") (package! auto-minor-mode :pin "17cfa1b54800fdef2975c0c0531dad34846a5065")
(package! gcmh :pin "b1bde5089169a74f62033d027e06e98cbeedd43f") (package! gcmh :pin "b1bde5089169a74f62033d027e06e98cbeedd43f")
;; core-packages.el
(package! straight
:type 'core
:recipe `(:host github
:repo "raxod502/straight.el"
:branch ,straight-repository-branch
:local-repo "straight.el"
:files ("straight*.el")
:no-build t)
:pin "f606bfaf9330cfb1ef6971bb1f6ac4e2c39a39c2")
;; core-modules.el
(package! use-package
:type 'core
:pin "c873d5529c9c80cb58222f22873a4f081c307cb2")
;; core-ui.el ;; core-ui.el
(package! all-the-icons :pin "0b74fc361817e885580c3f3408079f949f5830e1") (package! all-the-icons :pin "d6cb6d4a779eaa3570d8e451fd4d38b2b4554860")
(package! hide-mode-line :pin "88888825b5b27b300683e662fa3be88d954b1cea") (package! hide-mode-line :pin "88888825b5b27b300683e662fa3be88d954b1cea")
(package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307") (package! highlight-numbers :pin "8b4744c7f46c72b1d3d599d4fb75ef8183dee307")
(package! rainbow-delimiters :pin "5125f4e47604ad36c3eb4706310fcafac729ca8c") (package! rainbow-delimiters :pin "5125f4e47604ad36c3eb4706310fcafac729ca8c")
@ -14,8 +30,8 @@
;; core-editor.el ;; core-editor.el
(package! better-jumper :pin "6d240032ca213ccb3347e25f26c29b6822bf03a7") (package! better-jumper :pin "6d240032ca213ccb3347e25f26c29b6822bf03a7")
(package! dtrt-indent :pin "9163cd990fb1f43dafed3948c6e406c13a45a6be") (package! dtrt-indent :pin "50c440c80e0d15303d8ab543bce4c56e9c2bf407")
(package! helpful :pin "c54e9ddbd6a77858048c1a4c4b549de98af8f88e") (package! helpful :pin "c0662aa07266fe204f4e6d72ccaa6af089400556")
(when IS-MAC (when IS-MAC
(package! ns-auto-titlebar :pin "1efc30d38509647b417f05587fd7003457719256")) (package! ns-auto-titlebar :pin "1efc30d38509647b417f05587fd7003457719256"))
(package! pcre2el :pin "0b5b2a2c173aab3fd14aac6cf5e90ad3bf58fa7d") (package! pcre2el :pin "0b5b2a2c173aab3fd14aac6cf5e90ad3bf58fa7d")
@ -38,7 +54,7 @@
:pin "01b39044b9b65fa4ea7d3166f8b1ffab6f740362")) :pin "01b39044b9b65fa4ea7d3166f8b1ffab6f740362"))
;; core-projects.el ;; core-projects.el
(package! projectile :pin "5cd261dd75f4d711c0016617621349e2a98b43aa") (package! projectile :pin "768f0570cad57b6885c4472df803906d097cbc1a")
;; core-keybinds.el ;; core-keybinds.el
(package! general :pin "42e38034cd2305fa7432866323c923979d8f9b06") (package! general :pin "42e38034cd2305fa7432866323c923979d8f9b06")

View file

@ -1,25 +1,19 @@
Before you doom yourself, there are a few things you should know: But before you doom yourself, here are some things you should know:
1. Whenever you edit your doom! block in ~/.doom.d/init.el or modify your 1. Don't forget to run 'doom sync', then restart Emacs, after modifying
modules, run: ~/.doom.d/init.el or ~/.doom.d/packages.el.
bin/doom refresh This command ensures needed packages are installed, orphaned packages are
removed, and your autoloads/cache files are up to date. When in doubt, run
'doom sync'!
This will ensure all needed packages are installed, all orphaned packages are 2. If something goes wrong, run `doom doctor`. It diagnoses common issues with
removed, and your autoloads files are up to date. This is important! If you your environment and setup, and may offer clues about what is wrong.
forget to do this you will get errors!
2. If something inexplicably goes wrong, try `bin/doom doctor` 3. Use 'doom upgrade' to update Doom. Doing it any other way will require
additional steps. Run 'doom help upgrade' to understand those extra steps.
This will diagnose common issues with your environment and setup, and may 4. Access Doom's documentation from within Emacs via 'SPC h D' or 'C-h D' (or
give you clues about what is wrong. 'M-x doom/help')
3. Use `bin/doom upgrade` to update Doom. Doing it any other way may require
additional work. When in doubt, run `bin/doom sync`.
4. Check out `bin/doom help` to see what else `bin/doom` can do (and it is
recommended you add ~/.emacs.d/bin to your PATH).
5. You can find Doom's documentation via `M-x doom/help` or `SPC h D`.
Have fun! Have fun!

View file

@ -546,7 +546,7 @@ These are side-by-side comparisons, showing how to bind keys with and without
(fullscreen . ,fullscreen)))))) (fullscreen . ,fullscreen))))))
(defun save-frame-dimensions () (defun save-frame-dimensions ()
(doom-store-set 'last-frame-size (doom-store-put 'last-frame-size
(list (frame-position) (list (frame-position)
(frame-width) (frame-width)
(frame-height) (frame-height)

View file

@ -755,7 +755,7 @@ The ~package!~ macro possesses a ~:disable~ property:
(package! rtags :disable t) (package! rtags :disable t)
#+END_SRC #+END_SRC
Once a package is disabled, ~use-packages!~ and ~after!~ blocks for it will be 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 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. this to disable Doom's packages that you don't want or need.

View file

@ -128,7 +128,7 @@ Modules that bring support for a language or group of languages to Emacs.
+ [[file:../modules/lang/perl/README.org][perl]] - TODO + [[file:../modules/lang/perl/README.org][perl]] - TODO
+ [[file:../modules/lang/php/README.org][php]] =+lsp= - TODO + [[file:../modules/lang/php/README.org][php]] =+lsp= - TODO
+ plantuml - TODO + plantuml - TODO
+ purescript - TODO + purescript =+lsp= - TODO
+ [[file:../modules/lang/python/README.org][python]] =+lsp +pyenv +conda +poetry= - TODO + [[file:../modules/lang/python/README.org][python]] =+lsp +pyenv +conda +poetry= - TODO
+ qt - TODO + qt - TODO
+ racket - TODO + racket - TODO

View file

@ -47,7 +47,3 @@
;; And let 'er rip! ;; And let 'er rip!
(doom-initialize) (doom-initialize)
(if noninteractive
(doom-initialize-packages)
(doom-initialize-core)
(doom-initialize-modules))

View file

@ -5,7 +5,7 @@
(use-package! flycheck (use-package! flycheck
:commands flycheck-list-errors flycheck-buffer :commands flycheck-list-errors flycheck-buffer
:after-call doom-switch-buffer-hook after-find-file :hook (doom-first-buffer . global-flycheck-mode)
:config :config
(setq flycheck-emacs-lisp-load-path 'inherit) (setq flycheck-emacs-lisp-load-path 'inherit)
@ -39,9 +39,7 @@
:n "j" #'flycheck-error-list-next-error :n "j" #'flycheck-error-list-next-error
:n "k" #'flycheck-error-list-previous-error :n "k" #'flycheck-error-list-previous-error
:n "RET" #'flycheck-error-list-goto-error :n "RET" #'flycheck-error-list-goto-error
:n [return] #'flycheck-error-list-goto-error) :n [return] #'flycheck-error-list-goto-error))
(global-flycheck-mode +1))
(use-package! flycheck-popup-tip (use-package! flycheck-popup-tip

View file

@ -2,7 +2,7 @@
(use-package! company (use-package! company
:commands company-complete-common company-manual-begin company-grab-line :commands company-complete-common company-manual-begin company-grab-line
:after-call pre-command-hook after-find-file :hook (doom-first-input . global-company-mode)
:init :init
(setq company-idle-delay 0.25 (setq company-idle-delay 0.25
company-minimum-prefix-length 2 company-minimum-prefix-length 2
@ -10,7 +10,7 @@
company-tooltip-align-annotations t company-tooltip-align-annotations t
company-require-match 'never company-require-match 'never
company-global-modes company-global-modes
'(not erc-mode message-mode help-mode gud-mode eshell-mode) '(not erc-mode message-mode help-mode gud-mode)
company-frontends '(company-pseudo-tooltip-frontend company-frontends '(company-pseudo-tooltip-frontend
company-echo-metadata-frontend) company-echo-metadata-frontend)
@ -37,7 +37,14 @@
(unless (featurep! +childframe) (unless (featurep! +childframe)
;; Don't persist company popups when switching back to normal mode. ;; Don't persist company popups when switching back to normal mode.
;; `company-box' aborts on mode switch so it doesn't need this. ;; `company-box' aborts on mode switch so it doesn't need this.
(add-hook 'evil-normal-state-entry-hook #'company-abort)) (add-hook! 'evil-normal-state-entry-hook
(defun +company-abort-h ()
;; HACK `company-abort' doesn't no-op if company isn't active; causing
;; unwanted side-effects, like the suppression of messages in the
;; echo-area.
;; REVIEW Revisit this to refactor; shouldn't be necessary!
(when company-candidates
(company-abort)))))
;; Allow users to switch between backends on the fly. E.g. C-x C-s followed ;; Allow users to switch between backends on the fly. E.g. C-x C-s followed
;; by C-x C-n, will switch from `company-yasnippet' to ;; by C-x C-n, will switch from `company-yasnippet' to
;; `company-dabbrev-code'. ;; `company-dabbrev-code'.
@ -45,8 +52,7 @@
:before #'company-begin-backend :before #'company-begin-backend
(company-abort))) (company-abort)))
(add-hook 'after-change-major-mode-hook #'+company-init-backends-h 'append) (add-hook 'after-change-major-mode-hook #'+company-init-backends-h 'append))
(global-company-mode +1))
(use-package! company-tng (use-package! company-tng
@ -137,8 +143,7 @@
"This disables the company-box scrollbar, because: "This disables the company-box scrollbar, because:
https://github.com/sebastiencs/company-box/issues/44" https://github.com/sebastiencs/company-box/issues/44"
:around #'company-box--update-scrollbar :around #'company-box--update-scrollbar
(cl-letf (((symbol-function #'display-buffer-in-side-window) (letf! ((#'display-buffer-in-side-window #'ignore))
(symbol-function #'ignore)))
(apply orig-fn args)))) (apply orig-fn args))))

View file

@ -23,8 +23,7 @@ be negative.")
;;; Packages ;;; Packages
(use-package! helm-mode (use-package! helm-mode
:defer t :hook (doom-first-input . helm-mode)
:after-call pre-command-hook
:init :init
(map! [remap apropos] #'helm-apropos (map! [remap apropos] #'helm-apropos
[remap find-library] #'helm-locate-library [remap find-library] #'helm-locate-library
@ -43,7 +42,6 @@ be negative.")
[remap recentf-open-files] #'helm-recentf [remap recentf-open-files] #'helm-recentf
[remap yank-pop] #'helm-show-kill-ring) [remap yank-pop] #'helm-show-kill-ring)
:config :config
(helm-mode +1)
;; helm is too heavy for `find-file-at-point' ;; helm is too heavy for `find-file-at-point'
(add-to-list 'helm-completing-read-handlers-alist (cons #'find-file-at-point nil))) (add-to-list 'helm-completing-read-handlers-alist (cons #'find-file-at-point nil)))

View file

@ -8,12 +8,12 @@
;;; Packages ;;; Packages
(use-package! ido (use-package! ido
:after-call pre-command-hook :hook (doom-first-input . ido-mode)
:hook (ido-mode . ido-everywhere) :hook (ido-mode . ido-everywhere)
:hook (ido-mode . ido-ubiquitous-mode) :hook (ido-mode . ido-ubiquitous-mode)
:preface :preface
;; HACK `ido' is a really old package. It defines `ido-mode' manually and ;; HACK `ido' is a really old package. It defines `ido-mode' manually and
;; doesn't define a hook, so we define one for it.") ;; doesn't define a hook, so we define one for it, so we can use it!
(defadvice! +ido-run-hooks-a (&rest _) (defadvice! +ido-run-hooks-a (&rest _)
:after #'ido-mode :after #'ido-mode
(run-hooks 'ido-mode-hook)) (run-hooks 'ido-mode-hook))
@ -42,9 +42,7 @@
;; Go to $HOME with ~ ;; Go to $HOME with ~
"~" (λ! (if (looking-back "/" (point-min)) "~" (λ! (if (looking-back "/" (point-min))
(insert "~/") (insert "~/")
(call-interactively #'self-insert-command)))) (call-interactively #'self-insert-command)))))
(ido-mode +1))
(use-package! ido-vertical-mode (use-package! ido-vertical-mode

View file

@ -178,7 +178,7 @@ If ARG (universal argument), open selection in other-window."
(user-error "%S doesn't support wgrep" caller))))) (user-error "%S doesn't support wgrep" caller)))))
;;;###autoload ;;;###autoload
(defun +ivy-yas-prompt (prompt choices &optional display-fn) (defun +ivy-yas-prompt-fn (prompt choices &optional display-fn)
(yas-completing-prompt prompt choices display-fn #'ivy-completing-read)) (yas-completing-prompt prompt choices display-fn #'ivy-completing-read))
;;;###autoload ;;;###autoload

View file

@ -19,7 +19,7 @@ results buffer.")
;;; Packages ;;; Packages
(use-package! ivy (use-package! ivy
:after-call pre-command-hook :hook (doom-first-input . ivy-mode)
:init :init
(let ((standard-search-fn (let ((standard-search-fn
(if (featurep! +prescient) (if (featurep! +prescient)
@ -88,7 +88,7 @@ results buffer.")
(setq +ivy--origin nil))) (setq +ivy--origin nil)))
(after! yasnippet (after! yasnippet
(add-hook 'yas-prompt-functions #'+ivy-yas-prompt)) (add-hook 'yas-prompt-functions #'+ivy-yas-prompt-fn))
(defadvice! +ivy--inhibit-completion-in-region-a (orig-fn &rest args) (defadvice! +ivy--inhibit-completion-in-region-a (orig-fn &rest args)
"`ivy-completion-in-region' struggles with completing certain "`ivy-completion-in-region' struggles with completing certain
@ -98,12 +98,10 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(apply orig-fn args))) (apply orig-fn args)))
(define-key! ivy-minibuffer-map (define-key! ivy-minibuffer-map
"C-c C-e" #'+ivy/woccur
[remap doom/delete-backward-word] #'ivy-backward-kill-word [remap doom/delete-backward-word] #'ivy-backward-kill-word
"C-c C-e" #'+ivy/woccur
"C-o" #'ivy-dispatching-done "C-o" #'ivy-dispatching-done
"M-o" #'hydra-ivy/body) "M-o" #'hydra-ivy/body))
(ivy-mode +1))
(use-package! ivy-rich (use-package! ivy-rich
@ -116,12 +114,12 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(cadr (plist-get ivy-rich-display-transformers-list (cadr (plist-get ivy-rich-display-transformers-list
'ivy-switch-buffer)))) 'ivy-switch-buffer))))
;; Include variable value in `counsel-describe-variable' ;; Enahnce the appearance of a couple counsel commands
(plist-put! ivy-rich-display-transformers-list (plist-put! ivy-rich-display-transformers-list
'counsel-describe-variable 'counsel-describe-variable
'(:columns '(:columns
((counsel-describe-variable-transformer (:width 40)) ; the original transformer ((counsel-describe-variable-transformer (:width 40)) ; the original transformer
(+ivy-rich-describe-variable-transformer (:width 50)) (+ivy-rich-describe-variable-transformer (:width 50)) ; display variable value
(ivy-rich-counsel-variable-docstring (:face font-lock-doc-face)))) (ivy-rich-counsel-variable-docstring (:face font-lock-doc-face))))
'counsel-M-x 'counsel-M-x
'(:columns '(:columns
@ -141,10 +139,9 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
;; Highlight buffers differently based on whether they're in the same project ;; Highlight buffers differently based on whether they're in the same project
;; as the current project or not. ;; as the current project or not.
(let* ((plist (plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer)) (when-let* ((plist (plist-get ivy-rich-display-transformers-list 'ivy-switch-buffer))
(switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns)))) (switch-buffer-alist (assq 'ivy-rich-candidate (plist-get plist :columns))))
(when switch-buffer-alist (setcar switch-buffer-alist '+ivy-rich-buffer-name))
(setcar switch-buffer-alist '+ivy-rich-buffer-name)))
(ivy-rich-mode +1)) (ivy-rich-mode +1))
@ -265,9 +262,10 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
:override #'counsel--find-return-list :override #'counsel--find-return-list
(cl-destructuring-bind (find-program . args) (cl-destructuring-bind (find-program . args)
(cond ((executable-find doom-projectile-fd-binary) (cond ((executable-find doom-projectile-fd-binary)
(cons doom-projectile-fd-binary (append (list doom-projectile-fd-binary
(list "--color=never" "-E" ".git" "--color=never" "-E" ".git"
"--type" "file" "--type" "symlink" "--follow"))) "--type" "file" "--type" "symlink" "--follow")
(if IS-WINDOWS '("--path-separator=/"))))
((executable-find "rg") ((executable-find "rg")
(append (list "rg" "--files" "--follow" "--color=never" "--hidden" "--no-messages") (append (list "rg" "--files" "--follow" "--color=never" "--hidden" "--no-messages")
(cl-loop for dir in projectile-globally-ignored-directories (cl-loop for dir in projectile-globally-ignored-directories
@ -284,8 +282,8 @@ evil-ex-specific constructs, so we disable it solely in evil-ex."
(let ((offset (if (member find-program (list "rg" doom-projectile-fd-binary)) 0 2)) (let ((offset (if (member find-program (list "rg" doom-projectile-fd-binary)) 0 2))
files) files)
(while (< (point) (point-max)) (while (< (point) (point-max))
(push (buffer-substring (push (buffer-substring (+ offset (line-beginning-position)) (line-end-position))
(+ offset (line-beginning-position)) (line-end-position)) files) files)
(forward-line 1)) (forward-line 1))
(nreverse files))))))) (nreverse files)))))))

View file

@ -1,18 +1,18 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; completion/ivy/packages.el ;;; completion/ivy/packages.el
(package! swiper :pin "84efa3a2cbb9c5b0bbcc8d2e90671434eed74f94") (package! swiper :pin "04ca16420053a3a6d34a96f0d680dd449c2e5851")
(package! ivy) (package! ivy)
(package! ivy-hydra) (package! ivy-hydra)
(package! counsel) (package! counsel)
(package! amx :pin "7fb7b874291e0cdeb1f0acb18564a686ec86788d") (package! amx :pin "7fb7b874291e0cdeb1f0acb18564a686ec86788d")
(package! counsel-projectile :pin "b556ed8995f375e57496f3482aef4b0def565de8") (package! counsel-projectile :pin "126e825bbab872b3befd9ef88660571391ebfdc3")
(package! ivy-rich :pin "3f818b201769bc13cc75aa73645217e374136aca") (package! ivy-rich :pin "3f818b201769bc13cc75aa73645217e374136aca")
(package! wgrep :pin "5977b8e00051c9003ca96e9d35133e0dea68db2c") (package! wgrep :pin "f0ef9bfa44db503cdb2f83fcfbd2fa4e2382ef1f")
(if (featurep! +prescient) (if (featurep! +prescient)
(package! ivy-prescient :pin "0f4a89bdec61395138d968a38d375e63ccfbed63") (package! ivy-prescient :pin "3ab7605d997fb8337bf5ded2ad960b98ac0e1fd7")
(when (featurep! +fuzzy) (when (featurep! +fuzzy)
(package! flx :pin "17f5c9cb2af18aa6f52910ff4a5a63591261ced5"))) (package! flx :pin "17f5c9cb2af18aa6f52910ff4a5a63591261ced5")))

View file

@ -202,7 +202,14 @@
:desc "Send to Launchbar" "l" #'+macos/send-to-launchbar :desc "Send to Launchbar" "l" #'+macos/send-to-launchbar
:desc "Send project to Launchbar" "L" #'+macos/send-project-to-launchbar) :desc "Send project to Launchbar" "L" #'+macos/send-project-to-launchbar)
(:when (featurep! :tools docker) (:when (featurep! :tools docker)
:desc "Docker" "D" #'docker)) :desc "Docker" "D" #'docker)
(:when (featurep! :email mu4e)
:desc "mu4e" "m" #'=mu4e)
(:when (featurep! :email notmuch)
:desc "notmuch" "m" #'=notmuch)
(:when (featurep! :email wanderlust)
:desc "wanderlust" "m" #'=wanderlust))
;;; <leader> p --- project ;;; <leader> p --- project
(:prefix ("p" . "project") (:prefix ("p" . "project")

View file

@ -4,12 +4,12 @@
;; NOTE SPC u replaces C-u as the universal argument. ;; NOTE SPC u replaces C-u as the universal argument.
;; Minibuffer ;; Minibuffer
(define-key! :keymaps '(evil-ex-completion-map evil-ex-search-keymap) (map! :map (evil-ex-completion-map evil-ex-search-keymap)
"C-a" #'evil-beginning-of-line "C-a" #'evil-beginning-of-line
"C-b" #'evil-backward-char "C-b" #'evil-backward-char
"C-f" #'evil-forward-char "C-f" #'evil-forward-char
"C-j" #'next-complete-history-element :gi "C-j" #'next-complete-history-element
"C-k" #'previous-complete-history-element) :gi "C-k" #'previous-complete-history-element)
(define-key! :keymaps +default-minibuffer-maps (define-key! :keymaps +default-minibuffer-maps
[escape] #'abort-recursive-edit [escape] #'abort-recursive-edit
@ -26,6 +26,7 @@
"C-k" #'previous-line "C-k" #'previous-line
"C-S-j" #'scroll-up-command "C-S-j" #'scroll-up-command
"C-S-k" #'scroll-down-command) "C-S-k" #'scroll-down-command)
;; For folks with `evil-collection-setup-minibuffer' enabled
(define-key! :states 'insert :keymaps +default-minibuffer-maps (define-key! :states 'insert :keymaps +default-minibuffer-maps
"C-j" #'next-line "C-j" #'next-line
"C-k" #'previous-line) "C-k" #'previous-line)
@ -549,7 +550,13 @@
:desc "Send to Launchbar" "l" #'+macos/send-to-launchbar :desc "Send to Launchbar" "l" #'+macos/send-to-launchbar
:desc "Send project to Launchbar" "L" #'+macos/send-project-to-launchbar) :desc "Send project to Launchbar" "L" #'+macos/send-project-to-launchbar)
(:when (featurep! :tools docker) (:when (featurep! :tools docker)
:desc "Docker" "D" #'docker)) :desc "Docker" "D" #'docker)
(:when (featurep! :email mu4e)
:desc "mu4e" "m" #'=mu4e)
(:when (featurep! :email notmuch)
:desc "notmuch" "m" #'=notmuch)
(:when (featurep! :email wanderlust)
:desc "wanderlust" "m" #'=wanderlust))
;;; <leader> p --- project ;;; <leader> p --- project
(:prefix-map ("p" . "project") (:prefix-map ("p" . "project")

View file

@ -28,13 +28,15 @@
(defun +default/browse-notes () (defun +default/browse-notes ()
"Browse files from `org-directory'." "Browse files from `org-directory'."
(interactive) (interactive)
(require 'org) (unless (bound-and-true-p org-directory)
(require 'org))
(doom-project-browse org-directory)) (doom-project-browse org-directory))
;;;###autoload ;;;###autoload
(defun +default/find-in-notes () (defun +default/find-in-notes ()
"Find a file under `org-directory', recursively." "Find a file under `org-directory', recursively."
(interactive) (interactive)
(require 'org) (unless (bound-and-true-p org-directory)
(require 'org))
(doom-project-find-file org-directory)) (doom-project-find-file org-directory))
;;;###autoload ;;;###autoload

View file

@ -50,8 +50,8 @@ If `buffer-file-name' isn't set, uses `default-directory'."
(abbreviate-file-name path) (abbreviate-file-name path)
(file-name-nondirectory path))))) (file-name-nondirectory path)))))
;;;###autoload
(defun doom--backward-delete-whitespace-to-column () (defun doom/backward-delete-whitespace-to-column ()
"Delete back to the previous column of whitespace, or as much whitespace as "Delete back to the previous column of whitespace, or as much whitespace as
possible, or just one char if that's not possible." possible, or just one char if that's not possible."
(interactive) (interactive)
@ -74,7 +74,7 @@ possible, or just one char if that's not possible."
;; point and bol. ;; point and bol.
((and (not indent-tabs-mode) ((and (not indent-tabs-mode)
(not (bolp)) (not (bolp))
(not (sp-point-in-string)) (not (doom-point-in-string-p))
(save-excursion (>= (- (skip-chars-backward " \t")) tab-width))) (save-excursion (>= (- (skip-chars-backward " \t")) tab-width)))
(let ((movement (% (current-column) tab-width))) (let ((movement (% (current-column) tab-width)))
(when (= movement 0) (when (= movement 0)
@ -97,7 +97,7 @@ possible, or just one char if that's not possible."
{ {
| |
} => {|} } => {|}
+ Otherwise, resort to `doom--backward-delete-whitespace-to-column'. + Otherwise, resort to `doom/backward-delete-whitespace-to-column'.
+ Resorts to `delete-char' if n > 1" + Resorts to `delete-char' if n > 1"
(interactive "p\nP") (interactive "p\nP")
(or (integerp n) (or (integerp n)
@ -120,12 +120,14 @@ possible, or just one char if that's not possible."
(save-excursion (save-excursion
(insert-char ?\s (- ocol (current-column)) nil)))) (insert-char ?\s (- ocol (current-column)) nil))))
;; ;;
((and (= n 1) (bound-and-true-p smartparens-mode)) ((= n 1)
(cond ((and (memq (char-before) (list ?\ ?\t)) (cond ((or (not (featurep! +smartparens))
(save-excursion (not (bound-and-true-p smartparens-mode))
(and (/= (skip-chars-backward " \t" (line-beginning-position)) 0) (and (memq (char-before) (list ?\ ?\t))
(bolp)))) (save-excursion
(doom--backward-delete-whitespace-to-column)) (and (/= (skip-chars-backward " \t" (line-beginning-position)) 0)
(bolp)))))
(doom/backward-delete-whitespace-to-column))
((let* ((pair (ignore-errors (sp-get-thing))) ((let* ((pair (ignore-errors (sp-get-thing)))
(op (plist-get pair :op)) (op (plist-get pair :op))
(cl (plist-get pair :cl)) (cl (plist-get pair :cl))
@ -144,6 +146,6 @@ possible, or just one char if that's not possible."
(sp-insert-pair op) (sp-insert-pair op)
t) t)
((run-hook-with-args-until-success 'doom-delete-backward-functions)) ((run-hook-with-args-until-success 'doom-delete-backward-functions))
((doom--backward-delete-whitespace-to-column))))))) ((doom/backward-delete-whitespace-to-column)))))))
;; Otherwise, do simple deletion. ;; Otherwise, do simple deletion.
((delete-char (- n) killflag)))) ((delete-char (- n) killflag))))

View file

@ -204,52 +204,52 @@
;; This keybind allows * to skip over **. ;; This keybind allows * to skip over **.
(map! :map markdown-mode-map (map! :map markdown-mode-map
:ig "*" (λ! (if (looking-at-p "\\*\\* *$") :ig "*" (general-predicate-dispatch nil
(forward-char 2) (looking-at-p "\\*\\* *")
(call-interactively 'self-insert-command))))) (λ! (forward-char 2)))))))
;; Highjacks backspace to:
;; a) balance spaces inside brackets/parentheses ( | ) -> (|)
;; b) delete up to nearest column multiple of `tab-width' at a time
;; c) close empty multiline brace blocks in one step:
;; {
;; |
;; }
;; becomes {|}
;; d) refresh smartparens' :post-handlers, so SPC and RET expansions work
;; even after a backspace.
;; e) properly delete smartparen pairs when they are encountered, without
;; the need for strict mode.
;; f) do none of this when inside a string
(advice-add #'delete-backward-char :override #'+default--delete-backward-char-a))
;; HACK Makes `newline-and-indent' continue comments (and more reliably).
;; Consults `doom-point-in-comment-functions' to detect a commented
;; region and uses that mode's `comment-line-break-function' to continue
;; comments. If neither exists, it will fall back to the normal behavior
;; of `newline-and-indent'.
;;
;; We use an advice here instead of a remapping because many modes define
;; and remap to their own newline-and-indent commands, and tackling all
;; those cases was judged to be more work than dealing with the edge
;; cases on a case by case basis.
(defadvice! +default--newline-indent-and-continue-comments-a (&rest _)
"A replacement for `newline-and-indent'.
Continues comments if executed from a commented line. Consults
`doom-point-in-comment-functions' to determine if in a comment."
:before-until #'newline-and-indent
(interactive "*")
(when (and +default-want-RET-continue-comments
(doom-point-in-comment-p)
(fboundp comment-line-break-function))
(funcall comment-line-break-function nil)
t)))
;; ;;
;;; Keybinding fixes ;;; Keybinding fixes
;; Highjacks backspace to delete up to nearest column multiple of `tab-width' at
;; a time. If you have smartparens enabled, it will also:
;; a) balance spaces inside brackets/parentheses ( | ) -> (|)
;; b) close empty multiline brace blocks in one step:
;; {
;; |
;; }
;; becomes {|}
;; c) refresh smartparens' :post-handlers, so SPC and RET expansions work even
;; after a backspace.
;; d) properly delete smartparen pairs when they are encountered, without the
;; need for strict mode.
;; e) do none of this when inside a string
(advice-add #'delete-backward-char :override #'+default--delete-backward-char-a)
;; HACK Makes `newline-and-indent' continue comments (and more reliably).
;; Consults `doom-point-in-comment-functions' to detect a commented region
;; and uses that mode's `comment-line-break-function' to continue comments.
;; If neither exists, it will fall back to the normal behavior of
;; `newline-and-indent'.
;;
;; We use an advice here instead of a remapping because many modes define
;; and remap to their own newline-and-indent commands, and tackling all
;; those cases was judged to be more work than dealing with the edge cases
;; on a case by case basis.
(defadvice! +default--newline-indent-and-continue-comments-a (&rest _)
"A replacement for `newline-and-indent'.
Continues comments if executed from a commented line. Consults
`doom-point-in-comment-functions' to determine if in a comment."
:before-until #'newline-and-indent
(interactive "*")
(when (and +default-want-RET-continue-comments
(doom-point-in-comment-p)
(fboundp comment-line-break-function))
(funcall comment-line-break-function nil)
t))
;; This section is dedicated to "fixing" certain keys so that they behave ;; This section is dedicated to "fixing" certain keys so that they behave
;; sensibly (and consistently with similar contexts). ;; sensibly (and consistently with similar contexts).
@ -353,7 +353,7 @@ Continues comments if executed from a commented line. Consults
"dL" #'doom/help-search-loaded-files "dL" #'doom/help-search-loaded-files
"dm" #'doom/help-modules "dm" #'doom/help-modules
"dn" #'doom/help-news "dn" #'doom/help-news
"dN" #'doom/help-news-search "dN" #'doom/help-search-news
"dpc" #'doom/help-package-config "dpc" #'doom/help-package-config
"dpd" #'doom/goto-private-packages-file "dpd" #'doom/goto-private-packages-file
"dph" #'doom/help-package-homepage "dph" #'doom/help-package-homepage

View file

@ -1,13 +1,10 @@
;;; editor/evil/config.el -*- lexical-binding: t; -*- ;;; editor/evil/config.el -*- lexical-binding: t; -*-
;; I'm a vimmer at heart. Its modal philosophy suits me better, and this module
;; strives to make Emacs a much better vim than vim was.
(defvar +evil-repeat-keys (cons ";" ",") (defvar +evil-repeat-keys (cons ";" ",")
"The keys to use for universal repeating motions. "The keys to use for universal repeating motions.
This is a cons cell whose CAR is the key for repeating a motion forward, and This is a cons cell whose CAR is the key for repeating a motion forward, and
whose CDR is for repeating backward. They should both be kbd-able strings.") whose CDR is for repeating backward. They should both be `kbd'-able strings.")
(defvar +evil-want-o/O-to-continue-comments t (defvar +evil-want-o/O-to-continue-comments t
"If non-nil, the o/O keys will continue comment lines if the point is on a "If non-nil, the o/O keys will continue comment lines if the point is on a
@ -137,8 +134,8 @@ directives. By default, this only recognizes C directives.")
(and (>= char ?2) (<= char ?9))) (and (>= char ?2) (<= char ?9)))
;; REVIEW Fix #2493: dir-locals cannot target fundamental-mode when evil-mode ;; REVIEW Fix #2493: dir-locals cannot target fundamental-mode when evil-mode
;; is active. See https://github.com/hlissner/doom-emacs/issues/2493. ;; is active. See hlissner/doom-emacs#2493. Revert this if
;; Revert this if this is ever fixed upstream. ;; emacs-evil/evil#1268 is resolved upstream.
(defadvice! +evil--fix-local-vars-a (&rest _) (defadvice! +evil--fix-local-vars-a (&rest _)
:before #'turn-on-evil-mode :before #'turn-on-evil-mode
(when (eq major-mode 'fundamental-mode) (when (eq major-mode 'fundamental-mode)
@ -227,12 +224,12 @@ directives. By default, this only recognizes C directives.")
(use-package! evil-embrace (use-package! evil-embrace
:commands embrace-add-pair embrace-add-pair-regexp :commands embrace-add-pair embrace-add-pair-regexp
:hook (LaTeX-mode . embrace-LaTeX-mode-hook) :hook (LaTeX-mode . embrace-LaTeX-mode-hook)
:hook (LaTeX-mode . +evil-embrace-latex-mode-hook-h)
:hook (org-mode . embrace-org-mode-hook) :hook (org-mode . embrace-org-mode-hook)
:hook (ruby-mode . embrace-ruby-mode-hook) :hook (ruby-mode . embrace-ruby-mode-hook)
:hook (emacs-lisp-mode . embrace-emacs-lisp-mode-hook) :hook (emacs-lisp-mode . embrace-emacs-lisp-mode-hook)
:hook ((lisp-mode emacs-lisp-mode clojure-mode racket-mode hy-mode) :hook ((lisp-mode emacs-lisp-mode clojure-mode racket-mode hy-mode)
. +evil-embrace-lisp-mode-hook-h) . +evil-embrace-lisp-mode-hook-h)
:hook ((org-mode LaTeX-mode) . +evil-embrace-latex-mode-hook-h)
:hook ((c++-mode rustic-mode csharp-mode java-mode swift-mode typescript-mode) :hook ((c++-mode rustic-mode csharp-mode java-mode swift-mode typescript-mode)
. +evil-embrace-angle-bracket-modes-hook-h) . +evil-embrace-angle-bracket-modes-hook-h)
:init :init
@ -369,14 +366,12 @@ directives. By default, this only recognizes C directives.")
(defmacro set-repeater! (command next-func prev-func) (defmacro set-repeater! (command next-func prev-func)
"Makes ; and , the universal repeat-keys in evil-mode. "Makes ; and , the universal repeat-keys in evil-mode.
To change these keys see `+evil-repeat-keys'." To change these keys see `+evil-repeat-keys'."
(let ((fn-sym (intern (format "+evil/repeat-%s" (doom-unquote command))))) `(defadvice! ,(intern (format "+evil--repeat-%s-a" (doom-unquote command))) (&rest _)
`(progn :after-while #',command
(defun ,fn-sym (&rest _) (when +evil-repeat-keys
(when +evil-repeat-keys (evil-define-key* 'motion 'local
(evil-define-key* 'motion 'local (kbd (car +evil-repeat-keys)) #',next-func
(kbd (car +evil-repeat-keys)) #',next-func (kbd (cdr +evil-repeat-keys)) #',prev-func))))
(kbd (cdr +evil-repeat-keys)) #',prev-func)))
(advice-add #',command :after-while #',fn-sym))))
;; n/N ;; n/N
(set-repeater! evil-ex-search-next evil-ex-search-next evil-ex-search-previous) (set-repeater! evil-ex-search-next evil-ex-search-next evil-ex-search-previous)

View file

@ -1,5 +1,7 @@
;;; editor/evil/init.el -*- lexical-binding: t; -*- ;;; editor/evil/init.el -*- lexical-binding: t; -*-
(defvar evil-collection-key-blacklist)
;; We load evil-collection ourselves for these reasons: ;; We load evil-collection ourselves for these reasons:
;; ;;
;; 1. To truly lazy load it. Some of its modules, like ;; 1. To truly lazy load it. Some of its modules, like

View file

@ -56,6 +56,7 @@ PATTERN as literal. PATTERN is a delimited regexp (the same that :g or :s uses).
FLAGS can be g and/or i; which mean the same thing they do in FLAGS can be g and/or i; which mean the same thing they do in
`evil-ex-substitute'." `evil-ex-substitute'."
:evil-mc t :evil-mc t
:keep-visual t
(interactive "<R><//!><!>") (interactive "<R><//!><!>")
(unless (and (stringp pattern) (unless (and (stringp pattern)
(not (string-empty-p pattern))) (not (string-empty-p pattern)))

View file

@ -40,7 +40,7 @@
This is because there's no guarantee the remote system has GNU ls, which is the This is because there's no guarantee the remote system has GNU ls, which is the
only variant that supports --group-directories-first." only variant that supports --group-directories-first."
(when (file-remote-p default-directory) (when (file-remote-p default-directory)
(setq-local dired-listing-switches (car args)))))) (setq-local dired-actual-switches (car args))))))
;; Don't complain about this command being disabled when we use it ;; Don't complain about this command being disabled when we use it
(put 'dired-find-alternate-file 'disabled nil) (put 'dired-find-alternate-file 'disabled nil)

View file

@ -42,16 +42,16 @@
(when (featurep! :ui workspaces) (when (featurep! :ui workspaces)
(define-ibuffer-filter workspace-buffers (define-ibuffer-filter workspace-buffers
"Filter for workspace buffers" "Filter for workspace buffers"
(:reader (:reader (+workspace-get (read-string "workspace name: "))
(+workspace-get (read-string "workspace name: ")) :description "workspace") :description "workspace")
(memq buf (+workspace-buffer-list qualifier))) (memq buf (+workspace-buffer-list qualifier)))
(defun +ibuffer/workspace (workspace-name) (defun +ibuffer-workspace (workspace-name)
"Open an ibuffer window for a workspace" "Open an ibuffer window for a workspace"
(ibuffer nil (format "%s buffers" workspace-name) (ibuffer nil (format "%s buffers" workspace-name)
(list (cons 'workspace-buffers (+workspace-get workspace-name))))) (list (cons 'workspace-buffers (+workspace-get workspace-name)))))
(defun +ibuffer-current-workspace () (defun +ibuffer/open-for-current-workspace ()
"Open an ibuffer window for the current workspace" "Open an ibuffer window for the current workspace"
(interactive) (interactive)
(+ibuffer/workspace (+workspace-current-name)))) (+ibuffer/workspace (+workspace-current-name))))

View file

@ -2,8 +2,9 @@
(use-package! undo-fu (use-package! undo-fu
:unless (featurep! +tree) :unless (featurep! +tree)
:after-call doom-switch-buffer after-find-file :after-call pre-command-hook after-find-file
:init :init
;; `evil' activates undo-tree, so we must pre-emptively disable it.
(after! undo-tree (after! undo-tree
(global-undo-tree-mode -1)) (global-undo-tree-mode -1))
:config :config

View file

@ -3,5 +3,5 @@
(if (featurep! +tree) (if (featurep! +tree)
(package! undo-tree :pin "5b6df03781495d8a25695d846b0cce496d3d3058") (package! undo-tree :pin "5b6df03781495d8a25695d846b0cce496d3d3058")
(package! undo-fu :pin "0ce9ac36144e80316fff50bfe1bc5dd7e5e7ded6") (package! undo-fu :pin "2b1e53285a55ce50ca6fd60b050f2171e235d8f9")
(package! undo-fu-session :pin "b808ef0cdcdd2eef221c67eda567eed7fcb3d4af")) (package! undo-fu-session :pin "0400f15f2a0cfcedb69c06c3ff62f3f8814b62fb"))

View file

@ -80,7 +80,7 @@ environment.systemPackages = with pkgs; [
]; ];
#+END_SRC #+END_SRC
[[https://github.com/Emiller88/dotfiles/blob/master/modules/shell/mail.nix][An example of setting up mbsync with home-manager]] [[https://github.com/Emiller88/dotfiles/blob/5eaabedf1b141c80a8d32e1b496055231476f65e/modules/shell/mail.nix][An example of setting up mbsync and mu with home-manager]]
** openSUSE ** openSUSE
Remove ~#~ in ~#sync_program=offlineimap~ to choose ~offlineimap~ instead of Remove ~#~ in ~#sync_program=offlineimap~ to choose ~offlineimap~ instead of

View file

@ -0,0 +1,110 @@
#+TITLE: email/notmuch
#+DATE: May 5, 2019
#+SINCE: v2.0
#+STARTUP: inlineimages
* Table of Contents :TOC:
- [[#description][Description]]
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#macos][MacOS]]
- [[#arch-linux][Arch Linux]]
- [[#nixos][NixOS]]
- [[#opensuse][openSUSE]]
- [[#debianubuntu][Debian/Ubuntu]]
- [[#features][Features]]
- [[#configuration][Configuration]]
- [[#gmailier][Gmailier]]
- [[#offlineimap][offlineimap]]
- [[#mbsync][mbsync]]
- [[#notmuch][notmuch]]
- [[#troubleshooting][Troubleshooting]]
* Description
This module makes Emacs an email client, using ~notmuch~.
** Module Flags
+ This module install no module flags.
** Plugins
+ [[https://notmuchmail.org/][notmuch]]
+ [[https://github.com/org-mime/org-mime][org-mime]]
* Prerequisites
This module requires:
+ Either ~gmailieer~ (default), ~mbsync~ or ~offlineimap~ (to sync mail with)
+ ~notmuch~, to index and tag your downloaded messages.
+ ~afew~, optionally to initially tag your downloaded messages.
** TODO MacOS
** TODO Arch Linux
** NixOS
#+BEGIN_SRC nix
environment.systemPackages = with pkgs; [
notmuch
# And one of the following
gmailieer
isync
offlineimap
];
#+END_SRC
[[https://github.com/Emiller88/dotfiles/blob/319841bd3b89e59b01d169137cceee3183aba4fc/modules/shell/mail.nix][An example of setting up mbsync and notmuch with home-manager]]
** TODO openSUSE
** TODO Debian/Ubuntu
* TODO Features
* Configuration
** TODO Gmailier
** offlineimap
This module uses =Gmailier= by default. To use =offlineimap=, change ~+notmuch-sync-backend~:
#+BEGIN_SRC emacs-lisp
(setq +notmuch-sync-backend 'offlineimap)
#+END_SRC
Next, you need to write a configuration file for =offlineimap=. Mine can be found
[[https://github.com/hlissner/dotfiles/tree/master/shell/mu][in my dotfiles repository]]. It is configured to download mail to ~\~/.mail~. I
use [[https://www.passwordstore.org/][unix pass]] to securely store my login credentials. You can find a *very*
detailed configuration [[https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf][here]].
Next you can download your email with ~offlineimap -o~. This may take a while,
especially if you have thousands of mails.
You can now proceed with the [[*mu and mu4e][mu and mu4e]] section.
** mbsync
This module uses =Gmailier= by default. To use =mbsync=, change ~+notmuch-sync-backend~:
#+BEGIN_SRC emacs-lisp
(setq +notmuch-sync-backend 'mbsync)
#+END_SRC
The steps needed to set up =mu4e= with =mbsync= are very similar to the ones for
[[*offlineimap][offlineimap]].
Start with writing a ~\~/.mbsyncrc~. An example for GMAIL can be found on
[[http://pragmaticemacs.com/emacs/migrating-from-offlineimap-to-mbsync-for-mu4e/][pragmaticemacs.com]]. A non-GMAIL example is available as a gist [[https://gist.github.com/agraul/60977cc497c3aec44e10591f94f49ef0][here]]. The [[http://isync.sourceforge.net/mbsync.html][manual
page]] contains all needed information to set up your own.
Next you can download your email with ~mbsync --all~. This may take a while, but
should be quicker than =offlineimap= ;).
You can now proceed with the [[*mu and mu4e][mu and mu4e]] section.
** notmuch
You should have your email downloaded already. If you have not, you need to set
=Gmailier=, =offlineimap= or =mbsync= up before you proceed.
Before you can use =notmuch=, you need to index your email initially.
#+BEGIN_SRC sh
notmuch new
#+END_SRC
* Troubleshooting

View file

@ -1,7 +1,7 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*- ;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; lang/csharp/doctor.el ;;; lang/csharp/doctor.el
(require 'omnisharp) (when (and (require 'omnisharp nil t) (not (featurep! +lsp)))
(let ((omnisharp-bin (or omnisharp-server-executable-path (omnisharp--server-installation-path t)))) (let ((omnisharp-bin (or omnisharp-server-executable-path (omnisharp--server-installation-path t))))
(unless (file-exists-p omnisharp-bin) (unless (file-exists-p omnisharp-bin)
(warn! "Omnisharp server isn't installed, completion won't work"))) (warn! "Omnisharp server isn't installed, completion won't work"))))

View file

@ -16,10 +16,10 @@
* Description * Description
This module provides support for [[https://elixir-lang.org/][Elixir programming language]] via [[https://github.com/tonini/alchemist.el][alchemist.el]] This module provides support for [[https://elixir-lang.org/][Elixir programming language]] via [[https://github.com/tonini/alchemist.el][alchemist.el]]
or [[https://github.com/JakeBecker/elixir-ls/][elixir-ls]]. or [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]].
** Module flags ** Module flags
+ ~+lsp~ Enable LSP support. Requires [[https://github.com/JakeBecker/elixir-ls/][elixir-ls]]. + ~+lsp~ Enable LSP support. Requires [[https://github.com/elixir-lsp/elixir-ls/][elixir-ls]].
** Plugins ** Plugins
+ [[https://github.com/elixir-editors/emacs-elixir][elixir-mode]] + [[https://github.com/elixir-editors/emacs-elixir][elixir-mode]]

View file

@ -67,6 +67,9 @@ library/userland functions"
(byte-compile #'+emacs-lisp-highlight-vars-and-faces))) (byte-compile #'+emacs-lisp-highlight-vars-and-faces)))
;;
;;; Handlers
(defun +emacs-lisp--module-at-point () (defun +emacs-lisp--module-at-point ()
(let ((origin (point))) (let ((origin (point)))
(save-excursion (save-excursion
@ -126,11 +129,52 @@ if it's callable, `apropos' otherwise."
(thing (helpful-symbol (intern thing))) (thing (helpful-symbol (intern thing)))
((call-interactively #'helpful-at-point)))) ((call-interactively #'helpful-at-point))))
;; FIXME ;;;###autoload
;; (defun +emacs-lisp-lookup-file (thing) (defun +emacs-lisp-indent-function (indent-point state)
;; (when-let (module (+emacs-lisp--module-at-point thing)) "A replacement for `lisp-indent-function'.
;; (doom/help-modules (car module) (cadr module) 'visit-dir)
;; t)) Indents plists more sensibly. Adapted from
https://emacs.stackexchange.com/questions/10230/how-to-indent-keywords-aligned"
(let ((normal-indent (current-column))
(orig-point (point))
;; TODO Refactor `target' usage (ew!)
target)
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
(cond ((and (elt state 2)
(or (not (looking-at-p "\\sw\\|\\s_"))
(eq (char-after) ?:)))
(unless (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp)
(goto-char calculate-lisp-indent-last-sexp)
(beginning-of-line)
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t))
(backward-prefix-chars)
(current-column))
((and (save-excursion
(goto-char indent-point)
(skip-syntax-forward " ")
(not (eq (char-after) ?:)))
(save-excursion
(goto-char orig-point)
(and (eq (char-after) ?:)
(eq (char-before) ?\()
(setq target (current-column)))))
(save-excursion
(move-to-column target t)
target))
((let* ((function (buffer-substring (point) (progn (forward-sexp 1) (point))))
(method (or (function-get (intern-soft function) 'lisp-indent-function)
(get (intern-soft function) 'lisp-indent-hook))))
(cond ((or (eq method 'defun)
(and (null method)
(> (length function) 3)
(string-match-p "\\`def" function)))
(lisp-indent-defform state indent-point))
((integerp method)
(lisp-indent-specform method state indent-point normal-indent))
(method
(funcall method indent-point state))))))))
;; ;;
@ -170,6 +214,18 @@ if it's callable, `apropos' otherwise."
load-path))) load-path)))
(buttercup-run-discover))) (buttercup-run-discover)))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-on ()
"Toggle on instrumentalisation for the function under `defun'."
(interactive)
(eval-defun 'edebugit))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-off ()
"Toggle off instrumentalisation for the function under `defun'."
(interactive)
(eval-defun nil))
;; ;;
;;; Hooks ;;; Hooks
@ -234,62 +290,3 @@ verbosity when editing a file in `doom-private-dir' or `doom-emacs-dir'."
(when (and start finish) (when (and start finish)
(put-text-property start finish 'display "..."))))) (put-text-property start finish 'display "...")))))
nil) nil)
;;;###autoload
(defun +emacs-lisp-indent-function (indent-point state)
"A replacement for `lisp-indent-function'.
Indents plists more sensibly. Adapted from
https://emacs.stackexchange.com/questions/10230/how-to-indent-keywords-aligned"
(let ((normal-indent (current-column))
(orig-point (point))
;; TODO Refactor `target' usage (ew!)
target)
(goto-char (1+ (elt state 1)))
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
(cond ((and (elt state 2)
(or (not (looking-at-p "\\sw\\|\\s_"))
(eq (char-after) ?:)))
(unless (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp)
(goto-char calculate-lisp-indent-last-sexp)
(beginning-of-line)
(parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t))
(backward-prefix-chars)
(current-column))
((and (save-excursion
(goto-char indent-point)
(skip-syntax-forward " ")
(not (eq (char-after) ?:)))
(save-excursion
(goto-char orig-point)
(and (eq (char-after) ?:)
(eq (char-before) ?\()
(setq target (current-column)))))
(save-excursion
(move-to-column target t)
target))
((let* ((function (buffer-substring (point) (progn (forward-sexp 1) (point))))
(method (or (function-get (intern-soft function) 'lisp-indent-function)
(get (intern-soft function) 'lisp-indent-hook))))
(cond ((or (eq method 'defun)
(and (null method)
(> (length function) 3)
(string-match-p "\\`def" function)))
(lisp-indent-defform state indent-point))
((integerp method)
(lisp-indent-specform method state indent-point normal-indent))
(method
(funcall method indent-point state))))))))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-on ()
"Toggle on instrumentalisation for the function under `defun'."
(interactive)
(eval-defun 'edebugit))
;;;###autoload
(defun +emacs-lisp/edebug-instrument-defun-off ()
"Toggle off instrumentalisation for the function under `defun'."
(interactive)
(eval-defun nil))

View file

@ -3,15 +3,16 @@
(package! elisp-mode :built-in t) (package! elisp-mode :built-in t)
(package! highlight-quoted :pin "2410347815") ;; Fontification plugins
(package! highlight-quoted :pin "24103478158cd19fbcfb4339a3f1fa1f054f1469")
;; Tools ;; Tools
(package! macrostep :pin "424e3734a1") (package! macrostep :pin "424e3734a1ee526a1bd7b5c3cd1d3ef19d184267")
(package! overseer :pin "02d49f582e") (package! overseer :pin "02d49f582e80e36b4334c9187801c5ecfb027789")
(package! elisp-def :pin "368b04da68") (package! elisp-def :pin "368b04da68783601b52e3169312183381871cf9e")
(package! elisp-demos :pin "57dd4ae3e4") (package! elisp-demos :pin "4cd55a30d5dbd8d36a0e6f87261c4fef17fc6db0")
(when (featurep! :checkers syntax) (when (featurep! :checkers syntax)
(package! flycheck-cask :pin "3457ae553c")) (package! flycheck-cask :pin "3457ae553c4feaf8168008f063d78fdde8fb5f94"))
;; Libraries ;; Libraries
(package! buttercup :pin "a91f282025") (package! buttercup :pin "532d082a363add4f6d9838ca3f924a773ce12136")

View file

@ -1,15 +1,15 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; lang/go/packages.el ;;; lang/go/packages.el
(package! go-eldoc :pin "cbbd2ea1e9") (package! go-eldoc :pin "cbbd2ea1e94a36004432a9ac61414cb5a95a39bd")
(package! go-guru :pin "10d6ab43d9") (package! go-guru :pin "734d5232455ffde088021ea5908849ac570e890f")
(package! go-mode :pin "10d6ab43d9") (package! go-mode :pin "734d5232455ffde088021ea5908849ac570e890f")
(package! gorepl-mode :pin "6a73bf352e") (package! gorepl-mode :pin "6a73bf352e8d893f89cad36c958c4db2b5e35e07")
(package! go-tag :pin "59b243f2fa") (package! go-tag :pin "59b243f2fa079d9de9d56f6e2d94397e9560310a")
(package! go-gen-test :pin "44c202ac97") (package! go-gen-test :pin "44c202ac97e728e93a35cee028a0ea8dd6e4292c")
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-go :pin "4acdcbdea7")) (package! company-go :pin "4acdcbdea79de6b3dee1c637eca5cbea0fdbe37c"))
(when (featurep! :checkers syntax) (when (featurep! :checkers syntax)
(package! flycheck-golangci-lint :pin "8e446c6831")) (package! flycheck-golangci-lint :pin "8e446c68311048f0b87febf8ef0379e29d358851"))

View file

@ -31,7 +31,9 @@
(map! :map haskell-mode-map (map! :map haskell-mode-map
:n "o" #'+haskell/evil-open-below :n "o" #'+haskell/evil-open-below
:n "O" #'+haskell/evil-open-above) :n "O" #'+haskell/evil-open-above
(:when (featurep! :tools lookup)
[remap haskell-mode-jump-to-def-or-tag] #'+lookup/definition))
(map! :localleader (map! :localleader
:map haskell-mode-map :map haskell-mode-map

View file

@ -92,10 +92,6 @@ capture, the end position, and the output buffer.")
(use-package! evil-markdown (use-package! evil-markdown
:when (featurep! :editor evil +everywhere) :when (featurep! :editor evil +everywhere)
:hook (markdown-mode . evil-markdown-mode) :hook (markdown-mode . evil-markdown-mode)
:init
;; REVIEW Until Somelauw/evil-markdown#1 is resolved:
(defun evil-disable-insert-state-bindings ()
evil-disable-insert-state-bindings)
:config :config
(add-hook 'evil-markdown-mode-hook #'evil-normalize-keymaps) (add-hook 'evil-markdown-mode-hook #'evil-normalize-keymaps)
(map! :map evil-markdown-mode-map (map! :map evil-markdown-mode-map

View file

@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; lang/markdown/packages.el ;;; lang/markdown/packages.el
(package! markdown-mode :pin "c927a114b1b23cf7538181d62fd14679cce7fa25") (package! markdown-mode :pin "f47a2e9796dfdde6fae7920af23647fe027dc34e")
(package! markdown-toc :pin "eda9650a1bf0015e52e9678bd92b0a8beb1d7d71") (package! markdown-toc :pin "a9f13eecd0c7d8be960055dbc2d6f5d3fe6f40ca")
(package! edit-indirect :pin "935ded353b9ed3da67bc61abf245c21b58d88864") (package! edit-indirect :pin "935ded353b9ed3da67bc61abf245c21b58d88864")
(when (featurep! +grip) (when (featurep! +grip)
@ -11,4 +11,4 @@
(when (featurep! :editor evil +everywhere) (when (featurep! :editor evil +everywhere)
(package! evil-markdown (package! evil-markdown
:recipe (:host github :repo "Somelauw/evil-markdown") :recipe (:host github :repo "Somelauw/evil-markdown")
:pin "46cd81b37991c4325fc24015a610f832b0ff995d")) :pin "685d7fbb81bc02fa32779d2a127b99a0c8c7436b"))

View file

@ -46,11 +46,15 @@ exist, and `org-link' otherwise."
"Intepret LINK as an image file path and return its data." "Intepret LINK as an image file path and return its data."
(setq (setq
link (expand-file-name link (expand-file-name
link link (pcase protocol
(pcase protocol ("download"
("download" (or org-download-image-dir org-attach-id-dir default-directory)) (or (if (require 'org-download nil t) org-download-image-dir)
("attachment" org-attach-id-dir) (if (require 'org-attach) org-attach-id-dir)
(_ default-directory)))) default-directory))
("attachment"
(require 'org-attach)
org-attach-id-dir)
(_ default-directory))))
(when (and (file-exists-p link) (when (and (file-exists-p link)
(image-type-from-file-name link)) (image-type-from-file-name link))
(with-temp-buffer (with-temp-buffer

View file

@ -141,7 +141,7 @@ current file). Only scans first 2048 bytes of the document."
;;; Commands ;;; Commands
;;;###autoload ;;;###autoload
(defun +org/dwim-at-point () (defun +org/dwim-at-point (&optional arg)
"Do-what-I-mean at point. "Do-what-I-mean at point.
If on a: If on a:
@ -158,7 +158,7 @@ If on a:
- latex fragment: toggle it. - latex fragment: toggle it.
- link: follow it - link: follow it
- otherwise, refresh all inline images in current tree." - otherwise, refresh all inline images in current tree."
(interactive) (interactive "P")
(let* ((context (org-element-context)) (let* ((context (org-element-context))
(type (org-element-type context))) (type (org-element-type context)))
;; skip over unimportant contexts ;; skip over unimportant contexts
@ -206,7 +206,7 @@ If on a:
(`table-cell (`table-cell
(org-table-blank-field) (org-table-blank-field)
(org-table-recalculate) (org-table-recalculate arg)
(when (and (string-empty-p (string-trim (org-table-get-field))) (when (and (string-empty-p (string-trim (org-table-get-field)))
(bound-and-true-p evil-local-mode)) (bound-and-true-p evil-local-mode))
(evil-change-state 'insert))) (evil-change-state 'insert)))
@ -215,13 +215,13 @@ If on a:
(org-babel-lob-execute-maybe)) (org-babel-lob-execute-maybe))
(`statistics-cookie (`statistics-cookie
(save-excursion (org-update-statistics-cookies nil))) (save-excursion (org-update-statistics-cookies arg)))
((or `src-block `inline-src-block) ((or `src-block `inline-src-block)
(org-babel-execute-src-block)) (org-babel-execute-src-block arg))
((or `latex-fragment `latex-environment) ((or `latex-fragment `latex-environment)
(org-latex-preview)) (org-latex-preview arg))
(`link (`link
(let* ((lineage (org-element-lineage context '(link) t)) (let* ((lineage (org-element-lineage context '(link) t))
@ -229,7 +229,7 @@ If on a:
(if (or (equal (org-element-property :type lineage) "img") (if (or (equal (org-element-property :type lineage) "img")
(and path (image-type-from-file-name path))) (and path (image-type-from-file-name path)))
(+org--refresh-inline-images-in-subtree) (+org--refresh-inline-images-in-subtree)
(org-open-at-point)))) (org-open-at-point arg))))
((guard (org-element-property :checkbox (org-element-lineage context '(item) t))) ((guard (org-element-property :checkbox (org-element-lineage context '(item) t)))
(let ((match (and (org-at-item-checkbox-p) (match-string 1)))) (let ((match (and (org-at-item-checkbox-p) (match-string 1))))
@ -238,7 +238,7 @@ If on a:
(_ (_
(if (or (org-in-regexp org-ts-regexp-both nil t) (if (or (org-in-regexp org-ts-regexp-both nil t)
(org-in-regexp org-tsr-regexp-both nil t) (org-in-regexp org-tsr-regexp-both nil t)
(org-in-regexp org-any-link-re nil t)) (org-in-regexp org-link-any-re nil t))
(call-interactively #'org-open-at-point) (call-interactively #'org-open-at-point)
(+org--refresh-inline-images-in-subtree)))))) (+org--refresh-inline-images-in-subtree))))))
@ -306,6 +306,20 @@ the prefix ARG changes this command's behavior."
;;;###autoload ;;;###autoload
(defalias #'+org/close-fold #'outline-hide-subtree) (defalias #'+org/close-fold #'outline-hide-subtree)
;;;###autoload
(defun +org/close-all-folds (&optional level)
"Close all folds in the buffer (or below LEVEL)."
(interactive "p")
(outline-hide-sublevels (or level 1)))
;;;###autoload
(defun +org/open-all-folds (&optional level)
"Open all folds in the buffer (or up to LEVEL)."
(interactive "P")
(if (integerp level)
(outline-hide-sublevels level)
(outline-show-all)))
(defun +org--get-foldlevel () (defun +org--get-foldlevel ()
(let ((max 1)) (let ((max 1))
(save-restriction (save-restriction
@ -321,22 +335,20 @@ the prefix ARG changes this command's behavior."
max))) max)))
;;;###autoload ;;;###autoload
(defun +org/show-next-fold-level () (defun +org/show-next-fold-level (&optional count)
"Decrease the fold-level of the visible area of the buffer. This unfolds "Decrease the fold-level of the visible area of the buffer. This unfolds
another level of headings on each invocation." another level of headings on each invocation."
(interactive) (interactive "p")
(let* ((current-level (+org--get-foldlevel)) (let ((new-level (+ (+org--get-foldlevel) (or count 1))))
(new-level (1+ current-level)))
(outline-hide-sublevels new-level) (outline-hide-sublevels new-level)
(message "Folded to level %s" new-level))) (message "Folded to level %s" new-level)))
;;;###autoload ;;;###autoload
(defun +org/hide-next-fold-level () (defun +org/hide-next-fold-level (&optional count)
"Increase the global fold-level of the visible area of the buffer. This folds "Increase the global fold-level of the visible area of the buffer. This folds
another level of headings on each invocation." another level of headings on each invocation."
(interactive) (interactive "p")
(let* ((current-level (+org--get-foldlevel)) (let ((new-level (max 1 (- (+org--get-foldlevel) (or count 1)))))
(new-level (max 1 (1- current-level))))
(outline-hide-sublevels new-level) (outline-hide-sublevels new-level)
(message "Folded to level %s" new-level))) (message "Folded to level %s" new-level)))
@ -434,20 +446,14 @@ with `org-cycle')."
t)) t))
;;;###autoload ;;;###autoload
(defun +org-unfold-to-2nd-level-or-point-h () (defun +org-make-last-point-visible-h ()
"Alters '#+STARTUP overview' to only expand first-level headings. "Unfold subtree around point if saveplace places it to a folded region."
Expands the first level, but no further. If a different startup option was (and (not org-agenda-inhibit-startup)
provided, do that instead." (outline-invisible-p)
(unless org-agenda-inhibit-startup (ignore-errors
;; TODO Implement a custom #+STARTUP option? (save-excursion
(when (eq org-startup-folded t) (outline-previous-visible-heading 1)
(outline-hide-sublevels +org-initial-fold-level)) (org-show-subtree)))))
;; If point was left somewhere deeper, unfold to point on startup.
(when (outline-invisible-p)
(ignore-errors
(save-excursion
(outline-previous-visible-heading 1)
(org-show-subtree))))))
;;;###autoload ;;;###autoload
(defun +org-remove-occur-highlights-h () (defun +org-remove-occur-highlights-h ()

View file

@ -50,9 +50,6 @@ Is relative to `org-directory', unless it is absolute. Is used in Doom's default
(defvar +org-capture-projects-file "projects.org" (defvar +org-capture-projects-file "projects.org"
"Default, centralized target for org-capture templates.") "Default, centralized target for org-capture templates.")
(defvar +org-initial-fold-level 2
"The initial fold level of org files when no #+STARTUP options for it.")
(defvar +org-habit-graph-padding 2 (defvar +org-habit-graph-padding 2
"The padding added to the end of the consistency graph") "The padding added to the end of the consistency graph")
@ -163,7 +160,7 @@ This forces it to read the background before rendering."
("HOLD" . +org-todo-onhold) ("HOLD" . +org-todo-onhold)
("PROJ" . +org-todo-project))) ("PROJ" . +org-todo-project)))
(defadvice! +org-display-link-in-eldoc-a (&rest args) (defadvice! +org-display-link-in-eldoc-a (&rest _)
"Display full link in minibuffer when cursor/mouse is over it." "Display full link in minibuffer when cursor/mouse is over it."
:before-until #'org-eldoc-documentation-function :before-until #'org-eldoc-documentation-function
(when-let (link (org-element-property :raw-link (org-element-context))) (when-let (link (org-element-property :raw-link (org-element-context)))
@ -199,10 +196,10 @@ This forces it to read the background before rendering."
;; I prefer C-c C-c over C-c ' (more consistent) ;; I prefer C-c C-c over C-c ' (more consistent)
(define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit) (define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit)
(defadvice! +org-fix-newline-and-indent-in-src-blocks-a () (defadvice! +org-fix-newline-and-indent-in-src-blocks-a (&optional indent _arg _interactive)
"Mimic `newline-and-indent' in src blocks w/ lang-appropriate indentation." "Mimic `newline-and-indent' in src blocks w/ lang-appropriate indentation."
:after #'org-return-indent :after #'org-return
(when (org-in-src-block-p t) (when (and indent (org-in-src-block-p t))
(org-babel-do-in-edit-buffer (org-babel-do-in-edit-buffer
(call-interactively #'indent-for-tab-command)))) (call-interactively #'indent-for-tab-command))))
@ -322,11 +319,17 @@ I like:
(after! org-capture (after! org-capture
(org-capture-put :kill-buffer t)) (org-capture-put :kill-buffer t))
;; Fix #462: when refiling from org-capture, Emacs prompts to kill the
;; underlying, modified buffer. This fixes that.
(add-hook 'org-after-refile-insert-hook #'save-buffer)
;; HACK Doom doesn't support `customize'. Best not to advertise it as an ;; HACK Doom doesn't support `customize'. Best not to advertise it as an
;; option in `org-capture's menu. ;; option in `org-capture's menu.
(defadvice! +org--remove-customize-option-a (orig-fn table title &optional prompt specials) (defadvice! +org--remove-customize-option-a (orig-fn table title &optional prompt specials)
:around #'org-mks :around #'org-mks
(funcall orig-fn table title prompt (remove '("C" "Customize org-capture-templates") specials))) (funcall orig-fn table title prompt
(remove '("C" "Customize org-capture-templates")
specials)))
(defadvice! +org--capture-expand-variable-file-a (file) (defadvice! +org--capture-expand-variable-file-a (file)
"If a variable is used for a file path in `org-capture-template', it is used "If a variable is used for a file path in `org-capture-template', it is used
@ -337,13 +340,6 @@ relative to `org-directory', unless it is an absolute path."
(expand-file-name (symbol-value file) org-directory) (expand-file-name (symbol-value file) org-directory)
file)) file))
(defadvice! +org--prevent-save-prompts-when-refiling-a (&rest _)
"Fix #462: when refiling from org-capture, Emacs prompts to kill the
underlying, modified buffer. This fixes that."
:after #'org-refile
(when (bound-and-true-p org-capture-is-refiling)
(org-save-all-org-buffers)))
(add-hook! 'org-capture-mode-hook (add-hook! 'org-capture-mode-hook
(defun +org-show-target-in-capture-header-h () (defun +org-show-target-in-capture-header-h ()
(setq header-line-format (setq header-line-format
@ -436,28 +432,39 @@ underlying, modified buffer. This fixes that."
(setq org-pandoc-options (setq org-pandoc-options
'((standalone . t) '((standalone . t)
(mathjax . t) (mathjax . t)
(variable . "revealjs-url=https://revealjs.com"))))) (variable . "revealjs-url=https://revealjs.com"))))
(defadvice! +org--fix-async-export-a (orig-fn &rest args)
:around #'org-export-to-file
(if (not org-export-in-background)
(apply orig-fn args)
(setq org-export-async-init-file (make-temp-file "doom-org-async-export"))
(with-temp-file org-export-async-init-file
(prin1 `(progn (setq org-export-async-debug ,debug-on-error
load-path ',load-path)
(load ,user-init-file nil t))
(current-buffer)))
(apply orig-fn args))))
(defun +org-init-habit-h () (defun +org-init-habit-h ()
"TODO"
(add-hook! 'org-agenda-mode-hook (add-hook! 'org-agenda-mode-hook
(defun +org-habit-resize-graph-h () (defun +org-habit-resize-graph-h ()
"Right align and resize the consistency graphs based on "Right align and resize the consistency graphs based on
`+org-habit-graph-window-ratio'" `+org-habit-graph-window-ratio'"
(require 'org-habit) (when (featurep 'org-habit)
(let* ((total-days (float (+ org-habit-preceding-days org-habit-following-days))) (let* ((total-days (float (+ org-habit-preceding-days org-habit-following-days)))
(preceding-days-ratio (/ org-habit-preceding-days total-days)) (preceding-days-ratio (/ org-habit-preceding-days total-days))
(graph-width (floor (* (window-width) +org-habit-graph-window-ratio))) (graph-width (floor (* (window-width) +org-habit-graph-window-ratio)))
(preceding-days (floor (* graph-width preceding-days-ratio))) (preceding-days (floor (* graph-width preceding-days-ratio)))
(following-days (- graph-width preceding-days)) (following-days (- graph-width preceding-days))
(graph-column (- (window-width) (+ preceding-days following-days))) (graph-column (- (window-width) (+ preceding-days following-days)))
(graph-column-adjusted (if (> graph-column +org-habit-min-width) (graph-column-adjusted (if (> graph-column +org-habit-min-width)
(- graph-column +org-habit-graph-padding) (- graph-column +org-habit-graph-padding)
nil))) nil)))
(setq-local org-habit-preceding-days preceding-days) (setq-local org-habit-preceding-days preceding-days)
(setq-local org-habit-following-days following-days) (setq-local org-habit-following-days following-days)
(setq-local org-habit-graph-column graph-column-adjusted))))) (setq-local org-habit-graph-column graph-column-adjusted))))))
(defun +org-init-hacks-h () (defun +org-init-hacks-h ()
@ -467,10 +474,11 @@ underlying, modified buffer. This fixes that."
;; Open directory links in dired ;; Open directory links in dired
(add-to-list 'org-file-apps '(directory . emacs)) (add-to-list 'org-file-apps '(directory . emacs))
;; When you create a sparse tree and `org-indent-mode' is enabled, the ;; HACK Org is known to use a lot of unicode symbols (and large org files tend
;; highlighting destroys the invisibility added by `org-indent-mode'. ;; to be especially memory hungry). Compounded with
;; Therefore, don't highlight when creating a sparse tree. ;; `inhibit-compacting-font-caches' being non-nil, org needs more memory
(setq org-highlight-sparse-tree-matches nil) ;; to be performant.
(setq-hook! 'org-mode-hook gcmh-high-cons-threshold (* 2 gcmh-high-cons-threshold))
(add-hook! 'org-follow-link-hook (add-hook! 'org-follow-link-hook
(defun +org-delayed-recenter-h () (defun +org-delayed-recenter-h ()
@ -707,12 +715,12 @@ between the two."
:localleader :localleader
"d" #'org-agenda-deadline "d" #'org-agenda-deadline
(:prefix ("c" . "clock") (:prefix ("c" . "clock")
"c" #'org-agenda-clock-in "c" #'org-agenda-clock-cancel
"C" #'org-agenda-clock-out
"g" #'org-agenda-clock-goto "g" #'org-agenda-clock-goto
"i" #'org-agenda-clock-in
"o" #'org-agenda-clock-out
"r" #'org-agenda-clockreport-mode "r" #'org-agenda-clockreport-mode
"s" #'org-agenda-show-clocking-issues "s" #'org-agenda-show-clocking-issues)
"x" #'org-agenda-clock-cancel)
"q" #'org-agenda-set-tags "q" #'org-agenda-set-tags
"r" #'org-agenda-refile "r" #'org-agenda-refile
"s" #'org-agenda-schedule "s" #'org-agenda-schedule
@ -770,6 +778,11 @@ compelling reason, so..."
) )
(defun +org-init-smartparens-h ()
;; Disable the slow defaults
(provide 'smartparens-org))
;; ;;
;;; Packages ;;; Packages
@ -891,8 +904,8 @@ compelling reason, so..."
:ni "C-S-k" #'org-shiftup :ni "C-S-k" #'org-shiftup
:ni "C-S-j" #'org-shiftdown :ni "C-S-j" #'org-shiftdown
;; more intuitive RET keybinds ;; more intuitive RET keybinds
:i [return] #'org-return-indent :i [return] (λ! (org-return t))
:i "RET" #'org-return-indent :i "RET" (λ! (org-return t))
:n [return] #'+org/dwim-at-point :n [return] #'+org/dwim-at-point
:n "RET" #'+org/dwim-at-point :n "RET" #'+org/dwim-at-point
;; more vim-esque org motion keys (not covered by evil-org-mode) ;; more vim-esque org motion keys (not covered by evil-org-mode)
@ -911,11 +924,12 @@ compelling reason, so..."
:n "zc" #'+org/close-fold :n "zc" #'+org/close-fold
:n "zC" #'outline-hide-subtree :n "zC" #'outline-hide-subtree
:n "zm" #'+org/hide-next-fold-level :n "zm" #'+org/hide-next-fold-level
:n "zM" #'+org/close-all-folds
:n "zn" #'org-tree-to-indirect-buffer :n "zn" #'org-tree-to-indirect-buffer
:n "zo" #'+org/open-fold :n "zo" #'+org/open-fold
:n "zO" #'outline-show-subtree :n "zO" #'outline-show-subtree
:n "zr" #'+org/show-next-fold-level :n "zr" #'+org/show-next-fold-level
:n "zR" #'outline-show-all :n "zR" #'+org/open-all-folds
:n "zi" #'org-toggle-inline-images :n "zi" #'org-toggle-inline-images
:map org-read-date-minibuffer-local-map :map org-read-date-minibuffer-local-map
@ -971,15 +985,8 @@ compelling reason, so..."
)) ))
;;; Custom org modules ;;; Custom org modules
(if (featurep! +brain) (load! "contrib/brain")) (dolist (flag doom--current-flags)
(if (featurep! +dragndrop) (load! "contrib/dragndrop")) (load! (concat "contrib/" (substring (symbol-name flag) 1)) nil t))
(if (featurep! +ipython) (load! "contrib/ipython"))
(if (featurep! +journal) (load! "contrib/journal"))
(if (featurep! +jupyter) (load! "contrib/jupyter"))
(if (featurep! +pomodoro) (load! "contrib/pomodoro"))
(if (featurep! +present) (load! "contrib/present"))
(if (featurep! +roam) (load! "contrib/roam"))
(if (featurep! +noter) (load! "contrib/noter"))
;; Add our general hooks after the submodules, so that any hooks the ;; Add our general hooks after the submodules, so that any hooks the
;; submodules add run after them, and can overwrite any defaults if necessary. ;; submodules add run after them, and can overwrite any defaults if necessary.
@ -991,7 +998,7 @@ compelling reason, so..."
#'doom-disable-show-trailing-whitespace-h #'doom-disable-show-trailing-whitespace-h
#'+org-enable-auto-reformat-tables-h #'+org-enable-auto-reformat-tables-h
#'+org-enable-auto-update-cookies-h #'+org-enable-auto-update-cookies-h
#'+org-unfold-to-2nd-level-or-point-h) #'+org-make-last-point-visible-h)
(add-hook! 'org-load-hook (add-hook! 'org-load-hook
#'+org-init-org-directory-h #'+org-init-org-directory-h
@ -1009,7 +1016,8 @@ compelling reason, so..."
#'+org-init-keybinds-h #'+org-init-keybinds-h
#'+org-init-popup-rules-h #'+org-init-popup-rules-h
#'+org-init-protocol-h #'+org-init-protocol-h
#'+org-init-protocol-lazy-loader-h) #'+org-init-protocol-lazy-loader-h
#'+org-init-smartparens-h)
;; (Re)activate eldoc-mode in org-mode a little later, because it disables ;; (Re)activate eldoc-mode in org-mode a little later, because it disables
;; itself if started too soon (which is the case with `global-eldoc-mode'). ;; itself if started too soon (which is the case with `global-eldoc-mode').

View file

@ -41,19 +41,19 @@
(defadvice! +org-present--narrow-to-subtree-a (orig-fn &rest args) (defadvice! +org-present--narrow-to-subtree-a (orig-fn &rest args)
"Narrow to the target subtree when you start the presentation." "Narrow to the target subtree when you start the presentation."
:around #'org-tree-slide--display-tree-with-narrow :around #'org-tree-slide--display-tree-with-narrow
(letf! ((defun org-narrow-to-subtree () (letf! (defun org-narrow-to-subtree ()
(save-excursion (save-excursion
(save-match-data (save-match-data
(org-with-limited-levels (org-with-limited-levels
(narrow-to-region (narrow-to-region
(progn (progn
(when (org-before-first-heading-p) (when (org-before-first-heading-p)
(org-next-visible-heading 1)) (org-next-visible-heading 1))
(ignore-errors (org-up-heading-all 99)) (ignore-errors (org-up-heading-all 99))
(forward-line 1) (forward-line 1)
(point)) (point))
(progn (org-end-of-subtree t t) (progn (org-end-of-subtree t t)
(when (and (org-at-heading-p) (not (eobp))) (when (and (org-at-heading-p) (not (eobp)))
(backward-char 1)) (backward-char 1))
(point)))))))) (point)))))))
(apply orig-fn args)))) (apply orig-fn args))))

View file

@ -27,7 +27,7 @@
:recipe (:host github :recipe (:host github
:repo "emacs-straight/org-mode" :repo "emacs-straight/org-mode"
:files ("*.el" "lisp/*.el" "contrib/lisp/*.el")) :files ("*.el" "lisp/*.el" "contrib/lisp/*.el"))
:pin "b171ff02f6e69bcce0dec56ea23e11c75e558704") :pin "93c50e3a7867a1a85fc78b337172585f7a10dcc6")
;; ...And prevent other packages from pulling org; org-plus-contrib satisfies ;; ...And prevent other packages from pulling org; org-plus-contrib satisfies
;; the dependency already: https://github.com/raxod502/straight.el/issues/352 ;; the dependency already: https://github.com/raxod502/straight.el/issues/352
(package! org :recipe (:local-repo nil)) (package! org :recipe (:local-repo nil))
@ -51,7 +51,7 @@
(when (featurep! :tools magit) (when (featurep! :tools magit)
(package! orgit :pin "e147f055772cc934fe1f1d8619059badeb647c93")) (package! orgit :pin "e147f055772cc934fe1f1d8619059badeb647c93"))
(when (featurep! +brain) (when (featurep! +brain)
(package! org-brain :pin "ae7fe0f628bd093526786ece6917f7a4310e5e4d")) (package! org-brain :pin "ed99f7e38dd687800fb898f8934a0da0541ebcd9"))
(when (featurep! +dragndrop) (when (featurep! +dragndrop)
(package! org-download :pin "d248fcb8f2592a40507682e91eed9a31ead4e4a6")) (package! org-download :pin "d248fcb8f2592a40507682e91eed9a31ead4e4a6"))
(when (featurep! +gnuplot) (when (featurep! +gnuplot)
@ -62,7 +62,7 @@
(when (featurep! +jupyter) (when (featurep! +jupyter)
(package! jupyter :pin "785edbbff65abb0c929dc2fbd8b8305c77fd529e")) (package! jupyter :pin "785edbbff65abb0c929dc2fbd8b8305c77fd529e"))
(when (featurep! +journal) (when (featurep! +journal)
(package! org-journal :pin "8bf06b28d6f14f52d4968123e2b4b91930c8f947")) (package! org-journal :pin "2c43b10eed0659f8e47797e5e53d2973f939284d"))
(when (featurep! +noter) (when (featurep! +noter)
(package! org-noter :pin "9ead81d42dd4dd5074782d239b2efddf9b8b7b3d")) (package! org-noter :pin "9ead81d42dd4dd5074782d239b2efddf9b8b7b3d"))
(when (featurep! +pomodoro) (when (featurep! +pomodoro)
@ -72,11 +72,11 @@
:recipe (:host github :repo "anler/centered-window-mode") :recipe (:host github :repo "anler/centered-window-mode")
:pin "f50859941ab5c7cbeaee410f2d38716252b552ac") :pin "f50859941ab5c7cbeaee410f2d38716252b552ac")
(package! org-tree-slide :pin "7bf09a02bd2d8f1ccfcb5209bfb18fbe02d1f44e") (package! org-tree-slide :pin "7bf09a02bd2d8f1ccfcb5209bfb18fbe02d1f44e")
(package! org-re-reveal :pin "61549f4c00284a30e34caa3d76001b233ea5d2ad")) (package! org-re-reveal :pin "a9e9d4ef88417b3af7741a8d8f444ece820e7a3b"))
(when (featurep! +roam) (when (featurep! +roam)
(package! org-roam :pin "689f55908048eede3cb65aa30ab990be3ac93263") (package! org-roam :pin "1267a430431f11035798cc4007c5dd3efe543ced")
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-org-roam :pin "0913d86f167164e18831206e611f44bb8e7297e3"))) (package! company-org-roam :pin "674c2bd493f571c5323d69279557a6c18ccbd14e")))
;;; Babel ;;; Babel
(package! ob-async :pin "80a30b96a007d419ece12c976a81804ede340311") (package! ob-async :pin "80a30b96a007d419ece12c976a81804ede340311")

View file

@ -1,6 +1,9 @@
;;; lang/purescript/config.el -*- lexical-binding: t; -*- ;;; lang/purescript/config.el -*- lexical-binding: t; -*-
(after! purescript-mode (after! purescript-mode
(when (featurep! +lsp)
(add-hook 'purescript-mode-local-vars-hook #'lsp!))
(add-hook! 'purescript-mode-hook (add-hook! 'purescript-mode-hook
#'purescript-indentation-mode #'purescript-indentation-mode
#'rainbow-delimiters-mode) #'rainbow-delimiters-mode)

View file

@ -4,6 +4,7 @@
(defun +python/open-repl () (defun +python/open-repl ()
"Open the Python REPL." "Open the Python REPL."
(interactive) (interactive)
(require 'python)
(unless python-shell-interpreter (unless python-shell-interpreter
(user-error "`python-shell-interpreter' isn't set")) (user-error "`python-shell-interpreter' isn't set"))
(pop-to-buffer (pop-to-buffer
@ -23,6 +24,7 @@
(defun +python/open-ipython-repl () (defun +python/open-ipython-repl ()
"Open an IPython REPL." "Open an IPython REPL."
(interactive) (interactive)
(require 'python)
(let ((python-shell-interpreter (or (+python-executable-find "ipython") "ipython")) (let ((python-shell-interpreter (or (+python-executable-find "ipython") "ipython"))
(python-shell-interpreter-args (string-join +python-ipython-repl-args " "))) (python-shell-interpreter-args (string-join +python-ipython-repl-args " ")))
(+python/open-repl))) (+python/open-repl)))
@ -31,6 +33,7 @@
(defun +python/open-jupyter-repl () (defun +python/open-jupyter-repl ()
"Open a Jupyter console." "Open a Jupyter console."
(interactive) (interactive)
(require 'python)
(add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter") (add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter")
(let ((python-shell-interpreter (or (+python-executable-find "jupyter") "jupyter")) (let ((python-shell-interpreter (or (+python-executable-find "jupyter") "jupyter"))
(python-shell-interpreter-args (format "console %s" (string-join +python-jupyter-repl-args " ")))) (python-shell-interpreter-args (format "console %s" (string-join +python-jupyter-repl-args " "))))

View file

@ -5,7 +5,7 @@
"This module requires (:tools lsp)") "This module requires (:tools lsp)")
(if (not (executable-find "python")) (if (not (executable-find "python"))
(error! "Python isn't installed.") (error! "Couldn't find python in your PATH")
(unless (featurep! +lsp) (unless (featurep! +lsp)
(unless (zerop (shell-command "python -c 'import setuptools'")) (unless (zerop (shell-command "python -c 'import setuptools'"))
(warn! "setuptools wasn't detected, which anaconda-mode requires")))) (warn! "setuptools wasn't detected, which anaconda-mode requires"))))

View file

@ -50,6 +50,11 @@
(set-lookup-handlers! 'ruby-mode (set-lookup-handlers! 'ruby-mode
:definition #'robe-jump :definition #'robe-jump
:documentation #'robe-doc) :documentation #'robe-doc)
(when (boundp 'read-process-output-max)
;; Robe can over saturate IPC, making interacting with it slow/clobbering
;; the GC, so increase the amount of data Emacs reads from it at a time.
(setq-hook! '(robe-mode-hook inf-ruby-mode-hook)
read-process-output-max (* 1024 1024)))
(when (featurep! :editor evil) (when (featurep! :editor evil)
(add-hook 'robe-mode-hook #'evil-normalize-keymaps)) (add-hook 'robe-mode-hook #'evil-normalize-keymaps))
(map! :localleader (map! :localleader
@ -175,7 +180,9 @@
:when (featurep! +rails) :when (featurep! +rails)
:hook ((ruby-mode inf-ruby-mode projectile-rails-server-mode) . projectile-rails-mode) :hook ((ruby-mode inf-ruby-mode projectile-rails-server-mode) . projectile-rails-mode)
:hook (projectile-rails-server-mode . doom-mark-buffer-as-real-h) :hook (projectile-rails-server-mode . doom-mark-buffer-as-real-h)
:hook (projectile-rails-mode . auto-insert-mode)
:init :init
(setq auto-insert-query nil)
(setq inf-ruby-console-environment "development") (setq inf-ruby-console-environment "development")
(when (featurep! :lang web) (when (featurep! :lang web)
(add-hook 'web-mode-hook #'projectile-rails-mode)) (add-hook 'web-mode-hook #'projectile-rails-mode))

View file

@ -3,34 +3,34 @@
;; Major modes ;; Major modes
(package! ruby-mode :built-in t) (package! ruby-mode :built-in t)
(package! yard-mode :pin "ba74a47463") (package! yard-mode :pin "ba74a47463b0320ae152bd42a7dd7aeecd7b5748")
;; REPL ;; REPL
(package! inf-ruby :pin "41e5ed3a88") (package! inf-ruby :pin "41e5ed3a886fca56990486f1987bb3bae0dbd54b")
(when (featurep! :completion company) (when (featurep! :completion company)
(package! company-inf-ruby :pin "fe3e4863bc")) (package! company-inf-ruby :pin "fe3e4863bc971fbb81edad447efad5795ead1b17"))
;; Programming environment ;; Programming environment
(package! rubocop :pin "03bf15558a") (package! rubocop :pin "03bf15558a6eb65e4f74000cab29412efd46660e")
(package! robe :pin "68503b32bb") (package! robe :pin "68503b32bb3a005787ecb7a7fdeb3bb4a2317e2b")
;; Project tools ;; Project tools
(package! bundler :pin "43efb6be4e") (package! bundler :pin "43efb6be4ed118b06d787ce7fbcffd68a31732a7")
(package! rake :pin "9c204334b0") (package! rake :pin "9c204334b03b4e899fadae6e59c20cf105404128")
;; Environment management ;; Environment management
(when (featurep! +rbenv) (when (featurep! +rbenv)
(package! rbenv :pin "2ea1a5bdc1")) (package! rbenv :pin "2ea1a5bdc1266caef1dd77700f2c8f42429b03f1"))
(when (featurep! +rvm) (when (featurep! +rvm)
(package! rvm :pin "134497bc46")) (package! rvm :pin "134497bc460990c71ab8fa75431156e62c17da2d"))
(when (featurep! +chruby) (when (featurep! +chruby)
(package! chruby :pin "42bc6d521f")) (package! chruby :pin "42bc6d521f832eca8e2ba210f30d03ad5529788f"))
;; Testing frameworks ;; Testing frameworks
(package! rspec-mode :pin "9a2a9d2935") (package! rspec-mode :pin "9a2a9d2935ae17b8570485bdea7c347533b464f6")
(package! minitest :pin "97d7d1760b") (package! minitest :pin "ddd152c990a528ad09a696bfad23afa4330ea4d7")
;; Rails ;; Rails
(when (featurep! +rails) (when (featurep! +rails)
(package! projectile-rails :pin "0398d940a2") (package! projectile-rails :pin "11980b2bcb99208888856a9b8666ff329b6f0142")
(package! inflections :pin "e4f1372cf2")) (package! inflections :pin "e4f1372cf22e811faca52fc86bdd5d817498a4d8"))

View file

@ -0,0 +1,61 @@
#+TITLE: term/eshell
#+DATE: May 18, 2020
#+SINCE: v2.0
#+STARTUP: inlineimages nofold
* Table of Contents :TOC_3:noexport:
- [[#description][Description]]
- [[#maintainers][Maintainers]]
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#hacks][Hacks]]
- [[#prerequisites][Prerequisites]]
- [[#features][Features]]
- [[#configuration][Configuration]]
- [[#troubleshooting][Troubleshooting]]
* Description
This module provides additional features for the built-in [[https://www.gnu.org/software/emacs/manual/html_mono/eshell.html][Emacs Shell]]
The Emacs Shell or =eshell= is a shell-like command interpreter implemented in
Emacs Lisp. It is an alternative to traditional shells such as =bash=, =zsh=,
=fish=, etc. that is built into Emacs and entirely cross-platform.
** Maintainers
This module has no dedicated maintainers.
** Module Flags
This module provides no flags, but does gain auto-completion if =:completion
company= is enabled.
** Plugins
+ [[https://github.com/peterwvj/eshell-up][eshell-up]]
+ [[https://github.com/xuchunyang/eshell-z][eshell-z]]
+ [[https://github.com/tom-tan/esh-help][esh-help]]
+ [[https://gitlab.com/bennya/shrink-path.el][shrink-path]]
+ [[https://github.com/xuchunyang/eshell-did-you-mean][eshell-did-you-mean]]
+ =:completion company=
+ [[https://gitlab.com/ambrevar/emacs-fish-completion][fish-completion]]
+ [[https://github.com/szermatt/emacs-bash-completion][bash-completion]]
** Hacks
+ Even with =fish-completion-fallback-on-bash-p= non-nil, fish must be installed
for bash completion to work. Workaround in =config.el=.
+ =eshell-did-you-mean= does not work on first invocation, so we manually invoke
it once.
* Prerequisites
[[https://fishshell.com/][=fish= shell]] for completions, falling back to [[https://www.gnu.org/software/bash/][=bash= shell]] if =fish= is not
found. If neither shell is found, completions may not be available.
* Features
+ Command completion with Company
+ =fish=-style prompt with Git integration
+ [[https://github.com/rupa/z][=z=]]-like directory jumping
+ Command-not-found recommendations
* TODO Configuration
# How to configure this module, including common problems and how to address them.
* TODO Troubleshooting
# Common issues and their solution, or places to look for help.

View file

@ -21,13 +21,15 @@
t)) t))
(defun +eshell--bury-buffer (&optional dedicated-p) (defun +eshell--bury-buffer (&optional dedicated-p)
(unless (switch-to-prev-buffer nil 'bury) (let ((directory default-directory))
(switch-to-buffer (doom-fallback-buffer))) (unless (switch-to-prev-buffer nil 'bury)
(when (eq major-mode 'eshell-mode) (switch-to-buffer (doom-fallback-buffer)))
(switch-to-buffer (doom-fallback-buffer))) (when (eq major-mode 'eshell-mode)
(when +eshell-enable-new-shell-on-split (switch-to-buffer (doom-fallback-buffer)))
(when-let (win (get-buffer-window (+eshell/here))) (when +eshell-enable-new-shell-on-split
(set-window-dedicated-p win dedicated-p)))) (let ((default-directory directory))
(when-let (win (get-buffer-window (+eshell/here t)))
(set-window-dedicated-p win dedicated-p))))))
(defun +eshell--setup-window (window &optional flag) (defun +eshell--setup-window (window &optional flag)
(when (window-live-p window) (when (window-live-p window)

View file

@ -12,6 +12,10 @@
"Where to store eshell configuration files, as opposed to "Where to store eshell configuration files, as opposed to
`eshell-directory-name', which is where Doom will store temporary/data files.") `eshell-directory-name', which is where Doom will store temporary/data files.")
(defvar eshell-directory-name (concat doom-etc-dir "eshell")
"Where to store temporary/data files, as opposed to `eshell-config-dir',
which is where Doom will store eshell configuration files.")
(defvar +eshell-enable-new-shell-on-split t (defvar +eshell-enable-new-shell-on-split t
"If non-nil, spawn a new eshell session after splitting from an eshell "If non-nil, spawn a new eshell session after splitting from an eshell
buffer.") buffer.")
@ -22,11 +26,13 @@ buffer.")
(defvar +eshell-aliases (defvar +eshell-aliases
'(("q" "exit") ; built-in '(("q" "exit") ; built-in
("f" "find-file $1") ("f" "find-file $1")
("ff" "find-file $1")
("d" "dired $1") ("d" "dired $1")
("bd" "eshell-up $1") ("bd" "eshell-up $1")
("rg" "rg --color=always $*") ("rg" "rg --color=always $*")
("l" "ls -lh $*") ("l" "ls -lh $*")
("ll" "ls -lah $*") ("ll" "ls -lah $*")
("gg" "magit-status")
("clear" "clear-scrollback")) ; more sensible than default ("clear" "clear-scrollback")) ; more sensible than default
"An alist of default eshell aliases, meant to emulate useful shell utilities, "An alist of default eshell aliases, meant to emulate useful shell utilities,
like fasd and bd. Note that you may overwrite these in your like fasd and bd. Note that you may overwrite these in your
@ -35,15 +41,11 @@ to define your aliases.
You should use `set-eshell-alias!' to change this.") You should use `set-eshell-alias!' to change this.")
;;
(defvar eshell-directory-name (concat doom-etc-dir "eshell"))
;; These files are exceptions, because they may contain configuration ;; These files are exceptions, because they may contain configuration
(defvar eshell-aliases-file (concat +eshell-config-dir "aliases")) (defvar eshell-aliases-file (concat +eshell-config-dir "aliases"))
(defvar eshell-rc-script (concat +eshell-config-dir "profile")) (defvar eshell-rc-script (concat +eshell-config-dir "profile"))
(defvar eshell-login-script (concat +eshell-config-dir "login")) (defvar eshell-login-script (concat +eshell-config-dir "login"))
(defvar +eshell--default-aliases nil) (defvar +eshell--default-aliases nil)
@ -152,7 +154,11 @@ You should use `set-eshell-alias!' to change this.")
[remap doom/backward-kill-to-bol-and-indent] #'eshell-kill-input [remap doom/backward-kill-to-bol-and-indent] #'eshell-kill-input
[remap evil-delete-back-to-indentation] #'eshell-kill-input [remap evil-delete-back-to-indentation] #'eshell-kill-input
[remap evil-window-split] #'+eshell/split-below [remap evil-window-split] #'+eshell/split-below
[remap evil-window-vsplit] #'+eshell/split-right)))) [remap evil-window-vsplit] #'+eshell/split-right
(:localleader
"b" #'eshell-insert-buffer-name
"e" #'eshell-insert-envvar
"s" #'+eshell/search-history)))))
(use-package! eshell-up (use-package! eshell-up
@ -173,13 +179,26 @@ You should use `set-eshell-alias!' to change this.")
:config (setup-esh-help-eldoc)) :config (setup-esh-help-eldoc))
(use-package! eshell-did-you-mean
:after esh-mode ; Specifically esh-mode, not eshell
:config
(eshell-did-you-mean-setup)
;; HACK There is a known issue with `eshell-did-you-mean' where it does not
;; work on first invocation, so we invoke it once manually by setting the
;; last command and then calling the output filter.
(setq eshell-last-command-name "catt")
(eshell-did-you-mean-output-filter "catt: command not found"))
(use-package! fish-completion (use-package! fish-completion
:unless IS-WINDOWS
:hook (eshell-mode . fish-completion-mode) :hook (eshell-mode . fish-completion-mode)
:init (setq fish-completion-fallback-on-bash-p t) :init (setq fish-completion-fallback-on-bash-p t)
:config :config
;; HACK Even with `fish-completion-fallback-on-bash-p' non-nil, fish must be ;; HACK Even with `fish-completion-fallback-on-bash-p' non-nil,
;; installed for bash completion to work. How frustrating. This way we ;; `fish-completion--list-completions-with-desc' will throw an error if
;; can at least get bash completion whether or not fish is present. ;; fish isn't installed (and so, will fail to fall back to bash), so we
;; advise it to fail silently.
(defadvice! +eshell--fallback-to-bash-a (&rest _) (defadvice! +eshell--fallback-to-bash-a (&rest _)
:before-while #'fish-completion--list-completions-with-desc :before-until #'fish-completion--list-completions-with-desc
(executable-find "fish"))) (unless (executable-find "fish") "")))

View file

@ -5,7 +5,9 @@
(package! eshell-z :pin "337cb241e17bd472bd3677ff166a0800f684213c") (package! eshell-z :pin "337cb241e17bd472bd3677ff166a0800f684213c")
(package! shrink-path :pin "c14882c8599aec79a6e8ef2d06454254bb3e1e41") (package! shrink-path :pin "c14882c8599aec79a6e8ef2d06454254bb3e1e41")
(package! esh-help :pin "417673ed18a983930a66a6692dbfb288a995cb80") (package! esh-help :pin "417673ed18a983930a66a6692dbfb288a995cb80")
(package! eshell-did-you-mean :pin "7cb6ef8e2274d0a50a9e114d412307a6543533d5")
(when (featurep! :completion company) (unless IS-WINDOWS
(package! fish-completion :pin "10384881817b5ae38cf6197a077a663420090d2c") (when (featurep! :completion company)
(package! bash-completion :pin "96ce14af9674f3e605bacca87abc0c23b8f13cd5")) (package! fish-completion :pin "10384881817b5ae38cf6197a077a663420090d2c")
(package! bash-completion :pin "96ce14af9674f3e605bacca87abc0c23b8f13cd5")))

View file

@ -1,10 +1,10 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; tools/debugger/packages.el ;;; tools/debugger/packages.el
(when (package! realgud :pin "e03446f54c7ee0b4ed3ec7300597046cf1de2bb8") (when (package! realgud :pin "1238d8e72945a84bb06cd39d7ded75f37105d4d2")
(when (featurep! :lang javascript) (when (featurep! :lang javascript)
(package! realgud-trepan-ni :pin "6e9cac5e8097018aadf41c88de541168036cc227"))) (package! realgud-trepan-ni :pin "6e9cac5e8097018aadf41c88de541168036cc227")))
(when (featurep! +lsp) (when (featurep! +lsp)
(package! dap-mode :pin "cc2eb2fc1b2958ef01dad8c004d2f3bc4dc38bc3") (package! dap-mode :pin "8f69dc2e3c850571758744d271061549c19e11fc")
(package! posframe :pin "093b29a53cbeda6d637ccc9ef4dfc47123e79b9e")) (package! posframe :pin "093b29a53cbeda6d637ccc9ef4dfc47123e79b9e"))

View file

@ -12,8 +12,8 @@
;;; Packages ;;; Packages
(use-package! direnv (use-package! direnv
:hook (before-hack-local-variables . direnv--maybe-update-environment) :hook (before-hack-local-variables . direnv-update-environment)
:hook (flycheck-before-syntax-check . direnv--maybe-update-environment) :hook (flycheck-before-syntax-check . direnv-update-environment)
:hook (direnv-envrc-mode . +direnv-envrc-fontify-keywords-h) :hook (direnv-envrc-mode . +direnv-envrc-fontify-keywords-h)
:config :config
(add-to-list 'direnv-non-file-modes 'vterm-mode) (add-to-list 'direnv-non-file-modes 'vterm-mode)

View file

@ -82,7 +82,7 @@ export PATH="/usr/local/opt/sqlite/bin:$PATH"
** Arch Linux ** Arch Linux
#+BEGIN_SRC sh #+BEGIN_SRC sh
sudo pacman -S sqlite ripgrep sudo pacman -S sqlite ripgrep
sudo yay -S wordnet-cli yay -S wordnet-cli
#+END_SRC #+END_SRC
** NixOS ** NixOS

View file

@ -15,6 +15,12 @@ properties:
:definition FN :definition FN
Run when jumping to a symbol's definition. Used by `+lookup/definition'. Run when jumping to a symbol's definition. Used by `+lookup/definition'.
:implementations FN
Run when looking for implementations of a symbol in the current project. Used
by `+lookup/implementations'.
:type-definition FN
Run when jumping to a symbol's type definition. Used by
`+lookup/type-definition'.
:references FN :references FN
Run when looking for usage references of a symbol in the current project. Used Run when looking for usage references of a symbol in the current project. Used
by `+lookup/references'. by `+lookup/references'.
@ -46,6 +52,7 @@ change the current buffer or window or return non-nil when it succeeds.
If it doesn't change the current buffer, or it returns nil, the lookup module If it doesn't change the current buffer, or it returns nil, the lookup module
will fall back to the next handler in `+lookup-definition-functions', will fall back to the next handler in `+lookup-definition-functions',
`+lookup-implementations-functions', `+lookup-type-definition-functions',
`+lookup-references-functions', `+lookup-file-functions' or `+lookup-references-functions', `+lookup-file-functions' or
`+lookup-documentation-functions'. `+lookup-documentation-functions'.
@ -57,7 +64,7 @@ This can be passed nil as its second argument to unset handlers for MODES. e.g.
(set-lookup-handlers! 'python-mode nil) (set-lookup-handlers! 'python-mode nil)
\(fn MODES &key DEFINITION REFERENCES DOCUMENTATION FILE XREF-BACKEND ASYNC)" \(fn MODES &key DEFINITION IMPLEMENTATIONS TYPE-DEFINITION REFERENCES DOCUMENTATION FILE XREF-BACKEND ASYNC)"
(declare (indent defun)) (declare (indent defun))
(dolist (mode (doom-enlist modes)) (dolist (mode (doom-enlist modes))
(let ((hook (intern (format "%s-hook" mode))) (let ((hook (intern (format "%s-hook" mode)))
@ -69,15 +76,19 @@ This can be passed nil as its second argument to unset handlers for MODES. e.g.
(fset (fset
fn fn
(lambda () (lambda ()
(cl-destructuring-bind (&key definition references documentation file xref-backend async) (cl-destructuring-bind (&key definition implementations type-definition references documentation file xref-backend async)
plist plist
(cl-mapc #'+lookup--set-handler (cl-mapc #'+lookup--set-handler
(list definition (list definition
implementations
type-definition
references references
documentation documentation
file file
xref-backend) xref-backend)
(list '+lookup-definition-functions (list '+lookup-definition-functions
'+lookup-implementations-functions
'+lookup-type-definition-functions
'+lookup-references-functions '+lookup-references-functions
'+lookup-documentation-functions '+lookup-documentation-functions
'+lookup-file-functions '+lookup-file-functions
@ -133,6 +144,8 @@ This can be passed nil as its second argument to unset handlers for MODES. e.g.
(let* ((origin (point-marker)) (let* ((origin (point-marker))
(handlers (handlers
(plist-get (list :definition '+lookup-definition-functions (plist-get (list :definition '+lookup-definition-functions
:implementations '+lookup-implementations-functions
:type-definition '+lookup-type-definition-functions
:references '+lookup-references-functions :references '+lookup-references-functions
:documentation '+lookup-documentation-functions :documentation '+lookup-documentation-functions
:file '+lookup-file-functions) :file '+lookup-file-functions)
@ -241,6 +254,30 @@ evil-mode is active."
((+lookup--jump-to :definition identifier nil arg)) ((+lookup--jump-to :definition identifier nil arg))
((error "Couldn't find the definition of %S" identifier)))) ((error "Couldn't find the definition of %S" identifier))))
;;;###autoload
(defun +lookup/implementations (identifier &optional arg)
"Jump to the implementations of IDENTIFIER (defaults to the symbol at point).
Each function in `+lookup-implementations-functions' is tried until one changes
the point or current buffer."
(interactive (list (doom-thing-at-point-or-region)
current-prefix-arg))
(cond ((null identifier) (user-error "Nothing under point"))
((+lookup--jump-to :implementations identifier nil arg))
((error "Couldn't find the implementations of %S" identifier))))
;;;###autoload
(defun +lookup/type-definition (identifier &optional arg)
"Jump to the type definition of IDENTIFIER (defaults to the symbol at point).
Each function in `+lookup-type-definition-functions' is tried until one changes
the point or current buffer."
(interactive (list (doom-thing-at-point-or-region)
current-prefix-arg))
(cond ((null identifier) (user-error "Nothing under point"))
((+lookup--jump-to :type-definition identifier nil arg))
((error "Couldn't find the definition of %S" identifier))))
;;;###autoload ;;;###autoload
(defun +lookup/references (identifier &optional arg) (defun +lookup/references (identifier &optional arg)
"Show a list of usages of IDENTIFIER (defaults to the symbol at point) "Show a list of usages of IDENTIFIER (defaults to the symbol at point)

View file

@ -3,6 +3,8 @@
;; "What am I looking at?" This module helps you answer this question. ;; "What am I looking at?" This module helps you answer this question.
;; ;;
;; + `+lookup/definition': a jump-to-definition that should 'just work' ;; + `+lookup/definition': a jump-to-definition that should 'just work'
;; + `+lookup/implementations': find a symbol's implementations in the current
;; project
;; + `+lookup/references': find a symbol's references in the current project ;; + `+lookup/references': find a symbol's references in the current project
;; + `+lookup/file': open the file referenced at point ;; + `+lookup/file': open the file referenced at point
;; + `+lookup/online'; look up a symbol on online resources ;; + `+lookup/online'; look up a symbol on online resources
@ -52,6 +54,24 @@ If the argument is interactive (satisfies `commandp'), it is called with
argument: the identifier at point. See `set-lookup-handlers!' about adding to argument: the identifier at point. See `set-lookup-handlers!' about adding to
this list.") this list.")
(defvar +lookup-implementations-functions ()
"Function for `+lookup/implementations' to try. Stops at the first function to
return non-nil or change the current window/point.
If the argument is interactive (satisfies `commandp'), it is called with
`call-interactively' (with no arguments). Otherwise, it is called with one
argument: the identifier at point. See `set-lookup-handlers!' about adding to
this list.")
(defvar +lookup-type-definition-functions ()
"Functions for `+lookup/type-definition' to try. Stops at the first function to
return non-nil or change the current window/point.
If the argument is interactive (satisfies `commandp'), it is called with
`call-interactively' (with no arguments). Otherwise, it is called with one
argument: the identifier at point. See `set-lookup-handlers!' about adding to
this list.")
(defvar +lookup-references-functions (defvar +lookup-references-functions
'(+lookup-xref-references-backend-fn '(+lookup-xref-references-backend-fn
+lookup-project-search-backend-fn) +lookup-project-search-backend-fn)

View file

@ -28,9 +28,8 @@
(if IS-MAC (if IS-MAC
(package! osx-dictionary :pin "1b79ff64c72485cb078db9ab7ee3256b11a99f4b") (package! osx-dictionary :pin "1b79ff64c72485cb078db9ab7ee3256b11a99f4b")
(package! define-word :pin "08c71b1ff4fd07bf0c78d1fcf77efeaafc8f7443") (package! define-word :pin "08c71b1ff4fd07bf0c78d1fcf77efeaafc8f7443")
;; HACK Fix #2945: the main package is broken (see ;; HACK Fix #2945: the main package is broken due to
;; SavchenkoValeriy/emacs-powerthesaurus). We use this fork until it is ;; SavchenkoValeriy/emacs-powerthesaurus#11
;; merged.
(package! powerthesaurus (package! powerthesaurus
:recipe (:host github :repo "maxchaos/emacs-powerthesaurus" :branch "pt-api-change") :recipe (:host github :repo "maxchaos/emacs-powerthesaurus" :branch "pt-api-change")
:pin "4a834782a394f2dc70fc02d68b6962b44d87f0cf") :pin "4a834782a394f2dc70fc02d68b6962b44d87f0cf")

View file

@ -51,6 +51,7 @@ As of this writing, this is the state of LSP support in Doom Emacs:
| [[../../lang/sh/README.org][:lang sh]] | sh-mode | bash-language-server | | [[../../lang/sh/README.org][:lang sh]] | sh-mode | bash-language-server |
| [[../../lang/swift/README.org][:lang swift]] | swift-mode | sourcekit | | [[../../lang/swift/README.org][:lang swift]] | swift-mode | sourcekit |
| [[../../lang/web/README.org][:lang web]] | web-mode, css-mode, scss-mode, sass-mode, less-css-mode | vscode-css-languageserver-bin, vscode-html-languageserver-bin | | [[../../lang/web/README.org][:lang web]] | web-mode, css-mode, scss-mode, sass-mode, less-css-mode | vscode-css-languageserver-bin, vscode-html-languageserver-bin |
| [[../../lang/purescript/README.org][:lang purescript]] | purescript-mode | purescript-language-server |
** Module Flags ** Module Flags
+ =+peek= Use =lsp-ui-peek= when looking up definitions and references with + =+peek= Use =lsp-ui-peek= when looking up definitions and references with

View file

@ -54,6 +54,8 @@ working on that project after closing the last buffer.")
(set-lookup-handlers! 'lsp-mode :async t (set-lookup-handlers! 'lsp-mode :async t
:documentation #'lsp-describe-thing-at-point :documentation #'lsp-describe-thing-at-point
:definition #'lsp-find-definition :definition #'lsp-find-definition
:implementations #'lsp-find-implementation
:type-definition #'lsp-find-type-definition
:references #'lsp-find-references) :references #'lsp-find-references)
;; TODO Lazy load these. They don't need to be loaded all at once unless the ;; TODO Lazy load these. They don't need to be loaded all at once unless the
@ -91,6 +93,10 @@ This also logs the resolved project root, if found, so we know where we are."
;; development builds of Emacs 27 and above ;; development builds of Emacs 27 and above
(or (not (boundp 'read-process-output-max)) (or (not (boundp 'read-process-output-max))
(setq-local read-process-output-max (* 1024 1024))) (setq-local read-process-output-max (* 1024 1024)))
;; REVIEW LSP causes a lot of allocations, with or without Emacs 27+'s
;; native JSON library, so we up the GC threshold to stave off
;; GC-induced slowdowns/freezes.
(setq-local gcmh-high-cons-threshold (* 2 gcmh-high-cons-threshold))
(prog1 (lsp-mode 1) (prog1 (lsp-mode 1)
(setq-local lsp-buffer-uri (lsp--buffer-uri)) (setq-local lsp-buffer-uri (lsp--buffer-uri))
;; Announce what project root we're using, for diagnostic purposes ;; Announce what project root we're using, for diagnostic purposes
@ -189,6 +195,7 @@ auto-killed (which is a potentially expensive process)."
(when (featurep! +peek) (when (featurep! +peek)
(set-lookup-handlers! 'lsp-ui-mode :async t (set-lookup-handlers! 'lsp-ui-mode :async t
:definition 'lsp-ui-peek-find-definitions :definition 'lsp-ui-peek-find-definitions
:implementations 'lsp-ui-peek-find-implementation
:references 'lsp-ui-peek-find-references))) :references 'lsp-ui-peek-find-references)))

View file

@ -1,8 +1,8 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; tools/lsp/packages.el ;;; tools/lsp/packages.el
(package! lsp-mode :pin "11750e7b118858b38417a538c1c6eff8759c12f3") (package! lsp-mode :pin "bac42c50b370f3716f258506dc1ae9f62906313f")
(package! lsp-ui :pin "1288be94b4c37f89e80a03b1cff1b81aba9560bb") (package! lsp-ui :pin "ab55e306af9dd9eb62fe7463e4e05d948ad3dfc6")
(when (featurep! :completion ivy) (when (featurep! :completion ivy)
(package! lsp-ivy :pin "81e81ced99829358674c5a6bbe2c3e15cecd4ed8")) (package! lsp-ivy :pin "81e81ced99829358674c5a6bbe2c3e15cecd4ed8"))
(when (featurep! :completion helm) (when (featurep! :completion helm)

View file

@ -1,10 +1,22 @@
;;; tools/magit/autoload.el -*- lexical-binding: t; -*- ;;; tools/magit/autoload.el -*- lexical-binding: t; -*-
;; HACK Magit complains loudly when it can't determine its own version, which is ;; HACK Magit complains loudly (but harmlessly) when it can't determine its own
;; the case when magit is built through straight. The warning is harmless, ;; version (in the case of a sparse clone).
;; however, so we just need it to shut up.
;;;###autoload ;;;###autoload
(advice-add #'magit-version :override #'ignore) (defadvice! +magit--ignore-version-a (&optional print-dest)
:override #'magit-version
(when print-dest
(defvar magit-git-debug)
(princ (format "Magit (unknown), Git %s, Emacs %s, %s"
(or (let ((magit-git-debug
(lambda (err)
(display-warning '(magit git) err :error))))
(magit-git-version t))
"(unknown)")
emacs-version
system-type)
print-dest))
nil)
;;;###autoload ;;;###autoload
(defun +magit-display-buffer-fn (buffer) (defun +magit-display-buffer-fn (buffer)

View file

@ -25,6 +25,20 @@
(setq pdf-view-use-scaling t (setq pdf-view-use-scaling t
pdf-view-use-imagemagick nil) pdf-view-use-imagemagick nil)
;; Persist current page for PDF files viewed in Emacs
(defvar +pdf--page-restored-p nil)
(add-hook! 'pdf-view-change-page-hook
(defun +pdf-remember-page-number-h ()
(when-let (page (and buffer-file-name (pdf-view-current-page)))
(doom-store-put buffer-file-name page nil "pdf-view"))))
(add-hook! 'pdf-view-mode-hook
(defun +pdf-restore-page-number-h ()
(when-let (page (and buffer-file-name (doom-store-get buffer-file-name "pdf-view")))
(and (not +pdf--page-restored-p)
(<= page (or (pdf-cache-number-of-pages) 1))
(pdf-view-goto-page page)
(setq-local +pdf--page-restored-p t)))))
;; Add retina support for MacOS users ;; Add retina support for MacOS users
(when IS-MAC (when IS-MAC
(advice-add #'pdf-util-frame-scale-factor :around #'+pdf--util-frame-scale-factor-a) (advice-add #'pdf-util-frame-scale-factor :around #'+pdf--util-frame-scale-factor-a)
@ -51,29 +65,30 @@
(setq-hook! 'pdf-view-mode-hook evil-normal-state-cursor (list nil)) (setq-hook! 'pdf-view-mode-hook evil-normal-state-cursor (list nil))
;; Install epdfinfo binary if needed, blocking until it is finished ;; Install epdfinfo binary if needed, blocking until it is finished
(require 'pdf-tools) (when doom-interactive-mode
(unless (file-executable-p pdf-info-epdfinfo-program) (require 'pdf-tools)
(let ((wconf (current-window-configuration))) (unless (file-executable-p pdf-info-epdfinfo-program)
(pdf-tools-install) (let ((wconf (current-window-configuration)))
(message "Building epdfinfo, this will take a moment...") (pdf-tools-install)
;; HACK We reset all `pdf-view-mode' buffers to fundamental mode so that (message "Building epdfinfo, this will take a moment...")
;; `pdf-tools-install' has a chance to reinitialize them as ;; HACK We reset all `pdf-view-mode' buffers to fundamental mode so that
;; `pdf-view-mode' buffers. This is necessary because ;; `pdf-tools-install' has a chance to reinitialize them as
;; `pdf-tools-install' won't do this to buffers that are already in ;; `pdf-view-mode' buffers. This is necessary because
;; pdf-view-mode. ;; `pdf-tools-install' won't do this to buffers that are already in
(dolist (buffer (doom-buffers-in-mode 'pdf-view-mode)) ;; pdf-view-mode.
(with-current-buffer buffer (fundamental-mode))) (dolist (buffer (doom-buffers-in-mode 'pdf-view-mode))
(while compilation-in-progress (with-current-buffer buffer (fundamental-mode)))
;; Block until `pdf-tools-install' is done (while compilation-in-progress
(redisplay) ;; Block until `pdf-tools-install' is done
(sleep-for 1)) (redisplay)
;; HACK If pdf-tools was loaded by you opening a pdf file, once (sleep-for 1))
;; `pdf-tools-install' completes, `pdf-view-mode' will throw an error ;; HACK If pdf-tools was loaded by you opening a pdf file, once
;; because the compilation buffer is focused, not the pdf buffer. ;; `pdf-tools-install' completes, `pdf-view-mode' will throw an error
;; Therefore, it is imperative that the window config is restored. ;; because the compilation buffer is focused, not the pdf buffer.
(when (file-executable-p pdf-info-epdfinfo-program) ;; Therefore, it is imperative that the window config is restored.
(set-window-configuration wconf)))) (when (file-executable-p pdf-info-epdfinfo-program)
(set-window-configuration wconf))))
;; Sets up `pdf-tools-enable-minor-modes', `pdf-occur-global-minor-mode' and ;; Sets up `pdf-tools-enable-minor-modes', `pdf-occur-global-minor-mode' and
;; `pdf-virtual-global-minor-mode'. ;; `pdf-virtual-global-minor-mode'.
(pdf-tools-install-noverify)) (pdf-tools-install-noverify)))

View file

@ -1,4 +1,4 @@
;; -*- no-byte-compile: t; -*- ;; -*- no-byte-compile: t; -*-
;;; tools/pdf/packages.el ;;; tools/pdf/packages.el
(package! pdf-tools :pin "d9712989fc4715443f674459199bdffa987054ac") (package! pdf-tools :pin "c510442ab89c8a9e9881230eeb364f4663f59e76")

View file

@ -2,7 +2,7 @@
(use-package! evil-goggles (use-package! evil-goggles
:when (featurep! :editor evil) :when (featurep! :editor evil)
:after-call pre-command-hook :hook (doom-first-input . evil-goggles-mode)
:init :init
(setq evil-goggles-duration 0.1 (setq evil-goggles-duration 0.1
evil-goggles-pulse nil ; too slow evil-goggles-pulse nil ; too slow
@ -23,13 +23,12 @@
'(+eval:region '(+eval:region
:face evil-goggles-yank-face :face evil-goggles-yank-face
:switch evil-goggles-enable-yank :switch evil-goggles-enable-yank
:advice evil-goggles--generic-async-advice)) :advice evil-goggles--generic-async-advice)))
(evil-goggles-mode +1))
(use-package! volatile-highlights (use-package! volatile-highlights
:unless (featurep! :editor evil) :unless (featurep! :editor evil)
:after-call pre-command-hook :hook (doom-first-input . volatile-highlights-mode)
:config :config
(after! undo-fu (after! undo-fu
(vhl/define-extension 'undo-fu 'undo-fu-only-undo 'undo-fu-only-redo) (vhl/define-extension 'undo-fu 'undo-fu-only-undo 'undo-fu-only-redo)