From 48c65c2a2ddeeb83cad270bf5601313d347cc256 Mon Sep 17 00:00:00 2001 From: Aria Date: Thu, 17 May 2018 08:47:38 +1000 Subject: [PATCH 001/132] Add csv mode to data --- modules/lang/data/config.el | 13 +++++++++++++ modules/lang/data/packages.el | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/modules/lang/data/config.el b/modules/lang/data/config.el index 60b1af9b2..359c360ea 100644 --- a/modules/lang/data/config.el +++ b/modules/lang/data/config.el @@ -10,6 +10,19 @@ (def-package! graphql-mode :mode "\\.g\\(?:raph\\)?ql$") +(def-package! csv-mode + :mode "\\.csv$" + :config + (map! :map csv-mode-map + (:localleader + :desc "Align fields" :nvm "a" #'csv-align-fields + :desc "Unalign fields" :nvm "u" #'csv-unalign-fields + :desc "Sort fields" :nvm "s" #'csv-sort-fields + :desc "Sort fields (n)" :nvm "S" #'csv-sort-numeric-fields + :desc "Kill fields" :nvm "k" #'csv-kill-fields + :desc "Transpose fields" :nvm "t" #'csv-transpose))) + + (def-package! hexl ; For ROM hacking or debugging :mode ("\\.hex$" . hexl-mode) diff --git a/modules/lang/data/packages.el b/modules/lang/data/packages.el index fb60ce156..a34a56266 100644 --- a/modules/lang/data/packages.el +++ b/modules/lang/data/packages.el @@ -7,4 +7,4 @@ (package! toml-mode) (package! vimrc-mode) (package! yaml-mode) - +(package! csv-mode) From 1bbf5b7d190f1989d0f6f912c3c8e02ae7ee8ee0 Mon Sep 17 00:00:00 2001 From: Aria Date: Fri, 18 May 2018 13:45:06 +1000 Subject: [PATCH 002/132] lang/org Make agenda view span 10 days --- modules/lang/org/config.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index a2c17bb28..a6d69b199 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -126,7 +126,13 @@ unfold to point on startup." org-agenda-dim-blocked-tasks nil org-agenda-files (ignore-errors (directory-files +org-dir t "\\.org$" t)) org-agenda-inhibit-startup t - org-agenda-skip-unavailable-files t)) + org-agenda-skip-unavailable-files t) + ;; Move the agenda to show the previous 3 days and the next 7 days for a bit + ;; better context instead of just the current week which is a bit confusing + ;; on, for example, a sunday + (setq org-agenda-span 10 + org-agenda-start-on-weekday nil + org-agenda-start-day "-3d")) (defun +org|setup-ui () "Configures the UI for `org-mode'." From dcec3b9b25043152beb9c1972195d612e264bc94 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 12:07:11 +0200 Subject: [PATCH 003/132] feature/popup: add new autosave window parameter (autosave . CDR) This parameter determines what to do with modified buffers in closing popup windows. CDR can be a t, 'ignore, a function or nil. + If t, no prompts. Just save them automatically (if they're file-visiting buffers). + If 'ignore, no prompts, no saving. Just silently kill it. + If nil (the default), prompt the user what to do if the buffer is file-visiting and modified. + If a function, the return value must return one of the other values. It takes two arguments: the popup window and buffer. --- modules/ui/popup/autoload.el | 3 ++- modules/ui/popup/config.el | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/ui/popup/autoload.el b/modules/ui/popup/autoload.el index 8b33d7d91..844e3d1ef 100644 --- a/modules/ui/popup/autoload.el +++ b/modules/ui/popup/autoload.el @@ -68,7 +68,8 @@ and enables `+popup-buffer-mode'." ttl) (when (and (buffer-file-name buffer) (buffer-modified-p buffer) - (y-or-n-p "Popup buffer is modified. Save it?")) + (or (+popup-parameter-fn 'autosave window buffer) + (y-or-n-p "Popup buffer is modified. Save it?"))) (with-current-buffer buffer (save-buffer))) (set-buffer-modified-p nil) (let ((ignore-window-parameters t)) diff --git a/modules/ui/popup/config.el b/modules/ui/popup/config.el index 62c201748..d83c8d708 100644 --- a/modules/ui/popup/config.el +++ b/modules/ui/popup/config.el @@ -45,6 +45,18 @@ Modifying this has no effect, unless done before ui/popup loads. modeline defined with `def-modeline!', nil (show no modeline) or a function that returns one of these. The function takes one argument: the popup buffer. +(autosave . CDR) + This parameter determines what to do with modified buffers in closing popup + windows. CDR can be a t, 'ignore, a function or nil. + + If t, no prompts. Just save them automatically (if they're file-visiting + buffers). + If 'ignore, no prompts, no saving. Just silently kill it. + If nil (the default), prompt the user what to do if the buffer is + file-visiting and modified. + If a function, the return value must return one of the other values. It takes + two arguments: the popup window and buffer. + (popup . t) This is for internal use, do not change this. It simply marks a window as a popup window. @@ -103,13 +115,13 @@ deleted.") '((transient . 0) (quit . t))) (+popup-define "^\\*\\(?:scratch\\|Messages\\)" nil - '((transient))) + '((autosave . t) (transient))) (+popup-define "^\\*doom \\(?:term\\|eshell\\)" '((size . 0.25) (vslot . -10)) '((select . t) (quit) (transient . 0))) (+popup-define "^\\*doom:" '((size . 0.35) (side . bottom)) - '((select . t) (modeline . t) (quit) (transient . t))) + '((autosave . t) (select . t) (modeline . t) (quit) (transient . t))) (+popup-define "^\\*\\(?:\\(?:Pp E\\|doom e\\)val\\)" '((size . +popup-shrink-to-fit)) '((transient . 0) (select . ignore))) From 217ff2cd54fa25de90de7f0f1d3cdd9d58a0eefa Mon Sep 17 00:00:00 2001 From: James Conroy-Finn Date: Sat, 19 May 2018 15:02:54 +0100 Subject: [PATCH 004/132] Fix use of +workspaces-data-file in +workspace/load --- modules/feature/workspaces/autoload/workspaces.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/feature/workspaces/autoload/workspaces.el b/modules/feature/workspaces/autoload/workspaces.el index b014d5588..90b2d5b3c 100644 --- a/modules/feature/workspaces/autoload/workspaces.el +++ b/modules/feature/workspaces/autoload/workspaces.el @@ -211,7 +211,7 @@ current workspace (by name) from session files." (completing-read "Workspace to load: " (persp-list-persp-names-in-file - (expand-file-name +workspace-data-file persp-save-dir)))))) + (expand-file-name +workspaces-data-file persp-save-dir)))))) (if (not (+workspace-load name)) (+workspace-error (format "Couldn't load workspace %s" name)) (+workspace/switch-to name) From 59f510e85fb59b7c70da49b31d5fd3a740ac8368 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 16:32:12 +0200 Subject: [PATCH 005/132] Add four new functions for keywords & file collection --- core/core-lib.el | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/core-lib.el b/core/core-lib.el index 89008a283..8d430b617 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -43,6 +43,36 @@ "Return EXP wrapped in a list, or as-is if already a list." (if (listp exp) exp (list exp))) +(defun doom-keyword-intern (str) + "TODO" + (intern (concat ":" str))) + +(defun doom-keyword-name (keyword) + "TODO" + (or (keywordp keyword) + (signal 'wrong-type-argument (list 'keyword keyword))) + (substring (symbol-name keyword) 1)) + +(cl-defun doom-files-in (dirs &key when unless full map (nosort t) (match "^[^.]")) + "TODO" + (let ((results (cl-loop for dir in (doom-enlist dirs) + if (file-directory-p dir) + nconc (directory-files dir full match nosort)))) + (when when + (cl-delete-if-not when results)) + (when unless + (cl-delete-if unless results)) + (when map + (setq results (mapcar map results))) + results)) + +(cl-defun doom-files-under (dirs &key include-dirs (match "^[^.]")) + "Like `directory-files-recursively', but traverses symlinks." + (cl-letf (((symbol-function #'file-symlink-p) #'ignore)) + (cl-loop for dir in (doom-enlist dirs) + if (file-directory-p dir) + nconc (directory-files-recursively dir match include-dirs)))) + (defun doom*shut-up (orig-fn &rest args) "Generic advisor for silencing noisy functions." (quiet! (apply orig-fn args))) From fa37d7b05e2399f3506ae46de7aa0f77f2aa1ac2 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 16:42:31 +0200 Subject: [PATCH 006/132] Refactor core initialization process A vastly simpler bootstrap process. Also load core libs in core-lib (duh) --- core/core-lib.el | 5 +++++ core/core-packages.el | 11 ++--------- core/core.el | 19 ++++++++++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 8d430b617..08977c353 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -1,5 +1,10 @@ ;;; core-lib.el -*- lexical-binding: t; -*- +(let ((load-path doom-site-load-path)) + (require 'subr-x) + (require 'cl-lib) + (require 'map)) + (eval-and-compile (unless EMACS26+ (with-no-warnings diff --git a/core/core-packages.el b/core/core-packages.el index f06e50e2b..4508747f9 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -1,7 +1,5 @@ ;;; core-packages.el --- package management system -*- lexical-binding: t; -*- -(require 'core-lib (concat doom-core-dir "core-lib")) - ;; Emacs package management is opinionated. Unfortunately, so am I. I've bound ;; together `use-package', `quelpa' and package.el to create my own, ;; rolling-release, lazily-loaded package management system for Emacs. @@ -201,15 +199,10 @@ FORCE-P is non-nil, do it anyway. 4. Builds and caches `load-path', `Info-directory-list' and `doom-disabled-packages' in `doom-packages-file'" ;; Called early during initialization; only use native (and cl-lib) functions! - (let ((load-path doom-site-load-path)) - (require 'subr-x) - (require 'cl-lib) - (require 'map)) - (when (eq doom-init-p 'internal) - (setq force-p nil)) (when (or force-p (not doom-init-p)) ;; packages.el cache - (when (and force-p (file-exists-p doom-packages-file)) + (when (and (or force-p noninteractive) + (file-exists-p doom-packages-file)) (message "Deleting packages.el cache") (delete-file doom-packages-file)) (unless (load doom-packages-file 'noerror 'nomessage 'nosuffix) diff --git a/core/core.el b/core/core.el index 20cb1c018..4e304ff3c 100644 --- a/core/core.el +++ b/core/core.el @@ -173,14 +173,19 @@ this, you'll get stuttering and random freezes) and resets gc-cons-threshold 16777216 gc-cons-percentage 0.15)) -;; -(require 'core-packages (concat doom-core-dir "core-packages")) -(doom-initialize noninteractive) -(add-hook! '(emacs-startup-hook doom-reload-hook) - #'doom|finalize) -(when doom-private-dir - (load (concat doom-private-dir "init") t t)) +;; +;; Bootstrap Doom +;; + +(add-to-list 'load-path doom-core-dir) + +(require 'core-packages) +(require 'core-lib) +(require 'core-os) + +(unless noninteractive + (doom-initialize)) (provide 'core) ;;; core.el ends here From a19a64b16b29ced9610ffc10c5fc03e9ade20cb5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 18:01:49 +0200 Subject: [PATCH 007/132] Complain if using Emacs <25 More helpful than advice-add errors. --- core/core.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/core.el b/core/core.el index 4e304ff3c..a681f59b5 100644 --- a/core/core.el +++ b/core/core.el @@ -1,5 +1,10 @@ ;;; core.el --- the heart of the beast -*- lexical-binding: t; -*- +(eval-when-compile + (when (version< emacs-version "25") + (error "Doom only supports Emacs 25.1 and higher!"))) + +;; (defvar doom-version "2.0.9" "Current version of DOOM emacs.") From 17d5721102db9c546b51bfac0cde6d13eaf1f83e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 23:49:25 +0200 Subject: [PATCH 008/132] Minor reformatting of core startup config --- core/core.el | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/core.el b/core/core.el index a681f59b5..2cea52f61 100644 --- a/core/core.el +++ b/core/core.el @@ -75,6 +75,12 @@ XDG directory conventions if ~/.config/doom exists.") debug-on-error doom-debug-mode ffap-machine-p-known 'reject ; don't ping things that look like domain names idle-update-delay 2 ; update ui less often +;; be quiet at startup; don't load or display anything unnecessary + inhibit-startup-message t + inhibit-startup-echo-area-message user-login-name + inhibit-default-init t + initial-major-mode 'fundamental-mode + initial-scratch-message nil ;; keep the point out of the minibuffer minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt) ;; History & backup settings (save nothing, that's what git is for) @@ -98,14 +104,6 @@ XDG directory conventions if ~/.config/doom exists.") url-cache-directory (concat doom-cache-dir "url/") url-configuration-directory (concat doom-etc-dir "url/")) -;; be quiet at startup; don't load or display anything unnecessary -(unless noninteractive - (advice-add #'display-startup-echo-area-message :override #'ignore) - (setq inhibit-startup-message t - inhibit-startup-echo-area-message user-login-name - inhibit-default-init t - initial-major-mode 'fundamental-mode - initial-scratch-message nil)) ;; Custom init hooks; clearer than `after-init-hook', `emacs-startup-hook', and ;; `window-setup-hook'. @@ -153,6 +151,9 @@ with functions that require it (like modeline segments)." buffer)) (advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename) +;; Truly silence startup message +(advice-add #'display-startup-echo-area-message :override #'ignore) + ;; ;; Bootstrap From 6f5e710d981248d9ef85c91deafd1e745592dba6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 19 May 2018 23:58:14 +0200 Subject: [PATCH 009/132] Refactor startup process, hooks, doom-initialize & doom! + Brings back doom-pre-init-hook and doom-post-init-hook hooks. + Extracts autoload file loading logic into doom-initialize-autoloads function. --- core/core-packages.el | 67 +++++++++++++++++++++++++++---------------- core/core.el | 23 +++++++++++---- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 4508747f9..a06569712 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -78,9 +78,6 @@ missing) and shouldn't be deleted.") everyone in the universe and their dog, causing errors that make babies cry. No one wants that.") -(defvar doom-reload-hook nil - "A list of hooks to run when `doom/reload-load-path' is called.") - (defvar doom-site-load-path load-path "The starting load-path, before it is altered by `doom-initialize'.") @@ -91,6 +88,9 @@ one wants that.") "Where to cache `load-path', `Info-directory-list', `doom-disabled-packages' and `auto-mode-alist'.") +(defvar doom-reload-hook nil + "A list of hooks to run when `doom//reload-load-path' is called.") + (defvar doom--current-module nil) (defvar doom--refreshed-p nil) (defvar doom--stage 'init) @@ -181,8 +181,18 @@ If RETURN-P, return the message as a string instead of displaying it." (or doom-init-time (setq doom-init-time (float-time (time-subtract (current-time) before-init-time)))))) -(add-hook 'emacs-startup-hook #'doom|display-benchmark) -(add-hook 'doom-reload-hook #'doom|display-benchmark) +(defun doom|post-init () + "Run `doom-post-init-hook'. That's all." + (run-hooks 'doom-post-init-hook)) + +(defun doom|run-all-startup-hooks () + "Run all startup Emacs hooks. Meant to follow running Emacs in a vanilla +session, with a different init.el, like so: + + emacs -Q -l init.el -f doom|run-all-startup-hooks" + (run-hooks 'after-init-hook 'delayed-warnings-hook + 'emacs-startup-hook 'term-setup-hook + 'window-setup-hook)) ;; @@ -232,34 +242,41 @@ FORCE-P is non-nil, do it anyway. (if (package-installed-p package) (message "✓ Installed %s" package) (error "✕ Couldn't install %s" package))) - (message "Installing core packages...done")))) + (message "Installing core packages...done"))) + (unless noninteractive + (add-hook 'doom-pre-init-hook #'doom|refresh-cache))) ;; autoloads file - (condition-case-unless-debug e - (unless - (let (byte-compile-warnings) - (load (substring doom-autoload-file 0 -3) 'noerror 'nomessage)) - (error "No autoloads file! Run make autoloads")) - (error - (funcall (if noninteractive #'warn #'error) - "Autoload file error: %s -> %s" (car e) (error-message-string e)))) - (add-to-list 'load-path doom-core-dir)) + (doom-initialize-autoloads)) ;; initialize Doom core - (require 'core-os) (unless noninteractive - (unless doom-init-p - ;; Cache important packages.el state - (doom|refresh-cache)) (require 'core-ui) (require 'core-editor) (require 'core-projects) (require 'core-keybinds)) + ;; bootstrap Doom + (unless doom-init-p + (unless noninteractive + (add-hook! 'doom-reload-hook + #'(doom|refresh-cache doom|display-benchmark)) + (add-hook! 'emacs-startup-hook + #'(doom|post-init doom|display-benchmark))) + (run-hooks 'doom-pre-init-hook) + (when doom-private-dir + (load (concat doom-private-dir "init") t t))) (setq doom-init-p t)) (defun doom-initialize-autoloads () - "Ensures that `doom-autoload-file' exists and is loaded. Otherwise run -`doom//reload-autoloads' to generate it. Used from Doom's Makefile." - (unless (file-exists-p doom-autoload-file) - (quiet! (doom//reload-autoloads)))) + "Tries to load `doom-autoload-file', otherwise throws an error (unless in a +noninteractive session)." + (unless + (condition-case-unless-debug e + (load (substring doom-autoload-file 0 -3) 'noerror 'nomessage) + (error + (funcall (if noninteractive #'warn #'error) + "Autoload error: %s -> %s" + (car e) (error-message-string e)))) + (unless noninteractive + (error "No autoloads file! Run make autoloads")))) (defun doom-initialize-packages (&optional force-p) "Ensures that `doom-packages', `packages-alist' and `quelpa-cache' are @@ -448,11 +465,13 @@ MODULES is an malformed plist of modules to load." `(let (file-name-handler-alist) (setq doom-modules ',doom-modules) ,@(nreverse init-forms) + (run-hooks 'doom-init-hook) (unless noninteractive (let ((doom--stage 'config)) ,@(nreverse config-forms) (when doom-private-dir - (load ,(concat doom-private-dir "config") t t))))))) + (load ,(concat doom-private-dir "config") + t (not doom-debug-mode)))))))) (defmacro def-package! (name &rest plist) "A thin wrapper around `use-package'." diff --git a/core/core.el b/core/core.el index 2cea52f61..e9f68279f 100644 --- a/core/core.el +++ b/core/core.el @@ -107,8 +107,18 @@ XDG directory conventions if ~/.config/doom exists.") ;; Custom init hooks; clearer than `after-init-hook', `emacs-startup-hook', and ;; `window-setup-hook'. +(defvar doom-pre-init-hook nil + "Hooks run after Doom is first initialized; after Doom's core files are +loaded, but before your private init.el file or anything else is loaded.") + (defvar doom-init-hook nil - "A list of hooks run when DOOM is initialized.") + "Hooks run after all init.el files are loaded, including your private and all +module init.el files, but before their config.el files are loaded.") + +(defvar doom-post-init-hook nil + "A list of hooks run when Doom is fully initialized. Fires at the end of +`emacs-startup-hook', as late as possible. Guaranteed to run after everything +else (except for `window-setup-hook').") ;; @@ -156,7 +166,7 @@ with functions that require it (like modeline segments)." ;; -;; Bootstrap +;; Optimize startup ;; (defvar doom--file-name-handler-alist file-name-handler-alist) @@ -173,11 +183,12 @@ with functions that require it (like modeline segments)." "Resets garbage collection settings to reasonable defaults (if you don't do this, you'll get stuttering and random freezes) and resets `file-name-handler-alist'." - (unless noninteractive - (run-hooks 'doom-init-hook)) (setq file-name-handler-alist doom--file-name-handler-alist - gc-cons-threshold 16777216 - gc-cons-percentage 0.15)) + gc-cons-threshold 8388608 + gc-cons-percentage 0.1)) + +(add-hook 'emacs-startup-hook #'doom|finalize) +(add-hook 'doom-reload-hook #'doom|finalize) ;; From 5abdbaee38911e4d6fc48dfab01354474cacf442 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:01:07 +0200 Subject: [PATCH 010/132] Rewrite docstrings for doom-initialize{,-packages} --- core/core-packages.el | 50 +++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index a06569712..a0dcfdc9a 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -200,17 +200,34 @@ session, with a different init.el, like so: ;; (defun doom-initialize (&optional force-p) - "Bootstrap the bare essentials to get Doom running, if it hasn't already. If -FORCE-P is non-nil, do it anyway. + "Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil). -1. Ensures all the essential directories exist, -2. Ensures core packages are installed, -3. Loads your autoloads file in `doom-autoload-file', -4. Builds and caches `load-path', `Info-directory-list' and - `doom-disabled-packages' in `doom-packages-file'" - ;; Called early during initialization; only use native (and cl-lib) functions! +The bootstrap process involves making sure the essential directories exist, core +packages are installed, `doom-autoload-file' is loaded, `doom-packages-file' +cache exists (and is loaded) and, finally, loads your private init.el (which +should contain your `doom!' block). + +If the cache exists, much of this function isn't run, which substantially +reduces startup time. + +The overall load order of Doom is as follows: + + ~/.emacs.d/init.el + ~/.emacs.d/core/core.el + `doom-pre-init-hook' + ~/.doom.d/init.el + Module init.el files + `doom-init-hook' + Module config.el files + ~/.doom.d/config.el + `after-init-hook' + `emacs-startup-hook' + `doom-post-init-hook' (at end of `emacs-startup-hook') + +Module load order is determined by your `doom!' block. See `doom-modules-dirs' +for a list of all recognized module trees. Order defines precedence (from most +to least)." (when (or force-p (not doom-init-p)) - ;; packages.el cache (when (and (or force-p noninteractive) (file-exists-p doom-packages-file)) (message "Deleting packages.el cache") @@ -220,7 +237,7 @@ FORCE-P is non-nil, do it anyway. (dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-packages-dir)) (unless (file-directory-p dir) (make-directory dir t))) - ;; Ensure packages have been initialized + ;; Ensure plugins have been initialized (require 'package) (setq package-activated-list nil package--initialized nil) @@ -230,7 +247,7 @@ FORCE-P is non-nil, do it anyway. ('error (package-refresh-contents) (setq doom--refreshed-p t) (package-initialize)))) - ;; Ensure core packages are installed. + ;; Ensure core packages are installed (let ((core-packages (cl-remove-if #'package-installed-p doom-core-packages))) (when core-packages (message "Installing core packages") @@ -279,17 +296,18 @@ noninteractive session)." (error "No autoloads file! Run make autoloads")))) (defun doom-initialize-packages (&optional force-p) - "Ensures that `doom-packages', `packages-alist' and `quelpa-cache' are -populated. + "Ensures that Doom's package management system, package.el and quelpa are +initialized, and `doom-packages', `packages-alist' and `quelpa-cache' are +populated, if they aren't already. -This reads modules' packages.el files, runs `package-initialize', and -initializes quelpa, if they haven't already. If FORCE-P is non-nil, do it -anyway. If FORCE-P is 'internal, only (re)populate `doom-packages'. +If FORCE-P is non-nil, do it anyway. +If FORCE-P is 'internal, only (re)populate `doom-packages'. Use this before any of package.el, quelpa or Doom's package management's API to ensure all the necessary package metadata is initialized and available for them." (with-temp-buffer ; prevent buffer-local settings from propagating + ;; Prefer uncompiled files to reduce stale code issues (let ((load-prefer-newer t)) ;; package.el and quelpa handle themselves if their state changes during ;; the current session, but if you change an packages.el file in a module, From 85ee9ce459885b6618885418647b0fe3ee359c9c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:03:53 +0200 Subject: [PATCH 011/132] Refactor doom module API + Consolidate the CATEGORY -> MODULE terminology + Rename functions to make their function easier to understand + Rename doom-module-expand-file => doom-module-path + Rename doom-module-find-path => doom-module-locate-path --- bin/doom-doctor | 4 +- core/core-packages.el | 104 +++++++++++++++++++++++------------------- 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 08899c919..39d3c8fd4 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -297,8 +297,8 @@ (maphash (lambda (key plist) (condition-case ex - (let ((doctor-file (doom-module-expand-file (car key) (cdr key) "doctor.el")) - (packages-file (doom-module-expand-file (car key) (cdr key) "packages.el")) + (let ((doctor-file (doom-module-path (car key) (cdr key) "doctor.el")) + (packages-file (doom-module-path (car key) (cdr key) "packages.el")) doom-packages) (when (or (file-exists-p doctor-file) (file-exists-p packages-file)) diff --git a/core/core-packages.el b/core/core-packages.el index a0dcfdc9a..aa753e844 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -352,7 +352,7 @@ them." (let ((doom--stage 'packages)) (_load (expand-file-name "packages.el" doom-core-dir)) (cl-loop for key being the hash-keys of doom-modules - for path = (doom-module-expand-file (car key) (cdr key) "packages.el") + for path = (doom-module-path (car key) (cdr key) "packages.el") do (let ((doom--current-module key)) (_load path t))) (cl-loop for dir in doom-psuedo-module-dirs do (_load (expand-file-name "packages.el" dir) t)))))))) @@ -362,81 +362,91 @@ them." ;; Module API ;; -(defun doom-module-p (module submodule) - "Returns t if MODULE SUBMODULE is enabled (ie. present in `doom-modules')." +(defun doom-module-p (category module) + "Returns t if CATEGORY MODULE is enabled (ie. present in `doom-modules')." (and (hash-table-p doom-modules) - (gethash (cons module submodule) doom-modules) + (gethash (cons category module) doom-modules) t)) -(defun doom-module-get (module submodule &optional property) - "Returns the plist for MODULE/SUBMODULE. If PROPERTY is set, get its property." - (when-let* ((plist (gethash (cons module submodule) doom-modules))) +(defun doom-module-get (category module &optional property) + "Returns the plist for CATEGORY MODULE. Gets PROPERTY, specifically, if set." + (when-let* ((plist (gethash (cons category module) doom-modules))) (if property (plist-get plist property) plist))) -(defun doom-module-put (module submodule property value) - "Set a PROPERTY for MODULE SUBMODULE to VALUE." - (when-let* ((plist (doom-module-get module submodule))) - (puthash (cons module submodule) - (plist-put plist property value) - doom-modules))) +(defun doom-module-put (category module property value &rest rest) + "Set a PROPERTY for CATEGORY MODULE to VALUE. PLIST should be additional pairs +of PROPERTY and VALUEs." + (when-let* ((plist (doom-module-get category module))) + (plist-put plist property value) + (when rest + (when (cl-oddp (length rest)) + (signal 'wrong-number-of-arguments (length (length rest)))) + (while rest + (plist-put rest (pop rest) (pop rest)))) + (puthash (cons category module) plist doom-modules))) -(defun doom-module-set (module submodule &rest plist) - "Adds MODULE and SUBMODULE to `doom-modules' and sets its plist to PLIST, -which should contain a minimum of :flags and :path. +(defun doom-module-set (category module &rest plist) + "Enables a module by adding it to `doom-modules'. -MODULE is a keyword, SUBMODULE is a symbol, PLIST is a plist that accepts the +CATEGORY is a keyword, module is a symbol, PLIST is a plist that accepts the following properties: - :flags [SYMBOL LIST] list of enabled module flags - :path [STRING] path to module root directory + :flags [SYMBOL LIST] list of enabled category flags + :path [STRING] path to category root directory Example: - - (doom-module-set :lang 'haskell :flags '(+intero)) - -Used by `require!'." + (doom-module-set :lang 'haskell :flags '(+intero))" (when plist - (let ((old-plist (doom-module-get module submodule))) + (let ((old-plist (doom-module-get category module))) (unless (plist-member plist :flags) (plist-put plist :flags (plist-get old-plist :flags))) (unless (plist-member plist :path) (plist-put plist :path (or (plist-get old-plist :path) - (doom-module-find-path module submodule)))))) - (let ((key (cons module submodule))) + (doom-module-locate-path category module)))))) + (let ((key (cons category module))) (puthash key plist doom-modules))) -(defun doom-module-find-path (module submodule &optional file) - "Get the full path to a module: e.g. :lang emacs-lisp maps to -~/.emacs.d/modules/lang/emacs-lisp/ and will append FILE if non-nil." - (when (keywordp module) - (setq module (substring (symbol-name module) 1))) - (when (symbolp submodule) - (setq submodule (symbol-name submodule))) +(defun doom-module-path (category module &optional file) + "Like `expand-file-name', but expands FILE relative to CATEGORY (keywordp) and +MODULE (symbol). + +If the category isn't enabled this will always return nil. For finding disabled +modules use `doom-module-locate-path'." + (let ((path (doom-module-get category module :path))) + (if file (expand-file-name file path) + path))) + +(defun doom-module-locate-path (category &optional module file) + "Searches `doom-modules-dirs' to find the path to a module. + +CATEGORY is a keyword (e.g. :lang) and MODULE is a symbol (e.g. 'python). FILE +is a string that will be appended to the resulting path. If no path exists, this +returns nil, otherwise an absolute path. + +This doesn't require modules to be enabled. For enabled modules us +`doom-module-path'." + (when (keywordp category) + (setq category (substring (symbol-name category) 1))) + (when (and module (symbolp module)) + (setq module (symbol-name module))) (cl-loop for default-directory in doom-modules-dirs - for path = (concat module "/" submodule "/" file) + for path = (concat category "/" module "/" file) if (file-exists-p path) return (expand-file-name path))) (defun doom-module-from-path (&optional path) - "Get module cons cell (MODULE . SUBMODULE) for PATH, if possible." - (or doom--current-module + "Returns a cons cell (CATEGORY . MODULE) derived from PATH (a file path)." + (or doom--current-module + (when path (save-match-data (setq path (file-truename path)) (when (string-match "/modules/\\([^/]+\\)/\\([^/]+\\)/.*$" path) (when-let* ((module (match-string 1 path)) (submodule (match-string 2 path))) (cons (intern (concat ":" module)) - (intern submodule))))))) - -(defun doom-module-expand-file (module submodule &optional file) - "Like `expand-file-name', but expands FILE relative to MODULE (keywordp) and -SUBMODULE (symbol)" - (let ((path (doom-module-get module submodule :path))) - (if file - (expand-file-name file path) - path))) + (intern submodule)))))))) (defun doom-module-load-path () "Returns a list of absolute file paths to activated modules, with APPEND-FILE @@ -469,7 +479,7 @@ MODULES is an malformed plist of modules to load." ((not module) (error "No namespace specified in `doom!' for %s" m)) ((let ((submodule (if (listp m) (car m) m)) (flags (if (listp m) (cdr m)))) - (let ((path (doom-module-find-path module submodule))) + (let ((path (doom-module-locate-path module submodule))) (if (not path) (when doom-debug-mode (message "Couldn't find the %s %s module" module submodule)) @@ -579,7 +589,7 @@ The module is only loaded once. If RELOAD-P is non-nil, load it again." (apply #'doom-module-set module submodule (mapcar #'eval plist))) (when (or reload-p (not enabled-p)) - (let ((module-path (doom-module-find-path module submodule))) + (let ((module-path (doom-module-locate-path module submodule))) (if (file-directory-p module-path) `(condition-case-unless-debug ex (let ((doom--current-module ',(cons module submodule))) From dc4e0f155654b07124ead42d962edc21b5bfee1b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:07:06 +0200 Subject: [PATCH 012/132] Add doom-file-cookie-p to core-lib --- core/core-lib.el | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/core-lib.el b/core/core-lib.el index 08977c353..527188cdf 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -48,6 +48,16 @@ "Return EXP wrapped in a list, or as-is if already a list." (if (listp exp) exp (list exp))) +(defun doom-file-cookie-p (file) + "Returns the value of the ;;;###if predicate form in FILE." + (with-temp-buffer + (insert-file-contents-literally file nil 0 256) + (if (and (re-search-forward "^;;;###if " nil t) + (<= (line-number-at-pos) 3)) + (let ((load-file-name file)) + (eval (sexp-at-point))) + t))) + (defun doom-keyword-intern (str) "TODO" (intern (concat ":" str))) From 2d2ce3cff914d38e1ab519005306e045cacf5a0e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:08:19 +0200 Subject: [PATCH 013/132] Fix exec-path/osx-clipboard initializing too early --- core/core-os.el | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/core/core-os.el b/core/core-os.el index 6e2d9002d..b270aa375 100644 --- a/core/core-os.el +++ b/core/core-os.el @@ -30,20 +30,21 @@ ;; Don't open files from the workspace in a new frame ns-pop-up-frames nil) - (cond ((display-graphic-p) - ;; A known problem with GUI Emacs on MacOS: it runs in an isolated - ;; environment, so envvars will be wrong. That includes the PATH - ;; Emacs picks up. `exec-path-from-shell' fixes this. - (when (require 'exec-path-from-shell nil t) - (def-setting! :env (&rest vars) - "Inject VARS from your shell environment into Emacs." - `(exec-path-from-shell-copy-envs (list ,@vars))) - (setq exec-path-from-shell-check-startup-files nil - exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments)) - (defvaralias 'exec-path-from-shell-debug 'doom-debug-mode) - (exec-path-from-shell-initialize))) - ((require 'osx-clipboard nil t) - (osx-clipboard-mode +1)))) + (if (not (display-graphic-p)) + (add-hook 'doom-post-init-hook #'osx-clipboard-mode) + ;; A known problem with GUI Emacs on MacOS: it runs in an isolated + ;; environment, so envvars will be wrong. That includes the PATH Emacs + ;; picks up. `exec-path-from-shell' fixes this. + (defun doom|init-exec-path () + (when (require 'exec-path-from-shell nil t) + (def-setting! :env (&rest vars) + "Inject VARS from your shell environment into Emacs." + `(exec-path-from-shell-copy-envs (list ,@vars))) + (setq exec-path-from-shell-check-startup-files nil + exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments)) + (defvaralias 'exec-path-from-shell-debug 'doom-debug-mode) + (exec-path-from-shell-initialize))) + (add-hook 'doom-pre-init-hook #'doom|init-exec-path))) (IS-LINUX (setq x-gtk-use-system-tooltips nil ; native tooltips are ugly! From 1d99ee5017d325fd1e665ae5e1dd260984cfb9fa Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:37:48 +0200 Subject: [PATCH 014/132] Add esup back to core package list --- core/packages.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/packages.el b/core/packages.el index 7edaaa5ba..a6f962fde 100644 --- a/core/packages.el +++ b/core/packages.el @@ -36,3 +36,6 @@ ;; core-keybinds.el (package! which-key) (package! hydra) + +;; autoload/debug.el +(package! esup) From a46e7655dcfe8f8c1d8d932eabfd0f01ffd087d5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:57:18 +0200 Subject: [PATCH 015/132] Move batch commands from core-packages to autoload/modules --- core/autoload/modules.el | 288 ++++++++++++++++++++++++++++++++ core/core-packages.el | 347 +-------------------------------------- 2 files changed, 289 insertions(+), 346 deletions(-) create mode 100644 core/autoload/modules.el diff --git a/core/autoload/modules.el b/core/autoload/modules.el new file mode 100644 index 000000000..ffc6089ba --- /dev/null +++ b/core/autoload/modules.el @@ -0,0 +1,288 @@ +;;; core/autoload/modules.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun doom//reload () + "Reload your private Doom config. Experimental!" + (interactive) + (let ((load-prefer-newer t)) + (message "Reloading your private config...") + (setq doom-modules (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0)) + (doom-initialize t) + (doom//reload-autoloads)) + (message "✓ Done!")) + +;;;###autoload +(defun doom//reload-load-path () + "Reload `load-path' and recompile files (if necessary). + +Use this when `load-path' is out of sync with your plugins. This should only +happen if you manually modify/update/install packages from outside Emacs, while +an Emacs session is running. + +This isn't necessary if you use Doom's package management commands because they +call `doom//reload-load-path' remotely (through emacsclient)." + (interactive) + (unless doom--inhibit-reload + (when (file-exists-p doom-packages-file) + (delete-file doom-packages-file)) + (cond ((and noninteractive (not (daemonp))) + (require 'server) + (when (server-running-p) + (message "Reloading active Emacs session...") + (server-eval-at server-name '(doom//reload-load-path)))) + (t + (doom-initialize t) + (message "%d packages reloaded" (length package-alist)) + (run-hooks 'doom-reload-hook))))) + +(defvar generated-autoload-load-name) +;;;###autoload +(defun doom//reload-autoloads (&optional force) + "Refreshes the autoloads.el file, specified by `doom-autoload-file'. + +It scans and reads core/autoload/*.el, modules/*/*/autoload.el and +modules/*/*/autoload/*.el, and generates an autoloads file at the path specified +by `doom-autoload-file'. This file tells Emacs where to find lazy-loaded +functions. + +This should be run whenever init.el or an autoload file is modified. Running +'make autoloads' from the commandline executes this command." + (interactive) + ;; This function must not use autoloaded functions or external dependencies. + ;; It must assume nothing is set up! + (let ((default-directory doom-emacs-dir) + (targets + (file-expand-wildcards + (expand-file-name "autoload/*.el" doom-core-dir))) + (generate-autoload-section-continuation "") + (generate-autoload-section-header "") + (generate-autoload-section-trailer "") + (doom--stage 'autoloads) + outdated) + (doom-initialize) + (dolist (path (doom-module-load-path)) + (let ((auto-dir (expand-file-name "autoload" path)) + (auto-file (expand-file-name "autoload.el" path))) + (when (file-exists-p auto-file) + (push auto-file targets)) + (when (file-directory-p auto-dir) + (dolist (file (doom-files-under auto-dir :match "\\.el$")) + (push file targets))))) + (when (file-exists-p doom-autoload-file) + (delete-file doom-autoload-file) + (ignore-errors (delete-file (byte-compile-dest-file doom-autoload-file))) + (message "Deleted old autoloads.el")) + (message "Generating new autoloads.el") + (dolist (file (mapcar #'file-truename (reverse targets))) + (let ((generated-autoload-load-name (file-name-sans-extension file))) + (message + (cond ((not (doom-file-cookie-p file)) + "⚠ Ignoring %s") + ((update-file-autoloads file nil doom-autoload-file) + "✕ Nothing in %s") + ("✓ Scanned %s")) + (if (file-in-directory-p file default-directory) + (file-relative-name file) + (abbreviate-file-name file))))) + (make-directory (file-name-directory doom-autoload-file) t) + (let ((buf (find-file-noselect doom-autoload-file t)) + (load-path (append doom-psuedo-module-dirs + doom-modules-dirs + load-path)) + case-fold-search) + ;; FIXME Make me faster + (unwind-protect + (with-current-buffer buf + (goto-char (point-min)) + (insert ";;; -*- lexical-binding:t -*-\n" + ";; This file is autogenerated by `doom//reload-autoloads', DO NOT EDIT !!\n\n") + + ;; Replace autoload paths (only for module autoloads) with + ;; absolute paths for faster resolution during load and simpler + ;; `load-path' + (save-excursion + (let (cache) + (while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^\"]*\\)\"" nil t) + (let ((path (match-string 1))) + (replace-match + (or (cdr (assoc path cache)) + (when-let* ((libpath (locate-library path)) + (libpath (file-name-sans-extension libpath))) + (push (cons path (abbreviate-file-name libpath)) cache) + libpath) + (progn + (warn "Couldn't find absolute path for: %s" path) + path)) + t t nil 1)))) + (message "✓ Autoload paths expanded")) + + ;; insert package autoloads + (save-excursion + (dolist (spec package-alist) + (let ((pkg (car spec))) + (unless (memq pkg doom-autoload-excluded-packages) + (let ((file + (abbreviate-file-name + (concat (package--autoloads-file-name (cadr spec)) ".el")))) + (insert "(let ((load-file-name " (prin1-to-string file) "))\n") + (insert-file-contents file) + (while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\)" nil t) + (unless (nth 8 (syntax-ppss)) + (replace-match "" t t))) + (unless (bolp) (insert "\n")) + (insert ")\n"))))) + (message "✓ Package autoloads included")) + + ;; Remove `load-path' and `auto-mode-alist' modifications (most + ;; of them, at least); they are cached elsewhere, so these are + ;; unnecessary overhead. + (while (re-search-forward (concat "^\\s-*(\\(add-to-list\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)") + nil t) + (beginning-of-line) + (skip-chars-forward " \t") + (kill-sexp)) + (message "✓ load-path/auto-mode-alist entries removed") + + ;; Remove byte-compile inhibiting file variables so we can + ;; byte-compile the file. + (when (re-search-forward "^;; no-byte-compile: t\n$" nil t) + (replace-match "" t t)) + (save-buffer) + + ;; Byte compile it to give the file a chance to reveal errors. + (condition-case-unless-debug ex + (quiet! (byte-compile-file doom-autoload-file 'load)) + ('error + (delete-file doom-autoload-file) + (message "Deleting autoloads file!") + (error "Error in autoloads.el: %s -- %s" + (car ex) (error-message-string ex)))) + (message "Done!")) + (kill-buffer buf))))) + +;;;###autoload +(defun doom//byte-compile (&optional modules recompile-p) + "Byte compiles your emacs configuration. + +init.el is always byte-compiled by this. + +If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are +byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom +core. It always ignores unit tests and files with `no-byte-compile' enabled. + +Doom was designed to benefit from byte-compilation, but the process may take a +while. Also, while your config files are byte-compiled, changes to them will not +take effect! Use `doom//clean-byte-compiled-files' or `make clean' to remove +these files. + +If RECOMPILE-P is non-nil, only recompile out-of-date files." + (interactive + (list nil current-prefix-arg)) + (let ((default-directory doom-emacs-dir) + (recompile-p (or recompile-p (and (member "-r" (cdr argv)) t))) + (argv (delete "-r" argv))) + (unless recompile-p + (doom//clean-byte-compiled-files)) + (let ((total-ok 0) + (total-fail 0) + (total-noop 0) + (modules (or modules (cdr argv))) + compile-plugins + compile-targets) + ;; Ensure that Doom has been fully loaded, some of its state may be + ;; pertinent to files compiled later. + (let ((doom--stage 'compile) + noninteractive) + ;; Core libraries aren't fully loaded in a noninteractive session, so we + ;; pretend to be interactive and reinitialize + (doom-initialize)) + ;; Assemble el files we want to compile; taking into account that MODULES + ;; may be a list of MODULE/SUBMODULE strings from the command line. + (setq + modules (or modules (append (list doom-core-dir) (doom-module-load-path))) + compile-targets + (cl-loop for target in modules + if (equal target ":core") + nconc (nreverse (doom-files-under doom-core-dir :match "\\.el$")) + and collect (expand-file-name "init.el" doom-private-dir) + if (equal target ":private") + nconc (nreverse (doom-files-under doom-private-dir :match "\\.el$")) + if (equal target ":plugins") + do (setq compile-plugins t) + else if (file-directory-p target) + nconc (nreverse (doom-files-under target :match "\\.el$")) + else if (cl-member target doom-psuedo-module-dirs :test #'file-in-directory-p) + nconc (nreverse (doom-files-under it :match "\\.el$")) + else if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" target) + nconc (nreverse (doom-files-under + (doom-module-locate-path + (intern (format ":%s" (match-string 1 target))) + (intern (match-string 2 target))) + :match "\\.el$")) + else if (file-exists-p target) + collect target + finally do (setq argv nil))) + (if compile-plugins + (byte-recompile-directory package-user-dir 0 t) + (if (not compile-targets) + (message "No targets to compile") + (condition-case ex + (let ((use-package-expand-minimally t)) + (push (expand-file-name "init.el" doom-emacs-dir) compile-targets) + (dolist (target (cl-delete-duplicates (mapcar #'file-truename compile-targets) :test #'equal)) + (when (or (not recompile-p) + (let ((elc-file (byte-compile-dest-file target))) + (and (file-exists-p elc-file) + (file-newer-than-file-p target elc-file)))) + (let ((result (cond ((string-match-p "/\\(packages\\|doctor\\)\\.el$" target) + 'no-byte-compile) + ((doom-file-cookie-p target) + (byte-compile-file target)) + ('no-byte-compile))) + (short-name (if (file-in-directory-p target doom-emacs-dir) + (file-relative-name target doom-emacs-dir) + (abbreviate-file-name target)))) + (cl-incf + (cond ((eq result 'no-byte-compile) + (message! (dark (white "⚠ Ignored %s" short-name))) + total-noop) + ((null result) + (message! (red "✕ Failed to compile %s" short-name)) + total-fail) + (t + (message! (green "✓ Compiled %s" short-name)) + (quiet! (load target t t)) + total-ok)))))) + (message! + (bold + (color (if (= total-fail 0) 'green 'red) + "%s %d/%d file(s) (%d ignored)" + (if recompile-p "Recompiled" "Compiled") + total-ok (- (length compile-targets) total-noop) + total-noop)))) + (error + (message! (red "\n%%s\n\n%%s\n\n%%s") + "There were breaking errors." + (error-message-string ex) + "Reverting changes...") + (quiet! (doom//clean-byte-compiled-files)) + (message! (green "Finished (nothing was byte-compiled)"))))))))) + +;;;###autoload +(defun doom//clean-byte-compiled-files () + "Delete all the compiled elc files in your Emacs configuration. This excludes +compiled packages.'" + (interactive) + (cl-loop with default-directory = doom-emacs-dir + for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$") + (doom-files-in doom-psuedo-module-dirs :match "\\.elc$" :full t) + (doom-files-under doom-core-dir :match "\\.elc$") + (doom-files-under doom-modules-dirs :match "\\.elc$")) + for truepath = (file-truename path) + do (delete-file path) + and do + (message "✓ Deleted %s" + (if (file-in-directory-p truepath default-directory) + (file-relative-name truepath) + (abbreviate-file-name path))) + finally do (message "Everything is clean"))) diff --git a/core/core-packages.el b/core/core-packages.el index aa753e844..9e630ceef 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -717,352 +717,7 @@ loads MODULE SUBMODULE's packages.el file." (flags ,flags)) (when flags (doom-module-put ,module ',submodule :flags flags)) - (load! packages ,(doom-module-find-path module submodule) t))) - - -;; -;; Commands -;; - -(defun doom//reload () - "Reload your private Doom config. Experimental!" - (interactive) - (message "Reloading your private config...") - (load (concat doom-private-dir "init.el") nil nil 'nosuffix) - (doom-packages--async-run #'doom//reload-packages) - (let ((doom--stage 'config)) - (load (concat doom-private-dir "config.el") nil nil 'nosuffix)) - (message "✓ Done!")) - -(defun doom-packages--read-if-cookies (file) - "Returns the value of the ;;;###if predicate form in FILE." - (with-temp-buffer - (insert-file-contents-literally file nil 0 256) - (if (and (re-search-forward "^;;;###if " nil t) - (<= (line-number-at-pos) 3)) - (let ((load-file-name file)) - (eval (sexp-at-point))) - t))) - -(defun doom-packages--async-run (fn) - (let* ((default-directory doom-emacs-dir)) - (compile (format "%s --quick --batch -l core/core.el -f %s" - (executable-find "emacs") - (symbol-name fn))) - (while compilation-in-progress - (sit-for 1)))) - -(defun doom-packages--files (dir pattern) - "Like `directory-files-recursively', but traverses symlinks." - (cl-letf (((symbol-function #'file-symlink-p) #'ignore)) - (directory-files-recursively dir pattern))) - -(defun doom//reload-load-path () - "Reload `load-path' and recompile files (if necessary). - -Use this when `load-path' is out of sync with your plugins. This should only -happen if you manually modify/update/install packages from outside Emacs, while -an Emacs session is running. - -This isn't necessary if you use Doom's package management commands because they -call `doom//reload-load-path' remotely (through emacsclient)." - (interactive) - (unless doom--inhibit-reload - (when (file-exists-p doom-packages-file) - (delete-file doom-packages-file)) - (cond ((and noninteractive (not (daemonp))) - (require 'server) - (when (server-running-p) - (message "Reloading active Emacs session...") - (server-eval-at server-name '(doom//reload-load-path)))) - (t - (doom-initialize t) - (message "%d packages reloaded" (length package-alist)) - (run-hooks 'doom-reload-hook))))) - -(defvar generated-autoload-load-name) -(defun doom//reload-autoloads () - "Refreshes the autoloads.el file, specified by `doom-autoload-file'. - -It scans and reads core/autoload/*.el, modules/*/*/autoload.el and -modules/*/*/autoload/*.el, and generates an autoloads file at the path specified -by `doom-autoload-file'. This file tells Emacs where to find lazy-loaded -functions. - -This should be run whenever init.el or an autoload file is modified. Running -'make autoloads' from the commandline executes this command." - (interactive) - ;; This function must not use autoloaded functions or external dependencies. - ;; It must assume nothing is set up! - (if (not noninteractive) - ;; This is done in another instance to protect the current session's state - ;; in case this function has side effects. - (progn - (doom-packages--async-run 'doom//reload-autoloads) - (load doom-autoload-file 'noerror nil 'nosuffix)) - (let ((default-directory doom-emacs-dir) - (targets - (file-expand-wildcards - (expand-file-name "autoload/*.el" doom-core-dir)))) - (dolist (path (doom-module-load-path)) - (let ((auto-dir (expand-file-name "autoload" path)) - (auto-file (expand-file-name "autoload.el" path))) - (when (file-exists-p auto-file) - (push auto-file targets)) - (when (file-directory-p auto-dir) - (dolist (file (doom-packages--files auto-dir "\\.el$")) - (push file targets))))) - (when (file-exists-p doom-autoload-file) - (delete-file doom-autoload-file) - (ignore-errors (delete-file (byte-compile-dest-file doom-autoload-file))) - (message "Deleted old autoloads.el")) - (message "Generating new autoloads.el") - (dolist (file (mapcar #'file-truename (reverse targets))) - (let ((generated-autoload-load-name (file-name-sans-extension file))) - (message - (cond ((not (doom-packages--read-if-cookies file)) - "⚠ Ignoring %s") - ((update-file-autoloads file nil doom-autoload-file) - "✕ Nothing in %s") - ("✓ Scanned %s")) - (if (file-in-directory-p file default-directory) - (file-relative-name file) - (abbreviate-file-name file))))) - (make-directory (file-name-directory doom-autoload-file) t) - (let ((buf (find-file-noselect doom-autoload-file t)) - (load-path (append doom-psuedo-module-dirs - doom-modules-dirs - load-path)) - case-fold-search) - ;; FIXME Make me faster - (unwind-protect - (with-current-buffer buf - (goto-char (point-min)) - (insert ";;; -*- lexical-binding:t -*-\n" - ";; This file is autogenerated by `doom//reload-autoloads', DO NOT EDIT !!\n\n") - - ;; Replace autoload paths (only for module autoloads) with - ;; absolute paths for faster resolution during load and simpler - ;; `load-path' - (save-excursion - (let (cache) - (while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^/][^\"]*\\)\"" nil t) - (let ((path (match-string 1))) - (replace-match - (or (cdr (assoc path cache)) - (when-let* ((libpath (locate-library path)) - (libpath (file-name-sans-extension libpath))) - (push (cons path libpath) cache) - libpath) - (progn - (warn "Couldn't find absolute path for: %s" path) - path)) - t t nil 1)))) - (message "✓ Autoload paths expanded")) - - ;; insert package autoloads - (save-excursion - (dolist (spec package-alist) - (let ((pkg (car spec))) - (unless (memq pkg doom-autoload-excluded-packages) - (let ((file (concat (package--autoloads-file-name (cadr spec)) ".el"))) - (insert "(let ((load-file-name " (prin1-to-string file) "))") - (insert-file-contents file) - (while (re-search-forward "^;;\\(.*\n\\)" nil t) - (replace-match "" t t)) - (unless (bolp) (insert "\n")) - (insert ")\n"))))) - (message "✓ Package autoloads included")) - - ;; Remove `load-path' and `auto-mode-alist' modifications (most - ;; of them, at least); they are cached elsewhere, so these are - ;; unnecessary overhead. - (while (re-search-forward (concat "^\\s-*(\\(" - "add-to-list\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\|" - "if (fboundp 'register-definition-prefixes)" - "\\)") - nil t) - (beginning-of-line) - (skip-chars-forward " \t") - (kill-sexp)) - (message "✓ load-path/auto-mode-alist entries removed") - - ;; Remove byte-compile inhibiting file variables so we can - ;; byte-compile the file. - (when (re-search-forward "^;; no-byte-compile: t\n$" nil t) - (replace-match "" t t)) - (save-buffer) - - ;; Byte compile it to give the file a chance to reveal errors. - (condition-case-unless-debug ex - (quiet! (byte-compile-file doom-autoload-file 'load)) - ('error - (delete-file doom-autoload-file) - (message "Deleting autoloads file!") - (error "Error in autoloads.el: %s -- %s" - (car ex) (error-message-string ex)))) - (message "Done!")) - (kill-buffer buf)))))) - -(defun doom//byte-compile (&optional modules recompile-p) - "Byte compiles your emacs configuration. - -init.el is always byte-compiled by this. - -If MODULES is specified (a list of module strings, e.g. \"lang/php\"), those are -byte-compiled. Otherwise, all enabled modules are byte-compiled, including Doom -core. It always ignores unit tests and files with `no-byte-compile' enabled. - -Doom was designed to benefit from byte-compilation, but the process may take a -while. Also, while your config files are byte-compiled, changes to them will not -take effect! Use `doom//clean-byte-compiled-files' or `make clean' to remove -these files. - -If RECOMPILE-P is non-nil, only recompile out-of-date files." - (interactive - (list nil current-prefix-arg)) - (let ((default-directory doom-emacs-dir) - (recompile-p (or recompile-p (and (member "-r" (cdr argv)) t))) - (argv (delete "-r" argv))) - (if (not noninteractive) - ;; This is done in another instance to protect the current session's - ;; state, because this function has side effects. - (doom-packages--async-run 'doom//byte-compile) - (let ((total-ok 0) - (total-fail 0) - (total-noop 0) - (modules (or modules (cdr argv))) - compile-targets) - ;; Ensure that Doom has been fully loaded, some of its state may be - ;; pertinent to files compiled later. - (let (noninteractive) - ;; Core libraries aren't fully loaded in a noninteractive session, so - ;; we pretend to be interactive and reinitialize - (doom-initialize) - ;; In case autoloads.el hasn't been properly generated at this point. - (unless (file-exists-p doom-autoload-file) - (mapc #'load (file-expand-wildcards (expand-file-name "autoload/*.el" doom-core-dir))))) - ;; Assemble el files we want to compile; taking into account that - ;; MODULES may be a list of MODULE/SUBMODULE strings from the command - ;; line. - (setq compile-targets - (cl-loop for target - in (or modules (append (list doom-core-dir) (doom-module-load-path))) - if (equal target "core") - nconc (nreverse (doom-packages--files doom-core-dir "\\.el$")) - and collect (expand-file-name "init.el" doom-private-dir) - else if (file-directory-p target) - nconc (nreverse (doom-packages--files target "\\.el$")) - else if (cl-member target doom-psuedo-module-dirs :test #'file-in-directory-p) - nconc (nreverse (doom-packages--files it "\\.el$")) - else if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" target) - nconc (nreverse (doom-packages--files - (doom-module-find-path - (intern (format ":%s" (match-string 1 target))) - (intern (match-string 2 target))) - "\\.el$")) - else if (file-exists-p target) - collect target - finally do (setq argv nil))) - (if (not compile-targets) - (message "No targets to compile") - (condition-case ex - (let ((use-package-expand-minimally t)) - (push (expand-file-name "init.el" doom-emacs-dir) compile-targets) - (dolist (target (cl-delete-duplicates (mapcar #'file-truename compile-targets) :test #'equal)) - (when (and (not (string-match-p "/\\(packages\\|doctor\\)\\.el$" target)) - (or (not recompile-p) - (let ((elc-file (byte-compile-dest-file target))) - (and (file-exists-p elc-file) - (file-newer-than-file-p target elc-file))))) - (let ((result (if (doom-packages--read-if-cookies target) - (byte-compile-file target) - 'no-byte-compile)) - (short-name (if (file-in-directory-p target doom-emacs-dir) - (file-relative-name target doom-emacs-dir) - (abbreviate-file-name target)))) - (cl-incf - (cond ((eq result 'no-byte-compile) - (message! (dark (white "⚠ Ignored %s" short-name))) - total-noop) - ((null result) - (message! (red "✕ Failed to compile %s" short-name)) - total-fail) - (t - (message! (green "✓ Compiled %s" short-name)) - (quiet! (load target t t)) - total-ok)))))) - (message! - (bold - (color (if (= total-fail 0) 'green 'red) - "%s %s file(s) %s" - (if recompile-p "Recompiled" "Compiled") - (format "%d/%d" total-ok (- (length compile-targets) total-noop)) - (format "(%s ignored)" total-noop))))) - (error - (message! (red "\n%%s\n\n%%s\n\n%%s") - "There were breaking errors." - (error-message-string ex) - "Reverting changes...") - (quiet! (doom//clean-byte-compiled-files)) - (message! (green "Finished (nothing was byte-compiled)"))))))))) - -(defun doom//byte-compile-core (&optional recompile-p) - "Byte compile the core Doom files. - -This is faster than `doom//byte-compile', still yields considerable performance -benefits, and is more reliable in an ever-changing Emacs config (since you won't -likely change core files directly). - -If RECOMPILE-P is non-nil, only recompile out-of-date core files." - (interactive "P") - (if (not noninteractive) - ;; This is done in another instance to protect the current session's - ;; state. `doom-initialize-packages' will have side effects otherwise. - (doom-packages--async-run 'doom//byte-compile-core) - (doom//byte-compile (list "core") recompile-p))) - -(defun doom//byte-recompile-plugins () - "Recompile all installed plugins. If you're getting odd errors after upgrading -(or downgrading) Emacs, this may fix it." - (interactive) - (if (not noninteractive) - ;; This is done in another instance to protect the current session's - ;; state. `doom-initialize-packages' will have side effects otherwise. - (doom-packages--async-run 'doom//byte-recompile-plugins) - (byte-recompile-directory package-user-dir 0 t))) - -(defun doom//clean-byte-compiled-files () - "Delete all the compiled elc files in your Emacs configuration. This excludes -compiled packages.'" - (interactive) - (unless - (cl-loop with default-directory = doom-emacs-dir - for path - in (append (file-expand-wildcards "*.elc" t) - (doom-packages--files doom-core-dir "\\.elc$") - (cl-loop for dir in (doom-module-load-path) - nconc (doom-packages--files dir "\\.elc$"))) - for truepath = (file-truename path) - if (file-exists-p truepath) - collect path - and do (delete-file truepath) - and do - (message "✓ Deleted %s" - (if (file-in-directory-p truepath default-directory) - (file-relative-name truepath) - (abbreviate-file-name path)))) - (message "Everything is clean"))) - -(defun doom//reload-packages () - "Runs `doom//reload-autoloads', `doom//packages-autoremove' and -`doom//packages-install' before reloading your Emacs session." - (interactive) - (let ((doom--inhibit-reload t)) - (doom//packages-autoremove) - (doom//packages-install) - (doom//reload-autoloads)) - (doom//reload-load-path)) + (load! packages ,(doom-module-locate-path module submodule) t))) ;; From f984d46a9bef69a9ef4d307b7893e9248ea1b547 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 00:57:57 +0200 Subject: [PATCH 016/132] Fix featurep! & load! calls while byte-compiling The would prioritize load-file-name over byte-compile-current-file during byte-compiling, which would result featurep! being unable to resolve the current module and load! from figuring out where "here" was to build its relative paths from. --- core/core-packages.el | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 9e630ceef..e1d16bfc3 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -565,10 +565,13 @@ the lookup is relative to `load-file-name', `byte-compile-current-file' or If NOERROR is non-nil, don't throw an error if the file doesn't exist." (or (symbolp filesym) (signal 'wrong-type-argument (list 'symbolp filesym))) - (let ((path (or path - (and load-file-name (file-name-directory load-file-name)) + (let ((path (or (when path + (cond ((stringp path) path) + ((symbolp path) (symbol-value path)) + ((listp path) (eval path t)))) (and (bound-and-true-p byte-compile-current-file) (file-name-directory byte-compile-current-file)) + (and load-file-name (file-name-directory load-file-name)) (and buffer-file-name (file-name-directory buffer-file-name)) (error "Could not detect path to look for '%s' in" filesym))) @@ -618,7 +621,8 @@ Module FLAGs are set in your config's `doom!' block, typically in When this macro is used from inside a module, MODULE and SUBMODULE can be omitted. eg. (featurep! +flag1)" (unless submodule - (let* ((path (or load-file-name byte-compile-current-file)) + (let* ((path (or (bound-and-true-p byte-compile-current-file) + load-file-name)) (module-pair (doom-module-from-path path))) (unless module-pair (error "featurep! couldn't detect what module its in! (in %s)" path)) From 0d9db6f14990206997059ff7e40a65b1ba43a77a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 11:44:06 +0200 Subject: [PATCH 017/132] Rewrite autoload/message library + Rename message! => print! + New printerr! macro + Extended color support to interactive sessions (now propertized using term faces, so we don't have to rely on a popup window to display it). --- core/autoload/message.el | 123 +++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 50 deletions(-) diff --git a/core/autoload/message.el b/core/autoload/message.el index 33197690a..f1b84a1b9 100644 --- a/core/autoload/message.el +++ b/core/autoload/message.el @@ -1,55 +1,68 @@ ;;; core/autoload/message.el -*- lexical-binding: t; -*- (defconst doom-message-fg - '((reset . 0) - (black . 30) - (red . 31) - (green . 32) - (yellow . 33) - (blue . 34) - (magenta . 35) - (cyan . 36) - (white . 37)) + '((black 30 term-color-black) + (red 31 term-color-red) + (green 32 term-color-green) + (yellow 33 term-color-yellow) + (blue 34 term-color-blue) + (magenta 35 term-color-magenta) + (cyan 36 term-color-cyan) + (white 37 term-color-white)) "List of text colors.") (defconst doom-message-bg - '((on-black . 40) - (on-red . 41) - (on-green . 42) - (on-yellow . 43) - (on-blue . 44) - (on-magenta . 45) - (on-cyan . 46) - (on-white . 47)) + '((on-black 40 term-color-black) + (on-red 41 term-color-red) + (on-green 42 term-color-green) + (on-yellow 43 term-color-yellow) + (on-blue 44 term-color-blue) + (on-magenta 45 term-color-magenta) + (on-cyan 46 term-color-cyan) + (on-white 47 term-color-white)) "List of colors to draw text on.") (defconst doom-message-fx - '((bold . 1) - (dark . 2) - (italic . 3) - (underscore . 4) - (blink . 5) - (rapid . 6) - (contrary . 7) - (concealed . 8) - (strike . 9)) + '((bold 1 :weight bold) + (dark 2) + (italic 3 :slant italic) + (underscore 4 :underline t) + (blink 5) + (rapid 6) + (contrary 7) + (concealed 8) + (strike 9 :strike-through t)) "List of styles.") ;;;###autoload (defun doom-ansi-apply (code message &rest args) - "Apply the ansi CODE to formatted MESSAGE with ARGS." - (let ((rule (or (assq code doom-message-fg) - (assq code doom-message-bg) - (assq code doom-message-fx)))) - (format "\e[%dm%s\e[%dm" - (cdr rule) - (apply #'format message args) - 0))) + "Apply CODE to formatted MESSAGE with ARGS. CODE is derived from any of +`doom-message-fg', `doom-message-bg' or `doom-message-fx'. + +In a noninteractive session, this wraps the result in ansi color codes. +Otherwise, it maps colors to a term-color-* face." + (let ((text (apply #'format message args))) + (if noninteractive + (format "\e[%dm%s\e[%dm" + (cadr + (or (assq code doom-message-fg) + (assq code doom-message-bg) + (assq code doom-message-fx))) + text 0) + (require 'term) ; piggyback on term's color faces + (propertize + text 'face + (let (spec) + (cond ((setq spec (caddr (assq code doom-message-fg))) + `(:foreground ,(face-foreground spec))) + ((setq spec (caddr (assq code doom-message-bg))) + `(:background ,(face-background spec))) + ((cddr (assq code doom-message-fx))))))))) ;;;###autoload (defmacro format! (message &rest args) - "An alternative to `format' that strips out ANSI codes if used in an -interactive session." + "An alternative to `format' that understands (color ...) and converts them +into faces or ANSI codes depending on the type of sesssion we're in." `(cl-flet* (,@(cl-loop for rule in (append doom-message-fg doom-message-bg doom-message-fx) @@ -63,19 +76,29 @@ interactive session." (format ,message ,@args))) ;;;###autoload -(defmacro message! (message &rest args) - "An alternative to `message' that strips out ANSI codes if used in an -interactive session." +(defmacro printerr! (message &rest args) + "Uses `warn' in interative sessions and `message' otherwise (prints to +standard error). + +Can be colored using (color ...) blocks. See `print!' for details." `(if noninteractive (message (format! ,message ,@args)) - (let ((buf (get-buffer-create " *doom messages*"))) - (with-current-buffer buf - (goto-char (point-max)) - (let ((beg (point)) - end) - (insert (format! ,message ,@args)) - (insert "\n") - (setq end (point)) - (ansi-color-apply-on-region beg end))) - (pop-to-buffer buf) - (goto-char (point-max))))) + (warn ,message ,@args))) + +;;;###autoload +(defmacro print! (message &rest args) + "Uses `message' in interactive sessions and `princ' otherwise (prints to +standard out). + +Can be colored using (color ...) blocks: + + (print! \"Hello %s %s\" (bold (blue \"How are you?\"))) + (print! \"Hello %s %s\" (red \"World\")) + (print! (green \"Great %s!\" \"success\")) + +Uses faces in interactive sessions and ANSI codes otherwise." + `(if (not noninteractive) + (message (format! ,message ,@args)) + ;; princ prints to stdout, message to stderr + (princ (format! ,message ,@args)) + (princ "\n"))) From 61ca98fd3f1a623a717340fa073f4ca90da536a0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:03:46 +0200 Subject: [PATCH 018/132] Refactor package managent batch commands + Replace message! with print! + doom//packages-* commands now only return t if package list changed --- core/autoload/packages.el | 201 +++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 103 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index f5f6f7efa..09f55b420 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -26,15 +26,15 @@ (condition-case ex2 (progn ,@body) ('file-error - (message! (bold (red " FILE ERROR: %s" (error-message-string ex2)))) - (message! " Trying again...") + (print! (bold (red " FILE ERROR: %s" (error-message-string ex2)))) + (print! " Trying again...") (quiet! (doom-refresh-packages-maybe t)) ,@body)) ('user-error - (message! (bold (red " ERROR: %s" ex)))) + (print! (bold (red " ERROR: %s" ex)))) ('error (doom--refresh-pkg-cache) - (message! (bold (red " FATAL ERROR: %s" ex)))))) + (print! (bold (red " FATAL ERROR: %s" ex)))))) (defun doom--refresh-pkg-cache () "Clear the cache for `doom-refresh-packages-maybe'." @@ -336,152 +336,147 @@ package.el as appropriate." (defun doom//packages-install () "Interactive command for installing missing packages." (interactive) - (if (not noninteractive) - (doom-packages--async-run 'doom//packages-install) - (message! "Looking for packages to install...") - (let ((packages (reverse (doom-get-missing-packages)))) - (cond ((not packages) - (message! (green "No packages to install!")) - nil) + (doom-initialize-packages) + (print! "Looking for packages to install...") + (let ((packages (reverse (doom-get-missing-packages)))) + (cond ((not packages) + (print! (green "No packages to install!")) + nil) - ((not (or (getenv "YES") - (y-or-n-p - (format "%s packages will be installed:\n\n%s\n\nProceed?" - (length packages) - (mapconcat - (lambda (pkg) - (format "+ %s (%s)" - (car pkg) - (cond ((doom-package-different-recipe-p (car pkg)) - "new recipe") - ((doom-package-different-backend-p (car pkg)) - (if (plist-get (cdr pkg) :recipe) - "ELPA -> QUELPA" - "QUELPA -> ELPA")) - ((plist-get (cdr pkg) :recipe) - "QUELPA") - (t - "ELPA")))) - (sort (cl-copy-list packages) #'doom--sort-alpha) - "\n"))))) - (message! (yellow "Aborted!")) - nil) + ((not (or (getenv "YES") + (y-or-n-p + (format "%s packages will be installed:\n\n%s\n\nProceed?" + (length packages) + (mapconcat + (lambda (pkg) + (format "+ %s (%s)" + (car pkg) + (cond ((doom-package-different-recipe-p (car pkg)) + "new recipe") + ((doom-package-different-backend-p (car pkg)) + (if (plist-get (cdr pkg) :recipe) + "ELPA -> QUELPA" + "QUELPA -> ELPA")) + ((plist-get (cdr pkg) :recipe) + "QUELPA") + (t + "ELPA")))) + (sort (cl-copy-list packages) #'doom--sort-alpha) + "\n"))))) + (error "Aborted!")) - (t + ((let (success) (doom-refresh-packages-maybe doom-debug-mode) (dolist (pkg packages) - (message! "Installing %s" (car pkg)) + (print! "Installing %s" (car pkg)) (doom--condition-case! - (message! "%s%s" + (print! "%s%s" (if (and (package-installed-p (car pkg)) (not (doom-package-different-backend-p (car pkg))) (not (doom-package-different-recipe-p (car pkg)))) (dark (white "⚠ ALREADY INSTALLED")) (condition-case e (if (doom-install-package (car pkg) (cdr pkg)) - (green "✓ DONE") + (prog1 (green "✓ DONE") + (setq success t)) (red "✕ FAILED")) (error (red "✕ ERROR (%s)" e)))) (if (plist-member (cdr pkg) :pin) (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) "")))) - - (message! (bold (green "Finished!"))) + (print! (bold (green "Finished!"))) (doom//reload-load-path) - t))))) + success))))) ;;;###autoload (defun doom//packages-update () "Interactive command for updating packages." (interactive) - (if (not noninteractive) - (doom-packages--async-run 'doom//packages-update) - (message! "Looking for outdated packages...") - (doom-refresh-packages-maybe doom-debug-mode) - (let ((packages (sort (doom-get-outdated-packages) #'doom--sort-alpha))) - (cond ((not packages) - (message! (green "Everything is up-to-date")) - nil) + (doom-initialize-packages) + (print! "Looking for outdated packages...") + (doom-refresh-packages-maybe doom-debug-mode) + (let ((packages (sort (doom-get-outdated-packages) #'doom--sort-alpha))) + (cond ((not packages) + (print! (green "Everything is up-to-date")) + nil) - ((not (or (getenv "YES") - (y-or-n-p - (format "%s packages will be updated:\n\n%s\n\nProceed?" - (length packages) - (let ((max-len - (or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages) - (lambda (it other) (> it other)))) - 10))) - (mapconcat - (lambda (pkg) - (format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14) - (symbol-name (car pkg)) - (package-version-join (cadr pkg)) - (package-version-join (cl-caddr pkg)))) - packages - "\n")))))) - (message! (yellow "Aborted!")) - nil) + ((not (or (getenv "YES") + (y-or-n-p + (format "%s packages will be updated:\n\n%s\n\nProceed?" + (length packages) + (let ((max-len + (or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages) + (lambda (it other) (> it other)))) + 10))) + (mapconcat + (lambda (pkg) + (format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14) + (symbol-name (car pkg)) + (package-version-join (cadr pkg)) + (package-version-join (cl-caddr pkg)))) + packages + "\n")))))) + (error "Aborted!")) - (t + ((let (success) (dolist (pkg packages) - (message! "Updating %s" (car pkg)) + (print! "Updating %s" (car pkg)) (doom--condition-case! - (message! + (print! (let ((result (doom-update-package (car pkg) t))) + (when result (setq success t)) (color (if result 'green 'red) (if result "✓ DONE" "✕ FAILED")))))) - - (message! (bold (green "Finished!"))) + (print! (bold (green "Finished!"))) (doom//reload-load-path) - t))))) + success))))) ;;;###autoload (defun doom//packages-autoremove () "Interactive command for auto-removing orphaned packages." (interactive) - (if (not noninteractive) - (doom-packages--async-run 'doom//packages-autoremove) - (message! "Looking for orphaned packages...") - (let ((packages (doom-get-orphaned-packages))) - (cond ((not packages) - (message! (green "No unused packages to remove")) - nil) + (doom-initialize-packages) + (print! "Looking for orphaned packages...") + (let ((packages (doom-get-orphaned-packages))) + (cond ((not packages) + (print! (green "No unused packages to remove")) + nil) - ((not - (or (getenv "YES") - (y-or-n-p - (format - "%s packages will be deleted:\n\n%s\n\nProceed?" - (length packages) - (mapconcat - (lambda (sym) - (format "+ %s (%s)" sym - (let ((backend (doom-package-backend sym))) - (if (doom-package-different-backend-p sym) - (pcase backend - (`quelpa "QUELPA->ELPA") - (`elpa "ELPA->QUELPA") - (_ "removed")) - (upcase (symbol-name backend)))))) - (sort (cl-copy-list packages) #'string-lessp) - "\n"))))) - (message! (yellow "Aborted!")) - nil) + ((not + (or (getenv "YES") + (y-or-n-p + (format + "%s packages will be deleted:\n\n%s\n\nProceed?" + (length packages) + (mapconcat + (lambda (sym) + (format "+ %s (%s)" sym + (let ((backend (doom-package-backend sym))) + (if (doom-package-different-backend-p sym) + (pcase backend + (`quelpa "QUELPA->ELPA") + (`elpa "ELPA->QUELPA") + (_ "removed")) + (upcase (symbol-name backend)))))) + (sort (cl-copy-list packages) #'string-lessp) + "\n"))))) + (error "Aborted!")) - (t + ((let (success) (dolist (pkg packages) (doom--condition-case! - (message! + (print! (let ((result (doom-delete-package pkg t))) + (when result (setq success t)) (color (if result 'green 'red) "%s %s" (if result "✓ Removed" "✕ Failed to remove") pkg))))) - (message! (bold (green "Finished!"))) + (print! (bold (green "Finished!"))) (doom//reload-load-path) - t))))) + success))))) ;; From 0634289a01ead0c4b73fade0e760177554164dd3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:05:17 +0200 Subject: [PATCH 019/132] Autoload doom-*-package functions --- core/autoload/packages.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 09f55b420..49eb5e5d5 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -260,6 +260,7 @@ Used by `doom//packages-install'." ;; Main functions ;; +;;;###autoload (defun doom-install-package (name &optional plist) "Installs package NAME with optional quelpa RECIPE (see `quelpa-recipe' for an example; the package name can be omitted)." @@ -283,6 +284,7 @@ example; the package name can be omitted)." (map-put doom-packages name plist) name))) +;;;###autoload (defun doom-update-package (name &optional force-p) "Updates package NAME (a symbol) if it is out of date, using quelpa or package.el as appropriate." @@ -310,6 +312,7 @@ package.el as appropriate." (delete-directory old-dir t))) t)))) +;;;###autoload (defun doom-delete-package (name &optional force-p) "Uninstalls package NAME if it exists, and clears it from `quelpa-cache'." (unless (package-installed-p name) From c826f0f6a8d694c01cb8672fb237fdad4cc5136d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:06:50 +0200 Subject: [PATCH 020/132] Shrink dependency chains in core libraries --- core/autoload/cache.el | 2 -- core/autoload/help.el | 1 + core/autoload/packages.el | 4 ---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/autoload/cache.el b/core/autoload/cache.el index c4392be0a..1093bf9ce 100644 --- a/core/autoload/cache.el +++ b/core/autoload/cache.el @@ -12,8 +12,6 @@ ;; Like persistent-soft, caches assume a 2-tier structure, where all caches are ;; namespaced by location. -(require 'persistent-soft) - (defvar doom-cache-alists () "An alist of alists, containing lists of variables for the doom cache library to persist across Emacs sessions.") diff --git a/core/autoload/help.el b/core/autoload/help.el index 202b49980..969081464 100644 --- a/core/autoload/help.el +++ b/core/autoload/help.el @@ -75,6 +75,7 @@ in, or d) the module associated with the current major mode (see "init.el") (thing-at-point 'sexp t))) ((save-excursion + (require 'smartparens) (ignore-errors (sp-beginning-of-sexp) (unless (eq (char-after) ?\() diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 49eb5e5d5..3938c5c68 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -1,10 +1,6 @@ ;;; core/autoload/packages.el -*- lexical-binding: t; -*- (load! cache) -(require 'use-package) -(require 'quelpa) -(require 'package) -(require 'async) ;;; Private functions (defsubst doom--sort-alpha (it other) From b7b1445712f631f8349fcf2256879f9108ad05f8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:07:20 +0200 Subject: [PATCH 021/132] Update doom-get-outdated-packages to match new init process --- core/autoload/packages.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 3938c5c68..58a1a008b 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -197,9 +197,12 @@ Used by `doom//packages-update'." (message "New thread for: %s" pkg)) (push (async-start `(lambda () - (let ((doom-init-p 'internal) + (let ((doom-init-p t) (noninteractive t) (load-path ',load-path) + (package-alist ',package-alist) + (package-archive-contents ',package-archive-contents) + (package-selected-packages ',package-selected-packages) (doom-packages ',doom-packages) (doom-modules ',doom-modules) (quelpa-cache ',quelpa-cache) @@ -207,6 +210,8 @@ Used by `doom//packages-update'." doom-private-dir) (load ,(expand-file-name "core.el" doom-core-dir)) (load ,(expand-file-name "autoload/packages.el" doom-core-dir)) + (require 'package) + (require 'quelpa) (doom-package-outdated-p ',pkg)))) futures)) (delq nil From af7fb1c628f0290a5d65b9fdb0ab737e2cada815 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:10:03 +0200 Subject: [PATCH 022/132] Change doom/retab to reformat w/ opposite style if ARG --- core/autoload/editor.el | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/core/autoload/editor.el b/core/autoload/editor.el index b3b4ce058..4baa3fc93 100644 --- a/core/autoload/editor.el +++ b/core/autoload/editor.el @@ -215,17 +215,21 @@ possible, or just one char if that's not possible." (t (delete-char (- n) killflag)))) ;;;###autoload -(defun doom/retab (&optional beg end) +(defun doom/retab (arg &optional beg end) "Converts tabs-to-spaces or spaces-to-tabs within BEG and END (defaults to buffer start and end, to make indentation consistent. Which it does depends on -the value of `indent-tab-mode'." - (interactive "r") +the value of `indent-tab-mode'. + +If ARG (universal argument) is non-nil, retab the current buffer using the +opposite indentation style." + (interactive "Pr") (unless (and beg end) (setq beg (point-min) end (point-max))) - (if indent-tabs-mode - (tabify beg end) - (untabify beg end))) + (let ((indent-tabs-mode (if arg (not indent-tabs-mode) indent-tabs-mode))) + (if indent-tabs-mode + (tabify beg end) + (untabify beg end)))) (defvar-local doom--buffer-narrowed-origin nil) ;;;###autoload From 7b8917ed421fb0d89bf6b77837a7e4b9de8ec6e9 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:13:05 +0200 Subject: [PATCH 023/132] Split core/autoload/util.el into {help,debug}.el --- core/autoload/{util.el => debug.el} | 231 ++++++++++++---------------- core/autoload/help.el | 107 +++++++++---- 2 files changed, 176 insertions(+), 162 deletions(-) rename core/autoload/{util.el => debug.el} (63%) diff --git a/core/autoload/util.el b/core/autoload/debug.el similarity index 63% rename from core/autoload/util.el rename to core/autoload/debug.el index 2500df78b..db5764ee4 100644 --- a/core/autoload/util.el +++ b/core/autoload/debug.el @@ -1,126 +1,10 @@ -;;; core/autoload/util.el -*- lexical-binding: t; -*- - -;;;###autoload -(defun doom/what-face (&optional pos) - "Shows all faces and overlay faces at point. - -Interactively prints the list to the echo area. Noninteractively, returns a list -whose car is the list of faces and cadr is the list of overlay faces." - (interactive) - (let* ((pos (or pos (point))) - (faces (let ((face (get-text-property pos 'face))) - (if (keywordp (car-safe face)) - (list face) - (cl-loop for f in (doom-enlist face) collect f)))) - (overlays (cl-loop for ov in (overlays-at pos (1+ pos)) - nconc (doom-enlist (overlay-get ov 'face))))) - (cond ((called-interactively-p 'any) - (message "%s %s\n%s %s" - (propertize "Faces:" 'face 'font-lock-comment-face) - (if faces - (cl-loop for face in faces - if (listp face) - concat (format "'%s " face) - else - concat (concat (propertize (symbol-name face) 'face face) " ")) - "n/a ") - (propertize "Overlays:" 'face 'font-lock-comment-face) - (if overlays - (cl-loop for ov in overlays - concat (concat (propertize (symbol-name ov) 'face ov) " ")) - "n/a"))) - (t - (and (or faces overlays) - (list faces overlays)))))) - -;;;###autoload -(defun doom-active-minor-modes () - "Get a list of active minor-mode symbols." - (cl-loop for mode in minor-mode-list - if (and (boundp mode) (symbol-value mode)) - collect mode)) - -;;;###autoload -(defun doom/what-minor-mode (mode) - "Get information on an active minor mode. Use `describe-minor-mode' for a -selection of all minor-modes, active or not." - (interactive - (list (completing-read "Minor mode: " - (doom-active-minor-modes)))) - (describe-minor-mode-from-symbol - (cl-typecase mode - (string (intern mode)) - (symbol mode) - (t (error "Expected a symbol/string, got a %s" (type-of mode)))))) - -;;;###autoload -(defun doom/am-i-secure () - "Test to see if your root certificates are securely configured in emacs." - (declare (interactive-only t)) - (interactive) - (unless (string-match-p "\\_" system-configuration-features) - (warn "gnutls support isn't built into Emacs, there may be problems")) - (if-let* ((bad-hosts - (cl-loop for bad - in '("https://wrong.host.badssl.com/" - "https://self-signed.badssl.com/") - if (condition-case _e - (url-retrieve-synchronously bad) - (error nil)) - collect bad))) - (error (format "tls seems to be misconfigured (it got %s)." - bad-hosts)) - (url-retrieve "https://badssl.com" - (lambda (status) - (if (or (not status) (plist-member status :error)) - (warn "Something went wrong.\n\n%s" (pp-to-string status)) - (message "Your trust roots are set up properly.\n\n%s" (pp-to-string status)) - t))))) - -(defvar doom--profiler nil) -;;;###autoload -(defun doom/toggle-profiler () - "Toggle the Emacs profiler. Starts it if isn't running. Stops it and pops up -the profiling report otherwise." - (interactive) - (if (not doom--profiler) - (profiler-start 'cpu+mem) - (profiler-report) - (profiler-stop)) - (setq doom--profiler (not doom--profiler))) - -;;;###autoload -(defun doom/profile-emacs () - "Profile the startup time of Emacs in the background. -If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE." - (interactive) - (require 'esup) - (let ((init-file esup-user-init-file)) - (message "Starting esup...") - (esup-reset) - (setq esup-server-process (esup-server-create (esup-select-port))) - (setq esup-server-port (process-contact esup-server-process :service)) - (message "esup process started on port %s" esup-server-port) - (let ((process-args `("*esup-child*" - "*esup-child*" - ,esup-emacs-path - "-q" - "-L" ,esup-load-path - "-l" "esup-child" - ,(format "--eval=(esup-child-run \"%s\" \"%s\" %d)" - init-file - esup-server-port - esup-depth) - "--eval=(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)"))) - (when esup-run-as-batch-p - (setq process-args (append process-args '("--batch")))) - (setq esup-child-process (apply #'start-process process-args))) - (set-process-sentinel esup-child-process 'esup-child-process-sentinel))) +;;; core/autoload/debug.el -*- lexical-binding: t; -*- ;;;###autoload (defun doom-info () "Returns diagnostic information about the current Emacs session in markdown, ready to be pasted in a bug report on github." + (doom-initialize) (require 'vc-git) (let ((default-directory doom-emacs-dir)) (format @@ -136,7 +20,7 @@ ready to be pasted in a bug report on github." " packages: %s\n" " elc dirs: %s\n" " exec-path: %s\n" - " ```\n") + " ```") system-type system-configuration emacs-version (format-time-string "%b %d, %Y" emacs-build-time) doom-version @@ -144,7 +28,7 @@ ready to be pasted in a bug report on github." branch "n/a") (if-let* ((rev (vc-git-working-revision "core/core.el"))) - (format "https://github.com/hlissner/doom-emacs/commit/%s" rev) + rev "n/a") (display-graphic-p) (daemonp) (bound-and-true-p system-configuration-features) @@ -177,11 +61,11 @@ ready to be pasted in a bug report on github." (load ,(expand-file-name "core/autoload/packages.el" doom-emacs-dir)) (doom-get-packages)) (lambda (p) (setq packages p)))) - (mapcar (lambda (x) - (if (cdr x) - (format "%s" x) - (symbol-name (car x)))) - (cl-sort packages #'string-lessp :key (lambda (x) (symbol-name (car x))))))) + (cl-loop for pkg in (cl-sort packages #'string-lessp + :key (lambda (x) (symbol-name (car x)))) + collect (if (cdr pkg) + (format "%s" pkg) + (symbol-name (car pkg)))))) "n/a") (or (ignore-errors (cl-delete-duplicates @@ -191,22 +75,105 @@ ready to be pasted in a bug report on github." collect (file-relative-name (file-name-directory file) doom-emacs-dir)) :test #'equal)) "n/a") - exec-path))) + ;; abbreviate $HOME to hide username + (mapcar #'abbreviate-file-name exec-path)))) + + +;; +;; Commands +;; ;;;###autoload -(defun doom/info () +(defun doom//info () "Collects some debug information about your Emacs session, formats it into markdown and copies it to your clipboard, ready to be pasted into bug reports!" (declare (interactive-only t)) (interactive) + (message "Generating Doom info...") (if noninteractive - (message "%s" (doom-info)) - (message "Generating Doom info...") + (print! (doom-info)) (kill-new (doom-info)) (message "Done! Copied to clipboard."))) ;;;###autoload -(defun doom/toggle-debug-mode () +(defun doom//am-i-secure () + "Test to see if your root certificates are securely configured in emacs." + (declare (interactive-only t)) (interactive) - (setq doom-debug-mode (not doom-debug-mode)) - (toggle-debug-on-error)) + (unless (string-match-p "\\_" system-configuration-features) + (warn "gnutls support isn't built into Emacs, there may be problems")) + (if-let* ((bad-hosts + (cl-loop for bad + in '("https://wrong.host.badssl.com/" + "https://self-signed.badssl.com/") + if (condition-case _e + (url-retrieve-synchronously bad) + (error nil)) + collect bad))) + (error "tls seems to be misconfigured (it got %s)." + bad-hosts) + (url-retrieve "https://badssl.com" + (lambda (status) + (if (or (not status) (plist-member status :error)) + (warn "Something went wrong.\n\n%s" (pp-to-string status)) + (message "Your trust roots are set up properly.\n\n%s" (pp-to-string status)) + t))))) + +;;;###autoload +(defun doom//version () + "Display the current version of Doom & Emacs, including the current Doom +branch and commit." + (interactive) + (require 'vc-git) + (print! "Doom v%s (Emacs v%s)\nBranch: %s\nCommit: %s." + doom-version + emacs-version + (or (vc-git--symbolic-ref doom-core-dir) + "n/a") + (or (vc-git-working-revision doom-core-dir) + "n/a"))) + + +;; +;; Profiling +;; + +(defvar doom--profiler nil) +;;;###autoload +(defun doom//toggle-profiler () + "Toggle the Emacs profiler. Run it again to see the profiling report." + (interactive) + (if (not doom--profiler) + (profiler-start 'cpu+mem) + (profiler-report) + (profiler-stop)) + (setq doom--profiler (not doom--profiler))) + +;;;###autoload +(defun doom//profile-emacs () + "Profile the startup time of Emacs in the background with ESUP. +If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE." + (interactive) + (require 'esup) + (let ((init-file esup-user-init-file)) + (message "Starting esup...") + (esup-reset) + (setq esup-server-process (esup-server-create (esup-select-port))) + (setq esup-server-port (process-contact esup-server-process :service)) + (message "esup process started on port %s" esup-server-port) + (let ((process-args `("*esup-child*" + "*esup-child*" + ,esup-emacs-path + "-q" + "-L" ,esup-load-path + "-l" "esup-child" + ,(format "--eval=(esup-child-run \"%s\" \"%s\" %d)" + init-file + esup-server-port + esup-depth) + "--eval=(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)"))) + (when esup-run-as-batch-p + (setq process-args (append process-args '("--batch")))) + (setq esup-child-process (apply #'start-process process-args))) + (set-process-sentinel esup-child-process 'esup-child-process-sentinel))) + diff --git a/core/autoload/help.el b/core/autoload/help.el index 969081464..e4c311b96 100644 --- a/core/autoload/help.el +++ b/core/autoload/help.el @@ -1,22 +1,5 @@ ;;; core/autoload/help.el -*- lexical-binding: t; -*- -;;;###autoload -(defun doom/describe-setting (setting) - "Open the documentation of SETTING (a keyword defined with `def-setting!'). - -Defaults to the " - (interactive - (let ((sym (symbol-at-point))) - (list (completing-read "Describe setting: " - (sort (mapcar #'car doom-settings) #'string-lessp) - nil t (if (keywordp sym) (symbol-name sym)))))) - (let ((fn (cdr (assq (intern setting) doom-settings)))) - (unless fn - (error "'%s' is not a valid DOOM setting" setting)) - (describe-function fn))) - - -;; (defvar doom--module-mode-alist '((c-mode :lang cc) (c++-mode :lang cc) @@ -58,6 +41,39 @@ Defaults to the " (stylus-mode :lang web)) "TODO") + +;; +;; Helpers +;; + +;;;###autoload +(defun doom-active-minor-modes () + "Return a list of active minor-mode symbols." + (cl-loop for mode in minor-mode-list + if (and (boundp mode) (symbol-value mode)) + collect mode)) + + + +;; +;; Commands +;; + +;;;###autoload +(defun doom/describe-setting (setting) + "Open the documentation of SETTING (a keyword defined with `def-setting!'). + +Defaults to the " + (interactive + (let ((sym (symbol-at-point))) + (list (completing-read "Describe setting: " + (sort (mapcar #'car doom-settings) #'string-lessp) + nil t (if (keywordp sym) (symbol-name sym)))))) + (let ((fn (cdr (assq (intern setting) doom-settings)))) + (unless fn + (error "'%s' is not a valid DOOM setting" setting)) + (describe-function fn))) + ;;;###autoload (defun doom/describe-module (module) "Open the documentation of MODULE (a string that represents the category and @@ -98,22 +114,53 @@ in, or d) the module associated with the current major mode (see (mapcar #'intern (split-string module " ")) (unless (doom-module-p category submodule) (error "'%s' isn't a valid module" module)) - (let ((doc-path (doom-module-expand-file category submodule "README.org"))) + (let ((doc-path (doom-module-path category submodule "README.org"))) (unless (file-exists-p doc-path) (error "There is no documentation for this module")) (find-file doc-path)))) ;;;###autoload -(defun doom/version () - "Display the current version of Doom & Emacs, including the current Doom -branch and commit." +(defun doom/describe-active-minor-mode (mode) + "Get information on an active minor mode. Use `describe-minor-mode' for a +selection of all minor-modes, active or not." + (interactive + (list (completing-read "Minor mode: " + (doom-active-minor-modes)))) + (describe-minor-mode-from-symbol + (cl-typecase mode + (string (intern mode)) + (symbol mode) + (t (error "Expected a symbol/string, got a %s" (type-of mode)))))) + +;;;###autoload +(defun doom/what-face (&optional pos) + "Shows all faces and overlay faces at point. + +Interactively prints the list to the echo area. Noninteractively, returns a list +whose car is the list of faces and cadr is the list of overlay faces." (interactive) - (message "Doom v%s (Emacs v%s). Branch: %s. Commit: %s." - doom-version - emacs-version - (if-let* ((branch (vc-git--symbolic-ref "core/core.el"))) - branch - "n/a") - (if-let* ((rev (vc-git-working-revision "core/core.el"))) - rev - "n/a"))) + (let* ((pos (or pos (point))) + (faces (let ((face (get-text-property pos 'face))) + (if (keywordp (car-safe face)) + (list face) + (cl-loop for f in (doom-enlist face) collect f)))) + (overlays (cl-loop for ov in (overlays-at pos (1+ pos)) + nconc (doom-enlist (overlay-get ov 'face))))) + (cond ((called-interactively-p 'any) + (message "%s %s\n%s %s" + (propertize "Faces:" 'face 'font-lock-comment-face) + (if faces + (cl-loop for face in faces + if (listp face) + concat (format "'%s " face) + else + concat (concat (propertize (symbol-name face) 'face face) " ")) + "n/a ") + (propertize "Overlays:" 'face 'font-lock-comment-face) + (if overlays + (cl-loop for ov in overlays + concat (concat (propertize (symbol-name ov) 'face ov) " ")) + "n/a"))) + (t + (and (or faces overlays) + (list faces overlays)))))) From f80be3682b31270b1bad858292f6af2f1d693fbf Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:13:59 +0200 Subject: [PATCH 024/132] New open-bug-report & open-vanilla-sandbox commands --- core/autoload/debug.el | 126 +++++++++++++++++++++++++++++++++ core/templates/BUG_REPORT | 29 ++++++++ core/templates/VANILLA_SANDBOX | 7 ++ debug.el | 16 ----- 4 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 core/templates/BUG_REPORT create mode 100644 core/templates/VANILLA_SANDBOX delete mode 100644 debug.el diff --git a/core/autoload/debug.el b/core/autoload/debug.el index db5764ee4..03c944765 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -1,5 +1,14 @@ ;;; core/autoload/debug.el -*- lexical-binding: t; -*- +(defun doom-template-exists-p (template) + "TODO" + (file-exists-p (expand-file-name "templates/" doom-core-dir))) + +(defun doom-template-insert (template) + "TODO" + (let ((dir (expand-file-name "templates/" doom-core-dir))) + (insert-file-contents (expand-file-name template dir)))) + ;;;###autoload (defun doom-info () "Returns diagnostic information about the current Emacs session in markdown, @@ -134,6 +143,123 @@ branch and commit." "n/a"))) +;; +;; Vanilla sandbox +;; + +(defun doom--run-vanilla-sandbox () + "TODO" + (interactive) + (when (equal (buffer-name) "*doom:vanilla-sandbox*") + (let ((file (make-temp-file "doom-eval-"))) + (write-file file) + (require 'pp) + (require 'restart-emacs) + (restart-emacs--launch-other-emacs + (list "-Q" + "--eval" + (prin1-to-string + `(setq user-emacs-directory ,doom-emacs-dir + package--init-file-ensured t + package-user-dir ,package-user-dir + package-archives ',package-archives + debug-on-error t)) + "-f" "package-initialize" + "-l" file + "--eval" (prin1-to-string `(delete-file ,file))))))) + +;;;###autoload +(defun doom//open-vanilla-sandbox () + "Open an Emacs Lisp buffer destinated to run in a blank Emacs session. + +This vanilla sandbox is started with emacs -Q, and provides a testbed for +debugging code without Doom standing in the way, and without sacrificing +access to the installed packages." + (interactive) + (let ((buf (get-buffer-create "*doom:vanilla-sandbox*"))) + (with-current-buffer buf + (emacs-lisp-mode) + (local-set-key (kbd "C-c C-c") #'doom--run-vanilla-sandbox) + (local-set-key (kbd "C-c C-k") #'kill-this-buffer) + (setq header-line-format "C-c C-c to run the session / C-c C-k to abort it") + (setq-local default-directory doom-emacs-dir) + (doom-template-insert "VANILLA_SANDBOX") + (goto-char (point-max))) + (pop-to-buffer buf))) + + +;; +;; Reporting bugs +;; + +(defun doom--open-bug-report () + "TODO" + (interactive) + (let ((url "https://github.com/hlissner/doom-emacs/issues/new?body=")) + ;; TODO Refactor me + (save-restriction + (widen) + (goto-char (point-min)) + (re-search-forward "^-------------------------------------------------------------------\n" nil t) + (skip-chars-forward " \n\t") + (condition-case e + (progn + (save-excursion + (when (and (re-search-backward "\\+ [ ] " nil t) + (not (y-or-n-p "You haven't checked all the boxes. Continue anyway?"))) + (error "Aborted submit"))) + (narrow-to-region (point) (point-max)) + (let ((text (buffer-string))) + ;; `url-encode-url' doesn't encode ampersands + (setq text (replace-regexp-in-string "&" "%26" text)) + (setq url (url-encode-url (concat url text))) + ;; HACK: encode some characters according to HTML URL Encoding Reference + ;; http://www.w3schools.com/tags/ref_urlencode.asp + (setq url (replace-regexp-in-string "#" "%23" url)) + (setq url (replace-regexp-in-string ";" "%3B" url)) + (browse-url url))) + (error (signal (car e) (car e))))))) + +;;;###autoload +(defun doom//open-bug-report () + "Open a markdown buffer destinated to populate the New Issue page on Doom +Emacs' issue tracker. + +If called when a backtrace buffer is present, it and the output of `doom-info' +will be automatically appended to the result." + (interactive) + ;; TODO Refactor me + (let ((backtrace + (when (get-buffer "*Backtrace*") + (with-current-buffer "*Backtrace*" + (string-trim + (buffer-substring-no-properties + (point-min) + (min (point-max) 1000)))))) + (buf (get-buffer-create "*doom:vanilla-sandbox*"))) + (with-current-buffer buf + (erase-buffer) + (condition-case _ (gfm-mode) + (error (text-mode))) + (doom-template-insert "SUBMIT_BUG_REPORT") + (goto-char (point-max)) + (let ((pos (point))) + (save-excursion + (insert + "\n" (doom-info) "\n" + (if (and backtrace (not (string-empty-p backtrace))) + (format "\n
\nBacktrace\n\n```\n%s\n```\n
\n" + backtrace) + ""))) + (local-set-key (kbd "C-c C-c") #'doom--open-bug-report) + (local-set-key (kbd "C-c C-k") #'kill-this-buffer) + (setq header-line-format "C-c C-c to submit / C-c C-k to close") + ;; + (narrow-to-region (point-min) pos) + (goto-char (point-min))) + (pop-to-buffer buf)))) + + ;; ;; Profiling ;; diff --git a/core/templates/BUG_REPORT b/core/templates/BUG_REPORT new file mode 100644 index 000000000..a46909cce --- /dev/null +++ b/core/templates/BUG_REPORT @@ -0,0 +1,29 @@ +Please read through the following before you submit your issue. + ++ [ ] Running `make` (then restarting Emacs) did not fix my issue ++ [ ] If I have byte-compiled, I've tried recompiling with `make compile` ++ [ ] If I changed the version of Emacs installed, I've recompiled by plugins + with `make compile-elpa` ++ [ ] I ran `make doctor` and it produced no leads ++ [ ] My issue cannot be found [on the wiki](/docs/troubleshoot.org) ++ [ ] I filled out the four fields in the template below + +------------------------------------------------------------------- + +### Observed behavior + + + +### Expected behavior + + + +### Steps to reproduce + + + +### Extra details + + + +------------------------------------------------------------------- diff --git a/core/templates/VANILLA_SANDBOX b/core/templates/VANILLA_SANDBOX new file mode 100644 index 000000000..201ad51d1 --- /dev/null +++ b/core/templates/VANILLA_SANDBOX @@ -0,0 +1,7 @@ +;; Welcome to the vanilla sanbox! +;; +;; This is a test bed for Emacs Lisp to be run in a blank instance of Emacs +;; (free of Doom's clutches). This is equivalent to using emacs -Q with +;; package.el initialized and nothing else (so you have access to installed +;; plugins). + diff --git a/debug.el b/debug.el deleted file mode 100644 index 0aa3970a3..000000000 --- a/debug.el +++ /dev/null @@ -1,16 +0,0 @@ -;;; debug.el -*- lexical-binding: t; -*- - -;; To test something in a blank, vanilla Emacs session (Emacs -Q) load me: -;; -;; emacs -Q -l debug.el - -(setq user-emacs-directory (file-name-directory load-file-name) - package--init-file-ensured t - package-user-dir (expand-file-name ".local/packages/elpa" user-emacs-directory) - package-archives - '(("gnu" . "https://elpa.gnu.org/packages/") - ("melpa" . "https://melpa.org/packages/") - ("org" . "https://orgmode.org/elpa/"))) -(package-initialize) - -;; Then you can test packages in isolation here... From b82ef2cee67bc5891d79fa3b16706ec247f9205e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:14:36 +0200 Subject: [PATCH 025/132] Add open-manual command (docs don't exist yet though!) --- core/autoload/help.el | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/autoload/help.el b/core/autoload/help.el index e4c311b96..783492d12 100644 --- a/core/autoload/help.el +++ b/core/autoload/help.el @@ -41,6 +41,9 @@ (stylus-mode :lang web)) "TODO") +(defvar doom-docs-dir (concat doom-emacs-dir "docs/") + "TODO") + ;; ;; Helpers @@ -164,3 +167,8 @@ whose car is the list of faces and cadr is the list of overlay faces." (t (and (or faces overlays) (list faces overlays)))))) + +;;;###autoload +(defun doom//open-manual () + (interactive) + (find-file (expand-file-name "index.org" doom-docs-dir))) From 5c101f190904c964d1c1c01c402999a6a296c294 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:14:56 +0200 Subject: [PATCH 026/132] Update modules library: message! => print! --- core/autoload/modules.el | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index ffc6089ba..7535b6b4a 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -244,16 +244,16 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files." (abbreviate-file-name target)))) (cl-incf (cond ((eq result 'no-byte-compile) - (message! (dark (white "⚠ Ignored %s" short-name))) + (print! (dark (white "⚠ Ignored %s" short-name))) total-noop) ((null result) - (message! (red "✕ Failed to compile %s" short-name)) + (print! (red "✕ Failed to compile %s" short-name)) total-fail) (t - (message! (green "✓ Compiled %s" short-name)) + (print! (green "✓ Compiled %s" short-name)) (quiet! (load target t t)) total-ok)))))) - (message! + (print! (bold (color (if (= total-fail 0) 'green 'red) "%s %d/%d file(s) (%d ignored)" @@ -261,12 +261,12 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files." total-ok (- (length compile-targets) total-noop) total-noop)))) (error - (message! (red "\n%%s\n\n%%s\n\n%%s") + (print! (red "\n%%s\n\n%%s\n\n%%s") "There were breaking errors." (error-message-string ex) "Reverting changes...") (quiet! (doom//clean-byte-compiled-files)) - (message! (green "Finished (nothing was byte-compiled)"))))))))) + (print! (green "Finished (nothing was byte-compiled)"))))))))) ;;;###autoload (defun doom//clean-byte-compiled-files () From 6aaa13d05e91d48eb697ccde481de489154d1bdb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:15:17 +0200 Subject: [PATCH 027/132] doctor: update Doom initialization --- bin/doom-doctor | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 39d3c8fd4..4cad3f24e 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -279,11 +279,11 @@ (message "\n----") (let (doom-core-packages doom-debug-mode) (condition-case ex - (let ((inhibit-message t)) - (load "~/.emacs.d/core/core.el" nil t) - (let (noninteractive) - (doom-initialize t) - (doom|finalize)) + (let ((inhibit-message t) + (noninteractive t)) + (load (concat user-emacs-directory "init.el") nil t) + (doom-initialize) + (doom|run-all-startup-hooks) (success! "Attempt to load DOOM: success! Loaded v%s" doom-version)) ('error (warn! "Attempt to load DOOM: failed\n %s\n" From 7851e9e3b422f90884ddffb90d5e5847ca4254cb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:15:35 +0200 Subject: [PATCH 028/132] doctor: pluralize issue count at the end It's features like these that separate us from animals. --- bin/doom-doctor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 4cad3f24e..5d3210ace 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -316,5 +316,6 @@ ;; (message "\n----") (if (> doom-errors 0) - (warn! "There were %s issues!" doom-errors) + (warn! "There %s!" (if (= doom-errors 1) "is %d issue" "are %d issues") + doom-errors) (success! "Everything seems fine, happy Emacs'ing!")) From d4608c08f8c12ce3335afd0c7216db4eeeb50a8e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:16:45 +0200 Subject: [PATCH 029/132] Defer dtrt-indent & don't detect indent in noninteractive Doom --- core/core-editor.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/core-editor.el b/core/core-editor.el index da456d948..6971f2b67 100644 --- a/core/core-editor.el +++ b/core/core-editor.el @@ -176,13 +176,15 @@ fundamental-mode) for performance sake." command-log-mode-open-log-turns-on-mode t)) (def-package! dtrt-indent + :defer t :config (setq dtrt-indent-verbosity (if doom-debug-mode 2 0)) (defun doom|detect-indentation () (unless (or doom-inhibit-indent-detection (eq major-mode 'fundamental-mode)) (dtrt-indent-mode +1))) - (add-hook 'after-change-major-mode-hook #'doom|detect-indentation)) + (unless noninteractive + (add-hook 'after-change-major-mode-hook #'doom|detect-indentation))) (def-package! expand-region :commands (er/expand-region er/contract-region er/mark-symbol er/mark-word) From 8da3f56795b1cee0d2daf402dc9c296ccc09cdfc Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:17:19 +0200 Subject: [PATCH 030/132] core-project: rename autoload-project-mode => init-project-mode To be consistent with other initializing hooks. --- core/core-projects.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/core-projects.el b/core/core-projects.el index 497b6c5b6..2d9eb8197 100644 --- a/core/core-projects.el +++ b/core/core-projects.el @@ -13,7 +13,7 @@ :config (add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook) - (add-hook 'find-file-hook #'doom|autoload-project-mode) + (add-hook 'find-file-hook #'doom|init-project-mode) (projectile-mode +1) ;; a more generic project root file @@ -131,7 +131,7 @@ for .dir-locals.el.") "Hook run when a project is enabled. The name of the project's mode and its state are passed in.") -(defun doom|autoload-project-mode () +(defun doom|init-project-mode () "Auto-enable the project(s) listed in `doom-project'." (when doom-project (if (symbolp doom-project) From da5c7d27cf76c8f96bf56f9b0492b7f649c06ef8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:18:48 +0200 Subject: [PATCH 031/132] Use correct init hook (doom-post-init-hook) --- core/core-keybinds.el | 2 +- core/core-ui.el | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/core-keybinds.el b/core/core-keybinds.el index 0fca8ca65..0a3495720 100644 --- a/core/core-keybinds.el +++ b/core/core-keybinds.el @@ -56,7 +56,7 @@ If any hook returns non-nil, all hooks after it are ignored.") ;; embolden local bindings (set-face-attribute 'which-key-local-map-description-face nil :weight 'bold) (which-key-setup-side-window-bottom) - (add-hook 'doom-init-hook #'which-key-mode)) + (add-hook 'doom-post-init-hook #'which-key-mode)) (def-package! hydra diff --git a/core/core-ui.el b/core/core-ui.el index bf0bb9439..ad948c254 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -371,7 +371,7 @@ from the default." (advice-add #'switch-to-buffer :around #'doom*switch-buffer-hooks) (advice-add #'display-buffer :around #'doom*switch-buffer-hooks) (advice-add #'pop-to-buffer :around #'doom*switch-buffer-hooks)) -(add-hook 'doom-init-hook #'doom|init-custom-hooks) +(add-hook 'doom-post-init-hook #'doom|init-custom-hooks) (defun doom*load-theme-hooks (theme &rest _) (setq doom-theme theme) @@ -704,7 +704,7 @@ windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original ;; (run-hooks 'doom-init-ui-hook)) -(add-hook 'doom-init-hook #'doom|init-ui) +(add-hook 'doom-post-init-hook #'doom|init-ui) (provide 'core-ui) ;;; core-ui.el ends here From f058505306bf4209943799c43c4c4ce88ec40bf6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 12:21:13 +0200 Subject: [PATCH 032/132] New bin/doom (eventual replacement for make) This commit adds bin/doom, which acts as the middle man that make once was (and will stay for a while, though the documentation will shift away from using it). It does everything the previous make interface did, but is faster and more flexible. bin/doom should eventually replace the makefile. bin/doom also makes it easier to run Doom outside of ~/.emacs.d and ~/.doom.d with, for example: bin/doom run -p ~/.other.doom.d/ -e ~/.other.emacs.d bin/doom.cmd is included for Windows users, but I don't recommend using it yet. It hasn't been tested nor have I ever written a batch script before. Also update init.example.el with new defaults. --- Makefile | 102 +++++------ bin/doom | 70 ++++++++ bin/doom.cmd | 14 ++ core/autoload/modules.el | 1 - core/autoload/test.el | 94 +++++----- core/core-dispatcher.el | 253 +++++++++++++++++++++++++++ core/core-packages.el | 3 + core/test/autoload-buffers.el | 25 +-- core/test/autoload-package.el | 3 + early-init.el | 5 +- init.el | 5 + init.example.el | 84 +++++---- modules/feature/evil/config.el | 2 +- modules/feature/workspaces/config.el | 2 +- 14 files changed, 493 insertions(+), 170 deletions(-) create mode 100755 bin/doom create mode 100644 bin/doom.cmd create mode 100644 core/core-dispatcher.el diff --git a/Makefile b/Makefile index 47758ab40..3d1b0a8e5 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ # Ensure emacs always runs from this makefile's PWD -EMACS = emacs -q --eval "(setq user-emacs-directory default-directory load-prefer-newer t)" -DOOM = $(EMACS) --batch -l init.el -DOOMI = $(subst --batch,,$(DOOM)) +DOOM = bin/doom +EMACS = emacs -q $(ARGS) -l init.el MODULES = $(patsubst modules/%/, %, $(sort $(dir $(wildcard modules/*/ modules/*/*/)))) all: - @$(DOOM) -f doom//reload-packages + @$(DOOM) reload ## Shortcuts a: autoloads @@ -20,84 +19,65 @@ ce: compile-elpa re: recompile d: doctor -quickstart: | ~/.doom.d/init.el all recompile -~/.doom.d/init.el: - @echo "Creating ~/.doom.d directory" - @mkdir ~/.doom.d && cp init.example.el ~/.doom.d/init.el - @touch ~/.doom.d/config.el +quickstart: + @$(DOOM) quickstart + ## Package management -install: | .local/autoloads.el - @$(DOOM) -f doom//packages-install - -update: | .local/autoloads.el - @$(DOOM) -f doom//packages-update - -autoremove: | .local/autoloads.el - @$(DOOM) -f doom//packages-autoremove - +install: + @$(DOOM) install +update: + @$(DOOM) update +autoremove: + @$(DOOM) autoremove autoloads: - @$(DOOM) -f doom//reload-autoloads - -upgrade: | _upgrade recompile all -_upgrade: - @git pull origin $(shell git rev-parse --abbrev-ref HEAD) + @$(DOOM) autoloads +upgrade: + @$(DOOM) upgrade ## Byte compilation -# compile -# compile-core +compile: + @$(DOOM) compile +compile-core: + @$(DOOM) compile :core +compile-private: + @$(DOOM) compile :private +compile-plugins: + @$(DOOM) compile :plugins +recompile: + @$(DOOM) recompile +clean: + @$(DOOM) clean # compile-module # compile-module/submodule -compile: | clean - @$(DOOM) -f doom//byte-compile - -compile-core: | clean - @$(DOOM) -f doom//byte-compile-core - -compile-elpa: - @$(DOOM) -f doom//byte-recompile-plugins - $(patsubst %, compile-%, $(MODULES)): | .local/autoloads.el - @$(DOOM) -f doom//byte-compile -- $(patsubst compile-%, %, $@) - -recompile: - @$(DOOM) -f doom//byte-compile -- -r - -clean: - @$(DOOM) -f doom//clean-byte-compiled-files + @$(DOOM) $@ $(subst compile-, , $@) ## Unit tests -# test -# test-core +test: + @$(DOOM) test +test-core: + @$(DOOM) test :core # test-module # test-module/submodule -test: | .local/autoloads.el - @$(DOOM) -f doom//run-tests - -test-core $(patsubst %, test-%, $(MODULES)): | .local/autoloads.el - @$(DOOM) -f doom//run-tests -- $(subst test-, , $@) - +$(patsubst %, test-%, $(MODULES)): + @$(DOOM) test $(subst test-, , $@) # run tests interactively -testi: | .local/autoloads.el - @$(DOOMI) -f doom//run-tests +testi: + @$(EMACS) -l core/autoload/doom.el -f doom//run-tests ## Utility tasks # Runs Emacs from a different folder than ~/.emacs.d; only use this for testing! run: - @$(DOOMI) $(ARGS) --eval "(run-hooks 'after-init-hook 'emacs-startup-hook 'window-setup-hook)" + @$(EMACS) +# Prints debug info about your current setup +info: + @$(DOOM) info # Diagnoses potential OS/environment issues doctor: - @$(EMACS) --script bin/doom-doctor - -# Prints debug info about your current setup -info: - @$(EMACS) --batch -l core/core.el -l core/autoload/util.el -f doom/info - -## Internal tasks -.local/autoloads.el: - @$(DOOM) -f doom-initialize-autoloads + @$(DOOM) doctor .PHONY: all compile test testi clean diff --git a/bin/doom b/bin/doom new file mode 100755 index 000000000..f4001a61a --- /dev/null +++ b/bin/doom @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*- +":"; VERSION=$(emacs --version | head -n1) +":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run Doom. Check your PATH"; echo; exit 2; } +":"; [[ $1 != run ]] && { exec emacs --quick --script "$0" -- $@; exit 0; } +":"; cd $(dirname "${BASH_SOURCE:-${(%):-%x}}")/.. +":"; shift; exec emacs -Q -l bin/doom $@ +":"; exit 0 + +(defun usage () + (with-temp-buffer + (insert (format! "%s %s [COMMAND] [ARGS...]\n" + (bold "Usage:") (file-name-nondirectory load-file-name)) + "\n" + "A command line interfacing for managing Doom Emacs; including\n" + "package management, diagnostics, unit tests, and byte-compilation.\n" + "\n" + "This tool also makes it trivial to launch Emacs out of a different\n" + "folder or with a different private module.\n" + "\n" + (format! (bold "Example:\n")) + " doom install\n" + " doom help update\n" + " doom compile :core lang/php lang/python\n" + " doom run\n" + " doom run -nw file.txt file2.el\n" + " doom run -p ~/.other.doom.d -e ~/.other.emacs.d -nw file.txt\n" + "\n" + (format! (bold "Options:\n")) + " -d --debug\t\tTurns on doom-debug-mode (and debug-on-error)\n" + " -e --emacsd DIR\tUse the emacs config at DIR (e.g. ~/.emacs.d)\n" + " -p --private DIR\tUse the private module at DIR (e.g. ~/.doom.d)\n\n") + (princ (buffer-string))) + (doom--dispatch-help)) + +;; +(let ((argv (cdr (cdr (cdr command-line-args)))) + (emacs-dir (expand-file-name "../" (file-name-directory load-file-name)))) + ;; Parse options + (while (ignore-errors (string-prefix-p "-" (car argv))) + (pcase (pop argv) + ((or "-d" "--debug") + (setq doom-debug-mode t)) + ((or "-p" "--private") + (setq doom-private-dir (expand-file-name (pop argv))) + (or (file-directory-p doom-private-dir) + (error "%s does not exist" doom-private-dir))) + ((or "-e" "--emacsd") + (setq emacs-dir (expand-file-name (pop argv))) + (or (file-directory-p emacs-dir) + (error "%s does not exist" emacs-dir))) + ("--") + (_))) + + ;; Bootstrap Doom + (load (expand-file-name "init" emacs-dir) + nil 'nomessage) + + (cond ((not noninteractive) + ;; Just incase you aren't using Doom! + (when (fboundp 'doom|run-all-startup-hooks) + (doom|run-all-startup-hooks))) + ((equal argv '("help")) + (usage)) + ((not argv) + (message "Expecting a command!\n") + (usage)) + ((let ((default-directory user-emacs-directory)) + (doom-dispatch argv))))) + diff --git a/bin/doom.cmd b/bin/doom.cmd new file mode 100644 index 000000000..2eeb0f2fe --- /dev/null +++ b/bin/doom.cmd @@ -0,0 +1,14 @@ +:: Forward the ./doom script to Emacs + +@ECHO OFF +PUSHD "%~dp0" >NUL + +IF %1=="run" ( + SHIFT + emacs -Q $* -l init.el -f "doom|run-all-startup-hooks" +) ELSE ( + emacs --quick --script ./doom -- $* +) + +POPD >NUL +ECHO ON diff --git a/core/autoload/modules.el b/core/autoload/modules.el index 7535b6b4a..157a40b68 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -59,7 +59,6 @@ This should be run whenever init.el or an autoload file is modified. Running (generate-autoload-section-trailer "") (doom--stage 'autoloads) outdated) - (doom-initialize) (dolist (path (doom-module-load-path)) (let ((auto-dir (expand-file-name "autoload" path)) (auto-file (expand-file-name "autoload.el" path))) diff --git a/core/autoload/test.el b/core/autoload/test.el index 9017e9288..431fe0111 100644 --- a/core/autoload/test.el +++ b/core/autoload/test.el @@ -1,6 +1,5 @@ ;;; core/autoload/test.el -*- lexical-binding: t; no-byte-compile: t; -*- -;;;###autoload (defun doom//run-tests (&optional modules) "Run all loaded tests, specified by MODULES (a list of module cons cells) or command line args following a double dash (each arg should be in the @@ -8,56 +7,53 @@ command line args following a double dash (each arg should be in the If neither is available, run all tests in all enabled modules." (interactive) - (let ((doom-modules (make-hash-table :test #'equal))) - ;; ensure DOOM is initialized - (let (noninteractive) - ;; Core libraries aren't fully loaded in a noninteractive session, so we - ;; reload it with `noninteractive' set to nil to force them to. - (doom-initialize t) - (run-hooks 'doom-init-hook 'pre-command-hook 'doom-after-switch-buffer-hook)) - (condition-case-unless-debug ex - (let ((target-paths - ;; Convert targets (either from MODULES or `argv') into a list of - ;; string paths, pointing to the root directory of modules - (cond ((string= (car argv) "--") ; command line - (save-match-data - (cl-loop for arg in (cdr argv) - if (string= arg "core") collect doom-core-dir - else if (string-match-p "/" arg) - nconc (cl-loop for dir in doom-modules-dirs - collect (expand-file-name arg dir)) - else - nconc (cl-loop for dir in doom-modules-dirs - for path = (expand-file-name arg dir) - if (file-directory-p path) - nconc - (cl-remove-if-not - #'file-directory-p - (directory-files path t "^[^.]" t))) - finally do (setq argv nil)))) + (let (noninteractive) + ;; Core libraries aren't fully loaded in a noninteractive session, so we + ;; reload it with `noninteractive' set to nil to force them to. + (doom-initialize)) + (condition-case-unless-debug ex + (let ((target-paths + ;; Convert targets (either from MODULES or `argv') into a list of + ;; string paths, pointing to the root directory of modules + (cond ((stringp (car modules)) ; command line + (save-match-data + (cl-loop for arg in modules + if (string= arg "core") collect doom-core-dir + else if (string-match-p "/" arg) + nconc (cl-loop for dir in doom-modules-dirs + collect (expand-file-name arg dir)) + else + nconc (cl-loop for dir in doom-modules-dirs + for path = (expand-file-name arg dir) + if (file-directory-p path) + nconc + (cl-remove-if-not + #'file-directory-p + (directory-files path t "^[^.]" t))) + finally do (setq argv nil)))) - (modules ; cons-cells given to MODULES - (cl-loop for (module . submodule) in modules - if (doom-module-find-path module submodule) - collect it)) + (modules ; cons-cells given to MODULES + (cl-loop for (module . submodule) in modules + if (doom-module-locate-path module submodule) + collect it)) - ((let (noninteractive) - (load (expand-file-name "init.test.el" user-emacs-directory) nil t) - (append (list doom-core-dir) (doom-module-load-path))))))) - ;; Load all the unit test files... - (dolist (path target-paths) - (let ((test-path (expand-file-name "test/" path))) - (when (file-directory-p test-path) - (dolist (test-file (reverse (doom-packages--files test-path "\\.el$"))) - (load test-file nil :noerror))))) - ;; ... then run them - (if noninteractive - (ert-run-tests-batch-and-exit) - (call-interactively #'ert-run-tests-interactively))) - ('error - (lwarn 'doom-test :error - "%s -> %s" - (car ex) (error-message-string ex)))))) + ((append (list doom-core-dir) + (doom-module-load-path)))))) + ;; Load all the unit test files... + (dolist (path target-paths) + (let ((test-path (expand-file-name "test/" path))) + (when (file-directory-p test-path) + (dolist (test-file (reverse (doom-files-under test-path :match "\\.el$"))) + (load test-file nil :noerror))))) + ;; ... then run them + (switch-to-buffer (get-buffer-create "*blank*")) + (if noninteractive + (ert-run-tests-batch-and-exit) + (call-interactively #'ert-run-tests-interactively))) + ('error + (lwarn 'doom-test :error + "%s -> %s" + (car ex) (error-message-string ex))))) ;; --- Test helpers ----------------------- diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el new file mode 100644 index 000000000..c24112443 --- /dev/null +++ b/core/core-dispatcher.el @@ -0,0 +1,253 @@ +;;; -*- lexical-binding: t; no-byte-compile: t; -*- + +(load! autoload/packages) +(load! autoload/modules) +(load! autoload/debug) +(load! autoload/message) + + +;; +;; Dispatcher +;; + +(defvar doom-dispatch-command-alist () + "TODO") + +(defvar doom-dispatch-alias-alist () + "TODO") + +(defun doom--dispatch-format (desc &optional short) + (if (equal desc "TODO") + (format! (yellow "TODO")) + (with-temp-buffer + (let ((fill-column 72)) + (insert desc) + (goto-char (point-min)) + (while (re-search-forward "\n\n[^ \n]" nil t) + (fill-paragraph))) + (if (not short) + (buffer-string) + (goto-char (point-min)) + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))))) + +(defun doom--dispatch-help (&optional command desc &rest args) + "TODO" + (if command + (princ (doom--dispatch-format desc)) + (print! (bold "%-10s\t%s\t%s" "Command:" "Alias" "Description")) + (dolist (spec (sort doom-dispatch-command-alist + (lambda (x y) (string-lessp (car x) (car y))))) + (cl-destructuring-bind (command &key desc _body) spec + (let ((alias (car (rassq command doom-dispatch-alias-alist)))) + (print! " %-10s\t%s\t%s" + command (or alias "") + (doom--dispatch-format desc t))))))) + +(defun doom-dispatch (args) + "TODO" + (let ((help (equal (car args) "help"))) + (if help (pop args)) + (cl-destructuring-bind (command &key desc body) + (let ((sym (intern (car args)))) + (or (assq sym doom-dispatch-command-alist) + (assq (cdr (assq sym doom-dispatch-alias-alist)) doom-dispatch-command-alist) + (error "Invalid command: %s" (car args)))) + (if help + (apply #'doom--dispatch-help command desc (cdr args)) + (funcall body (cdr args)))))) + +;; FIXME Clumsy way of registering commands, refactor! +(defmacro def-dispatcher! (command desc &rest body) + "TODO" + (declare (doc-string 2)) + (let* ((command (doom-enlist command)) + (cmd (car command)) + (alias (car (cdr command)))) + `(progn + ,(when alias + `(map-put doom-dispatch-alias-alist ',alias ',cmd)) + (map-put doom-dispatch-command-alist + ',cmd (list :desc ,desc :body (lambda (args) ,@body)))))) + +;; +(def-dispatcher! run + "Run Doom Emacs from bin/doom's parent directory. + +All arguments are passed on to Emacs (except for -p and -e). + + doom run + doom run -nw init.el + +Warning, this is for convenience and testing purposes, Doom will not run its +best or fastest when started in this manner.") + +(def-dispatcher! quickstart + "TODO" + (doom//quickstart)) + +(def-dispatcher! (install i) + "Installs requested plugins that aren't installed." + (doom-initialize) + (when (doom//packages-install) + (doom//reload-autoloads))) + +(def-dispatcher! (update u) + "Checks for and updates outdated plugins." + (doom-initialize) + (when (doom//packages-update) + (doom//reload-autoloads))) + +(def-dispatcher! (autoremove r) + "Removes orphaned plugins." + (doom-initialize) + (when (doom//packages-autoremove) + (doom//reload-autoloads))) + +(def-dispatcher! (autoloads a) + "Regenerates Doom's autoloads file. + +This file tells Emacs where to find your module's autoloaded functions and +plugins." + (doom-initialize) + (doom//reload-autoloads)) + +(def-dispatcher! (upgrade up) + "Checks out the latest Doom on this branch." + (doom//upgrade)) + +(def-dispatcher! (compile c) + "Byte-compiles your config or selected modules. + + compile [TARGETS...] + compile :core :private lang/python + compile feature lang + +Accepts :core, :private and :plugins as special arguments, indicating you want +to byte-compile Doom's core files, your private config or your ELPA plugins, +respectively." + (doom//byte-compile args)) + +(def-dispatcher! (recompile cc) + "Re-byte-compiles outdated *.elc files." + (doom//byte-compile args 'recompile)) + +(def-dispatcher! clean + "Delete all *.elc files." + (doom//clean-byte-compiled-files)) + +(def-dispatcher! test + "Run Doom unit tests." + (load! autoload/test) + (doom//run-tests args)) + +(def-dispatcher! info + "Output system info in markdown for bug reports." + (doom//info)) + +(def-dispatcher! (doctor d) + "Checks for issues with your current Doom config." + (load (expand-file-name "bin/doom-doctor" doom-emacs-dir) + nil t t)) + +(def-dispatcher! (version v) + "Reports the version of Doom and Emacs." + (doom//version)) + +(def-dispatcher! (reload re) + "Reload Doom. + +This is the equivalent of running autoremove, install, autoloads, then +recompile. Run this whenever you: + + 1. Modify your `doom!' block, + 2. Add or remove `package!' blocks to your config, + 3. Add or remove autoloaded functions in module autoloaded files. + 4. Update Doom outside of Doom (e.g. with git)" + (doom-initialize) + (if (let* ((doom--inhibit-reload t) + (autoremove-p (doom//packages-autoremove)) + (install-p (doom//packages-install))) + (or autoremove-p install-p)) + (doom//reload) + (doom//reload-autoloads)) + (doom//byte-compile nil 'recompile)) + + +;; +;; Quality of Life Commands +;; + +(defvar doom-remote "origin" + "TODO") + +(defun doom//upgrade () + "TODO" + (declare (interactive-only t)) + (interactive) + (let ((core-file (expand-file-name "init.el" doom-core-dir)) + (branch (vc-git--symbolic-ref core-file)) + (default-directory doom-emacs-dir)) + (unless (file-exists-p core-file) + (error "Couldn't find %s, was Doom cloned properly?" + (abbreviate-file-name core-file))) + (unless branch + (error "Couldn't detect what branch you're using. Is %s a repo?" + (abbreviate-file-name doom-emacs-dir))) + (unless (eq (vc-state core-file 'Git) 'up-to-date) + (user-error "Doom has been modified; refusing to upgrade. Stash or undo your changes")) + (with-temp-buffer + (let ((buf (current-buffer))) + (when (zerop (process-file "git" nil buf nil + "fetch" "--tags" doom-remote branch)) + (let ((current-rev (vc-git-working-revision core-file)) + (rev (shell-command-to-string (format "git rev-parse %s/%s" doom-remote branch)))) + (unless rev + (error "Couldn't detect Doom's version. Is %s a repo?" + (abbreviate-file-name doom-emacs-dir))) + (if (equal current-rev rev) + (message "Doom is up to date!") + + (when (or (getenv "YES") + (y-or-n-p "Doom is out of date, update?")) + (unless (zerop (process-file "git" nil buf nil + "checkout" (format "%s/%s" doom-remote branch))) + (error "An error occurred while checking out the latest commit")) + (when (file-exists-p (byte-compile-dest-file core-file)) + (message "Your config is byte-compiled, removing byte-compiled files") + (doom//clean-byte-compiled-files)) + (doom//reload) + (message "Done! Please restart Emacs for changes to take effect"))))))))) + +(defun doom//quickstart () + "TODO" + (declare (interactive-only t)) + (interactive) + (let ((short-private-dir (abbreviate-file-name doom-private-dir))) + (when (file-directory-p doom-private-dir) + (error "%s already exists! Aborting." short-private-dir)) + (message "Creating %s directory" short-private-dir) + (make-directory doom-private-dir) + (let ((init-file (expand-file-name "init.el" doom-private-dir))) + (if (not (file-exists-p init-file)) + (message "%sinit.el already exists. Skipping.") + (message "Copying init.example.el to %s" short-private-dir) + (copy-file (expand-file-name "init.example.el" doom-emacs-dir) + init-file))) + (let ((config-file (expand-file-name "config.el" doom-private-dir))) + (if (file-exists-p config-file) + (with-temp-file config-file + (insert "")) + (message "%sconfig.el already exists. Skipping.")))) + (doom-initialize) + (let* ((doom--inhibit-reload t) + (autoremove-p (doom//packages-autoremove)) + (install-p (doom//packages-install))) + (or autoremove-p install-p)) + (doom//reload-autoloads) + (message "\n\nDone! Doom Emacs is ready.\n") + (message "Remember to run M-x all-the-icons-install-fonts after starting Emacs for the first time.")) + +(provide 'core-dispatcher) +;;; core-dispatcher.el ends here diff --git a/core/core-packages.el b/core/core-packages.el index e1d16bfc3..08e67ad04 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -462,6 +462,9 @@ added, if the file exists." (autoload 'use-package "use-package" nil nil 'macro) +;; TODO :after-hook HOOK (load packages on first run of HOOK) +;; TODO Make + ;; diff --git a/core/test/autoload-buffers.el b/core/test/autoload-buffers.el index 49f27c113..98242988a 100644 --- a/core/test/autoload-buffers.el +++ b/core/test/autoload-buffers.el @@ -7,17 +7,18 @@ (dolist (bsym buffer-args) (push `(,bsym (get-buffer-create ,(symbol-name bsym))) buffers)) - `(cl-flet ((buffer-list - (lambda () - (cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers))))))) - (let* ((split-width-threshold 0) - (window-min-width 0) - persp-mode - ,@buffers) - (delete-other-windows) - ,@body - (let (kill-buffer-query-functions kill-buffer-hook) - (mapc #'kill-buffer (buffer-list))))))) + `(save-window-excursion + (cl-flet ((buffer-list + (lambda () + (cl-remove-if-not #'buffer-live-p (list ,@(reverse (mapcar #'car buffers))))))) + (let* ((split-width-threshold 0) + (window-min-width 0) + persp-mode + ,@buffers) + (delete-other-windows) + ,@body + (let (kill-buffer-query-functions kill-buffer-hook) + (mapc #'kill-buffer (buffer-list)))))))) ;; (def-test! get-buffers @@ -93,7 +94,7 @@ (with-temp-buffers!! (a b c d e) (dolist (buf (list a b)) (with-current-buffer buf - (emacs-lisp-mode))) + (delay-mode-hooks (emacs-lisp-mode)))) (dolist (buf (list c d e)) (with-current-buffer buf (text-mode))) diff --git a/core/test/autoload-package.el b/core/test/autoload-package.el index 22103070f..cb5f8595e 100644 --- a/core/test/autoload-package.el +++ b/core/test/autoload-package.el @@ -1,6 +1,9 @@ ;; -*- no-byte-compile: t; -*- ;;; core/test/autoload-package.el +(require 'package) +(require 'quelpa) + (defun -pkg (name version &optional reqs) (package-desc-create :name name :version version :reqs reqs)) diff --git a/early-init.el b/early-init.el index e86bca68b..e47330734 100644 --- a/early-init.el +++ b/early-init.el @@ -11,7 +11,8 @@ ;; Faster to disable these here (before they've been initialized) (setq tool-bar-mode nil - menu-bar-mode nil) -(set-scroll-bar-mode nil) + menu-bar-mode nil + scroll-bar-mode nil) +(modify-all-frames-parameters '((vertical-scroll-bars))) ;; TODO Once Emacs 27 hits stable, perhaps replace init.el with early-init.el diff --git a/init.el b/init.el index 50621daa5..497941f17 100644 --- a/init.el +++ b/init.el @@ -27,4 +27,9 @@ ;; ;;; License: MIT +(setq user-emacs-directory (file-name-directory load-file-name) + load-prefer-newer noninteractive) + (require 'core (concat user-emacs-directory "core/core")) +(when noninteractive + (require 'core-dispatcher)) diff --git a/init.example.el b/init.example.el index 92a2163f1..6ad2287c4 100644 --- a/init.example.el +++ b/init.example.el @@ -26,9 +26,6 @@ +childframe) ; uses childframes for popups (Emacs 26+ only) :ui - (popup ; tame sudden yet inevitable temporary windows - +all ; catch all popups that start with an asterix - +defaults) ; default popup rules doom ; what makes DOOM look the way it does doom-dashboard ; a nifty splash screen for Emacs doom-modeline ; a snazzy Atom-inspired mode-line @@ -37,6 +34,9 @@ hl-todo ; highlight TODO/FIXME/NOTE tags nav-flash ; blink the current line after jumping neotree ; a project drawer, like NERDTree for vim + (popup ; tame sudden yet inevitable temporary windows + +all ; catch all popups that start with an asterix + +defaults) ; default popup rules ;tabbar ; FIXME an (incomplete) tab bar for Emacs ;unicode ; extended unicode support for various languages vi-tilde-fringe ; fringe tildes to mark beyond EOB @@ -45,68 +45,66 @@ :tools dired ; making dired pretty [functional] editorconfig ; let someone else argue about tabs vs spaces - ein ; tame Jupyter notebooks with emacs electric-indent ; smarter, keyword-based electric-indent + ;ein ; tame Jupyter notebooks with emacs eshell ; a consistent, cross-platform shell (WIP) - gist ; interacting with github gists + ;gist ; interacting with github gists imenu ; an imenu sidebar and searchable code index ;macos ; MacOS-specific commands - make ; run make tasks from Emacs + ;make ; run make tasks from Emacs ;magit ; - password-store ; password manager for nerds + ;password-store ; password manager for nerds pdf ; pdf enhancements - prodigy ; Managing external services + ;prodigy ; FIXME managing external services & code builders ;rgb ; creating color strings rotate-text ; cycle region at point between text candidates - term ; terminals in Emacs + ;term ; terminals in Emacs tmux ; an API for interacting with tmux upload ; map local to remote projects via ssh/ftp :lang - assembly ; assembly for fun or debugging - cc ; C/C++/Obj-C madness - crystal ; ruby at the speed of c - clojure ; java with a lisp - csharp ; unity, .NET, and mono shenanigans + ;assembly ; assembly for fun or debugging + ;cc ; C/C++/Obj-C madness + ;crystal ; ruby at the speed of c + ;clojure ; java with a lisp + ;csharp ; unity, .NET, and mono shenanigans data ; config/data formats ;erlang ; an elegant language for a more civilized age - elixir ; erlang done right - elm ; care for a cup of TEA? + ;elixir ; erlang done right + ;elm ; care for a cup of TEA? emacs-lisp ; drown in parentheses - ess ; emacs speaks statistics - go ; the hipster dialect - (haskell +intero) ; a language that's lazier than I am - hy ; readability of scheme w/ speed of python - (java +meghanada) ; the poster child for carpal tunnel syndrome - javascript ; all(hope(abandon(ye(who(enter(here)))))) - julia ; a better, faster MATLAB - latex ; writing papers in Emacs has never been so fun - ledger ; an accounting system in Emacs - lua ; one-based indices? one-based indices + ;ess ; emacs speaks statistics + ;go ; the hipster dialect + ;(haskell +intero) ; a language that's lazier than I am + ;hy ; readability of scheme w/ speed of python + ;(java +meghanada) ; the poster child for carpal tunnel syndrome + ;javascript ; all(hope(abandon(ye(who(enter(here)))))) + ;julia ; a better, faster MATLAB + ;latex ; writing papers in Emacs has never been so fun + ;ledger ; an accounting system in Emacs + ;lua ; one-based indices? one-based indices markdown ; writing docs for people to ignore - nim ; python + lisp at the speed of c - nix ; I hereby declare "nix geht mehr!" - ocaml ; an objective camel + ;nim ; python + lisp at the speed of c + ;nix ; I hereby declare "nix geht mehr!" + ;ocaml ; an objective camel (org ; organize your plain life in plain text +attach ; custom attachment system +babel ; running code in org +capture ; org-capture in and outside of Emacs +export ; Exporting org to whatever you want - +present ; Emacs for presentations - +publish) ; Emacs+Org as a static site generator - perl ; write code no one else can comprehend - php ; perl's insecure younger brother - plantuml ; diagrams for confusing people more - purescript ; javascript, but functional - python ; beautiful is better than ugly - rest ; Emacs as a REST client - ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} - rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() - scala ; java, but good + +present) ; Emacs for presentations + ;perl ; write code no one else can comprehend + ;php ; perl's insecure younger brother + ;plantuml ; diagrams for confusing people more + ;purescript ; javascript, but functional + ;python ; beautiful is better than ugly + ;rest ; Emacs as a REST client + ;ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} + ;rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() + ;scala ; java, but good sh ; she sells (ba|z)sh shells on the C xor - swift ; who asked for emoji variables? - typescript ; javascript, but better - web ; the tubes + ;swift ; who asked for emoji variables? + ;web ; the tubes ;; Applications are complex and opinionated modules that transform Emacs ;; toward a specific purpose. They may have additional dependencies and diff --git a/modules/feature/evil/config.el b/modules/feature/evil/config.el index 39c3830a7..dc28e4d68 100644 --- a/modules/feature/evil/config.el +++ b/modules/feature/evil/config.el @@ -61,7 +61,7 @@ evil-visual-state-cursor 'hollow) :config - (add-hook 'doom-init-hook #'evil-mode) + (add-hook 'doom-post-init-hook #'evil-mode) (evil-select-search-module 'evil-search-module 'evil-search) (set! :popup "^\\*evil-registers" '((size . 0.3))) diff --git a/modules/feature/workspaces/config.el b/modules/feature/workspaces/config.el index fd8df7a29..4b6d1f4b4 100644 --- a/modules/feature/workspaces/config.el +++ b/modules/feature/workspaces/config.el @@ -77,7 +77,7 @@ Uses `+workspaces-main' to determine the name of the main workspace." (display-buffer-in-side-window warnings '((window-height . shrink-window-if-larger-than-buffer)))))))))) - (add-hook 'doom-init-hook #'+workspaces|init t) + (add-hook 'doom-post-init-hook #'+workspaces|init t) :config (setq persp-autokill-buffer-on-remove 'kill-weak persp-nil-hidden t From f3f817257920d8e4b1cb541e9a72d4487328fea6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 15:17:59 +0200 Subject: [PATCH 033/132] Fix {copy,move}-this-file commands when file doesn't exist yet --- core/autoload/files.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/autoload/files.el b/core/autoload/files.el index c2bf906b3..e77df3ec0 100644 --- a/core/autoload/files.el +++ b/core/autoload/files.el @@ -56,9 +56,10 @@ (not force-p) (not (y-or-n-p (format "File already exists at %s, overwrite?" short-new-name)))) (throw 'status 'aborted)) - (t + ((file-exists-p old-path) (copy-file old-path new-path t) - short-new-name)))) + short-new-name) + (short-new-name)))) ;;;###autoload (defun doom/delete-this-file (&optional path force-p) @@ -107,7 +108,8 @@ file if it exists, without confirmation." (let ((old-path (buffer-file-name)) (new-path (expand-file-name new-path))) (when-let* ((dest (doom--copy-file old-path new-path force-p))) - (delete-file old-path) + (when (file-exists-p old-path) + (delete-file old-path)) (kill-this-buffer) (find-file new-path) (doom--forget-file old-path new-path) From ddadb7995231526e9f5f6c664d0f0c817557652a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 15:18:36 +0200 Subject: [PATCH 034/132] Reduce noise from doom doctor And fix not-enough-arguments error from format. --- bin/doom-doctor | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 5d3210ace..0eb4b1b8e 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -112,11 +112,8 @@ (message "Compiled with:\n%s" (indented 2 system-configuration-features))) (message "uname -a:\n%s\n" (indented 2 (sh "uname -a"))) -(msg! "----\n") - ;; --- is emacs set up properly? ------------------------------ -(section! "test-emacs") (when (version< emacs-version "25.1") (error! "Important: Emacs %s detected [%s]" emacs-version (executable-find "emacs")) (explain! @@ -125,7 +122,6 @@ (concat "\nMacOS users should use homebrew (https://brew.sh) to install Emacs\n" " brew install emacs --with-modules --with-imagemagick --with-cocoa")))) -(section! "test-private-config") (let ((xdg-dir (concat (or (getenv "XDG_CONFIG_HOME") "~/.config") "/doom/")) @@ -140,14 +136,12 @@ ;; --- is the environment set up properly? -------------------- -;; windows? windows -(section! "test-windows") +;; on windows? (when (memq system-type '(windows-nt ms-dos cygwin)) (warn! "Warning: Windows detected") (explain! "DOOM was designed for MacOS and Linux. Expect a bumpy ride!")) -;; are all default fonts present -(section! "test-fonts") +;; are all default fonts present? (if (not (fboundp 'find-font)) (progn (warn! "Warning: unable to detect font") @@ -170,7 +164,6 @@ "case, ignore this warning.")))))) ;; gnutls-cli & openssl -(section! "test-gnutls") (cond ((executable-find "gnutls-cli")) ((executable-find "openssl") (let* ((output (sh "openssl ciphers -v")) @@ -205,7 +198,7 @@ "network, provider, government, neckbearded mother-in-laws, geeky roommates, " "or just about anyone who knows more about computers than you do!"))) -(section! "test-tls") +;; are certificates validated properly? (cond ((not (string-match-p "\\_" system-configuration-features)) (warn! "Warning: You didn't install Emacs with gnutls support") (explain! @@ -254,8 +247,7 @@ ((error! "Nope!"))) -;; bsd vs gnu tar -(section! "test-tar") +;; which variant of tar is on your system? bsd or gnu tar? (let ((tar-bin (or (executable-find "gtar") (executable-find "tar")))) (if tar-bin @@ -291,7 +283,7 @@ (setq doom-modules nil)))) (when (bound-and-true-p doom-modules) - (section! "test-modules") + (section! "Running module doctors...") (let ((indent 4)) (advice-add #'require :around #'doom*shut-up) (maphash @@ -316,6 +308,7 @@ ;; (message "\n----") (if (> doom-errors 0) - (warn! "There %s!" (if (= doom-errors 1) "is %d issue" "are %d issues") - doom-errors) + (warn! "There %s!" + (format (if (= doom-errors 1) "is %d issue" "are %d issues") + doom-errors)) (success! "Everything seems fine, happy Emacs'ing!")) From f2c02e32c81c686e1e9200b0ac9b4904c388fd1f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 15:23:37 +0200 Subject: [PATCH 035/132] General minor refactor & comment updates --- core/autoload/files.el | 3 +-- core/autoload/packages.el | 11 +++++----- core/core-packages.el | 45 ++++++++++++++++++++------------------- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/core/autoload/files.el b/core/autoload/files.el index e77df3ec0..687ee2d91 100644 --- a/core/autoload/files.el +++ b/core/autoload/files.el @@ -75,8 +75,7 @@ kills the buffer. If FORCE-P, force the deletion (don't ask for confirmation)." ((not (or force-p (y-or-n-p (format "Really delete %s?" fbase)))) (message "Aborted") nil) - (t - (unwind-protect + ((unwind-protect (progn (delete-file path) t) (let ((short-path (file-relative-name path (doom-project-root)))) (if (file-exists-p path) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 58a1a008b..3439dab28 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -3,9 +3,6 @@ (load! cache) ;;; Private functions -(defsubst doom--sort-alpha (it other) - (string-lessp (symbol-name (car it)) - (symbol-name (car other)))) (defun doom--packages-choose (prompt) (let ((table (cl-loop for pkg in package-alist @@ -365,7 +362,8 @@ package.el as appropriate." "QUELPA") (t "ELPA")))) - (sort (cl-copy-list packages) #'doom--sort-alpha) + (cl-sort (cl-copy-list packages) #'string-lessp + :key #'car) "\n"))))) (error "Aborted!")) @@ -400,7 +398,8 @@ package.el as appropriate." (doom-initialize-packages) (print! "Looking for outdated packages...") (doom-refresh-packages-maybe doom-debug-mode) - (let ((packages (sort (doom-get-outdated-packages) #'doom--sort-alpha))) + (let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp + :key #'car))) (cond ((not packages) (print! (green "Everything is up-to-date")) nil) @@ -411,7 +410,7 @@ package.el as appropriate." (length packages) (let ((max-len (or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages) - (lambda (it other) (> it other)))) + #'>)) 10))) (mapconcat (lambda (pkg) diff --git a/core/core-packages.el b/core/core-packages.el index 08e67ad04..3d431f1c7 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -248,29 +248,28 @@ to least)." (setq doom--refreshed-p t) (package-initialize)))) ;; Ensure core packages are installed - (let ((core-packages (cl-remove-if #'package-installed-p doom-core-packages))) - (when core-packages - (message "Installing core packages") - (unless doom--refreshed-p - (package-refresh-contents)) - (dolist (package core-packages) - (let ((inhibit-message t)) - (package-install package)) - (if (package-installed-p package) - (message "✓ Installed %s" package) - (error "✕ Couldn't install %s" package))) - (message "Installing core packages...done"))) + (when-let* ((core-packages (cl-remove-if #'package-installed-p doom-core-packages))) + (message "Installing core packages") + (unless doom--refreshed-p + (package-refresh-contents)) + (dolist (package core-packages) + (let ((inhibit-message t)) + (package-install package)) + (if (package-installed-p package) + (message "✓ Installed %s" package) + (error "✕ Couldn't install %s" package))) + (message "Installing core packages...done")) (unless noninteractive (add-hook 'doom-pre-init-hook #'doom|refresh-cache))) - ;; autoloads file + ;; Load autoloads file (doom-initialize-autoloads)) - ;; initialize Doom core + ;; Initialize Doom core (unless noninteractive (require 'core-ui) (require 'core-editor) (require 'core-projects) (require 'core-keybinds)) - ;; bootstrap Doom + ;; Bootstrap Doom (unless doom-init-p (unless noninteractive (add-hook! 'doom-reload-hook @@ -517,6 +516,7 @@ MODULES is an malformed plist of modules to load." (and (plist-member plist :when) (not (eval (plist-get plist :when) t))) (and (plist-member plist :unless) (eval (plist-get plist :unless) t)))) `(progn + ;; TODO Replace with custom use-package keyword ,(when-let* ((defer (plist-get plist :defer)) (value (or (car-safe defer) defer))) (setq plist (plist-put plist :defer (or (cdr-safe defer) t))) @@ -554,8 +554,7 @@ to have them return non-nil (or exploit that to overwrite Doom's config)." package (substring (symbol-name when) 1))) ,@body))) - (t - (error "'%s' isn't a valid hook for def-package-hook!" when)))) + ((error "'%s' isn't a valid hook for def-package-hook!" when)))) (defmacro load! (filesym &optional path noerror) "Load a file relative to the current executing file (`load-file-name'). @@ -750,11 +749,13 @@ loads MODULE SUBMODULE's packages.el file." ;; Cross-module configuration ;; -;; I needed a way to reliably cross-configure modules without worrying about -;; whether they were enabled or not, so I wrote `set!'. If a setting doesn't -;; exist at runtime, the `set!' call is ignored and its arguments are left -;; unevaluated (and entirely omitted when byte-compiled). -(defvar doom-settings nil) +;; I needed a way to reliably cross-configure modules without littering my +;; modules with `after!' blocks or testing whether they were enabled, so I wrote +;; `set!'. If a setting doesn't exist at runtime, the `set!' call is ignored and +;; its arguments are left unevaluated (and entirely omitted when byte-compiled). + +(defvar doom-settings nil + "An alist mapping setting keywords to functions.") (defmacro def-setting! (keyword arglist &optional docstring &rest forms) "Define a setting. Like `defmacro', this should return a form to be executed From 16a9126b3ef03234816840faa9cd9b8e2328a067 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 15:51:47 +0200 Subject: [PATCH 036/132] Make after! noop if package is disabled After disabling a package, def-package! blocks for that package are ignored. Now, after! blocks for those packages will be ignored too. --- core/core-lib.el | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 527188cdf..67da60898 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -108,27 +108,29 @@ "A smart wrapper around `with-eval-after-load'. Supresses warnings during compilation." (declare (indent defun) (debug t)) - (list (if (or (not (bound-and-true-p byte-compile-current-file)) - (dolist (next (doom-enlist targets)) - (if (symbolp next) - (require next nil :no-error) - (load next :no-message :no-error)))) - #'progn - #'with-no-warnings) - (cond ((symbolp targets) - `(eval-after-load ',targets '(progn ,@body))) - ((and (consp targets) - (memq (car targets) '(:or :any))) - `(progn - ,@(cl-loop for next in (cdr targets) - collect `(after! ,next ,@body)))) - ((and (consp targets) - (memq (car targets) '(:and :all))) - (dolist (next (cdr targets)) - (setq body `(after! ,next ,@body))) - body) - ((listp targets) - `(after! (:all ,@targets) ,@body))))) + (unless (and (symbolp targets) + (memq targets doom-disabled-packages)) + (list (if (or (not (bound-and-true-p byte-compile-current-file)) + (dolist (next (doom-enlist targets)) + (if (symbolp next) + (require next nil :no-error) + (load next :no-message :no-error)))) + #'progn + #'with-no-warnings) + (cond ((symbolp targets) + `(eval-after-load ',targets '(progn ,@body))) + ((and (consp targets) + (memq (car targets) '(:or :any))) + `(progn + ,@(cl-loop for next in (cdr targets) + collect `(after! ,next ,@body)))) + ((and (consp targets) + (memq (car targets) '(:and :all))) + (dolist (next (cdr targets)) + (setq body `(after! ,next ,@body))) + body) + ((listp targets) + `(after! (:all ,@targets) ,@body)))))) (defmacro quiet! (&rest forms) "Run FORMS without making any output." From 454a962d6bade0546c6b69b227d8ea8b6279f582 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:03:37 +0200 Subject: [PATCH 037/132] Rewrite doom//reload (merge reload-load-path into it) --- core/autoload/modules.el | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index 157a40b68..7c23b2e34 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -4,33 +4,19 @@ (defun doom//reload () "Reload your private Doom config. Experimental!" (interactive) - (let ((load-prefer-newer t)) - (message "Reloading your private config...") - (setq doom-modules (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0)) - (doom-initialize t) - (doom//reload-autoloads)) - (message "✓ Done!")) + (when (file-exists-p doom-packages-file) + (delete-file doom-packages-file)) + (cond ((and noninteractive (not (daemonp))) + (doom-initialize) + (doom//reload-autoloads) + (require 'server) + (when (server-running-p) + (message "Reloading active Emacs session...") + (server-eval-at server-name '(doom//reload)))) -;;;###autoload -(defun doom//reload-load-path () - "Reload `load-path' and recompile files (if necessary). - -Use this when `load-path' is out of sync with your plugins. This should only -happen if you manually modify/update/install packages from outside Emacs, while -an Emacs session is running. - -This isn't necessary if you use Doom's package management commands because they -call `doom//reload-load-path' remotely (through emacsclient)." - (interactive) - (unless doom--inhibit-reload - (when (file-exists-p doom-packages-file) - (delete-file doom-packages-file)) - (cond ((and noninteractive (not (daemonp))) - (require 'server) - (when (server-running-p) - (message "Reloading active Emacs session...") - (server-eval-at server-name '(doom//reload-load-path)))) - (t + ((let ((load-prefer-newer t) + doom-init-p) + (setq doom-modules (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0)) (doom-initialize t) (message "%d packages reloaded" (length package-alist)) (run-hooks 'doom-reload-hook))))) From 89c52e7d999b4c76c265c4c4f5b3af0b30d24d52 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:05:35 +0200 Subject: [PATCH 038/132] Rename reload dispatcher to refresh & refactor --- core/core-dispatcher.el | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index c24112443..33b887335 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -155,8 +155,8 @@ respectively." "Reports the version of Doom and Emacs." (doom//version)) -(def-dispatcher! (reload re) - "Reload Doom. +(def-dispatcher! (refresh re) + "Refresh Doom. This is the equivalent of running autoremove, install, autoloads, then recompile. Run this whenever you: @@ -166,13 +166,13 @@ recompile. Run this whenever you: 3. Add or remove autoloaded functions in module autoloaded files. 4. Update Doom outside of Doom (e.g. with git)" (doom-initialize) - (if (let* ((doom--inhibit-reload t) - (autoremove-p (doom//packages-autoremove)) - (install-p (doom//packages-install))) - (or autoremove-p install-p)) - (doom//reload) - (doom//reload-autoloads)) - (doom//byte-compile nil 'recompile)) + (let (reload-p) + (when (let* ((doom--inhibit-reload t) + (autoremove-p (doom//packages-autoremove)) + (install-p (doom//packages-install))) + (or autoremove-p install-p)) + (doom//reload)) + (doom//byte-compile nil 'recompile))) ;; From 1369c51000834ea3f0f94bc5dc70e84187f57002 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:07:15 +0200 Subject: [PATCH 039/132] Replace :defer HOOK/FN with :after-call keyword --- core/core-editor.el | 16 ++++++++------ core/core-packages.el | 51 +++++++++++++++++++++++++++++++------------ core/core-ui.el | 4 ++-- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/core/core-editor.el b/core/core-editor.el index 6971f2b67..844052373 100644 --- a/core/core-editor.el +++ b/core/core-editor.el @@ -83,14 +83,15 @@ fundamental-mode) for performance sake." ;; revert buffers for changed files (def-package! autorevert - :defer doom-before-switch-buffer-hook + :after-call doom-before-switch-buffer-hook :config (setq auto-revert-verbose nil) (global-auto-revert-mode +1)) ;; persist variables across sessions (def-package! savehist - :defer (pre-command-hook . 1) + :defer 1 + :after-call post-command-hook :config (setq savehist-file (concat doom-cache-dir "savehist") savehist-save-minibuffer-history t @@ -100,7 +101,7 @@ fundamental-mode) for performance sake." ;; persistent point location in buffers (def-package! saveplace - :defer doom-before-switch-buffer-hook + :after-call doom-before-switch-buffer-hook :config (setq save-place-file (concat doom-cache-dir "saveplace")) (defun doom*recenter-on-load-saveplace (&rest _) @@ -112,7 +113,8 @@ fundamental-mode) for performance sake." ;; Keep track of recently opened files (def-package! recentf - :defer (pre-command-hook . 1) + :defer 1 + :after-call find-file-hook :commands recentf-open-files :config (setq recentf-save-file (concat doom-cache-dir "recentf") @@ -135,7 +137,7 @@ fundamental-mode) for performance sake." ;; Auto-close delimiters and blocks as you type (def-package! smartparens - :defer doom-before-switch-buffer-hook + :after-call doom-before-switch-buffer-hook :commands (sp-pair sp-local-pair sp-with-modes) :config (require 'smartparens-config) @@ -155,7 +157,7 @@ fundamental-mode) for performance sake." ;; Branching undo (def-package! undo-tree - :defer doom-before-switch-buffer-hook + :after-call doom-before-switch-buffer-hook :config ;; persistent undo history is known to cause undo history corruption, which ;; can be very destructive! So disable it! @@ -176,7 +178,7 @@ fundamental-mode) for performance sake." command-log-mode-open-log-turns-on-mode t)) (def-package! dtrt-indent - :defer t + :after-call doom-before-switch-buffer-hook :config (setq dtrt-indent-verbosity (if doom-debug-mode 2 0)) diff --git a/core/core-packages.el b/core/core-packages.el index 3d431f1c7..ece2af661 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -459,11 +459,44 @@ added, if the file exists." ;; Use-package modifications ;; -(autoload 'use-package "use-package" nil nil 'macro) +(autoload 'use-package "use-package-core" nil 'macro) -;; TODO :after-hook HOOK (load packages on first run of HOOK) -;; TODO Make +(after! use-package-core + (add-to-list 'use-package-deferring-keywords :after-call nil #'eq) + (setq use-package-keywords + (use-package-list-insert :after-call use-package-keywords :after)) + + (defalias 'use-package-normalize/:after-call + 'use-package-normalize-symlist) + + (defvar doom--deferred-packages-alist () + "TODO") + + (defun use-package-handler/:after-call (name-symbol _keyword hooks rest state) + (let ((fn (intern (format "doom|transient-hook--load-%s" name-symbol))) + (hooks (delete-dups hooks))) + (if (plist-get state :demand) + (use-package-process-keywords name rest state) + (use-package-concat + `((fset ',fn + (lambda (&rest _) + (require ',name-symbol) + (dolist (hook (cdr (assq ',name-symbol doom--deferred-packages-alist))) + (if (functionp hook) + (advice-remove hook #',fn) + (remove-hook hook #',fn))) + (map-delete doom--deferred-packages-alist ',name-symbol) + (fmakunbound ',fn)))) + (cl-mapcan (lambda (hook) + (if (functionp hook) + `((advice-add #',hook :before #',fn)) + `((add-hook ',hook #',fn)))) + hooks) + `((map-put doom--deferred-packages-alist + ',name-symbol + '(,@hooks ,@(cdr (assq name-symbol doom--deferred-packages-alist))))) + (use-package-process-keywords name rest state)))))) ;; @@ -515,17 +548,7 @@ MODULES is an malformed plist of modules to load." (or (and (plist-member plist :if) (not (eval (plist-get plist :if) t))) (and (plist-member plist :when) (not (eval (plist-get plist :when) t))) (and (plist-member plist :unless) (eval (plist-get plist :unless) t)))) - `(progn - ;; TODO Replace with custom use-package keyword - ,(when-let* ((defer (plist-get plist :defer)) - (value (or (car-safe defer) defer))) - (setq plist (plist-put plist :defer (or (cdr-safe defer) t))) - (unless (or (memq value '(t nil)) - (number-or-marker-p value)) - `(add-transient-hook! ',value - ,(intern (format "load-%s" name)) - (require ',name)))) - (use-package ,name ,@plist)))) + `(use-package ,name ,@plist))) (defmacro def-package-hook! (package when &rest body) "Reconfigures a package's `def-package!' block. diff --git a/core/core-ui.el b/core/core-ui.el index ad948c254..f6f7faa5f 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -290,13 +290,13 @@ DEFAULT is non-nil, set the default mode-line for all buffers." ;; undo/redo changes to Emacs' window layout (def-package! winner - :defer doom-before-switch-window-hook + :after-call doom-before-switch-window-hook :preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself :config (winner-mode +1)) ;; highlight matching delimiters (def-package! paren - :defer doom-before-switch-buffer-hook + :after-call doom-before-switch-buffer-hook :config (setq show-paren-delay 0.1 show-paren-highlight-openparen t From 8ce5e96ea5676c54db1562d94681665613200928 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:07:46 +0200 Subject: [PATCH 040/132] recentf: auto-cleanup = 120; refactor temp-file detector --- core/core-editor.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/core-editor.el b/core/core-editor.el index 844052373..b4984600d 100644 --- a/core/core-editor.el +++ b/core/core-editor.el @@ -118,16 +118,16 @@ fundamental-mode) for performance sake." :commands recentf-open-files :config (setq recentf-save-file (concat doom-cache-dir "recentf") - recentf-auto-cleanup 60 + recentf-auto-cleanup 120 recentf-max-menu-items 0 recentf-max-saved-items 300 recentf-filename-handlers '(file-truename) recentf-exclude - (list #'file-remote-p "\\.\\(gz\\|gif\\|svg\\|png\\|jpe?g\\)$" + (list #'file-remote-p "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\)$" "^/tmp/" "^/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$" "^/var/folders/.+$" ;; ignore private DOOM temp files (but not all of them) - (concat "^" (file-truename doom-local-dir)))) + (lambda (file) (file-in-directory-p file doom-local-dir)))) (recentf-mode +1)) From ac5eaf0fb32ad71f028453a77c63d88f70ec716f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:08:03 +0200 Subject: [PATCH 041/132] Load core-lib before core-package So that core-package may use the Doom standard library. --- core/core-lib.el | 7 +++---- core/core.el | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 67da60898..6429d7699 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -1,9 +1,8 @@ ;;; core-lib.el -*- lexical-binding: t; -*- -(let ((load-path doom-site-load-path)) - (require 'subr-x) - (require 'cl-lib) - (require 'map)) +(require 'subr-x) +(require 'cl-lib) +(require 'map) (eval-and-compile (unless EMACS26+ diff --git a/core/core.el b/core/core.el index e9f68279f..3ea6b195c 100644 --- a/core/core.el +++ b/core/core.el @@ -197,8 +197,8 @@ this, you'll get stuttering and random freezes) and resets (add-to-list 'load-path doom-core-dir) -(require 'core-packages) (require 'core-lib) +(require 'core-packages) (require 'core-os) (unless noninteractive From 67269fdf2b87ea459633e0a02c2273d0e3307c3e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:08:38 +0200 Subject: [PATCH 042/132] add-transient-hook!: unintern => fmakunbound --- core/core-lib.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-lib.el b/core/core-lib.el index 6429d7699..2182b03f2 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -167,7 +167,7 @@ HOOK can be a quoted hook or a sharp-quoted function (which will be advised)." ,@forms (cond ((functionp ,hook) (advice-remove ,hook #',fn)) ((symbolp ,hook) (remove-hook ,hook #',fn))) - (unintern ',fn nil))) + (fmakunbound ',fn))) (cond ((functionp ,hook) (advice-add ,hook ,(if append :after :before) #',fn)) ((symbolp ,hook) From 337d2e95338e222d0876810e2fdd860fa90d6e8e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:09:01 +0200 Subject: [PATCH 043/132] Make bin/doom (with no args) equivalent to make all --- bin/doom | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/doom b/bin/doom index f4001a61a..b18d68e44 100755 --- a/bin/doom +++ b/bin/doom @@ -63,8 +63,8 @@ ((equal argv '("help")) (usage)) ((not argv) - (message "Expecting a command!\n") - (usage)) + (let ((default-directory user-emacs-directory)) + (doom-dispatch (list "refresh")))) ((let ((default-directory user-emacs-directory)) (doom-dispatch argv))))) From f853d8b407045ea2bc1334c4379a418d6c56df14 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 20 May 2018 20:11:51 +0200 Subject: [PATCH 044/132] Update core autoload-message tests --- core/test/autoload-message.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/test/autoload-message.el b/core/test/autoload-message.el index c3e456a2f..0cdae9f09 100644 --- a/core/test/autoload-message.el +++ b/core/test/autoload-message.el @@ -10,15 +10,15 @@ "Hello World")) (should (equal (format! (green "Hello %s" "World")) (format "\e[%dm%s\e[0m" - (cdr (assq 'green doom-message-fg)) + (cadr (assq 'green doom-message-fg)) "Hello World"))) (should (equal (format! (on-red "Hello %s" "World")) (format "\e[%dm%s\e[0m" - (cdr (assq 'on-red doom-message-bg)) + (cadr (assq 'on-red doom-message-bg)) "Hello World"))) (should (equal (format! (bold "Hello %s" "World")) (format "\e[%dm%s\e[0m" - (cdr (assq 'bold doom-message-fx)) + (cadr (assq 'bold doom-message-fx)) "Hello World"))))) (def-test! ansi-format-nested From fbf8a7be56782ffcf654f334024582dfcc10a6ee Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 01:25:58 +0200 Subject: [PATCH 045/132] Remove vestigial references to doom//reload-load-path --- core/autoload/packages.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 3439dab28..7e405a0f5 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -388,7 +388,7 @@ package.el as appropriate." (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) "")))) (print! (bold (green "Finished!"))) - (doom//reload-load-path) + (doom//reload) success))))) ;;;###autoload @@ -432,7 +432,7 @@ package.el as appropriate." (color (if result 'green 'red) (if result "✓ DONE" "✕ FAILED")))))) (print! (bold (green "Finished!"))) - (doom//reload-load-path) + (doom//reload) success))))) ;;;###autoload @@ -478,7 +478,7 @@ package.el as appropriate." pkg))))) (print! (bold (green "Finished!"))) - (doom//reload-load-path) + (doom//reload) success))))) From cf54b3705b1b3dee84cfbfbf9dd1d12cd5ffbad4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 15:42:00 +0200 Subject: [PATCH 046/132] bin/doom: alias h => help --- bin/doom | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/doom b/bin/doom index b18d68e44..9ce2f8a0b 100755 --- a/bin/doom +++ b/bin/doom @@ -60,7 +60,8 @@ ;; Just incase you aren't using Doom! (when (fboundp 'doom|run-all-startup-hooks) (doom|run-all-startup-hooks))) - ((equal argv '("help")) + ((and (not (cdr argv)) + (member (car argv) '("help" "h"))) (usage)) ((not argv) (let ((default-directory user-emacs-directory)) From 553d00b598b8c4bb03c93575a03f84fa69afe639 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 15:42:27 +0200 Subject: [PATCH 047/132] Add doctor/help dummy dispatchers This way they show up in doom help + documentation. --- core/core-dispatcher.el | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index 33b887335..70a71e5e4 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -83,6 +83,13 @@ All arguments are passed on to Emacs (except for -p and -e). Warning, this is for convenience and testing purposes, Doom will not run its best or fastest when started in this manner.") +(def-dispatcher! (doctor doc) + "Checks for issues with your current Doom config.") + +(def-dispatcher! (help h) + "Look up additional information about a command.") + +;; (def-dispatcher! quickstart "TODO" (doom//quickstart)) @@ -146,11 +153,6 @@ respectively." "Output system info in markdown for bug reports." (doom//info)) -(def-dispatcher! (doctor d) - "Checks for issues with your current Doom config." - (load (expand-file-name "bin/doom-doctor" doom-emacs-dir) - nil t t)) - (def-dispatcher! (version v) "Reports the version of Doom and Emacs." (doom//version)) From 1b8dce260bf65a510e412f6eb6ca2a78ad3befc3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:13:49 +0200 Subject: [PATCH 048/132] config/default: restore find-in-snippets command #597 And conditionally bind snippets keybinds --- modules/config/default/+bindings.el | 12 +++++++----- modules/config/default/autoload/default.el | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index a72aa6e2c..33df90bba 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -295,11 +295,13 @@ :desc "Browse remote files" :n "." #'ssh-deploy-browse-remote-handler :desc "Detect remote changes" :n ">" #'ssh-deploy-remote-changes-handler)) - (:desc "snippets" :prefix "s" - :desc "New snippet" :n "n" #'yas-new-snippet - :desc "Insert snippet" :nv "i" #'yas-insert-snippet - :desc "Find snippet for mode" :n "s" #'yas-visit-snippet-file - :desc "Find snippet" :n "S" #'+default/find-in-snippets) + (:when (featurep! :feature snippets) + (:desc "snippets" :prefix "s" + :desc "New snippet" :n "n" #'yas-new-snippet + :desc "Insert snippet" :nv "i" #'yas-insert-snippet + :desc "Find snippet" :n "s" #'+default/find-in-snippets + :desc "Find snippet for mode" :n "S" #'+default/browse-snippets + :desc "Find global snippet" :n "/" #'yas-visit-snippet-file)) (:desc "toggle" :prefix "t" :desc "Flyspell" :n "s" #'flyspell-mode diff --git a/modules/config/default/autoload/default.el b/modules/config/default/autoload/default.el index 6526c029e..738ea0a7b 100644 --- a/modules/config/default/autoload/default.el +++ b/modules/config/default/autoload/default.el @@ -36,8 +36,10 @@ ;;;###autoload (defun +default/browse-snippets () - (interactive) (doom-project-browse emacs-snippets-dir)) -;; NOTE No need for a browse-snippets variant, use `yas-visit-snippet-file' + (interactive) (doom-project-browse +snippets-dir)) +;;;###autoload +(defun +default/find-in-snippets () + (interactive) (doom-project-find-file +snippets-dir)) ;;;###autoload (defun +default/find-in-config () From af97dcdfe8a6e14f6d8c184bcaf6a69675fe2ddb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:33:15 +0200 Subject: [PATCH 049/132] config/default: add SPC-g-o/SPC-g-I for browsing remote/issues --- modules/config/default/+bindings.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 33df90bba..50eb4bb28 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -197,8 +197,10 @@ :desc "Magit status" :n "g" #'magit-status :desc "List gists" :n "G" #'+gist:list :desc "Initialize repo" :n "i" #'magit-init + :desc "Browse issues tracker" :n "I" #'+vcs/git-browse-issues :desc "Magit buffer log" :n "l" #'magit-log-buffer-file :desc "List repositories" :n "L" #'magit-list-repositories + :desc "Browse remote" :n "o" #'+vcs/git-browse :desc "Magit push popup" :n "p" #'magit-push-popup :desc "Magit pull popup" :n "P" #'magit-pull-popup :desc "Git revert hunk" :n "r" #'git-gutter:revert-hunk From 4e18722d497ee91f324036c7d56123a068d12ed3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:33:50 +0200 Subject: [PATCH 050/132] config/default: update doom help/debug keybinds --- modules/config/default/+bindings.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 50eb4bb28..01b3bf7cc 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -215,9 +215,11 @@ (:desc "help" :prefix "h" :n "h" help-map :desc "Apropos" :n "a" #'apropos + :desc "Open Bug Report" :n "b" #'doom//open-bug-report :desc "Describe char" :n "c" #'describe-char :desc "Describe DOOM module" :n "d" #'doom/describe-module - :desc "Open Doom manual" :n "D" #'doom/help + :desc "Open Doom manual" :n "D" #'doom//open-manual + :desc "Open vanilla sandbox" :n "E" #'doom//open-vanilla-sandbox :desc "Describe function" :n "f" #'describe-function :desc "Describe face" :n "F" #'describe-face :desc "Info" :n "i" #'info-lookup-symbol @@ -227,7 +229,7 @@ :desc "Command log" :n "L" #'global-command-log-mode :desc "Toggle Emacs log" :n "m" #'view-echo-area-messages :desc "Describe mode" :n "M" #'describe-mode - :desc "Toggle profiler" :n "p" #'doom/toggle-profiler + :desc "Toggle profiler" :n "p" #'doom//toggle-profiler :desc "Reload theme" :n "r" #'doom//reload-theme :desc "Reload private config" :n "R" #'doom//reload :desc "Describe DOOM setting" :n "s" #'doom/describe-setting @@ -235,7 +237,7 @@ :desc "Print Doom version" :n "V" #'doom/version :desc "Describe at point" :n "." #'helpful-at-point :desc "What face" :n "'" #'doom/what-face - :desc "What minor modes" :n ";" #'doom/what-minor-mode) + :desc "What minor modes" :n ";" #'doom/describe-active-minor-mode) (:desc "insert" :prefix "i" :desc "From kill-ring" :nv "y" #'counsel-yank-pop From 6a0812819466cc316dc353f40610b227bd2fa9aa Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:50:54 +0200 Subject: [PATCH 051/132] doctor: make feedback more informative --- bin/doom-doctor | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 0eb4b1b8e..5bf6865ed 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -18,6 +18,7 @@ ;; (defvar doom-init-p nil) +(defvar doom-warnings 0) (defvar doom-errors 0) (defmacro when! (cond &rest body) (declare (indent defun)) @@ -62,7 +63,7 @@ (format (concat prefix ,msg) ,@args)))) (defmacro error! (&rest args) `(progn (msg! (color 31 ,@args)) (setq doom-errors (+ doom-errors 1)))) -(defmacro warn! (&rest args) `(progn (msg! (color 33 ,@args)) (setq doom-errors (+ doom-errors 1)))) +(defmacro warn! (&rest args) `(progn (msg! (color 33 ,@args)) (setq doom-warnings (+ doom-warnings 1)))) (defmacro success! (&rest args) `(msg! (color 32 ,@args))) (defmacro section! (&rest args) `(msg! (color 1 (color 34 ,@args)))) @@ -137,11 +138,13 @@ ;; --- is the environment set up properly? -------------------- ;; on windows? +(section! "Checking your OS...") (when (memq system-type '(windows-nt ms-dos cygwin)) (warn! "Warning: Windows detected") (explain! "DOOM was designed for MacOS and Linux. Expect a bumpy ride!")) ;; are all default fonts present? +(section! "Checking your fonts...") (if (not (fboundp 'find-font)) (progn (warn! "Warning: unable to detect font") @@ -164,6 +167,7 @@ "case, ignore this warning.")))))) ;; gnutls-cli & openssl +(section! "Checking gnutls/openssl...") (cond ((executable-find "gnutls-cli")) ((executable-find "openssl") (let* ((output (sh "openssl ciphers -v")) @@ -199,6 +203,7 @@ "or just about anyone who knows more about computers than you do!"))) ;; are certificates validated properly? +(section! "Testing your root certificates...") (cond ((not (string-match-p "\\_" system-configuration-features)) (warn! "Warning: You didn't install Emacs with gnutls support") (explain! @@ -248,6 +253,7 @@ ((error! "Nope!"))) ;; which variant of tar is on your system? bsd or gnu tar? +(section! "Checking for GNU/BSD tar...") (let ((tar-bin (or (executable-find "gtar") (executable-find "tar")))) (if tar-bin @@ -268,7 +274,6 @@ ;; --- are your modules set up properly? ---------------------- -(message "\n----") (let (doom-core-packages doom-debug-mode) (condition-case ex (let ((inhibit-message t) @@ -283,7 +288,7 @@ (setq doom-modules nil)))) (when (bound-and-true-p doom-modules) - (section! "Running module doctors...") + (section! "Checking your enabled modules...") (let ((indent 4)) (advice-add #'require :around #'doom*shut-up) (maphash @@ -306,9 +311,13 @@ doom-modules))) ;; -(message "\n----") -(if (> doom-errors 0) - (warn! "There %s!" - (format (if (= doom-errors 1) "is %d issue" "are %d issues") - doom-errors)) +(message "\n") +(dolist (msg (list (list doom-errors "error" 31) + (list doom-warnings "warning" 33))) + (when (> (car msg) 0) + (message (color (nth 2 msg) (if (= (car msg) 1) "There is %d %s!" "There are %d %ss!") + (car msg) (nth 1 msg))))) + +(when (and (zerop doom-errors) + (zerop doom-warnings)) (success! "Everything seems fine, happy Emacs'ing!")) From 2e7831b8a4e8d54932367eff63ed0bad9a8016c8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:51:10 +0200 Subject: [PATCH 052/132] doctor: reduce output for cert test --- bin/doom-doctor | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 5bf6865ed..33121fea9 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -225,8 +225,7 @@ (gnutls-verify-error t)) (dolist (url '("https://elpa.gnu.org" "https://melpa.org")) (when! (condition-case-unless-debug e - (if (let ((inhibit-message t)) (url-retrieve-synchronously url)) - (ignore (success! "Validated %s" url)) + (unless (let ((inhibit-message t)) (url-retrieve-synchronously url)) 'empty) ('timed-out 'timeout) ('error e)) @@ -243,7 +242,7 @@ t 'empty) ('timed-out 'timeout) - ('error (ignore (success! "Successfully rejected %s" url)))) + ('error)) (pcase it (`empty (error! "Couldn't reach %s" url)) (`timeout (error! "Timed out trying to contact %s" ex)) From 8ea0f3427088f59166fa814921b2395bd43a2f72 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Mon, 21 May 2018 16:51:38 +0200 Subject: [PATCH 053/132] doctor: update doom bootstrap logic & fix error on built-in packages --- bin/doom-doctor | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 33121fea9..2f2030a1f 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -275,11 +275,9 @@ (let (doom-core-packages doom-debug-mode) (condition-case ex - (let ((inhibit-message t) - (noninteractive t)) + (let ((inhibit-message t)) (load (concat user-emacs-directory "init.el") nil t) - (doom-initialize) - (doom|run-all-startup-hooks) + (doom-initialize-modules) (success! "Attempt to load DOOM: success! Loaded v%s" doom-version)) ('error (warn! "Attempt to load DOOM: failed\n %s\n" @@ -302,7 +300,8 @@ (doom--stage 'packages)) (when (load packages-file t t) (dolist (package (cl-remove-if #'package-installed-p doom-packages :key #'car)) - (error! "%s is not installed" (car package)))) + (unless (package-built-in-p (car package)) + (error! "%s is not installed" (car package))))) (let ((doom--stage 'doctor)) (load doctor-file t t))))) ('error From 53a7e3508213c7688f3e56b6bda2b15fc9d58a67 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Tue, 22 May 2018 01:47:40 +0200 Subject: [PATCH 054/132] lang/javascript: fix rjsx-electric-gt reparsing advice --- modules/lang/javascript/config.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index 8d7c4d202..ff5991288 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -67,8 +67,8 @@ ;; However, the parser doesn't run immediately, so a fast typist can outrun ;; it, causing issues, so force it to parse. (defun +javascript|reparse (n) - ;; if n != 0, then rjsx-maybe-reparse will be run elsewhere - (if (= n 0) (rjsx-maybe-reparse))) + ;; if n != 1, then rjsx-maybe-reparse will be run elsewhere + (if (= n 1) (rjsx-maybe-reparse))) (advice-add #'rjsx-electric-gt :before #'+javascript|reparse)) From 2637c415d3596082fe8468b7e2e348fedfc5f896 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 23 May 2018 19:09:09 +0200 Subject: [PATCH 055/132] Add error checks & docstrings to doom-keyword-* lib functions --- core/core-lib.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 2182b03f2..2ebfdc9fc 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -58,13 +58,15 @@ t))) (defun doom-keyword-intern (str) - "TODO" + "Converts STR (a string) into a keyword (`keywordp')." + (or (stringp str) + (signal 'wrong-type-argument (list 'stringp str))) (intern (concat ":" str))) (defun doom-keyword-name (keyword) - "TODO" + "Returns the string name of KEYWORD (`keywordp') minus the leading colon." (or (keywordp keyword) - (signal 'wrong-type-argument (list 'keyword keyword))) + (signal 'wrong-type-argument (list 'keywordp keyword))) (substring (symbol-name keyword) 1)) (cl-defun doom-files-in (dirs &key when unless full map (nosort t) (match "^[^.]")) From dc0175b8e13a223ff1d4c46f70a42b85cf31cc93 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 23 May 2018 19:16:33 +0200 Subject: [PATCH 056/132] Merge doom-files-under into doom-files-in; more powerful doom-files-in --- core/core-lib.el | 82 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 2ebfdc9fc..54655819d 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -69,25 +69,71 @@ (signal 'wrong-type-argument (list 'keywordp keyword))) (substring (symbol-name keyword) 1)) -(cl-defun doom-files-in (dirs &key when unless full map (nosort t) (match "^[^.]")) - "TODO" - (let ((results (cl-loop for dir in (doom-enlist dirs) - if (file-directory-p dir) - nconc (directory-files dir full match nosort)))) - (when when - (cl-delete-if-not when results)) - (when unless - (cl-delete-if unless results)) - (when map - (setq results (mapcar map results))) - results)) +(cl-defun doom-files-in + (path-or-paths &rest rest + &key + filter + map + full + (follow-symlinks t) + (type 'files) + (relative-to (unless full (if (nlistp path-or-paths) path-or-paths))) + (depth 99999) + (match "^[^.]")) + "Returns a list of files/directories in PATH-OR-PATHS (one string path or a +list of them). -(cl-defun doom-files-under (dirs &key include-dirs (match "^[^.]")) - "Like `directory-files-recursively', but traverses symlinks." - (cl-letf (((symbol-function #'file-symlink-p) #'ignore)) - (cl-loop for dir in (doom-enlist dirs) - if (file-directory-p dir) - nconc (directory-files-recursively dir match include-dirs)))) +FILTER is a function or symbol that takes one argument (the path). If it returns +non-nil, the entry will be excluded. + +MAP is a function or symbol which will be used to transform each entry in the +results. + +TYPE determines what kind of path will be included in the results. This can be t +(files and folders), 'files or 'dirs. + +By default, this function returns paths relative to PATH-OR-PATHS if it is a +single path. If it a list of paths, this function returns absolute paths. +Otherwise, by setting RELATIVE-TO to a path, the results will be transformed to +be relative to it. + +The search recurses up to DEPTH and no further. DEPTH is an integer. + +MATCH is a string regexp. Only entries that match it will be included." + (cond + ((listp path-or-paths) + (cl-loop for path in path-or-paths + if (file-directory-p path) + nconc (apply #'doom-files-in path (plist-put rest :relative-to relative-to)))) + ((let ((path path-or-paths) + result) + (dolist (file (file-name-all-completions "" path)) + (unless (member file '("./" "../")) + (let ((fullpath (expand-file-name file path))) + (cond ((directory-name-p fullpath) + (when (and (memq type '(t dirs)) + (string-match-p match file) + (not (and filter (funcall filter fullpath))) + (not (and (file-symlink-p fullpath) + (not follow-symlinks)))) + (setq result + (nconc result + (list (cond (map (funcall map fullpath)) + (relative-to (file-relative-name fullpath relative-to)) + (fullpath)))))) + (unless (<= depth 1) + (setq result + (nconc result (apply #'doom-files-in fullpath + (append `(:depth ,(1- depth) :relative-to ,relative-to) + rest)))))) + ((and (memq type '(t files)) + (string-match-p match file) + (not (and filter (funcall filter fullpath)))) + (push (if relative-to + (file-relative-name fullpath relative-to) + fullpath) + result)))))) + result)))) (defun doom*shut-up (orig-fn &rest args) "Generic advisor for silencing noisy functions." From b452aded76f32ee549b7827b863fb1ab466cf5a3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 11:44:17 +0200 Subject: [PATCH 057/132] Mention doom-emacs-dir must end with a slash --- core/core.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core.el b/core/core.el index 3ea6b195c..9c2baa1b4 100644 --- a/core/core.el +++ b/core/core.el @@ -20,7 +20,7 @@ line or use --debug-init to enable this.") ;; (defvar doom-emacs-dir (eval-when-compile (file-truename user-emacs-directory)) - "The path to this emacs.d directory.") + "The path to this emacs.d directory. Must end in a slash.") (defvar doom-core-dir (concat doom-emacs-dir "core/") "Where essential files are stored.") From 5d42b1512b708e9201f9f50ffd1b00e3b4937014 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 11:49:01 +0200 Subject: [PATCH 058/132] Fix naive path concatenation for doom-private-dir #513 --- core/core.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/core.el b/core/core.el index 9c2baa1b4..3a504f5f9 100644 --- a/core/core.el +++ b/core/core.el @@ -49,9 +49,10 @@ Use this for files that change often, like cache files.") (defvar doom-private-dir (eval-when-compile - (or (let ((xdg-path (concat (or (getenv "XDG_CONFIG_HOME") - "~/.config") - "/doom/"))) + (or (let ((xdg-path + (expand-file-name "doom/" + (or (getenv "XDG_CONFIG_HOME") + "~/.config")))) (if (file-directory-p xdg-path) xdg-path)) "~/.doom.d/")) "Where your private customizations are placed. Must end in a slash. Respects From a48f75371b49f89d0a9cc0046e98b7976068f1e3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 13:02:02 +0200 Subject: [PATCH 059/132] core-lib (doom-files-in): default relative-to to default-directory --- core/core-lib.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-lib.el b/core/core-lib.el index 54655819d..9c1205e96 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -77,7 +77,7 @@ full (follow-symlinks t) (type 'files) - (relative-to (unless full (if (nlistp path-or-paths) path-or-paths))) + (relative-to (unless full default-directory)) (depth 99999) (match "^[^.]")) "Returns a list of files/directories in PATH-OR-PATHS (one string path or a From 499630fdcd445da636450318804c846bedfc1fe9 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:00:46 +0200 Subject: [PATCH 060/132] bin/doom: handle doc/doctor especially --- bin/doom | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/doom b/bin/doom index 9ce2f8a0b..b2d15728f 100755 --- a/bin/doom +++ b/bin/doom @@ -2,9 +2,10 @@ ":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*- ":"; VERSION=$(emacs --version | head -n1) ":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run Doom. Check your PATH"; echo; exit 2; } -":"; [[ $1 != run ]] && { exec emacs --quick --script "$0" -- $@; exit 0; } -":"; cd $(dirname "${BASH_SOURCE:-${(%):-%x}}")/.. -":"; shift; exec emacs -Q -l bin/doom $@ +":"; DOOMDIR=$(dirname "${BASH_SOURCE:-${(%):-%x}}")/.. +":"; [[ $1 == doc || $1 == doctor ]] && { cd "$DOOMDIR"; exec emacs --script bin/doom-doctor; exit 0; } +":"; [[ $1 == run ]] && { cd "$DOOMDIR"; shift; exec emacs -Q -l bin/doom "$@"; exit 0; } +":"; exec emacs --quick --script "$0" -- $@ ":"; exit 0 (defun usage () From 8a7ebebf160dbe073504c4b5c404c01a5d92671d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:02:57 +0200 Subject: [PATCH 061/132] bin/doom: add -y/--yes option --- bin/doom | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/doom b/bin/doom index b2d15728f..856028da7 100755 --- a/bin/doom +++ b/bin/doom @@ -30,7 +30,8 @@ (format! (bold "Options:\n")) " -d --debug\t\tTurns on doom-debug-mode (and debug-on-error)\n" " -e --emacsd DIR\tUse the emacs config at DIR (e.g. ~/.emacs.d)\n" - " -p --private DIR\tUse the private module at DIR (e.g. ~/.doom.d)\n\n") + " -p --private DIR\tUse the private module at DIR (e.g. ~/.doom.d)\n" + " -y --yes\t\tAuto-accept all confirmation prompts\n\n") (princ (buffer-string))) (doom--dispatch-help)) @@ -50,8 +51,8 @@ (setq emacs-dir (expand-file-name (pop argv))) (or (file-directory-p emacs-dir) (error "%s does not exist" emacs-dir))) - ("--") - (_))) + ((or "-y" "--yes") + (setq doom-auto-accept t)))) ;; Bootstrap Doom (load (expand-file-name "init" emacs-dir) From e1e47b91738321edbef0aadcc1d9b8fd19932883 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:03:23 +0200 Subject: [PATCH 062/132] bin/doom: minor refactor; no longer default to doom refresh Better to be explicit, otherwise you get some weird cases where incorrect commands fall through to a doom refresh. --- bin/doom | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/bin/doom b/bin/doom index 856028da7..3e7a2f4de 100755 --- a/bin/doom +++ b/bin/doom @@ -11,7 +11,8 @@ (defun usage () (with-temp-buffer (insert (format! "%s %s [COMMAND] [ARGS...]\n" - (bold "Usage:") (file-name-nondirectory load-file-name)) + (bold "Usage:") + (file-name-nondirectory load-file-name)) "\n" "A command line interfacing for managing Doom Emacs; including\n" "package management, diagnostics, unit tests, and byte-compilation.\n" @@ -36,38 +37,36 @@ (doom--dispatch-help)) ;; -(let ((argv (cdr (cdr (cdr command-line-args)))) +(let ((args (cdr (cdr (cdr command-line-args)))) (emacs-dir (expand-file-name "../" (file-name-directory load-file-name)))) ;; Parse options - (while (ignore-errors (string-prefix-p "-" (car argv))) - (pcase (pop argv) + (while (ignore-errors (string-prefix-p "-" (car args))) + (pcase (pop args) ((or "-d" "--debug") (setq doom-debug-mode t)) ((or "-p" "--private") - (setq doom-private-dir (expand-file-name (pop argv))) + (setq doom-private-dir (expand-file-name (pop args))) (or (file-directory-p doom-private-dir) (error "%s does not exist" doom-private-dir))) ((or "-e" "--emacsd") - (setq emacs-dir (expand-file-name (pop argv))) + (setq emacs-dir (expand-file-name (pop args))) (or (file-directory-p emacs-dir) (error "%s does not exist" emacs-dir))) ((or "-y" "--yes") (setq doom-auto-accept t)))) ;; Bootstrap Doom + (setq noninteractive 'doom) (load (expand-file-name "init" emacs-dir) nil 'nomessage) (cond ((not noninteractive) - ;; Just incase you aren't using Doom! - (when (fboundp 'doom|run-all-startup-hooks) - (doom|run-all-startup-hooks))) - ((and (not (cdr argv)) - (member (car argv) '("help" "h"))) + (doom|run-all-startup-hooks)) + ((and (not (cdr args)) + (member (car args) '("help" "h"))) (usage)) - ((not argv) - (let ((default-directory user-emacs-directory)) - (doom-dispatch (list "refresh")))) + ((not args) + (error "Expecting a command")) ((let ((default-directory user-emacs-directory)) - (doom-dispatch argv))))) + (doom-dispatch args))))) From bf3d35c287ed7b223c10aa3b480db27dc1b8de8c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:05:52 +0200 Subject: [PATCH 063/132] Clean up makefile & update it to match bin/doom --- Makefile | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 3d1b0a8e5..a233df3cf 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,8 @@ -# Ensure emacs always runs from this makefile's PWD DOOM = bin/doom -EMACS = emacs -q $(ARGS) -l init.el - MODULES = $(patsubst modules/%/, %, $(sort $(dir $(wildcard modules/*/ modules/*/*/)))) all: - @$(DOOM) reload + @$(DOOM) refresh ## Shortcuts a: autoloads @@ -15,7 +12,7 @@ U: upgrade r: autoremove c: compile cc: compile-core -ce: compile-elpa +cp: compile-plugins re: recompile d: doctor @@ -63,15 +60,12 @@ test-core: # test-module/submodule $(patsubst %, test-%, $(MODULES)): @$(DOOM) test $(subst test-, , $@) -# run tests interactively -testi: - @$(EMACS) -l core/autoload/doom.el -f doom//run-tests ## Utility tasks # Runs Emacs from a different folder than ~/.emacs.d; only use this for testing! run: - @$(EMACS) + @$(DOOM) run $(ARGS) # Prints debug info about your current setup info: @$(DOOM) info From 7cfab92f7cd5517987722cc96e5a21c31d7373fc Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:39:08 +0200 Subject: [PATCH 064/132] bin/doom-doctor: refactor bash bootstrapper --- bin/doom-doctor | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/doom-doctor b/bin/doom-doctor index 2f2030a1f..0ad1e003a 100755 --- a/bin/doom-doctor +++ b/bin/doom-doctor @@ -1,6 +1,8 @@ #!/usr/bin/env bash ":"; command -v emacs >/dev/null || { >&2 echo "Emacs isn't installed"; exit 1; } # -*-emacs-lisp-*- -":"; [[ $(emacs --version | head -n1) == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $(emacs --version | head -n1)"; echo "That version is too old to run the doctor. Check your PATH"; echo; exit 2; } || exec emacs --quick --script "$0" +":"; VERSION=$(emacs --version | head -n1) +":"; [[ $VERSION == *\ 2[0-2].[0-1].[0-9] ]] && { echo "You're running $VERSION"; echo "That version is too old to run the doctor. Check your PATH"; echo; exit 2; } +":"; exec emacs --quick --script "$0"; exit 0 ;; Uses a couple simple heuristics to locate issues with your environment that ;; could interfere with running or setting up DOOM Emacs. From 592e16d76d6600b391a929699c78651ea2fd682f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:40:37 +0200 Subject: [PATCH 065/132] Conform debug commands to naming convention --- core/autoload/debug.el | 14 +++++++------- modules/config/default/+bindings.el | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 03c944765..586c0dc20 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -93,7 +93,7 @@ ready to be pasted in a bug report on github." ;; ;;;###autoload -(defun doom//info () +(defun doom/info () "Collects some debug information about your Emacs session, formats it into markdown and copies it to your clipboard, ready to be pasted into bug reports!" (declare (interactive-only t)) @@ -105,7 +105,7 @@ markdown and copies it to your clipboard, ready to be pasted into bug reports!" (message "Done! Copied to clipboard."))) ;;;###autoload -(defun doom//am-i-secure () +(defun doom/am-i-secure () "Test to see if your root certificates are securely configured in emacs." (declare (interactive-only t)) (interactive) @@ -129,7 +129,7 @@ markdown and copies it to your clipboard, ready to be pasted into bug reports!" t))))) ;;;###autoload -(defun doom//version () +(defun doom/version () "Display the current version of Doom & Emacs, including the current Doom branch and commit." (interactive) @@ -169,7 +169,7 @@ branch and commit." "--eval" (prin1-to-string `(delete-file ,file))))))) ;;;###autoload -(defun doom//open-vanilla-sandbox () +(defun doom/open-vanilla-sandbox () "Open an Emacs Lisp buffer destinated to run in a blank Emacs session. This vanilla sandbox is started with emacs -Q, and provides a testbed for @@ -221,7 +221,7 @@ access to the installed packages." (error (signal (car e) (car e))))))) ;;;###autoload -(defun doom//open-bug-report () +(defun doom/open-bug-report () "Open a markdown buffer destinated to populate the New Issue page on Doom Emacs' issue tracker. @@ -266,7 +266,7 @@ will be automatically appended to the result." (defvar doom--profiler nil) ;;;###autoload -(defun doom//toggle-profiler () +(defun doom/toggle-profiler () "Toggle the Emacs profiler. Run it again to see the profiling report." (interactive) (if (not doom--profiler) @@ -276,7 +276,7 @@ will be automatically appended to the result." (setq doom--profiler (not doom--profiler))) ;;;###autoload -(defun doom//profile-emacs () +(defun doom/profile-emacs () "Profile the startup time of Emacs in the background with ESUP. If INIT-FILE is non-nil, profile that instead of USER-INIT-FILE." (interactive) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 01b3bf7cc..2d4f221a3 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -215,11 +215,11 @@ (:desc "help" :prefix "h" :n "h" help-map :desc "Apropos" :n "a" #'apropos - :desc "Open Bug Report" :n "b" #'doom//open-bug-report + :desc "Open Bug Report" :n "b" #'doom/open-bug-report :desc "Describe char" :n "c" #'describe-char :desc "Describe DOOM module" :n "d" #'doom/describe-module :desc "Open Doom manual" :n "D" #'doom//open-manual - :desc "Open vanilla sandbox" :n "E" #'doom//open-vanilla-sandbox + :desc "Open vanilla sandbox" :n "E" #'doom/open-vanilla-sandbox :desc "Describe function" :n "f" #'describe-function :desc "Describe face" :n "F" #'describe-face :desc "Info" :n "i" #'info-lookup-symbol @@ -229,7 +229,7 @@ :desc "Command log" :n "L" #'global-command-log-mode :desc "Toggle Emacs log" :n "m" #'view-echo-area-messages :desc "Describe mode" :n "M" #'describe-mode - :desc "Toggle profiler" :n "p" #'doom//toggle-profiler + :desc "Toggle profiler" :n "p" #'doom/toggle-profiler :desc "Reload theme" :n "r" #'doom//reload-theme :desc "Reload private config" :n "R" #'doom//reload :desc "Describe DOOM setting" :n "s" #'doom/describe-setting @@ -255,7 +255,7 @@ :desc "REPL" :n "r" #'+eval/open-repl :v "r" #'+eval:repl :desc "Neotree" :n "n" #'+neotree/open - :desc "Neotree: on this file" :n "N" #'+neotree/find-this-file + :desc "Neotree: find file" :n "N" #'+neotree/find-this-file :desc "Imenu sidebar" :nv "i" #'imenu-list-smart-toggle :desc "Terminal" :n "t" #'+term/open-popup-in-project From b25e215d59acc25e364f4c49583fc64c74698806 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 16:41:14 +0200 Subject: [PATCH 066/132] Increase last-pkg-refresh ttl from 900 -> 1200s --- core/autoload/packages.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 7e405a0f5..849816193 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -50,7 +50,7 @@ (progn (message "Refreshing package archives") (package-refresh-contents) - (doom-cache-set 'last-pkg-refresh t 900)) + (doom-cache-set 'last-pkg-refresh t 1200)) ('error (doom--refresh-pkg-cache) (message "Failed to refresh packages: (%s) %s" From e3bdeabe0b62dc0f6ebed1dbe070bf1843ed7c7b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 18:29:56 +0200 Subject: [PATCH 067/132] bin/doom: discard extra command line args --- bin/doom | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/doom b/bin/doom index 3e7a2f4de..1e455534a 100755 --- a/bin/doom +++ b/bin/doom @@ -68,5 +68,6 @@ ((not args) (error "Expecting a command")) ((let ((default-directory user-emacs-directory)) + (setq argv nil) (doom-dispatch args))))) From 47ccbb5d416c8dd701cf51c4db4a70b1725e46b5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 18:30:36 +0200 Subject: [PATCH 068/132] print!: use terpri instead of princ for newline Will produce the appropriate newline for the current OS. --- core/autoload/message.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/autoload/message.el b/core/autoload/message.el index f1b84a1b9..8aba7b918 100644 --- a/core/autoload/message.el +++ b/core/autoload/message.el @@ -101,4 +101,4 @@ Uses faces in interactive sessions and ANSI codes otherwise." (message (format! ,message ,@args)) ;; princ prints to stdout, message to stderr (princ (format! ,message ,@args)) - (princ "\n"))) + (terpri))) From b2186745b7750d5580b519f1f06de02b78261a1e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 18:35:06 +0200 Subject: [PATCH 069/132] Refactor doom--resolve-path-forms --- core/core-lib.el | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 9c1205e96..57fe6da0d 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -15,18 +15,40 @@ ;; Helpers ;; -(defun doom--resolve-path-forms (paths &optional root) - (cond ((stringp paths) +(defun doom--resolve-path-forms (spec &optional directory) + "Converts a simple nested series of or/and forms into a series of +`file-exists-p' checks. + +For example + + (doom--resolve-path-forms + '(or \"some-file\" (and path-var \"/an/absolute/path\")) + \"~\") + +Returns + + '(or (file-exists-p (expand-file-name \"some-file\" \"~\")) + (and (file-exists-p (expand-file-name path-var \"~\")) + (file-exists-p \"/an/absolute/path\"))) + +This is used by `associate!', `file-exists-p!' and `project-file-exists-p!'." + (cond ((stringp spec) `(file-exists-p - (expand-file-name - ,paths ,(if (or (string-prefix-p "./" paths) - (string-prefix-p "../" paths)) - 'default-directory - (or root `(doom-project-root)))))) - ((listp paths) - (cl-loop for i in paths - collect (doom--resolve-path-forms i root))) - (t paths))) + ,(if (file-name-absolute-p spec) + spec + `(expand-file-name ,spec ,directory)))) + ((symbolp spec) + `(file-exists-p ,(if directory + `(expand-file-name ,spec ,directory) + path))) + ((and (listp spec) + (memq (car spec) '(or and))) + `(,(car spec) + ,@(cl-loop for i in (cdr spec) + collect (doom--resolve-path-forms i directory)))) + ((listp spec) + (doom--resolve-path-forms (eval spec t) directory)) + (t spec))) (defun doom--resolve-hook-forms (hooks) (cl-loop with quoted-p = (eq (car-safe hooks) 'quote) @@ -314,7 +336,7 @@ Body forms can access the hook's arguments through the let-bound variable (not ,mode) (and buffer-file-name (not (file-remote-p buffer-file-name))) ,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t) - ,(if files (doom--resolve-path-forms files) t) + ,(if files (doom--resolve-path-forms files '(doom-project-root)) t) ,(or pred-form t)) (,mode 1))) ,@(if (and modes (listp modes)) From 4ee0b5ba6df1fb9ed88d77460909ce63e96c9a1d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 18:35:42 +0200 Subject: [PATCH 070/132] New macros file-exists-p! & project-file-exists-p! The latter replaces the doom-project-has! macro --- core/core-lib.el | 14 ++++++++++++++ core/core-projects.el | 4 ++-- core/test/core-lib.el | 4 ++-- core/test/core-projects.el | 12 ++++++------ modules/lang/cc/autoload.el | 2 +- modules/lang/java/autoload.el | 6 +++--- 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 57fe6da0d..cbb4d16ea 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -348,5 +348,19 @@ Body forms can access the hook's arguments through the let-bound variable (t (user-error "associate! invalid rules for mode [%s] (modes %s) (match %s) (files %s)" mode modes match files)))))) +(defmacro file-exists-p! (spec &optional directory) + "Returns t if the files in SPEC all exist. + +SPEC can be a single file or a list of forms/files. It understands nested (and +...) and (or ...), as well. + +DIRECTORY is where to look for the files in SPEC if they aren't absolute. This +doesn't apply to variables, however. + +For example: + + (file-exists-p (or doom-core-dir \"~/.config\" \"some-file\") \"~\")" + (doom--resolve-path-forms spec directory)) + (provide 'core-lib) ;;; core-lib.el ends here diff --git a/core/core-projects.el b/core/core-projects.el index 2d9eb8197..5ad28773b 100644 --- a/core/core-projects.el +++ b/core/core-projects.el @@ -94,12 +94,12 @@ If NOCACHE, don't fetch a cached answer." (defalias 'doom-project-expand #'projectile-expand-root) -(defmacro doom-project-has! (files) +(defmacro project-file-exists-p! (files) "Checks if the project has the specified FILES. Paths are relative to the project root, unless they start with ./ or ../ (in which case they're relative to `default-directory'). If they start with a slash, they are absolute." - (doom--resolve-path-forms files (doom-project-root))) + (doom--resolve-path-forms files '(doom-project-root))) (defun doom-project-find-file (dir) "Fuzzy-find a file under DIR." diff --git a/core/test/core-lib.el b/core/test/core-lib.el index 2fff1fd6e..10a9d6ee3 100644 --- a/core/test/core-lib.el +++ b/core/test/core-lib.el @@ -7,8 +7,8 @@ (def-test! resolve-path-forms (should (equal (doom--resolve-path-forms '(and "fileA" "fileB")) - '(and (file-exists-p (expand-file-name "fileA" (doom-project-root))) - (file-exists-p (expand-file-name "fileB" (doom-project-root))))))) + '(and (file-exists-p (expand-file-name "fileA" nil)) + (file-exists-p (expand-file-name "fileB" nil)))))) ;; `doom--resolve-hook-forms' (def-test! resolve-hook-forms diff --git a/core/test/core-projects.el b/core/test/core-projects.el index d580b921e..47435061b 100644 --- a/core/test/core-projects.el +++ b/core/test/core-projects.el @@ -33,15 +33,15 @@ (should (equal (doom-project-expand "init.el") (expand-file-name "init.el" (doom-project-root)))))) -;; `doom-project-has!' +;; `project-file-exists-p!' (def-test! project-has! :minor-mode projectile-mode (let ((default-directory doom-core-dir)) ;; Resolve from project root - (should (doom-project-has! "init.el")) + (should (project-file-exists-p! "init.el")) ;; Chained file checks - (should (doom-project-has! (and "init.el" "LICENSE"))) - (should (doom-project-has! (or "init.el" "does-not-exist"))) - (should (doom-project-has! (and "init.el" (or "LICENSE" "does-not-exist")))) + (should (project-file-exists-p! (and "init.el" "LICENSE"))) + (should (project-file-exists-p! (or "init.el" "does-not-exist"))) + (should (project-file-exists-p! (and "init.el" (or "LICENSE" "does-not-exist")))) ;; Should resolve relative paths from `default-directory' - (should (doom-project-has! (and "./core.el" "../init.el"))))) + (should (project-file-exists-p! (and "core/core.el" "./init.el"))))) diff --git a/modules/lang/cc/autoload.el b/modules/lang/cc/autoload.el index d14f7c28e..cf6580425 100644 --- a/modules/lang/cc/autoload.el +++ b/modules/lang/cc/autoload.el @@ -6,7 +6,7 @@ (interactive) (unless (memq major-mode '(c-mode c++-mode objc-mode)) (user-error "Not a C/C++/ObjC buffer")) - (unless (doom-project-has! "compile_commands.json") + (unless (project-file-exists-p! "compile_commands.json") (user-error "No compile_commands.json file")) ;; first rtag (when (and (featurep 'rtags) diff --git a/modules/lang/java/autoload.el b/modules/lang/java/autoload.el index 3e7a73c78..fa1689503 100644 --- a/modules/lang/java/autoload.el +++ b/modules/lang/java/autoload.el @@ -24,9 +24,9 @@ ;;;###autoload (defun +java|android-mode-maybe () - (when (doom-project-has! (or "local.properties" - "AndroidManifest.xml" - "src/main/AndroidManifest.xml")) + (when (project-file-exists-p! (or "local.properties" + "AndroidManifest.xml" + "src/main/AndroidManifest.xml")) (android-mode +1) (doom/set-build-command "./gradlew %s" "build.gradle"))) From 3dd291a67590eaf1b7b3fd317e9942d6862f570b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 18:38:50 +0200 Subject: [PATCH 071/132] core-lib: improve function docstrings --- core/core-lib.el | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index cbb4d16ea..5f46425f7 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -1,5 +1,6 @@ ;;; core-lib.el -*- lexical-binding: t; -*- +;; Built in packages we use a lot of (require 'subr-x) (require 'cl-lib) (require 'map) @@ -7,6 +8,8 @@ (eval-and-compile (unless EMACS26+ (with-no-warnings + ;; if-let and when-let are deprecated in Emacs 26+ in favor of their + ;; if-let* variants, so we alias them for 25 users. (defalias 'if-let* #'if-let) (defalias 'when-let* #'when-let)))) @@ -59,6 +62,11 @@ This is used by `associate!', `file-exists-p!' and `project-file-exists-p!'." collect hook else collect (intern (format "%s-hook" (symbol-name hook))))) + +;; +;; Functions +;; + (defun doom-unquote (exp) "Return EXP unquoted." (while (memq (car-safe exp) '(quote function)) @@ -70,7 +78,7 @@ This is used by `associate!', `file-exists-p!' and `project-file-exists-p!'." (if (listp exp) exp (list exp))) (defun doom-file-cookie-p (file) - "Returns the value of the ;;;###if predicate form in FILE." + "Returns the return value of the ;;;###if predicate form in FILE." (with-temp-buffer (insert-file-contents-literally file nil 0 256) (if (and (re-search-forward "^;;;###if " nil t) @@ -175,7 +183,7 @@ MATCH is a string regexp. Only entries that match it will be included." (defmacro after! (targets &rest body) "A smart wrapper around `with-eval-after-load'. Supresses warnings during -compilation." +compilation. This will no-op on features that have been disabled by the user." (declare (indent defun) (debug t)) (unless (and (symbolp targets) (memq targets doom-disabled-packages)) @@ -254,7 +262,7 @@ HOOK can be a quoted hook or a sharp-quoted function (which will be advised)." 3. A function, list of functions, or body forms to be wrapped in a lambda. Examples: - (add-hook! 'some-mode-hook 'enable-something) + (add-hook! 'some-mode-hook 'enable-something) (same as `add-hook') (add-hook! some-mode '(enable-something and-another)) (add-hook! '(one-mode-hook second-mode-hook) 'enable-something) (add-hook! (one-mode second-mode) 'enable-something) @@ -317,7 +325,19 @@ Body forms can access the hook's arguments through the let-bound variable (nreverse forms)))) (defmacro associate! (mode &rest plist) - "Associate a minor mode to certain patterns and project files." + "Enables a minor mode if certain conditions are met. + +The available conditions are: + + :modes SYMBOL_LIST + A list of major/minor modes in which this minor mode may apply. + :match REGEXP + A regexp to be tested against the current file path. + :files SPEC + Accepts what `project-file-exists-p!' accepts. Checks if certain files exist + relative to the project root. + :when FORM + Whenever FORM returns non-nil." (declare (indent 1)) (unless noninteractive (let ((modes (plist-get plist :modes)) From 8746c12fae3324a700ec0b9571b32f72efc953de Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:00:41 +0200 Subject: [PATCH 072/132] Redesign Doom bootstrap, caching & autoload generation logic The autoloads file has been split into doom-autoload-file and doom-package-autoload-file. The former is for Doom's modules and standard library; the latter is for compiling all package autoloads like load-path and auto-mode-alist (among other things). This reduced my startup speed from ~1s to ~0.5s --- core/autoload/modules.el | 350 +++++++++++++++++++++++++-------------- core/core-packages.el | 282 ++++++++++++++++++------------- core/core.el | 38 ++--- init.el | 2 - 4 files changed, 413 insertions(+), 259 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index 7c23b2e34..ed8f162b1 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -1,149 +1,255 @@ ;;; core/autoload/modules.el -*- lexical-binding: t; -*- -;;;###autoload -(defun doom//reload () - "Reload your private Doom config. Experimental!" - (interactive) - (when (file-exists-p doom-packages-file) - (delete-file doom-packages-file)) - (cond ((and noninteractive (not (daemonp))) - (doom-initialize) - (doom//reload-autoloads) - (require 'server) - (when (server-running-p) - (message "Reloading active Emacs session...") - (server-eval-at server-name '(doom//reload)))) +(autoload 'print! "autoload/message" nil 'macro) +(autoload 'printerr! "autoload/message" nil 'macro) - ((let ((load-prefer-newer t) - doom-init-p) - (setq doom-modules (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0)) - (doom-initialize t) - (message "%d packages reloaded" (length package-alist)) - (run-hooks 'doom-reload-hook))))) +(defun doom--server-eval (body) + (require 'server) + (when (server-running-p) + (server-eval-at server-name body))) + +;;;###autoload +(defun doom//reload (&optional force-p) + "Reloads your config. This is experimental! + +If called from a noninteractive session, this will try to communicate with a +live server (if one is found) to tell it to run this function. + +If called from an interactive session, tries to reload autoloads files (if +necessary), reinistalize doom (via `doom-initialize') and reloads your private +init.el and config.el. Then runs `doom-reload-hook'." + (interactive) + (unless doom--inhibit-reload + (cond ((and noninteractive (not (daemonp))) + (require 'server) + (if (not (server-running-p)) + (doom//reload-autoloads force-p) + (print! "Reloading active Emacs session...") + (print! + (bold "%%s") + (if (server-eval-at server-name '(doom//reload)) + (green "Done!") + (red "There were issues!"))))) + ((let ((load-prefer-newer t)) + (doom//reload-autoloads force-p) + (doom-initialize t) + (doom-initialize-modules t) + (print! (green "%d packages reloaded" (length package-alist))) + (run-hooks 'doom-reload-hook)))))) + + +;; +;; Autoload file generation +;; + +(defvar doom-autoload-excluded-packages '(marshal gh) + "Packages that have silly or destructive autoload files that try to load +everyone in the universe and their dog, causing errors that make babies cry. No +one wants that.") + +(defun doom--byte-compile (file) + (let ((short-name (file-name-nondirectory file))) + (condition-case-unless-debug ex + (when (byte-compile-file file) + (load (byte-compile-dest-file file) nil t) + (unless noninteractive + (message "Finished compiling %s" short-name))) + ('error + (doom-delete-autoloads-file file) + (error "Error in %s: %s -- %s" + short-name + (car ex) (error-message-string ex)))))) + +;;;###autoload +(defun doom-delete-autoloads-file (file) + "Delete FILE (an autoloads file), and delete the accompanying *.elc file, if +it exists." + (or (stringp file) + (signal 'wrong-type-argument (list 'stringp file))) + (when (file-exists-p file) + (delete-file file) + (ignore-errors (delete-file (byte-compile-dest-file file))) + (print! "Deleted old %s" (file-name-nondirectory file)))) + +;;;###autoload +(defun doom//reload-autoloads (&optional file force-p) + "Reloads FILE (an autoload file), if it needs reloading. + +FILE should be one of `doom-autoload-file' or `doom-package-autoload-file'. If +it is nil, it will try to reload both. If FORCE-P (universal argument) do it +even if it doesn't need reloading!" + (interactive + (list nil current-prefix-arg)) + (or (null file) + (stringp file) + (signal 'wrong-type-argument (list 'stringp file))) + (cond ((equal file doom-autoload-file) + (doom//reload-doom-autoloads force-p)) + ((equal file doom-package-autoload-file) + (doom//reload-package-autoloads force-p)) + ((progn + (doom//reload-doom-autoloads force-p) + (doom//reload-package-autoloads force-p))))) (defvar generated-autoload-load-name) ;;;###autoload -(defun doom//reload-autoloads (&optional force) - "Refreshes the autoloads.el file, specified by `doom-autoload-file'. +(defun doom//reload-doom-autoloads (&optional force-p) + "Refreshes the autoloads.el file, specified by `doom-autoload-file', if +necessary (or if FORCE-P is non-nil). It scans and reads core/autoload/*.el, modules/*/*/autoload.el and -modules/*/*/autoload/*.el, and generates an autoloads file at the path specified -by `doom-autoload-file'. This file tells Emacs where to find lazy-loaded -functions. +modules/*/*/autoload/*.el, and generates `doom-autoload-file'. This file tells +Emacs where to find lazy-loaded functions. -This should be run whenever init.el or an autoload file is modified. Running -'make autoloads' from the commandline executes this command." +This should be run whenever your `doom!' block, or a module autoload file, is +modified." (interactive) - ;; This function must not use autoloaded functions or external dependencies. - ;; It must assume nothing is set up! - (let ((default-directory doom-emacs-dir) + (let ((doom-modules (doom-module-table)) + (default-directory doom-emacs-dir) (targets (file-expand-wildcards - (expand-file-name "autoload/*.el" doom-core-dir))) - (generate-autoload-section-continuation "") - (generate-autoload-section-header "") - (generate-autoload-section-trailer "") - (doom--stage 'autoloads) - outdated) + (expand-file-name "autoload/*.el" doom-core-dir)))) (dolist (path (doom-module-load-path)) (let ((auto-dir (expand-file-name "autoload" path)) (auto-file (expand-file-name "autoload.el" path))) (when (file-exists-p auto-file) (push auto-file targets)) (when (file-directory-p auto-dir) - (dolist (file (doom-files-under auto-dir :match "\\.el$")) + (dolist (file (doom-files-in auto-dir :match "\\.el$" :full t)) (push file targets))))) - (when (file-exists-p doom-autoload-file) - (delete-file doom-autoload-file) - (ignore-errors (delete-file (byte-compile-dest-file doom-autoload-file))) - (message "Deleted old autoloads.el")) - (message "Generating new autoloads.el") - (dolist (file (mapcar #'file-truename (reverse targets))) - (let ((generated-autoload-load-name (file-name-sans-extension file))) - (message - (cond ((not (doom-file-cookie-p file)) - "⚠ Ignoring %s") - ((update-file-autoloads file nil doom-autoload-file) - "✕ Nothing in %s") - ("✓ Scanned %s")) - (if (file-in-directory-p file default-directory) - (file-relative-name file) - (abbreviate-file-name file))))) - (make-directory (file-name-directory doom-autoload-file) t) - (let ((buf (find-file-noselect doom-autoload-file t)) - (load-path (append doom-psuedo-module-dirs - doom-modules-dirs - load-path)) - case-fold-search) - ;; FIXME Make me faster - (unwind-protect - (with-current-buffer buf - (goto-char (point-min)) - (insert ";;; -*- lexical-binding:t -*-\n" - ";; This file is autogenerated by `doom//reload-autoloads', DO NOT EDIT !!\n\n") + (if (and (not force-p) + (file-exists-p doom-autoload-file) + (not (cl-loop for file in targets + if (file-newer-than-file-p file doom-autoload-file) + return t))) + (ignore (print! (green "Doom core autoloads is up-to-date")) + (doom-initialize-autoloads doom-autoload-file)) + (doom-delete-autoloads-file doom-autoload-file) + ;; in case the buffer is open somewhere and modified + (when-let* ((buf (find-buffer-visiting doom-autoload-file))) + (with-current-buffer buf + (set-buffer-modified-p nil)) + (kill-buffer buf)) + (message "Generating new autoloads.el") + (dolist (file (nreverse targets)) + (let* ((file (file-truename file)) + (generated-autoload-load-name (file-name-sans-extension file)) + (noninteractive (not doom-debug-mode))) + (print! + (cond ((not (doom-file-cookie-p file)) + "⚠ Ignoring %s") + ((update-file-autoloads file nil doom-autoload-file) + (yellow "✕ Nothing in %%s")) + ((green "✓ Scanned %%s"))) + (if (file-in-directory-p file default-directory) + (file-relative-name file) + (abbreviate-file-name file))))) + (make-directory (file-name-directory doom-autoload-file) t) + (let ((buf (find-file-noselect doom-autoload-file t)) + case-fold-search) + (unwind-protect + (with-current-buffer buf + (goto-char (point-min)) + (insert ";;; -*- lexical-binding:t -*-\n" + ";; This file is autogenerated by `doom//reload-doom-autoloads', DO NOT EDIT !!\n\n") + (save-excursion + ;; Replace autoload paths (only for module autoloads) with + ;; absolute paths for faster resolution during load and + ;; simpler `load-path' + (let ((load-path (append doom-psuedo-module-dirs + doom-modules-dirs + load-path)) + cache) + (save-excursion + (while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^\"]*\\)\"" nil t) + (let ((path (match-string 1))) + (replace-match + (or (cdr (assoc path cache)) + (when-let* ((libpath (locate-library path)) + (libpath (file-name-sans-extension libpath))) + (push (cons path (abbreviate-file-name libpath)) cache) + libpath) + path) + t t nil 1))) + (print! (green "✓ Autoload paths expanded"))))) + ;; Remove byte-compile inhibiting file variables so we can + ;; byte-compile the file. + (when (re-search-forward "^;; no-byte-compile: t\n" nil t) + (replace-match "" t t)) + ;; Byte compile it to give the file a chance to reveal errors. + (save-buffer) + (doom--byte-compile doom-autoload-file) + (when (and noninteractive (not (daemonp))) + (doom--server-eval `(load-file ,doom-autoload-file))) + t) + (kill-buffer buf)))))) - ;; Replace autoload paths (only for module autoloads) with - ;; absolute paths for faster resolution during load and simpler - ;; `load-path' - (save-excursion - (let (cache) - (while (re-search-forward "^\\s-*(autoload\\s-+'[^ ]+\\s-+\"\\([^\"]*\\)\"" nil t) - (let ((path (match-string 1))) - (replace-match - (or (cdr (assoc path cache)) - (when-let* ((libpath (locate-library path)) - (libpath (file-name-sans-extension libpath))) - (push (cons path (abbreviate-file-name libpath)) cache) - libpath) - (progn - (warn "Couldn't find absolute path for: %s" path) - path)) - t t nil 1)))) - (message "✓ Autoload paths expanded")) +;;;###autoload +(defun doom//reload-package-autoloads (&optional force-p) + "Compiles `doom-package-autoload-file' from the autoloads files of all +installed packages. It also caches `load-path', `Info-directory-list', +`doom-disabled-packages', `package-activated-list' and `auto-mode-alist'. - ;; insert package autoloads - (save-excursion - (dolist (spec package-alist) - (let ((pkg (car spec))) - (unless (memq pkg doom-autoload-excluded-packages) - (let ((file - (abbreviate-file-name - (concat (package--autoloads-file-name (cadr spec)) ".el")))) - (insert "(let ((load-file-name " (prin1-to-string file) "))\n") - (insert-file-contents file) - (while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\)" nil t) - (unless (nth 8 (syntax-ppss)) - (replace-match "" t t))) - (unless (bolp) (insert "\n")) - (insert ")\n"))))) - (message "✓ Package autoloads included")) +Will do nothing if none of your installed packages have been modified. If +FORCE-P (universal argument) is non-nil, regenerate it anyway. - ;; Remove `load-path' and `auto-mode-alist' modifications (most - ;; of them, at least); they are cached elsewhere, so these are - ;; unnecessary overhead. - (while (re-search-forward (concat "^\\s-*(\\(add-to-list\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)") - nil t) - (beginning-of-line) - (skip-chars-forward " \t") - (kill-sexp)) - (message "✓ load-path/auto-mode-alist entries removed") +This should be run whenever your `doom!' block or update your packages." + (interactive) + (if (and (not force-p) + (file-exists-p doom-package-autoload-file) + (not (cl-loop initially do (doom-ensure-packages-initialized t) + for (_pkg desc) in package-alist + for autoload-file = (concat (package--autoloads-file-name desc) ".el") + if (file-newer-than-file-p autoload-file doom-package-autoload-file) + return t))) + (ignore (print! (green "Doom package autoloads is up-to-date")) + (doom-initialize-autoloads doom-package-autoload-file)) + (doom-delete-autoloads-file doom-package-autoload-file) + (with-temp-file doom-package-autoload-file + (insert ";;; -*- lexical-binding:t -*-\n" + ";; This file is autogenerated by `doom//reload-package-autoloads', DO NOT EDIT !!\n\n") + ;; insert package autoloads + (save-excursion + (dolist (spec package-alist) + (cl-destructuring-bind (pkg desc) spec + (unless (memq pkg doom-autoload-excluded-packages) + (let ((file + (abbreviate-file-name + (concat (package--autoloads-file-name desc) ".el")))) + (when (file-exists-p file) + (insert "(let ((load-file-name " (prin1-to-string file) "))\n") + (insert-file-contents file) + (while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\)" nil t) + (unless (nth 8 (syntax-ppss)) + (replace-match "" t t))) + (unless (bolp) (insert "\n")) + (insert ")\n")))))) + (print! (green "✓ Package autoloads included")) + ;; Cache the important and expensive-to-initialize state here. + (doom-initialize-packages 'internal) + (prin1 `(setq load-path ',load-path + auto-mode-alist ',auto-mode-alist + Info-directory-list ',Info-directory-list + doom-disabled-packages ',doom-disabled-packages + package-activated-list ',package-activated-list) + (current-buffer)) + (print! (green "✓ Cached package state"))) + ;; Remove `load-path' and `auto-mode-alist' modifications (most of them, + ;; at least); they are cached later, so all those membership checks are + ;; unnecessary overhead. + (while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|when (boundp \\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t) + (goto-char (match-beginning 1)) + (kill-sexp)) + (print! (green "✓ Removed load-path/auto-mode-alist entries"))) + (doom--byte-compile doom-package-autoload-file) + (when (and noninteractive (not (daemonp))) + (doom--server-eval `(load-file ,doom-package-autoload-file))) + t)) - ;; Remove byte-compile inhibiting file variables so we can - ;; byte-compile the file. - (when (re-search-forward "^;; no-byte-compile: t\n$" nil t) - (replace-match "" t t)) - (save-buffer) - ;; Byte compile it to give the file a chance to reveal errors. - (condition-case-unless-debug ex - (quiet! (byte-compile-file doom-autoload-file 'load)) - ('error - (delete-file doom-autoload-file) - (message "Deleting autoloads file!") - (error "Error in autoloads.el: %s -- %s" - (car ex) (error-message-string ex)))) - (message "Done!")) - (kill-buffer buf))))) +;; +;; Byte compilation +;; ;;;###autoload (defun doom//byte-compile (&optional modules recompile-p) diff --git a/core/core-packages.el b/core/core-packages.el index ece2af661..08b4f89e4 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -40,53 +40,47 @@ ;; See core/autoload/packages.el for more functions. (defvar doom-init-p nil - "Non-nil if doom is done initializing (once `doom-post-init-hook' is done). If -this is nil after Emacs has started something is wrong.") + "Non-nil if `doom-initialize' has run.") + +(defvar doom-init-modules-p nil + "Non-nil if `doom-initialize-modules' has run.") (defvar doom-init-time nil "The time it took, in seconds, for DOOM Emacs to initialize.") -(defvar doom-modules - (make-hash-table :test #'equal :size 100 :rehash-threshold 1.0) +(defvar doom-modules () "A hash table of enabled modules. Set by `doom-initialize-modules'.") (defvar doom-modules-dirs (list (expand-file-name "modules/" doom-private-dir) doom-modules-dir) "A list of module root directories. Order determines priority.") -(defvar doom-psuedo-module-dirs - (list doom-private-dir) +(defvar doom-psuedo-module-dirs (list doom-private-dir) "Additional paths for modules that are outside of `doom-modules-dirs'. -`doom//reload-autoloads', `doom//byte-compile' and `doom-initialize-packages' -will include the directories in this list.") +`doom//reload-doom-autoloads', `doom//byte-compile' and +`doom-initialize-packages' will include the directories in this list.") (defvar doom-packages () "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!' declaration. Set by `doom-initialize-packages'.") -(defvar doom-core-packages - '(persistent-soft use-package quelpa async) +(defvar doom-core-packages '(persistent-soft use-package quelpa async) "A list of packages that must be installed (and will be auto-installed if missing) and shouldn't be deleted.") (defvar doom-disabled-packages () "A list of packages that should be ignored by `def-package!'.") -(defvar doom-autoload-excluded-packages '(marshal gh) - "Packages that have silly or destructive autoload files that try to load -everyone in the universe and their dog, causing errors that make babies cry. No -one wants that.") - (defvar doom-site-load-path load-path "The starting load-path, before it is altered by `doom-initialize'.") (defvar doom-autoload-file (concat doom-local-dir "autoloads.el") - "Where `doom//reload-autoloads' will generate its autoloads file.") + "Where `doom//reload-doom-autoloads' will generate its core autoloads file.") -(defvar doom-packages-file (concat doom-cache-dir "packages.el") - "Where to cache `load-path', `Info-directory-list', `doom-disabled-packages' -and `auto-mode-alist'.") +(defvar doom-package-autoload-file (concat doom-local-dir "autoloads.pkg.el") + "Where `doom//reload-package-autoloads' will generate its package.el autoloads +file.") (defvar doom-reload-hook nil "A list of hooks to run when `doom//reload-load-path' is called.") @@ -150,22 +144,6 @@ and `auto-mode-alist'.") (file-relative-name load-file-name doom-emacs-dir) (abbreviate-file-name load-file-name)))) -(defun doom|refresh-cache () - "Refresh `doom-packages-file', which caches `load-path', -`Info-directory-list', `doom-disabled-packages', `auto-mode-alist' and -`package-activated-list'." - (doom-initialize-packages 'internal) - (let ((coding-system-for-write 'emacs-internal)) - (with-temp-file doom-packages-file - (insert ";;; -*- lexical-binding:t -*-\n" - ";; This file was autogenerated by `doom|refresh-cache', DO NOT EDIT!\n") - (prin1 `(setq load-path ',load-path - auto-mode-alist ',auto-mode-alist - Info-directory-list ',Info-directory-list - doom-disabled-packages ',doom-disabled-packages - package-activated-list ',package-activated-list) - (current-buffer))))) - (defun doom|display-benchmark (&optional return-p) "Display a benchmark, showing number of packages and modules, and how quickly they were loaded at startup. @@ -195,17 +173,59 @@ session, with a different init.el, like so: 'window-setup-hook)) +;; +;; Bootstrap helpers +;; + +(defun doom-ensure-packages-initialized (&optional force-p) + "Make sure package.el is initialized." + (when (or force-p (not package--initialized)) + (require 'package) + (setq package-activated-list nil + package--initialized nil) + (let (byte-compile-warnings) + (condition-case _ + (quiet! (package-initialize)) + ('error (package-refresh-contents) + (setq doom--refreshed-p t) + (package-initialize)))))) + +(defun doom-ensure-core-packages () + "Make sure `doom-core-packages' are installed." + (when-let* ((core-packages (cl-remove-if #'package-installed-p doom-core-packages))) + (message "Installing core packages") + (unless doom--refreshed-p + (package-refresh-contents)) + (dolist (package core-packages) + (let ((inhibit-message t)) + (package-install package)) + (if (package-installed-p package) + (message "✓ Installed %s" package) + (error "✕ Couldn't install %s" package))) + (message "Installing core packages...done"))) + +(defun doom-ensure-core-directories () + "Make sure all Doom's essential local directories (in and including +`doom-local-dir') exist." + (dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-packages-dir)) + (unless (file-directory-p dir) + (make-directory dir t)))) + + ;; ;; Bootstrap API ;; +(autoload 'doom//reload-doom-autoloads "autoload/modules" nil t) +(autoload 'doom//reload-package-autoloads "autoload/modules" nil t) + (defun doom-initialize (&optional force-p) "Bootstrap Doom, if it hasn't already (or if FORCE-P is non-nil). -The bootstrap process involves making sure the essential directories exist, core -packages are installed, `doom-autoload-file' is loaded, `doom-packages-file' -cache exists (and is loaded) and, finally, loads your private init.el (which -should contain your `doom!' block). +The bootstrap process involves making sure 1) the essential directories exist, +2) the core packages are installed, 3) `doom-autoload-file' and +`doom-package-autoload-file' exist and have been loaded, and 4) Doom's core +files are loaded. If the cache exists, much of this function isn't run, which substantially reduces startup time. @@ -228,71 +248,54 @@ Module load order is determined by your `doom!' block. See `doom-modules-dirs' for a list of all recognized module trees. Order defines precedence (from most to least)." (when (or force-p (not doom-init-p)) - (when (and (or force-p noninteractive) - (file-exists-p doom-packages-file)) - (message "Deleting packages.el cache") - (delete-file doom-packages-file)) - (unless (load doom-packages-file 'noerror 'nomessage 'nosuffix) - ;; Ensure core folders exist, otherwise we get errors - (dolist (dir (list doom-local-dir doom-etc-dir doom-cache-dir doom-packages-dir)) - (unless (file-directory-p dir) - (make-directory dir t))) - ;; Ensure plugins have been initialized - (require 'package) - (setq package-activated-list nil - package--initialized nil) - (let (byte-compile-warnings) - (condition-case _ - (package-initialize) - ('error (package-refresh-contents) - (setq doom--refreshed-p t) - (package-initialize)))) - ;; Ensure core packages are installed - (when-let* ((core-packages (cl-remove-if #'package-installed-p doom-core-packages))) - (message "Installing core packages") - (unless doom--refreshed-p - (package-refresh-contents)) - (dolist (package core-packages) - (let ((inhibit-message t)) - (package-install package)) - (if (package-installed-p package) - (message "✓ Installed %s" package) - (error "✕ Couldn't install %s" package))) - (message "Installing core packages...done")) - (unless noninteractive - (add-hook 'doom-pre-init-hook #'doom|refresh-cache))) - ;; Load autoloads file - (doom-initialize-autoloads)) + ;; Set this to prevent infinite recursive calls to `doom-initialize' + (setq doom-init-p t) + ;; `doom-autoload-file' tells Emacs where to load all its autoloaded + ;; functions from. This includes everything in core/autoload/*.el and all + ;; the autoload files in your enabled modules. + (unless (doom-initialize-autoloads doom-autoload-file force-p) + (doom-ensure-core-directories) + (doom-ensure-packages-initialized force-p) + (doom-ensure-core-packages) + ;; Regenerate `doom-autoload-file', which tells Doom where to find all its + ;; module autoloaded functions. + (unless (or force-p noninteractive) + (doom//reload-doom-autoloads))) + ;; Loads `doom-package-autoload-file', which caches `load-path', + ;; `auto-mode-alist', `Info-directory-list', `doom-disabled-packages' and + ;; `package-activated-list'. A big reduction in startup time. + (unless (doom-initialize-autoloads doom-package-autoload-file force-p) + (unless (or force-p noninteractive) + (doom//reload-package-autoloads)))) ;; Initialize Doom core (unless noninteractive (require 'core-ui) (require 'core-editor) (require 'core-projects) - (require 'core-keybinds)) - ;; Bootstrap Doom - (unless doom-init-p + (require 'core-keybinds))) + +(defun doom-initialize-modules (&optional force-p) + "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 +non-nil." + (when (or force-p (not doom-init-modules-p)) + ;; Set `doom-init-modules-p' early, so `doom-pre-init-hook' won't infinitely + ;; recurse by accident if any of them need `doom-initialize-modules'. + (setq doom-init-modules-p t) (unless noninteractive - (add-hook! 'doom-reload-hook - #'(doom|refresh-cache doom|display-benchmark)) (add-hook! 'emacs-startup-hook #'(doom|post-init doom|display-benchmark))) (run-hooks 'doom-pre-init-hook) (when doom-private-dir - (load (concat doom-private-dir "init") t t))) - (setq doom-init-p t)) + (let ((load-prefer-newer t)) + (load (expand-file-name "init" doom-private-dir) + 'noerror 'nomessage))))) -(defun doom-initialize-autoloads () - "Tries to load `doom-autoload-file', otherwise throws an error (unless in a -noninteractive session)." - (unless - (condition-case-unless-debug e - (load (substring doom-autoload-file 0 -3) 'noerror 'nomessage) - (error - (funcall (if noninteractive #'warn #'error) - "Autoload error: %s -> %s" - (car e) (error-message-string e)))) - (unless noninteractive - (error "No autoloads file! Run make autoloads")))) +(defun doom-initialize-autoloads (file &optional clear-p) + "Tries to load FILE (an autoloads file). Otherwise tries to regenerate it. If +CLEAR-P is non-nil, regenerate it anyway." + (unless clear-p + (load (file-name-sans-extension file) 'noerror 'nomessage))) (defun doom-initialize-packages (&optional force-p) "Ensures that Doom's package management system, package.el and quelpa are @@ -306,8 +309,8 @@ Use this before any of package.el, quelpa or Doom's package management's API to ensure all the necessary package metadata is initialized and available for them." (with-temp-buffer ; prevent buffer-local settings from propagating - ;; Prefer uncompiled files to reduce stale code issues - (let ((load-prefer-newer t)) + (let ((load-prefer-newer t) ; reduce stale code issues + (doom-modules (doom-module-table))) ;; package.el and quelpa handle themselves if their state changes during ;; the current session, but if you change an packages.el file in a module, ;; there's no non-trivial way to detect that, so we give you a way to @@ -454,6 +457,37 @@ added, if the file exists." collect (plist-get plist :path)) (cl-remove-if-not #'file-directory-p doom-psuedo-module-dirs))) +(defun doom-module-table (&optional modules) + "Converts MODULES (a malformed plist) into a hash table of modules, fit for +`doom-modules'. If MODULES is omitted, it will fetch your module mplist from the +`doom!' block in your private init.el file." + (let* ((doom-modules (make-hash-table :test #'equal + :size (if modules (length modules) 100) + :rehash-threshold 1.0))) + (when (null modules) + (let ((init-file (expand-file-name "init.el" doom-private-dir))) + (if (not (file-exists-p init-file)) + (error "%s doesn't exist" (abbreviate-file-name init-file)) + (with-temp-buffer + (insert-file-contents init-file) + (when (re-search-forward "^\\s-*\\((doom! \\)" nil t) + (goto-char (match-beginning 1)) + (setq modules (cdr (sexp-at-point)))))) + (unless modules + (error "Couldn't gather module list from %s" init-file)))) + (if (eq modules t) (setq modules nil)) + (let (category) + (dolist (m modules) + (cond ((keywordp m) (setq category m)) + ((not category) (error "No module category specified for %s" m)) + ((let ((module (if (listp m) (car m) m)) + (flags (if (listp m) (cdr m)))) + (if-let* ((path (doom-module-locate-path category module))) + (doom-module-set category module :flags flags :path path) + (when doom-debug-mode + (message "Couldn't find the %s %s module" category module)))))))) + doom-modules)) + ;; ;; Use-package modifications @@ -506,25 +540,40 @@ added, if the file exists." (defmacro doom! (&rest modules) "Bootstraps DOOM Emacs and its modules. -MODULES is an malformed plist of modules to load." - (let (init-forms config-forms file-name-handler-alist) - (let (module) - (dolist (m modules) - (cond ((keywordp m) (setq module m)) - ((not module) (error "No namespace specified in `doom!' for %s" m)) - ((let ((submodule (if (listp m) (car m) m)) - (flags (if (listp m) (cdr m)))) - (let ((path (doom-module-locate-path module submodule))) - (if (not path) - (when doom-debug-mode - (message "Couldn't find the %s %s module" module submodule)) - (doom-module-set module submodule :flags flags :path path) - (push `(let ((doom--current-module ',(cons module submodule))) - (load! init ,path t)) - init-forms) - (push `(let ((doom--current-module ',(cons module submodule))) - (load! config ,path t)) - config-forms)))))))) +The bootstrap process involves making sure the essential directories exist, core +packages are installed, `doom-autoload-file' is loaded, `doom-packages-file' +cache exists (and is loaded) and, finally, loads your private init.el (which +should contain your `doom!' block). + +If the cache exists, much of this function isn't run, which substantially +reduces startup time. + +The overall load order of Doom is as follows: + + ~/.emacs.d/init.el + ~/.emacs.d/core/core.el + `doom-pre-init-hook' + ~/.doom.d/init.el + Module init.el files + `doom-init-hook' + Module config.el files + ~/.doom.d/config.el + `after-init-hook' + `emacs-startup-hook' + `doom-post-init-hook' (at end of `emacs-startup-hook') + +Module load order is determined by your `doom!' block. See `doom-modules-dirs' +for a list of all recognized module trees. Order defines precedence (from most +to least)." + (let ((doom-modules (doom-module-table (or modules t))) + init-forms config-forms file-name-handler-alist) + (maphash (lambda (key value) + (let ((path (plist-get value :path))) + (push `(let ((doom--current-module ',key)) (load! init ,path t)) + init-forms) + (push `(let ((doom--current-module ',key)) (load! config ,path t)) + config-forms))) + doom-modules) `(let (file-name-handler-alist) (setq doom-modules ',doom-modules) ,@(nreverse init-forms) @@ -533,8 +582,9 @@ MODULES is an malformed plist of modules to load." (let ((doom--stage 'config)) ,@(nreverse config-forms) (when doom-private-dir - (load ,(concat doom-private-dir "config") - t (not doom-debug-mode)))))))) + (let ((load-prefer-newer t)) + (load ,(expand-file-name "config" doom-private-dir) + t (not doom-debug-mode))))))))) (defmacro def-package! (name &rest plist) "A thin wrapper around `use-package'." diff --git a/core/core.el b/core/core.el index 3a504f5f9..bfe831b34 100644 --- a/core/core.el +++ b/core/core.el @@ -58,6 +58,20 @@ Use this for files that change often, like cache files.") "Where your private customizations are placed. Must end in a slash. Respects XDG directory conventions if ~/.config/doom exists.") +;; Doom hooks +(defvar doom-pre-init-hook nil + "Hooks run after Doom is first initialized; after Doom's core files are +loaded, but before your private init.el file or anything else is loaded.") + +(defvar doom-init-hook nil + "Hooks run after all init.el files are loaded, including your private and all +module init.el files, but before their config.el files are loaded.") + +(defvar doom-post-init-hook nil + "A list of hooks run when Doom is fully initialized. Fires at the end of +`emacs-startup-hook', as late as possible. Guaranteed to run after everything +else (except for `window-setup-hook').") + ;;; ;; UTF-8 as the default coding system @@ -106,22 +120,6 @@ XDG directory conventions if ~/.config/doom exists.") url-configuration-directory (concat doom-etc-dir "url/")) -;; Custom init hooks; clearer than `after-init-hook', `emacs-startup-hook', and -;; `window-setup-hook'. -(defvar doom-pre-init-hook nil - "Hooks run after Doom is first initialized; after Doom's core files are -loaded, but before your private init.el file or anything else is loaded.") - -(defvar doom-init-hook nil - "Hooks run after all init.el files are loaded, including your private and all -module init.el files, but before their config.el files are loaded.") - -(defvar doom-post-init-hook nil - "A list of hooks run when Doom is fully initialized. Fires at the end of -`emacs-startup-hook', as late as possible. Guaranteed to run after everything -else (except for `window-setup-hook').") - - ;; ;; Emacs fixes/hacks ;; @@ -163,7 +161,7 @@ with functions that require it (like modeline segments)." (advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename) ;; Truly silence startup message -(advice-add #'display-startup-echo-area-message :override #'ignore) +(fset #'display-startup-echo-area-message #'ignore) ;; @@ -202,8 +200,10 @@ this, you'll get stuttering and random freezes) and resets (require 'core-packages) (require 'core-os) -(unless noninteractive - (doom-initialize)) +(doom-initialize noninteractive) +(if noninteractive + (require 'core-dispatcher) + (doom-initialize-modules)) (provide 'core) ;;; core.el ends here diff --git a/init.el b/init.el index 497941f17..eda0e8894 100644 --- a/init.el +++ b/init.el @@ -31,5 +31,3 @@ load-prefer-newer noninteractive) (require 'core (concat user-emacs-directory "core/core")) -(when noninteractive - (require 'core-dispatcher)) From 3261f1fd710a09abd0f4f61ae76c9b84f02e3e3b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:03:36 +0200 Subject: [PATCH 073/132] Finalize core-dispatcher API + Add doom-auto-accept to replace YES envvar. + Add docstrings & documentation to all commands. + Make dispatcher support more than one alias. + Document quickstart command + Update autoloads/install/autoremove/update/refresh to fit new initialization workflows + Rename doom//info and doom//version + Recompile alias is now rc instead of cc + Improve reliability of doom//quickstart --- core/core-dispatcher.el | 163 +++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 69 deletions(-) diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index 70a71e5e4..861e58958 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -1,5 +1,8 @@ ;;; -*- lexical-binding: t; no-byte-compile: t; -*- +;; Eagerly load these libraries because this module may be loaded in a session +;; that hasn't been fully initialized (where autoloads files haven't been +;; generated or `load-path' populated). (load! autoload/packages) (load! autoload/modules) (load! autoload/debug) @@ -7,14 +10,16 @@ ;; -;; Dispatcher +;; Dispatcher API ;; -(defvar doom-dispatch-command-alist () - "TODO") +(defvar doom-auto-accept (getenv "YES") + "If non-nil, Doom will auto-accept any confirmation prompts during batch +commands like `doom//packages-install', `doom//packages-update' and +`doom//packages-autoremove'.") -(defvar doom-dispatch-alias-alist () - "TODO") +(defconst doom--dispatch-command-alist ()) +(defconst doom--dispatch-alias-alist ()) (defun doom--dispatch-format (desc &optional short) (if (equal desc "TODO") @@ -33,26 +38,29 @@ (line-end-position)))))) (defun doom--dispatch-help (&optional command desc &rest args) - "TODO" + "Display help documentation for a dispatcher command. If COMMAND and DESC are +omitted, show all available commands, their aliases and brief descriptions." (if command (princ (doom--dispatch-format desc)) (print! (bold "%-10s\t%s\t%s" "Command:" "Alias" "Description")) - (dolist (spec (sort doom-dispatch-command-alist + (dolist (spec (sort doom--dispatch-command-alist (lambda (x y) (string-lessp (car x) (car y))))) (cl-destructuring-bind (command &key desc _body) spec - (let ((alias (car (rassq command doom-dispatch-alias-alist)))) + (let ((aliases (cl-loop for (alias . cmd) in doom--dispatch-alias-alist + if (eq cmd command) + collect (symbol-name alias)))) (print! " %-10s\t%s\t%s" - command (or alias "") + command (if aliases (string-join aliases ",") "") (doom--dispatch-format desc t))))))) (defun doom-dispatch (args) - "TODO" + "Invoke a dispatcher command and pass ARGS to it." (let ((help (equal (car args) "help"))) (if help (pop args)) (cl-destructuring-bind (command &key desc body) (let ((sym (intern (car args)))) - (or (assq sym doom-dispatch-command-alist) - (assq (cdr (assq sym doom-dispatch-alias-alist)) doom-dispatch-command-alist) + (or (assq sym doom--dispatch-command-alist) + (assq (cdr (assq sym doom--dispatch-alias-alist)) doom--dispatch-command-alist) (error "Invalid command: %s" (car args)))) (if help (apply #'doom--dispatch-help command desc (cdr args)) @@ -60,18 +68,31 @@ ;; FIXME Clumsy way of registering commands, refactor! (defmacro def-dispatcher! (command desc &rest body) - "TODO" + "Define a dispatcher command. COMMAND is a symbol or a list of symbols +representing the aliases for this command. DESC is a string description. The +first line should be short (under 60 letters), as it will be displayed for +bin/doom help. + +BODY will be run when this dispatcher is called." (declare (doc-string 2)) (let* ((command (doom-enlist command)) (cmd (car command)) - (alias (car (cdr command)))) + (aliases (cdr command))) `(progn - ,(when alias - `(map-put doom-dispatch-alias-alist ',alias ',cmd)) - (map-put doom-dispatch-command-alist - ',cmd (list :desc ,desc :body (lambda (args) ,@body)))))) + ,(when aliases + `(dolist (alias ',aliases) + (map-put doom--dispatch-alias-alist alias ',cmd))) + (map-put doom--dispatch-command-alist + ',cmd (list :desc ,desc + ;; FIXME Implicit args var; ew + :body (lambda (args) ,@body)))))) + ;; +;; Dispatch commands +;; + +;; Dummy dispatchers (no-op because they're handled especially) (def-dispatcher! run "Run Doom Emacs from bin/doom's parent directory. @@ -80,8 +101,9 @@ All arguments are passed on to Emacs (except for -p and -e). doom run doom run -nw init.el -Warning, this is for convenience and testing purposes, Doom will not run its -best or fastest when started in this manner.") +WARNING: this command exists for convenience and testing. Doom will suffer +additional overhead for be started this way. For the best performance, it +is best to run Doom out of ~/.emacs.d and ~/.doom.d.") (def-dispatcher! (doctor doc) "Checks for issues with your current Doom config.") @@ -89,36 +111,43 @@ best or fastest when started in this manner.") (def-dispatcher! (help h) "Look up additional information about a command.") -;; -(def-dispatcher! quickstart - "TODO" - (doom//quickstart)) +;; Real dispatchers +(def-dispatcher! (quickstart qs) + "Quickly deploy a private module and Doom. + +This deploys a barebones config to ~/.doom.d. The destination can be changed +with the -p option, e.g. + + doom -p ~/.config/doom quickstart + +This command will refuse to overwrite the private directory if it already +exists." + (doom//quickstart args)) (def-dispatcher! (install i) "Installs requested plugins that aren't installed." - (doom-initialize) - (when (doom//packages-install) - (doom//reload-autoloads))) + (doom//reload-doom-autoloads) + (when (doom//packages-install doom-auto-accept) + (doom//reload))) (def-dispatcher! (update u) "Checks for and updates outdated plugins." - (doom-initialize) - (when (doom//packages-update) - (doom//reload-autoloads))) + (doom//reload-doom-autoloads) + (when (doom//packages-update doom-auto-accept) + (doom//reload))) (def-dispatcher! (autoremove r) "Removes orphaned plugins." - (doom-initialize) - (when (doom//packages-autoremove) - (doom//reload-autoloads))) + (doom//reload-doom-autoloads) + (when (doom//packages-autoremove doom-auto-accept) + (doom//reload))) (def-dispatcher! (autoloads a) "Regenerates Doom's autoloads file. This file tells Emacs where to find your module's autoloaded functions and plugins." - (doom-initialize) - (doom//reload-autoloads)) + (doom//reload-autoloads nil 'force)) (def-dispatcher! (upgrade up) "Checks out the latest Doom on this branch." @@ -136,7 +165,7 @@ to byte-compile Doom's core files, your private config or your ELPA plugins, respectively." (doom//byte-compile args)) -(def-dispatcher! (recompile cc) +(def-dispatcher! (recompile rc) "Re-byte-compiles outdated *.elc files." (doom//byte-compile args 'recompile)) @@ -151,14 +180,14 @@ respectively." (def-dispatcher! info "Output system info in markdown for bug reports." - (doom//info)) + (doom/info)) (def-dispatcher! (version v) "Reports the version of Doom and Emacs." - (doom//version)) + (doom/version)) (def-dispatcher! (refresh re) - "Refresh Doom. + "Refresh Doom. Same as autoremove+install+autoloads. This is the equivalent of running autoremove, install, autoloads, then recompile. Run this whenever you: @@ -167,26 +196,25 @@ recompile. Run this whenever you: 2. Add or remove `package!' blocks to your config, 3. Add or remove autoloaded functions in module autoloaded files. 4. Update Doom outside of Doom (e.g. with git)" - (doom-initialize) - (let (reload-p) - (when (let* ((doom--inhibit-reload t) - (autoremove-p (doom//packages-autoremove)) - (install-p (doom//packages-install))) - (or autoremove-p install-p)) - (doom//reload)) - (doom//byte-compile nil 'recompile))) + (if (let* ((doom--inhibit-reload t) + (autoremove-p (with-demoted-errors "%s" (doom//packages-autoremove))) + (install-p (with-demoted-errors "%s" (doom//packages-install)))) + (or autoremove-p install-p)) + (doom//reload) + (doom//reload-autoloads)) + (doom//byte-compile nil 'recompile)) ;; ;; Quality of Life Commands ;; +;; FIXME Detect & enforce remote (defvar doom-remote "origin" "TODO") (defun doom//upgrade () - "TODO" - (declare (interactive-only t)) + "Upgrade Doom to the latest version." (interactive) (let ((core-file (expand-file-name "init.el" doom-core-dir)) (branch (vc-git--symbolic-ref core-file)) @@ -210,8 +238,7 @@ recompile. Run this whenever you: (abbreviate-file-name doom-emacs-dir))) (if (equal current-rev rev) (message "Doom is up to date!") - - (when (or (getenv "YES") + (when (or doom-auto-accept (y-or-n-p "Doom is out of date, update?")) (unless (zerop (process-file "git" nil buf nil "checkout" (format "%s/%s" doom-remote branch))) @@ -223,33 +250,31 @@ recompile. Run this whenever you: (message "Done! Please restart Emacs for changes to take effect"))))))))) (defun doom//quickstart () - "TODO" + "Quickly deploy a private module and Doom. + +This deploys a barebones config to `doom-private-dir', installs all missing +packages and regenerates the autoloads file." (declare (interactive-only t)) (interactive) (let ((short-private-dir (abbreviate-file-name doom-private-dir))) - (when (file-directory-p doom-private-dir) - (error "%s already exists! Aborting." short-private-dir)) - (message "Creating %s directory" short-private-dir) - (make-directory doom-private-dir) + (unless (file-directory-p doom-private-dir) + (print! "Creating %s" short-private-dir) + (make-directory doom-private-dir t)) (let ((init-file (expand-file-name "init.el" doom-private-dir))) - (if (not (file-exists-p init-file)) - (message "%sinit.el already exists. Skipping.") - (message "Copying init.example.el to %s" short-private-dir) + (if (file-exists-p init-file) + (print! "%sinit.el already exists. Skipping." short-private-dir) + (print! "Copying init.example.el to %s" short-private-dir) (copy-file (expand-file-name "init.example.el" doom-emacs-dir) init-file))) (let ((config-file (expand-file-name "config.el" doom-private-dir))) (if (file-exists-p config-file) - (with-temp-file config-file - (insert "")) - (message "%sconfig.el already exists. Skipping.")))) - (doom-initialize) - (let* ((doom--inhibit-reload t) - (autoremove-p (doom//packages-autoremove)) - (install-p (doom//packages-install))) - (or autoremove-p install-p)) + (print! "%sconfig.el already exists. Skipping." short-private-dir) + (with-temp-file config-file (insert ""))))) + (print! "Installing plugins & generating autoloads file, if necessary") + (doom//packages-install) (doom//reload-autoloads) - (message "\n\nDone! Doom Emacs is ready.\n") - (message "Remember to run M-x all-the-icons-install-fonts after starting Emacs for the first time.")) + (print! "\n\nDone! Doom Emacs is ready.\n") + (print! "Remember to run M-x all-the-icons-install-fonts after starting Emacs for the first time.")) (provide 'core-dispatcher) ;;; core-dispatcher.el ends here From 6ea5430c4dc5e630f3d8e3bc2bf138f1f4714605 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:09:23 +0200 Subject: [PATCH 074/132] Fix doom//byte-compile --- core/autoload/modules.el | 139 +++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 71 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index ed8f162b1..5a886c028 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -269,95 +269,92 @@ these files. If RECOMPILE-P is non-nil, only recompile out-of-date files." (interactive (list nil current-prefix-arg)) - (let ((default-directory doom-emacs-dir) - (recompile-p (or recompile-p (and (member "-r" (cdr argv)) t))) - (argv (delete "-r" argv))) + (let ((default-directory doom-emacs-dir)) (unless recompile-p (doom//clean-byte-compiled-files)) (let ((total-ok 0) (total-fail 0) (total-noop 0) - (modules (or modules (cdr argv))) - compile-plugins - compile-targets) - ;; Ensure that Doom has been fully loaded, some of its state may be - ;; pertinent to files compiled later. - (let ((doom--stage 'compile) - noninteractive) - ;; Core libraries aren't fully loaded in a noninteractive session, so we - ;; pretend to be interactive and reinitialize - (doom-initialize)) + compile-plugins-p + targets) + (dolist (module (delete-dups modules) (nreverse targets)) + (pcase module + (":core" (push doom-core-dir targets)) + (":private" (push doom-private-dir targets)) + (":plugins" + (byte-recompile-directory package-user-dir 0 t) + (setq compile-plugins-p t)) + ((pred file-directory-p) + (push module targets)) + ((pred (string-match "^\\([^/]+\\)/\\([^/]+\\)$")) + (push (doom-module-locate-path + (intern (format ":%s" (match-string 1 module))) + (intern (match-string 2 module))) + targets)))) + (unless (equal modules (list ":plugins")) + (let ((inhibit-message t) + noninteractive) + ;; 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. + (doom//reload-autoloads) + (doom-initialize t) + (unless (equal modules (list ":core")) + (doom-initialize-modules t)))) + ;; If no targets were supplied, then we use your module list. + (unless targets + (setq targets (append (list doom-core-dir) + (doom-module-load-path)))) ;; Assemble el files we want to compile; taking into account that MODULES ;; may be a list of MODULE/SUBMODULE strings from the command line. - (setq - modules (or modules (append (list doom-core-dir) (doom-module-load-path))) - compile-targets - (cl-loop for target in modules - if (equal target ":core") - nconc (nreverse (doom-files-under doom-core-dir :match "\\.el$")) - and collect (expand-file-name "init.el" doom-private-dir) - if (equal target ":private") - nconc (nreverse (doom-files-under doom-private-dir :match "\\.el$")) - if (equal target ":plugins") - do (setq compile-plugins t) - else if (file-directory-p target) - nconc (nreverse (doom-files-under target :match "\\.el$")) - else if (cl-member target doom-psuedo-module-dirs :test #'file-in-directory-p) - nconc (nreverse (doom-files-under it :match "\\.el$")) - else if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" target) - nconc (nreverse (doom-files-under - (doom-module-locate-path - (intern (format ":%s" (match-string 1 target))) - (intern (match-string 2 target))) - :match "\\.el$")) - else if (file-exists-p target) - collect target - finally do (setq argv nil))) - (if compile-plugins - (byte-recompile-directory package-user-dir 0 t) - (if (not compile-targets) - (message "No targets to compile") + (let ((target-files (doom-files-in targets :depth 2 :match "\\.el$"))) + (if (not target-files) + (unless compile-plugins-p + (message "No targets to %scompile" (if recompile-p "re" ""))) (condition-case ex (let ((use-package-expand-minimally t)) - (push (expand-file-name "init.el" doom-emacs-dir) compile-targets) - (dolist (target (cl-delete-duplicates (mapcar #'file-truename compile-targets) :test #'equal)) - (when (or (not recompile-p) - (let ((elc-file (byte-compile-dest-file target))) - (and (file-exists-p elc-file) - (file-newer-than-file-p target elc-file)))) - (let ((result (cond ((string-match-p "/\\(packages\\|doctor\\)\\.el$" target) - 'no-byte-compile) - ((doom-file-cookie-p target) - (byte-compile-file target)) - ('no-byte-compile))) - (short-name (if (file-in-directory-p target doom-emacs-dir) - (file-relative-name target doom-emacs-dir) - (abbreviate-file-name target)))) - (cl-incf - (cond ((eq result 'no-byte-compile) - (print! (dark (white "⚠ Ignored %s" short-name))) - total-noop) - ((null result) - (print! (red "✕ Failed to compile %s" short-name)) - total-fail) - (t - (print! (green "✓ Compiled %s" short-name)) - (quiet! (load target t t)) - total-ok)))))) + ;; Always compile private init file + (cl-pushnew (expand-file-name "init.el" doom-private-dir) + target-files :test #'equal) + (cl-pushnew (expand-file-name "init.el" doom-emacs-dir) + target-files :test #'equal) + (dolist (target (cl-delete-duplicates (mapcar #'file-truename target-files) :test #'equal)) + (if (or (not recompile-p) + (let ((elc-file (byte-compile-dest-file target))) + (and (file-exists-p elc-file) + (file-newer-than-file-p target elc-file)))) + (let ((result (if (or (string-match-p "/\\(?:packages\\|doctor\\)\\.el$" target) + (not (doom-file-cookie-p target))) + 'no-byte-compile + (byte-compile-file target))) + (short-name (if (file-in-directory-p target doom-emacs-dir) + (file-relative-name target doom-emacs-dir) + (abbreviate-file-name target)))) + (cl-incf + (cond ((eq result 'no-byte-compile) + (print! (dark (white "⚠ Ignored %s" short-name))) + total-noop) + ((null result) + (print! (red "✕ Failed to compile %s" short-name)) + total-fail) + (t + (print! (green "✓ Compiled %s" short-name)) + (quiet! (load target t t)) + total-ok)))) + (cl-incf total-noop))) (print! (bold (color (if (= total-fail 0) 'green 'red) "%s %d/%d file(s) (%d ignored)" (if recompile-p "Recompiled" "Compiled") - total-ok (- (length compile-targets) total-noop) + total-ok (- (length target-files) total-noop) total-noop)))) (error (print! (red "\n%%s\n\n%%s\n\n%%s") - "There were breaking errors." - (error-message-string ex) - "Reverting changes...") + "There were breaking errors." + (error-message-string ex) + "Reverting changes...") (quiet! (doom//clean-byte-compiled-files)) - (print! (green "Finished (nothing was byte-compiled)"))))))))) + (print! (yellow "Finished (nothing was byte-compiled)"))))))))) ;;;###autoload (defun doom//clean-byte-compiled-files () From b629f4f50765caaea1939a1fb75e39ddda7898e2 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:09:29 +0200 Subject: [PATCH 075/132] Fix doom//clean-byte-compiled-files --- core/autoload/modules.el | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index 5a886c028..c5bcec55c 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -358,19 +358,20 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files." ;;;###autoload (defun doom//clean-byte-compiled-files () - "Delete all the compiled elc files in your Emacs configuration. This excludes -compiled packages.'" + "Delete all the compiled elc files in your Emacs configuration and private +module. This does not include your byte-compiled, third party packages.'" (interactive) (cl-loop with default-directory = doom-emacs-dir - for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$") - (doom-files-in doom-psuedo-module-dirs :match "\\.elc$" :full t) - (doom-files-under doom-core-dir :match "\\.elc$") - (doom-files-under doom-modules-dirs :match "\\.elc$")) + for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$" :depth 1) + (doom-files-in doom-psuedo-module-dirs :match "\\.elc$" :depth 1) + (doom-files-in doom-core-dir :match "\\.elc$") + (doom-files-in doom-modules-dirs :match "\\.elc$" :depth 4)) for truepath = (file-truename path) + if (file-exists-p path) do (delete-file path) and do - (message "✓ Deleted %s" - (if (file-in-directory-p truepath default-directory) - (file-relative-name truepath) - (abbreviate-file-name path))) - finally do (message "Everything is clean"))) + (print! (green "✓ Deleted %%s") + (if (file-in-directory-p truepath default-directory) + (file-relative-name truepath) + (abbreviate-file-name truepath))) + finally do (print! (bold (green "Everything is clean"))))) From 87e9365a41630fda5d4fd01ec9ecb94f31a865ab Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:10:29 +0200 Subject: [PATCH 076/132] Fix package autoremove/install/update batch commands --- core/autoload/packages.el | 305 +++++++++++++++++++------------------- 1 file changed, 152 insertions(+), 153 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 849816193..a94da7b7f 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -329,159 +329,6 @@ package.el as appropriate." t))) -;; -;; Batch/interactive commands -;; - -;;;###autoload -(defun doom//packages-install () - "Interactive command for installing missing packages." - (interactive) - (doom-initialize-packages) - (print! "Looking for packages to install...") - (let ((packages (reverse (doom-get-missing-packages)))) - (cond ((not packages) - (print! (green "No packages to install!")) - nil) - - ((not (or (getenv "YES") - (y-or-n-p - (format "%s packages will be installed:\n\n%s\n\nProceed?" - (length packages) - (mapconcat - (lambda (pkg) - (format "+ %s (%s)" - (car pkg) - (cond ((doom-package-different-recipe-p (car pkg)) - "new recipe") - ((doom-package-different-backend-p (car pkg)) - (if (plist-get (cdr pkg) :recipe) - "ELPA -> QUELPA" - "QUELPA -> ELPA")) - ((plist-get (cdr pkg) :recipe) - "QUELPA") - (t - "ELPA")))) - (cl-sort (cl-copy-list packages) #'string-lessp - :key #'car) - "\n"))))) - (error "Aborted!")) - - ((let (success) - (doom-refresh-packages-maybe doom-debug-mode) - (dolist (pkg packages) - (print! "Installing %s" (car pkg)) - (doom--condition-case! - (print! "%s%s" - (if (and (package-installed-p (car pkg)) - (not (doom-package-different-backend-p (car pkg))) - (not (doom-package-different-recipe-p (car pkg)))) - (dark (white "⚠ ALREADY INSTALLED")) - (condition-case e - (if (doom-install-package (car pkg) (cdr pkg)) - (prog1 (green "✓ DONE") - (setq success t)) - (red "✕ FAILED")) - (error - (red "✕ ERROR (%s)" e)))) - (if (plist-member (cdr pkg) :pin) - (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) - "")))) - (print! (bold (green "Finished!"))) - (doom//reload) - success))))) - -;;;###autoload -(defun doom//packages-update () - "Interactive command for updating packages." - (interactive) - (doom-initialize-packages) - (print! "Looking for outdated packages...") - (doom-refresh-packages-maybe doom-debug-mode) - (let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp - :key #'car))) - (cond ((not packages) - (print! (green "Everything is up-to-date")) - nil) - - ((not (or (getenv "YES") - (y-or-n-p - (format "%s packages will be updated:\n\n%s\n\nProceed?" - (length packages) - (let ((max-len - (or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages) - #'>)) - 10))) - (mapconcat - (lambda (pkg) - (format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14) - (symbol-name (car pkg)) - (package-version-join (cadr pkg)) - (package-version-join (cl-caddr pkg)))) - packages - "\n")))))) - (error "Aborted!")) - - ((let (success) - (dolist (pkg packages) - (print! "Updating %s" (car pkg)) - (doom--condition-case! - (print! - (let ((result (doom-update-package (car pkg) t))) - (when result (setq success t)) - (color (if result 'green 'red) - (if result "✓ DONE" "✕ FAILED")))))) - (print! (bold (green "Finished!"))) - (doom//reload) - success))))) - -;;;###autoload -(defun doom//packages-autoremove () - "Interactive command for auto-removing orphaned packages." - (interactive) - (doom-initialize-packages) - (print! "Looking for orphaned packages...") - (let ((packages (doom-get-orphaned-packages))) - (cond ((not packages) - (print! (green "No unused packages to remove")) - nil) - - ((not - (or (getenv "YES") - (y-or-n-p - (format - "%s packages will be deleted:\n\n%s\n\nProceed?" - (length packages) - (mapconcat - (lambda (sym) - (format "+ %s (%s)" sym - (let ((backend (doom-package-backend sym))) - (if (doom-package-different-backend-p sym) - (pcase backend - (`quelpa "QUELPA->ELPA") - (`elpa "ELPA->QUELPA") - (_ "removed")) - (upcase (symbol-name backend)))))) - (sort (cl-copy-list packages) #'string-lessp) - "\n"))))) - (error "Aborted!")) - - ((let (success) - (dolist (pkg packages) - (doom--condition-case! - (print! - (let ((result (doom-delete-package pkg t))) - (when result (setq success t)) - (color (if result 'green 'red) - "%s %s" - (if result "✓ Removed" "✕ Failed to remove") - pkg))))) - - (print! (bold (green "Finished!"))) - (doom//reload) - success))))) - - ;; ;; Interactive commands ;; @@ -531,3 +378,155 @@ calls." (when (file-exists-p path) (delete-directory path t)))))) + +;; +;; Package Management +;; + +;;;###autoload +(defun doom//packages-install (&optional auto-accept-p) + "Interactive command for installing missing packages." + (interactive "P") + (doom-initialize-packages) + (print! "Looking for packages to install...") + (let ((packages (reverse (doom-get-missing-packages)))) + (cond ((not packages) + (print! (green "No packages to install!")) + nil) + + ((not (or auto-accept-p + (y-or-n-p + (format "%s packages will be installed:\n\n%s\n\nProceed?" + (length packages) + (mapconcat + (lambda (pkg) + (format "+ %s (%s)" + (car pkg) + (cond ((doom-package-different-recipe-p (car pkg)) + "new recipe") + ((doom-package-different-backend-p (car pkg)) + (if (plist-get (cdr pkg) :recipe) + "ELPA -> QUELPA" + "QUELPA -> ELPA")) + ((plist-get (cdr pkg) :recipe) + "QUELPA") + (t + "ELPA")))) + (cl-sort (cl-copy-list packages) #'string-lessp + :key #'car) + "\n"))))) + (error "Aborted!")) + + ((let (success) + (doom-refresh-packages-maybe doom-debug-mode) + (dolist (pkg packages) + (print! "Installing %s" (car pkg)) + (doom--condition-case! + (print! "%s%s" + (if (and (package-installed-p (car pkg)) + (not (doom-package-different-backend-p (car pkg))) + (not (doom-package-different-recipe-p (car pkg)))) + (dark (white "⚠ ALREADY INSTALLED")) + (condition-case e + (if (doom-install-package (car pkg) (cdr pkg)) + (prog1 (green "✓ DONE") + (setq success t)) + (red "✕ FAILED")) + (error + (red "✕ ERROR (%s)" e)))) + (if (plist-member (cdr pkg) :pin) + (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) + "")))) + (print! (bold (green "Finished!"))) + (if success (doom-delete-autoloads-file doom-package-autoload-file)) + success))))) + +;;;###autoload +(defun doom//packages-update (&optional auto-accept-p) + "Interactive command for updating packages." + (interactive "P") + (doom-initialize-packages) + (print! "Looking for outdated packages...") + (doom-refresh-packages-maybe doom-debug-mode) + (let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp + :key #'car))) + (cond ((not packages) + (print! (green "Everything is up-to-date")) + nil) + + ((not (or auto-accept-p + (y-or-n-p + (format "%s packages will be updated:\n\n%s\n\nProceed?" + (length packages) + (let ((max-len + (or (car (sort (mapcar (lambda (it) (length (symbol-name (car it)))) packages) + #'>)) + 10))) + (mapconcat + (lambda (pkg) + (format (format "+ %%-%ds %%-%ds -> %%s" (+ max-len 2) 14) + (symbol-name (car pkg)) + (package-version-join (cadr pkg)) + (package-version-join (cl-caddr pkg)))) + packages + "\n")))))) + (error "Aborted!")) + + ((let (success) + (dolist (pkg packages) + (print! "Updating %s" (car pkg)) + (doom--condition-case! + (print! + (let ((result (doom-update-package (car pkg) t))) + (when result (setq success t)) + (color (if result 'green 'red) + (if result "✓ DONE" "✕ FAILED")))))) + (print! (bold (green "Finished!"))) + (if success (doom-delete-autoloads-file doom-package-autoload-file)) + success))))) + +;;;###autoload +(defun doom//packages-autoremove (&optional auto-accept-p) + "Interactive command for auto-removing orphaned packages." + (interactive "P") + (doom-initialize-packages) + (print! "Looking for orphaned packages...") + (let ((packages (doom-get-orphaned-packages))) + (cond ((not packages) + (print! (green "No unused packages to remove")) + nil) + + ((not + (or auto-accept-p + (y-or-n-p + (format + "%s packages will be deleted:\n\n%s\n\nProceed?" + (length packages) + (mapconcat + (lambda (sym) + (format "+ %s (%s)" sym + (let ((backend (doom-package-backend sym))) + (if (doom-package-different-backend-p sym) + (pcase backend + (`quelpa "QUELPA->ELPA") + (`elpa "ELPA->QUELPA") + (_ "removed")) + (upcase (symbol-name backend)))))) + (sort (cl-copy-list packages) #'string-lessp) + "\n"))))) + (error "Aborted!")) + + ((let (success) + (dolist (pkg packages) + (doom--condition-case! + (print! + (let ((result (doom-delete-package pkg t))) + (when result (setq success t)) + (color (if result 'green 'red) + "%s %s" + (if result "✓ Removed" "✕ Failed to remove") + pkg))))) + + (print! (bold (green "Finished!"))) + (if success (doom-delete-autoloads-file doom-package-autoload-file)) + success))))) From 18a6df5e6f96b7ea9c2cfb119baae15352d27818 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:11:33 +0200 Subject: [PATCH 077/132] Fix doom/info --- core/autoload/debug.el | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 586c0dc20..82a7d9424 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -15,7 +15,8 @@ ready to be pasted in a bug report on github." (doom-initialize) (require 'vc-git) - (let ((default-directory doom-emacs-dir)) + (let ((default-directory doom-emacs-dir) + (doom-modules (doom-module-table))) (format (concat "- OS: %s (%s)\n" "- Emacs: %s (%s)\n" @@ -64,11 +65,11 @@ ready to be pasted in a bug report on github." (async-get (async-start `(lambda () - (setq load-path ',load-path) - (load ,(expand-file-name "core/core.el" doom-emacs-dir)) - (load ,(expand-file-name "init.el" doom-emacs-dir)) - (load ,(expand-file-name "core/autoload/packages.el" doom-emacs-dir)) - (doom-get-packages)) + (let ((noninteractive t) + (load-path ',load-path) + (package-alist ',package-alist)) + (load ,(expand-file-name "init.el" doom-emacs-dir)) + (doom-get-packages))) (lambda (p) (setq packages p)))) (cl-loop for pkg in (cl-sort packages #'string-lessp :key (lambda (x) (symbol-name (car x)))) From 6dc375a8916bbf83be071df7cce63bf76b9a6ed7 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 19:12:36 +0200 Subject: [PATCH 078/132] Fix catch-all text-mode entry in auto-mode-alist This indirectly fixes an issue where the elfeed db was opened in text-mode, triggering the large-file check. --- core/core-editor.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-editor.el b/core/core-editor.el index b4984600d..491c50001 100644 --- a/core/core-editor.el +++ b/core/core-editor.el @@ -70,7 +70,7 @@ fundamental-mode) for performance sake." ;; Built-in plugins ;; -(push '("/[A-Z]+$" . text-mode) auto-mode-alist) +(push '("/LICENSE\\'" . text-mode) auto-mode-alist) (electric-indent-mode -1) ; enabled by default in Emacs 25+. No thanks. From 2a8da07e31c129227ff24ea9afea455963543949 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:14:40 +0200 Subject: [PATCH 079/132] Rename autoload-debug.el test to autoload-help.el --- core/test/{autoload-debug.el => autoload-help.el} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core/test/{autoload-debug.el => autoload-help.el} (94%) diff --git a/core/test/autoload-debug.el b/core/test/autoload-help.el similarity index 94% rename from core/test/autoload-debug.el rename to core/test/autoload-help.el index 062a16de5..262f8fecb 100644 --- a/core/test/autoload-debug.el +++ b/core/test/autoload-help.el @@ -1,5 +1,5 @@ ;; -*- no-byte-compile: t; -*- -;;; core/test/autoload-debug.el +;;; core/test/autoload-help.el (def-test! what-face (insert (propertize "Hello " 'face 'font-lock-keyword-face)) From b70ed84a3312725c47f2d2177d534e99941cee70 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:15:44 +0200 Subject: [PATCH 080/132] Fix doom//run-tests --- core/autoload/test.el | 57 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/core/autoload/test.el b/core/autoload/test.el index 431fe0111..0a65a6c33 100644 --- a/core/autoload/test.el +++ b/core/autoload/test.el @@ -7,43 +7,46 @@ command line args following a double dash (each arg should be in the If neither is available, run all tests in all enabled modules." (interactive) + (doom//reload-autoloads) (let (noninteractive) ;; Core libraries aren't fully loaded in a noninteractive session, so we ;; reload it with `noninteractive' set to nil to force them to. - (doom-initialize)) + (doom-initialize t) + (doom-initialize-modules t)) (condition-case-unless-debug ex - (let ((target-paths - ;; Convert targets (either from MODULES or `argv') into a list of - ;; string paths, pointing to the root directory of modules - (cond ((stringp (car modules)) ; command line - (save-match-data - (cl-loop for arg in modules - if (string= arg "core") collect doom-core-dir - else if (string-match-p "/" arg) - nconc (cl-loop for dir in doom-modules-dirs - collect (expand-file-name arg dir)) - else - nconc (cl-loop for dir in doom-modules-dirs - for path = (expand-file-name arg dir) - if (file-directory-p path) - nconc - (cl-remove-if-not - #'file-directory-p - (directory-files path t "^[^.]" t))) - finally do (setq argv nil)))) + (let* ((doom-modules (doom-module-table)) + (target-paths + ;; Convert targets (either from MODULES or `argv') into a list of + ;; string paths, pointing to the root directory of modules + (cond ((stringp (car modules)) ; command line + (save-match-data + (cl-loop for arg in modules + if (string= arg ":core") collect doom-core-dir + else if (string-match-p "/" arg) + nconc (cl-loop for dir in doom-modules-dirs + collect (expand-file-name arg dir)) + else + nconc (cl-loop for dir in doom-modules-dirs + for path = (expand-file-name arg dir) + if (file-directory-p path) + nconc + (cl-remove-if-not + #'file-directory-p + (directory-files path t "^[^.]" t))) + finally do (setq argv nil)))) - (modules ; cons-cells given to MODULES - (cl-loop for (module . submodule) in modules - if (doom-module-locate-path module submodule) - collect it)) + (modules ; cons-cells given to MODULES + (cl-loop for (module . submodule) in modules + if (doom-module-locate-path module submodule) + collect it)) - ((append (list doom-core-dir) - (doom-module-load-path)))))) + ((append (list doom-core-dir) + (doom-module-load-path)))))) ;; Load all the unit test files... (dolist (path target-paths) (let ((test-path (expand-file-name "test/" path))) (when (file-directory-p test-path) - (dolist (test-file (reverse (doom-files-under test-path :match "\\.el$"))) + (dolist (test-file (reverse (doom-files-in test-path :match "\\.el$" :full t))) (load test-file nil :noerror))))) ;; ... then run them (switch-to-buffer (get-buffer-create "*blank*")) From ea86b1075fad7cae57d37841e9c2b8f6da538e8e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:15:54 +0200 Subject: [PATCH 081/132] Fix doom-template-exists-p --- core/autoload/debug.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 82a7d9424..f53e5b33d 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -2,7 +2,9 @@ (defun doom-template-exists-p (template) "TODO" - (file-exists-p (expand-file-name "templates/" doom-core-dir))) + (file-exists-p + (expand-file-name (format "templates/%s" template) + doom-core-dir))) (defun doom-template-insert (template) "TODO" From 8282280965275c602805073971b60035974cb8b8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:17:23 +0200 Subject: [PATCH 082/132] core-packages: revise docstrings & comments --- core/core-packages.el | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 08b4f89e4..19c1746de 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -1,17 +1,17 @@ ;;; core-packages.el --- package management system -*- lexical-binding: t; -*- -;; Emacs package management is opinionated. Unfortunately, so am I. I've bound -;; together `use-package', `quelpa' and package.el to create my own, -;; rolling-release, lazily-loaded package management system for Emacs. +;; Emacs package management is opinionated, and so am I. I've bound together +;; `use-package', `quelpa' and package.el to create my own, rolling-release, +;; lazily-loaded package management system for Emacs. ;; ;; The three key commands are: ;; -;; + `make install` or `doom//packages-install': Installs packages that are +;; + `bin/doom install` or `doom//packages-install': Installs packages that are ;; wanted, but not installed. -;; + `make update` or `doom//packages-update': Updates packages that are +;; + `bin/doom update` or `doom//packages-update': Updates packages that are ;; out-of-date. -;; + `make autoremove` or `doom//packages-autoremove': Uninstalls packages that -;; are no longer needed. +;; + `bin/doom autoremove` or `doom//packages-autoremove': Uninstalls packages +;; that are no longer needed. ;; ;; This system reads packages.el files located in each activated module (and one ;; in `doom-core-dir'). These contain `package!' blocks that tell DOOM what @@ -164,8 +164,8 @@ If RETURN-P, return the message as a string instead of displaying it." (run-hooks 'doom-post-init-hook)) (defun doom|run-all-startup-hooks () - "Run all startup Emacs hooks. Meant to follow running Emacs in a vanilla -session, with a different init.el, like so: + "Run all startup Emacs hooks. Meant to be executed after starting Emacs with +-q or -Q, for example: emacs -Q -l init.el -f doom|run-all-startup-hooks" (run-hooks 'after-init-hook 'delayed-warnings-hook @@ -495,6 +495,15 @@ added, if the file exists." (autoload 'use-package "use-package-core" nil 'macro) +;; Adds the :after-call custom keyword to `use-package' (and consequently, +;; `def-package!'). :after-call takes a symbol ro list of symbols. These symbols +;; can be functions to hook variables. +;; +;; (use-package X :after-call find-file-hook) +;; +;; This will load X on the first invokation of `find-file-hook' (then it will +;; remove itself from the hook). +(defvar doom--deferred-packages-alist ()) (after! use-package-core (add-to-list 'use-package-deferring-keywords :after-call nil #'eq) @@ -504,9 +513,6 @@ added, if the file exists." (defalias 'use-package-normalize/:after-call 'use-package-normalize-symlist) - (defvar doom--deferred-packages-alist () - "TODO") - (defun use-package-handler/:after-call (name-symbol _keyword hooks rest state) (let ((fn (intern (format "doom|transient-hook--load-%s" name-symbol))) (hooks (delete-dups hooks))) From 30893b0ff1d8ec80fae7a96152ff998b1610c6bd Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:17:35 +0200 Subject: [PATCH 083/132] Fix doom-initialize-packages --- core/core-packages.el | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 19c1746de..f91ee5e1d 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -316,28 +316,28 @@ them." ;; there's no non-trivial way to detect that, so we give you a way to ;; reload only doom-packages (by passing 'internal as FORCE-P). ;; `doom-packages' + (unless (eq force-p 'internal) + ;; `package-alist' + (when (or force-p (not (bound-and-true-p package-alist))) + (setq load-path doom-site-load-path) + (require 'package) + (setq package-activated-list nil + package--initialized nil) + (let (byte-compile-warnings) + (condition-case _ + (quiet! (package-initialize)) + ('error (package-refresh-contents) + (setq doom--refreshed-p t) + (package-initialize))))) + + ;; `quelpa-cache' + (when (or force-p (not (bound-and-true-p quelpa-cache))) + (require 'quelpa) + (setq quelpa-initialized-p nil) + (or (quelpa-setup-p) + (error "Could not initialize quelpa")))) + (when (or force-p (not doom-packages)) - (unless (eq force-p 'internal) - ;; `package-alist' - (when (or force-p (not (bound-and-true-p package-alist))) - (setq load-path doom-site-load-path) - (require 'package) - (setq package-activated-list nil - package--initialized nil) - (let (byte-compile-warnings) - (condition-case _ - (package-initialize) - ('error (package-refresh-contents) - (setq doom--refreshed-p t) - (package-initialize))))) - - ;; `quelpa-cache' - (when (or force-p (not (bound-and-true-p quelpa-cache))) - (require 'quelpa) - (setq quelpa-initialized-p nil) - (or (quelpa-setup-p) - (error "Could not initialize quelpa")))) - (setq doom-packages nil) (cl-flet ((_load From 9e07940b7ce386e22e68fb9f364f9c768c0a3c1c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:17:45 +0200 Subject: [PATCH 084/132] Fix use-package autoload --- core/core-packages.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-packages.el b/core/core-packages.el index f91ee5e1d..b258e1ece 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -493,7 +493,7 @@ added, if the file exists." ;; Use-package modifications ;; -(autoload 'use-package "use-package-core" nil 'macro) +(autoload 'use-package "use-package-core" nil nil t) ;; Adds the :after-call custom keyword to `use-package' (and consequently, ;; `def-package!'). :after-call takes a symbol ro list of symbols. These symbols From d35598520f8e917a8bda245eb36285bacc2a01d3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:18:00 +0200 Subject: [PATCH 085/132] Only package-initialize if uninitialized (from package.el API advice) --- core/core-packages.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/core-packages.el b/core/core-packages.el index b258e1ece..5f70d6396 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -809,7 +809,9 @@ loads MODULE SUBMODULE's packages.el file." ;; Make package.el cooperate with Doom ;; -(defun doom*initialize-packages (&rest _) (package-initialize)) +(defun doom*initialize-packages (&rest _) + (unless package--initialized + (package-initialize))) (advice-add #'package-delete :before #'doom*initialize-packages) (advice-add #'package-install :before #'doom*initialize-packages) From a55e2251e65c4a9df105102120fc16e88613e64f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:18:42 +0200 Subject: [PATCH 086/132] auto-mode-case-fold = nil This disables the case insensitive second pass through auto-mode-alist on case sensitive systems. --- core/core.el | 1 + 1 file changed, 1 insertion(+) diff --git a/core/core.el b/core/core.el index bfe831b34..389004d16 100644 --- a/core/core.el +++ b/core/core.el @@ -90,6 +90,7 @@ else (except for `window-setup-hook').") debug-on-error doom-debug-mode ffap-machine-p-known 'reject ; don't ping things that look like domain names idle-update-delay 2 ; update ui less often + auto-mode-case-fold nil ;; be quiet at startup; don't load or display anything unnecessary inhibit-startup-message t inhibit-startup-echo-area-message user-login-name From dea7c107717c19e05c185c2d4ee9c067373ab552 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 21:20:39 +0200 Subject: [PATCH 087/132] Don't do naive path concatenation for private custom-theme-directory --- core/core-ui.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-ui.el b/core/core-ui.el index f6f7faa5f..8231627cd 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -57,7 +57,7 @@ with `doom//reload-theme').") compilation-scroll-output 'first-error confirm-nonexistent-file-or-buffer t cursor-in-non-selected-windows nil ; hide cursors in other windows - custom-theme-directory (concat doom-private-dir "themes/") + custom-theme-directory (expand-file-name "themes/" doom-private-dir) display-line-numbers-width 3 enable-recursive-minibuffers nil frame-inhibit-implied-resize t From 7c611df6a6dd3d56aa8820bdf5205be0d17a3b62 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:01:26 +0200 Subject: [PATCH 088/132] Have doom//reload return t on success --- core/autoload/modules.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index c5bcec55c..462cf6411 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -35,7 +35,8 @@ init.el and config.el. Then runs `doom-reload-hook'." (doom-initialize t) (doom-initialize-modules t) (print! (green "%d packages reloaded" (length package-alist))) - (run-hooks 'doom-reload-hook)))))) + (run-hooks 'doom-reload-hook) + t))))) ;; From 0b48575c1462f1c9bfa871005dd6de7760457792 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:03:17 +0200 Subject: [PATCH 089/132] Remove def-hydra! macro alias Causes byte-compilation issues and the alias is unnecessary. --- core/core-keybinds.el | 10 +++------- core/core-ui.el | 1 + modules/completion/ivy/config.el | 2 +- modules/feature/version-control/+git.el | 2 +- modules/feature/version-control/config.el | 10 +++++----- modules/tools/ein/config.el | 2 +- modules/tools/rgb/config.el | 2 +- 7 files changed, 13 insertions(+), 16 deletions(-) diff --git a/core/core-keybinds.el b/core/core-keybinds.el index 0a3495720..3d9e1ed57 100644 --- a/core/core-keybinds.el +++ b/core/core-keybinds.el @@ -60,15 +60,11 @@ If any hook returns non-nil, all hooks after it are ignored.") (def-package! hydra - :commands (defhydra defhydradio) - :init - ;; In case I later need to wrap defhydra in any special functionality. - (defalias 'def-hydra! 'defhydra) - (defalias 'def-hydra-radio! 'defhydradio) + :defer t :config (setq lv-use-seperator t) - (def-hydra! doom@text-zoom (:hint t :color red) + (defhydra doom@text-zoom (:hint t :color red) " Text zoom: _j_:zoom in, _k_:zoom out, _0_:reset " @@ -76,7 +72,7 @@ If any hook returns non-nil, all hooks after it are ignored.") ("k" text-scale-decrease "out") ("0" (text-scale-set 0) "reset")) - (def-hydra! doom@window-nav (:hint nil) + (defhydra doom@window-nav (:hint nil) " Split: _v_ert _s_:horz Delete: _c_lose _o_nly diff --git a/core/core-ui.el b/core/core-ui.el index 8231627cd..438dc515b 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -24,6 +24,7 @@ Expects a `font-spec'.") return a string). This changes the 'long' name of a major-mode, allowing for shorter major mode name in the mode-line. See `doom|set-mode-name'.") +;; (defvar doom-init-ui-hook nil "List of hooks to run when the UI has been initialized.") diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index 60a201d32..51434fb26 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -141,7 +141,7 @@ immediately runs it on the current candidate (ending the ivy session)." "C-o" #'+ivy@coo/body "M-o" #'ivy-dispatching-done-hydra) :config - (def-hydra! +ivy@coo (:hint nil :color pink) + (defhydra +ivy@coo (:hint nil :color pink) " Move ^^^^^^^^^^ | Call ^^^^ | Cancel^^ | Options^^ | Action _w_/_s_/_a_: %s(ivy-action-name) ----------^^^^^^^^^^-+--------------^^^^-+-------^^-+--------^^-+--------------------------------- diff --git a/modules/feature/version-control/+git.el b/modules/feature/version-control/+git.el index cbb110f5f..88d610089 100644 --- a/modules/feature/version-control/+git.el +++ b/modules/feature/version-control/+git.el @@ -33,7 +33,7 @@ (ignore (git-gutter)))) (add-hook 'doom-escape-hook #'+version-control|update-git-gutter t)) - (def-hydra! +version-control@git-gutter + (defhydra +version-control@git-gutter (:body-pre (git-gutter-mode 1) :hint nil) " ╭─────────────────┐ diff --git a/modules/feature/version-control/config.el b/modules/feature/version-control/config.el index 4a2a9791d..d49a806b1 100644 --- a/modules/feature/version-control/config.el +++ b/modules/feature/version-control/config.el @@ -28,11 +28,11 @@ (defalias #'smerge-diff-upper-lower #'smerge-diff-mine-other) (defalias #'smerge-diff-base-lower #'smerge-diff-base-other))) - (def-hydra! +hydra-smerge (:hint nil - :pre (smerge-mode 1) - ;; Disable `smerge-mode' when quitting hydra if - ;; no merge conflicts remain. - :post (smerge-auto-leave)) + (defhydra +hydra-smerge (:hint nil + :pre (smerge-mode 1) + ;; Disable `smerge-mode' when quitting hydra if + ;; no merge conflicts remain. + :post (smerge-auto-leave)) " ╭────────┐ Movement Keep Diff Other │ smerge │ diff --git a/modules/tools/ein/config.el b/modules/tools/ein/config.el index 5633bf690..812e815a5 100644 --- a/modules/tools/ein/config.el +++ b/modules/tools/ein/config.el @@ -45,7 +45,7 @@ ;; Avy is required for showing links in the notebook list with ace-link. (require 'avy) ;; add hydra - (def-hydra! +ein/hydra (:hint t :color red) + (defhydra +ein/hydra (:hint t :color red) " Operations on Cells^^^^^^ Other ----------------------------^^^^^^ ----------------------------------^^^^ diff --git a/modules/tools/rgb/config.el b/modules/tools/rgb/config.el index b69768ce7..ffab008eb 100644 --- a/modules/tools/rgb/config.el +++ b/modules/tools/rgb/config.el @@ -10,7 +10,7 @@ (def-package! kurecolor :after rainbow-mode :config - (def-hydra! +rgb@kurecolor (:color pink :hint nil) + (defhydra +rgb@kurecolor (:color pink :hint nil) " Inc/Dec _w_/_W_ brightness _d_/_D_ saturation _e_/_E_ hue " ("w" kurecolor-decrease-brightness-by-step) From 4c73ac01117b1d6ef67beac9c1c50cb915729dbb Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:12:32 +0200 Subject: [PATCH 090/132] config/default: Fix evil-collection anti-hacks #604 --- modules/config/default/+bindings.el | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 2d4f221a3..9b2ef077d 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -772,14 +772,16 @@ ;; Evil-collection fixes ;; -(when (featurep 'evil-collection) - (defun +config|deal-with-evil-collections-bs (_feature keymaps) - "Unmap keys that conflict with Doom's defaults." - (dolist (map keymaps) - (evil-define-key '(normal visual motion) map - doom-leader-key nil - "C-j" nil "C-k" nil - "gd" nil "gf" nil - "K" nil - "]" nil "[" nil))) - (add-hook 'evil-collection-setup-hook #'+config|deal-with-evil-collections-bs)) +(defun +config|deal-with-evil-collections-bs (_feature keymaps) + "Unmap keys that conflict with Doom's defaults." + (dolist (map keymaps) + (evil-delay `(and (boundp ',map) (keymapp ,map)) + `(evil-define-key* '(normal visual motion) ,map + (kbd doom-leader-key) nil + (kbd "C-j") nil (kbd "C-k") nil + "gd" nil "gf" nil "K" nil + "]" nil "[" nil) + 'after-load-functions t nil + (format "+default-redefine-key-in-%s" map)))) + +(add-hook 'evil-collection-setup-hook #'+config|deal-with-evil-collections-bs) From b806ff937c21cdbf82835614a98ebde54ec30133 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:20:45 +0200 Subject: [PATCH 091/132] feature/file-templates: rewrite & fix wrong-number-of-args errors #602 --- modules/feature/file-templates/autoload.el | 8 +- modules/feature/file-templates/config.el | 219 ++++++++++----------- 2 files changed, 113 insertions(+), 114 deletions(-) diff --git a/modules/feature/file-templates/autoload.el b/modules/feature/file-templates/autoload.el index 2566434c0..348c14915 100644 --- a/modules/feature/file-templates/autoload.el +++ b/modules/feature/file-templates/autoload.el @@ -66,8 +66,12 @@ evil is loaded and enabled)." ;;;###autoload (defun +file-templates-get-short-path () "Fetches a short file path for the header in Doom module templates." - (when (string-match "/modules/\\(.+\\)$" buffer-file-truename) - (match-string 1 buffer-file-truename))) + (let ((path (file-truename (or buffer-file-name default-directory)))) + (cond ((string-match "/modules/\\(.+\\)$" path) + (match-string 1 path)) + ((file-in-directory-p path doom-emacs-dir) + (file-relative-name path doom-emacs-dir)) + ((abbreviate-file-name path))))) ;; diff --git a/modules/feature/file-templates/config.el b/modules/feature/file-templates/config.el index 511bca956..8a9963c3d 100644 --- a/modules/feature/file-templates/config.el +++ b/modules/feature/file-templates/config.el @@ -6,142 +6,137 @@ (expand-file-name "templates/" (file-name-directory load-file-name)) "The path to a directory of yasnippet folders to use for file templates.") -(defvar +file-templates-alist () - "An alist of file template rules. The CAR of each rule is either a major mode -symbol or regexp string. The CDR is a plist. See `doom--set:file-template' for -more information.") - (defvar +file-templates-default-trigger "__" "The default yasnippet trigger key (a string) for file template rules that don't have a :trigger property in `+file-templates-alist'.") +(defvar +file-templates-alist + `(;; General + (gitignore-mode) + (dockerfile-mode) + ("/docker-compose\\.yml$" :mode yaml-mode) + ("/Makefile$" :mode makefile-gmake-mode) + ;; elisp + ("/.dir-locals.el$") + ("/packages\\.el$" :when +file-templates-in-emacs-dirs-p + :trigger "__doom-packages" + :mode emacs-lisp-mode) + ("/doctor\\.el$" :when +file-templates-in-emacs-dirs-p + :trigger "__doom-doctor" + :mode emacs-lisp-mode) + ("/test/.+\\.el$" :when +file-templates-in-emacs-dirs-p + :trigger "__doom-test" + :mode emacs-lisp-mode) + ("\\.el$" :when +file-templates-in-emacs-dirs-p + :trigger "__doom-module" + :mode emacs-lisp-mode) + ("-test\\.el$" :mode emacs-ert-mode) + (emacs-lisp-mode :trigger "__initfile") + (snippet-mode) + ;; C/C++ + ("/main\\.c\\(?:c\\|pp\\)$" :trigger "__main.cpp" :mode c++-mode) + ("/win32_\\.c\\(?:c\\|pp\\)$" :trigger "__winmain.cpp" :mode c++-mode) + ("\\.c\\(?:c\\|pp\\)$" :trigger "__cpp" :mode c++-mode) + ("\\.h\\(?:h\\|pp\\|xx\\)$" :trigger "__hpp" :mode c++-mode) + ("\\.h$" :trigger "__h" :mode c-mode) + (c-mode :trigger "__c" :mode c-mode) + ;; go + ("/main\\.go$" :trigger "__main.go" :mode go-mode :project t) + (go-mode :trigger "__.go") + ;; web-mode + ("/normalize\\.scss$" :trigger "__normalize.scss" :mode scss-mode) + ("/master\\.scss$" :trigger "__master.scss" :mode scss-mode) + ("\\.html$" :trigger "__.html" :mode web-mode) + (scss-mode) + ;; java + ("/main\\.java$" :trigger "__main" :mode java-mode) + ("/build\\.gradle$" :trigger "__build.gradle" :mode android-mode) + ("/src/.+\\.java$" :mode java-mode) + ;; javascript + ("/package\\.json$" :trigger "__package.json" :mode json-mode) + ("/bower\\.json$" :trigger "__bower.json" :mode json-mode) + ("/gulpfile\\.js$" :trigger "__gulpfile.js" :mode js-mode) + ("/webpack\\.config\\.js$" :trigger "__webpack.config.js" :mode js-mode) + ("\\.js\\(?:on\\|hintrc\\)$" :mode json-mode) + ;; Lua + ("/main\\.lua$" :trigger "__main.lua" :mode love-mode) + ("/conf\\.lua$" :trigger "__conf.lua" :mode love-mode) + ;; Markdown + (markdown-mode) + ;; Org + ("\\.org$" :trigger "__" :mode org-mode) + ("/README\\.org$" + :when +file-templates-in-emacs-dirs-p + :trigger "__doom-readme" + :mode org-mode) + ;; PHP + ("\\.class\\.php$" :trigger "__.class.php" :mode php-mode) + (php-mode) + ;; Python + ;; TODO ("tests?/test_.+\\.py$" :trigger "__" :mode nose-mode) + ;; TODO ("/setup\\.py$" :trigger "__setup.py" :mode python-mode) + (python-mode) + ;; Ruby + ("/lib/.+\\.rb$" :trigger "__module" :mode ruby-mode :project t) + ("/spec_helper\\.rb$" :trigger "__helper" :mode rspec-mode :project t) + ("_spec\\.rb$" :mode rspec-mode :project t) + ("/\\.rspec$" :trigger "__.rspec" :mode rspec-mode :project t) + ("\\.gemspec$" :trigger "__.gemspec" :mode ruby-mode :project t) + ("/Gemfile$" :trigger "__Gemfile" :mode ruby-mode :project t) + ("/Rakefile$" :trigger "__Rakefile" :mode ruby-mode :project t) + (ruby-mode) + ;; Rust + ("/Cargo.toml$" :trigger "__Cargo.toml" :mode rust-mode) + ("/main\\.rs$" :trigger "__main.rs" :mode rust-mode) + ;; Slim + ("/\\(?:index\\|main\\)\\.slim$" :mode slim-mode) + ;; Shell scripts + ("\\.zunit$" :trigger "__zunit" :mode sh-mode) + (fish-mode) + (sh-mode)) + "An alist of file template rules. The CAR of each rule is either a major mode +symbol or regexp string. The CDR is a plist. See `doom--set:file-template' for +more information.") + ;; -;; Bootstrap +;; Library ;; -(after! yasnippet - (add-to-list 'yas-snippet-dirs '+file-templates-dir 'append #'eq)) - (defun +file-template-p (rule) "Return t if RULE applies to the current buffer." (let ((pred (car rule)) (plist (cdr rule))) - (and (cond ((stringp pred) (string-match-p pred)) + (and (cond ((and (stringp pred) buffer-file-name) (string-match-p pred buffer-file-name)) ((symbolp pred) (eq major-mode pred))) (or (not (plist-member plist :when)) (funcall (plist-get plist :when) buffer-file-name)) rule))) -(defun +file-templates|init () - "Check if the current buffer is a candidate for file template expansion. It -must be non-read-only, empty, and there must be a rule in -`+file-templates-alist' that applies to it." - (when (and (not buffer-read-only) - (bobp) (eobp)) - (when-let* ((rule (cl-find-if #'+file-template-p +file-templates-alist))) - (apply #'+file-templates--expand rule)))) - -(add-hook 'find-file-hook #'+file-templates|init) - - -;; -;; File templates -;; - (defun +file-templates-in-emacs-dirs-p (file) "Returns t if FILE is in Doom or your private directory." (or (file-in-directory-p file doom-private-dir) (file-in-directory-p file doom-emacs-dir))) -(setq +file-templates-alist - `(;; General - (gitignore-mode) - (dockerfile-mode) - ("/docker-compose\\.yml$" :mode yaml-mode) - ("/Makefile$" :mode makefile-gmake-mode) - ;; elisp - ("/.dir-locals.el$") - ("/packages\\.el$" :when +file-templates-in-emacs-dirs-p - :trigger "__doom-packages" - :mode emacs-lisp-mode) - ("/doctor\\.el$" :when +file-templates-in-emacs-dirs-p - :trigger "__doom-doctor" - :mode emacs-lisp-mode) - ("/test/.+\\.el$" :when +file-templates-in-emacs-dirs-p - :trigger "__doom-test" - :mode emacs-lisp-mode) - ("\\.el$" :when +file-templates-in-emacs-dirs-p - :trigger "__doom-module" - :mode emacs-lisp-mode) - ("-test\\.el$" :mode emacs-ert-mode) - (emacs-lisp-mode :trigger "__initfile") - (snippet-mode) - ;; C/C++ - ("/main\\.c\\(?:c\\|pp\\)$" :trigger "__main.cpp" :mode c++-mode) - ("/win32_\\.c\\(?:c\\|pp\\)$" :trigger "__winmain.cpp" :mode c++-mode) - ("\\.c\\(?:c\\|pp\\)$" :trigger "__cpp" :mode c++-mode) - ("\\.h\\(?:h\\|pp\\|xx\\)$" :trigger "__hpp" :mode c++-mode) - ("\\.h$" :trigger "__h" :mode c-mode) - (c-mode :trigger "__c" :mode c-mode) - ;; go - ("/main\\.go$" :trigger "__main.go" :mode go-mode :project t) - (go-mode :trigger "__.go") - ;; web-mode - ("/normalize\\.scss$" :trigger "__normalize.scss" :mode scss-mode) - ("/master\\.scss$" :trigger "__master.scss" :mode scss-mode) - ("\\.html$" :trigger "__.html" :mode web-mode) - (scss-mode) - ;; java - ("/main\\.java$" :trigger "__main" :mode java-mode) - ("/build\\.gradle$" :trigger "__build.gradle" :mode android-mode) - ("/src/.+\\.java$" :mode java-mode) - ;; javascript - ("/package\\.json$" :trigger "__package.json" :mode json-mode) - ("/bower\\.json$" :trigger "__bower.json" :mode json-mode) - ("/gulpfile\\.js$" :trigger "__gulpfile.js" :mode js-mode) - ("/webpack\\.config\\.js$" :trigger "__webpack.config.js" :mode js-mode) - ("\\.js\\(?:on\\|hintrc\\)$" :mode json-mode) - ;; Lua - ("/main\\.lua$" :trigger "__main.lua" :mode love-mode) - ("/conf\\.lua$" :trigger "__conf.lua" :mode love-mode) - ;; Markdown - (markdown-mode) - ;; Org - ("\\.org$" :trigger "__" :mode org-mode) - ("/README\\.org$" - :when +file-templates-in-emacs-dirs-p - :trigger "__doom-readme" - :mode org-mode) - ;; PHP - ("\\.class\\.php$" :trigger "__.class.php" :mode php-mode) - (php-mode) - ;; Python - ;; TODO ("tests?/test_.+\\.py$" :trigger "__" :mode nose-mode) - ;; TODO ("/setup\\.py$" :trigger "__setup.py" :mode python-mode) - (python-mode) - ;; Ruby - ("/lib/.+\\.rb$" :trigger "__module" :mode ruby-mode :project t) - ("/spec_helper\\.rb$" :trigger "__helper" :mode rspec-mode :project t) - ("_spec\\.rb$" :mode rspec-mode :project t) - ("/\\.rspec$" :trigger "__.rspec" :mode rspec-mode :project t) - ("\\.gemspec$" :trigger "__.gemspec" :mode ruby-mode :project t) - ("/Gemfile$" :trigger "__Gemfile" :mode ruby-mode :project t) - ("/Rakefile$" :trigger "__Rakefile" :mode ruby-mode :project t) - (ruby-mode) - ;; Rust - ("/Cargo.toml$" :trigger "__Cargo.toml" :mode rust-mode) - ("/main\\.rs$" :trigger "__main.rs" :mode rust-mode) - ;; Slim - ("/\\(?:index\\|main\\)\\.slim$" :mode slim-mode) - ;; Shell scripts - ("\\.zunit$" :trigger "__zunit" :mode sh-mode) - (fish-mode) - (sh-mode) - )) +(defun +file-templates|check () + "Check if the current buffer is a candidate for file template expansion. It +must be non-read-only, empty, and there must be a rule in +`+file-templates-alist' that applies to it." + (when (and (not buffer-read-only) + (bobp) (eobp) + (not (string-match-p "^ *\\*" (buffer-name)))) + (when-let* ((rule (cl-find-if #'+file-template-p +file-templates-alist))) + (apply #'+file-templates--expand rule)))) ;; -;; Plugins +;; Bootstrap ;; +(defun +file-templates|init () + (after! yasnippet + (add-to-list 'yas-snippet-dirs '+file-templates-dir 'append #'eq)) + (add-hook 'find-file-hook #'+file-templates|check)) + +(add-hook 'doom-post-init-hook #'+file-templates|init) + From e8653d06289d2cd027574fd1b81370cf5add933d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:21:00 +0200 Subject: [PATCH 092/132] feature/file-templates: revise doom module README.org file template --- .../file-templates/templates/org-mode/__doom-readme | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/feature/file-templates/templates/org-mode/__doom-readme b/modules/feature/file-templates/templates/org-mode/__doom-readme index 901c25faf..8a6f23a5d 100644 --- a/modules/feature/file-templates/templates/org-mode/__doom-readme +++ b/modules/feature/file-templates/templates/org-mode/__doom-readme @@ -11,10 +11,9 @@ ${2:A short summary about what this module does.} ${3:If necessary, include a longer description below it that goes into more detail. This may be as long as you like. -+ If possible, include a list of features -+ Include links to major plugins that the module uses, if applicable -+ Use links whenever you can -+ Mention dependencies on other modules here} ++ If possible, include a brief list of feature highlights here ++ Like code completion, syntax checking or available snippets ++ Include links to packages & external things where possible * Table of Contents :TOC: @@ -25,11 +24,15 @@ This module provides no flags. This module has no prereqisites. * Features -A list of features, how to use them, and their dependencies. +An in-depth list of features, how to use them, and their dependencies. * Configuration +How to configure this module, including common problems and how to address them. * Appendix ** Commands ++ A list or table of public commands (and their keybinds) and functions that this module exposes. ++ A brief description of how to use them ** Hacks ++ Include a list of ways this module changes default behavior $0 \ No newline at end of file From 9e7703db2afa2293bc9b8cb44300cb29e3d5ccf8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 22:35:45 +0200 Subject: [PATCH 093/132] core-lib (add-transient-hook!): set permanent-local-hook on hook fn --- core/core-lib.el | 1 + 1 file changed, 1 insertion(+) diff --git a/core/core-lib.el b/core/core-lib.el index 5f46425f7..9e76dc0dc 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -249,6 +249,7 @@ HOOK can be a quoted hook or a sharp-quoted function (which will be advised)." (cond ((functionp ,hook) (advice-add ,hook ,(if append :after :before) #',fn)) ((symbolp ,hook) + (put ',fn 'permanent-local-hook t) (add-hook ,hook #',fn ,append)))))) (defmacro add-hook! (&rest args) From 6a140209b8ea648d9047480f4f8f9860c1a1979c Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 24 May 2018 23:41:40 +0200 Subject: [PATCH 094/132] Optimize Doom core package configs --- core/core-ui.el | 91 ++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/core/core-ui.el b/core/core-ui.el index 438dc515b..7a4256f5c 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -178,15 +178,11 @@ DEFAULT is non-nil, set the default mode-line for all buffers." ;; Plugins ;; -(def-package! ace-link - :commands (ace-link-help ace-link-org ace-link-addr ace-link-mu4e)) - -(def-package! avy - :commands (avy-goto-char-2 avy-goto-line) - :config - (setq avy-all-windows nil - avy-background t)) +;; `avy' +(setq avy-all-windows nil + avy-background t) +;; `all-the-icons' (def-package! all-the-icons :commands (all-the-icons-octicon all-the-icons-faicon all-the-icons-fileicon all-the-icons-wicon all-the-icons-material all-the-icons-alltheicon @@ -201,19 +197,41 @@ DEFAULT is non-nil, set the default mode-line for all buffers." all-the-icons-wicon all-the-icons-alltheicon)) (advice-add fn :around #'doom*disable-all-the-icons-in-tty))) -(def-package! hideshow ; built-in - :commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p) - :config (setq hs-hide-comments-when-hiding-all nil)) +;; `hide-mode-line-mode' +(add-hook 'completion-list-mode-hook #'hide-mode-line-mode) -(def-package! hide-mode-line - :commands hide-mode-line-mode - :init (add-hook 'completion-list-mode-hook #'hide-mode-line-mode)) +;; `rainbow-delimiters' Helps us distinguish stacked delimiter pairs. Especially +;; in parentheses-drunk languages like Lisp. +(def-package! rainbow-delimiters + :hook (lisp-mode . rainbow-delimiters-mode) + :config (setq rainbow-delimiters-max-face-count 3)) -(def-package! highlight-indentation - :commands (highlight-indentation-mode highlight-indentation-current-column-mode)) +;; `restart-emacs' +(setq restart-emacs--args (list "--restore")) -;; For modes with sub-par number fontification -(def-package! highlight-numbers :commands highlight-numbers-mode) +;; `visual-fill-column' For a distractions-free-like UI, that dynamically +;; resizes margins and can center a buffer. +(setq visual-fill-column-center-text t + visual-fill-column-width + ;; take Emacs 26 line numbers into account + (+ (if (boundp 'display-line-numbers) 6 0) + fill-column)) + + +;; +;; Built-in packages +;; + +;; `hideshow' +(setq hs-hide-comments-when-hiding-all nil) + +;; show typed keystrokes in minibuffer +(defun doom|enable-ui-keystrokes () (setq echo-keystrokes 0.02)) +(defun doom|disable-ui-keystrokes () (setq echo-keystrokes 0)) +(doom|enable-ui-keystrokes) +;; ...but hide them while isearch is active +(add-hook 'isearch-mode-hook #'doom|disable-ui-keystrokes) +(add-hook 'isearch-mode-end-hook #'doom|enable-ui-keystrokes) ;; Highlights the current line (def-package! hl-line ; built-in @@ -254,41 +272,6 @@ DEFAULT is non-nil, set the default mode-line for all buffers." (add-hook 'evil-visual-state-entry-hook #'doom|disable-hl-line) (add-hook 'evil-visual-state-exit-hook #'doom|enable-hl-line-maybe))) -;; Helps us distinguish stacked delimiter pairs. Especially in parentheses-drunk -;; languages like Lisp. -(def-package! rainbow-delimiters - :hook (lisp-mode . rainbow-delimiters-mode) - :config (setq rainbow-delimiters-max-face-count 3)) - -(def-package! restart-emacs - :commands restart-emacs - :config (setq restart-emacs--args (list "--restore"))) - -;; For a distractions-free-like UI, that dynamically resizes margins and can -;; center a buffer. -(def-package! visual-fill-column - :commands visual-fill-column-mode - :config - (setq-default - visual-fill-column-center-text t - visual-fill-column-width - ;; take Emacs 26 line numbers into account - (+ (if (boundp 'display-line-numbers) 6 0) - fill-column))) - - -;; -;; Built-in packages -;; - -;; show typed keystrokes in minibuffer -(defun doom|enable-ui-keystrokes () (setq echo-keystrokes 0.02)) -(defun doom|disable-ui-keystrokes () (setq echo-keystrokes 0)) -(doom|enable-ui-keystrokes) -;; ...but hide them while isearch is active -(add-hook 'isearch-mode-hook #'doom|disable-ui-keystrokes) -(add-hook 'isearch-mode-end-hook #'doom|enable-ui-keystrokes) - ;; undo/redo changes to Emacs' window layout (def-package! winner :after-call doom-before-switch-window-hook @@ -317,7 +300,7 @@ DEFAULT is non-nil, set the default mode-line for all buffers." (remove-hook 'kill-buffer-query-functions #'server-kill-buffer-query-function)) (add-hook 'server-visit-hook #'server-remove-kill-buffer-hook) -;; whitespace-mode settings +;; `whitespace-mode' (setq whitespace-line-column nil whitespace-style '(face indentation tabs tab-mark spaces space-mark newline newline-mark From 09cb4f6716129bb8267c0812eb1ea2ed3f194430 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:46:11 +0200 Subject: [PATCH 095/132] Major refactor & optimization of how modules load their packages Now that we are loading package autoloads files (as part of the generated doom-package-autoload-file when running make autoloads), many :commands properties are redundant. In fact, many def-package! blocks are redundant. In some cases, we can do without a config.el file entirely, and can move into the autoloads file or rely entirely on package autoloads. Also, many settings have been moved in their module's autoloads files, which makes them available ASAP; their use no longer depends on module load order. This gained me a modest ~10% boost in startup speed. --- modules/collab/impatient-mode/autoload.el | 3 +- modules/collab/impatient-mode/config.el | 6 -- modules/completion/company/config.el | 25 ++---- modules/completion/helm/config.el | 3 +- modules/completion/ivy/autoload/ivy.el | 6 +- modules/completion/ivy/config.el | 5 +- modules/config/default/config.el | 9 ++ modules/feature/debugger/config.el | 3 +- modules/feature/eval/config.el | 7 +- modules/feature/evil/autoload/evil.el | 20 +++++ modules/feature/evil/config.el | 38 +-------- modules/feature/lookup/autoload/devdocs.el | 11 +++ modules/feature/lookup/autoload/docsets.el | 40 +++++++++ modules/feature/lookup/config.el | 83 +++++-------------- modules/feature/snippets/config.el | 36 ++++---- modules/feature/snippets/doctor.el | 7 -- modules/feature/spellcheck/config.el | 2 +- modules/feature/spellcheck/packages.el | 14 ++-- modules/feature/syntax-checker/config.el | 22 ++--- modules/feature/version-control/+git.el | 17 +--- modules/feature/workspaces/config.el | 2 +- .../workspaces/test/autoload-workspaces.el | 1 + modules/lang/assembly/autoload.el | 4 + modules/lang/assembly/config.el | 8 -- modules/lang/cc/autoload.el | 7 -- modules/lang/cc/config.el | 34 ++++---- modules/lang/cc/doctor.el | 6 +- modules/lang/clojure/config.el | 10 +-- modules/lang/crystal/config.el | 6 +- modules/lang/csharp/config.el | 9 +- modules/lang/data/config.el | 43 +++------- modules/lang/elixir/config.el | 31 ++++--- modules/lang/elm/config.el | 15 ++-- modules/lang/emacs-lisp/autoload.el | 8 ++ modules/lang/emacs-lisp/config.el | 33 +++----- modules/lang/erlang/config.el | 22 +++-- modules/lang/ess/config.el | 6 +- modules/lang/go/config.el | 30 ++----- modules/lang/haskell/config.el | 15 +--- modules/lang/hy/config.el | 4 +- modules/lang/java/config.el | 4 +- modules/lang/javascript/config.el | 74 ++++++----------- modules/lang/julia/config.el | 1 - modules/lang/latex/config.el | 3 - modules/lang/ledger/config.el | 8 +- modules/lang/lua/config.el | 21 +---- modules/lang/markdown/config.el | 4 +- modules/lang/nim/config.el | 20 +---- modules/lang/nix/config.el | 4 - modules/lang/ocaml/config.el | 8 +- modules/lang/org/config.el | 8 +- modules/lang/plantuml/config.el | 2 +- modules/lang/purescript/config.el | 10 ++- modules/lang/python/config.el | 3 +- modules/lang/rest/config.el | 5 +- modules/lang/ruby/config.el | 27 ++---- modules/lang/rust/config.el | 12 +-- modules/lang/scala/config.el | 22 +++-- modules/lang/sh/config.el | 14 ++-- modules/lang/swift/config.el | 15 ++-- modules/lang/swift/packages.el | 3 + modules/lang/web/+css.el | 32 +++---- modules/lang/web/+html.el | 12 +-- modules/lang/web/packages.el | 6 +- modules/tools/editorconfig/config.el | 11 ++- modules/tools/ein/autoload.el | 30 ++++--- modules/tools/ein/config.el | 62 +++++++------- modules/tools/electric-indent/config.el | 22 ++--- modules/tools/eshell/config.el | 4 +- modules/tools/gist/config.el | 4 +- modules/tools/imenu/config.el | 9 +- modules/tools/magit/config.el | 9 +- modules/tools/password-store/config.el | 27 +++--- modules/tools/password-store/packages.el | 2 +- modules/tools/pdf/config.el | 3 +- modules/tools/prodigy/autoload.el | 20 +++++ modules/tools/prodigy/config.el | 27 +----- modules/tools/rgb/config.el | 3 - modules/tools/rotate-text/autoload.el | 17 ++++ modules/tools/rotate-text/config.el | 22 +---- modules/tools/term/config.el | 18 ++-- modules/ui/doom-dashboard/config.el | 21 ++--- modules/ui/doom-modeline/config.el | 11 +-- modules/ui/doom/config.el | 7 +- modules/ui/evil-goggles/config.el | 2 +- modules/ui/nav-flash/config.el | 2 +- modules/ui/popup/autoload.el | 68 +++++++++++++++ modules/ui/popup/init.el | 61 -------------- modules/ui/unicode/autoload.el | 23 +++++ modules/ui/unicode/config.el | 19 ----- modules/ui/vi-tilde-fringe/autoload.el | 4 + modules/ui/vi-tilde-fringe/config.el | 6 -- modules/ui/window-select/config.el | 7 +- 93 files changed, 644 insertions(+), 846 deletions(-) delete mode 100644 modules/collab/impatient-mode/config.el create mode 100644 modules/feature/lookup/autoload/devdocs.el create mode 100644 modules/feature/lookup/autoload/docsets.el delete mode 100644 modules/feature/snippets/doctor.el create mode 100644 modules/lang/assembly/autoload.el delete mode 100644 modules/lang/assembly/config.el delete mode 100644 modules/lang/nix/config.el create mode 100644 modules/tools/rotate-text/autoload.el delete mode 100644 modules/ui/popup/init.el create mode 100644 modules/ui/unicode/autoload.el delete mode 100644 modules/ui/unicode/config.el create mode 100644 modules/ui/vi-tilde-fringe/autoload.el delete mode 100644 modules/ui/vi-tilde-fringe/config.el diff --git a/modules/collab/impatient-mode/autoload.el b/modules/collab/impatient-mode/autoload.el index 3222b5477..41047d359 100644 --- a/modules/collab/impatient-mode/autoload.el +++ b/modules/collab/impatient-mode/autoload.el @@ -2,9 +2,8 @@ ;;;###autoload (defun +impatient-mode/toggle () - "TODO" + "Toggle `impatient-mode' in the current buffer." (interactive) - (require 'simple-httpd) (unless (process-status "httpd") (httpd-start)) (impatient-mode) diff --git a/modules/collab/impatient-mode/config.el b/modules/collab/impatient-mode/config.el deleted file mode 100644 index 0087bee52..000000000 --- a/modules/collab/impatient-mode/config.el +++ /dev/null @@ -1,6 +0,0 @@ -;;; collab/impatient-mode/config.el -*- lexical-binding: t; -*- - -;; Show off code as you write it - -(def-package! impatient-mode - :commands impatient-mode) diff --git a/modules/completion/company/config.el b/modules/completion/company/config.el index 12a1f352b..ec6113713 100644 --- a/modules/completion/company/config.el +++ b/modules/completion/company/config.el @@ -24,8 +24,7 @@ MODES should be one major-mode symbol or a list of them." ;; (def-package! company - :commands (company-mode global-company-mode company-complete - company-complete-common company-manual-begin company-grab-line) + :commands (company-complete-common company-manual-begin company-grab-line) :init (setq company-idle-delay nil company-tooltip-limit 14 @@ -48,7 +47,8 @@ MODES should be one major-mode symbol or a list of them." (def-package! company :when (featurep! +auto) - :defer pre-command-hook + :defer 2 + :after-call pre-command-hook :config (setq company-idle-delay 0.2)) @@ -73,27 +73,12 @@ MODES should be one major-mode symbol or a list of them." (def-package! company-dict - :commands company-dict + :defer t :config (defun +company|enable-project-dicts (mode &rest _) "Enable per-project dictionaries." (if (symbol-value mode) - (cl-pushnew mode company-dict-minor-mode-list :test #'eq) + (add-to-list 'company-dict-minor-mode-list mode #'eq) (setq company-dict-minor-mode-list (delq mode company-dict-minor-mode-list)))) (add-hook 'doom-project-hook #'+company|enable-project-dicts)) - -;; -;; Included with company.el -;; - -(autoload 'company-capf "company-capf") -(autoload 'company-dabbrev "company-dabbrev") -(autoload 'company-dabbrev-code "company-dabbrev-code") -(autoload 'company-elisp "company-elisp") -(autoload 'company-etags "company-etags") -(autoload 'company-files "company-files") -(autoload 'company-gtags "company-gtags") -(autoload 'company-ispell "company-ispell") -(autoload 'company-yasnippet "company-yasnippet") - diff --git a/modules/completion/helm/config.el b/modules/completion/helm/config.el index b4e6c5282..702208166 100644 --- a/modules/completion/helm/config.el +++ b/modules/completion/helm/config.el @@ -11,7 +11,8 @@ ;; (def-package! helm-mode - :defer (pre-command-hook . 1) + :defer 1 + :after-call pre-command-hook :config (helm-mode +1) ;; helm is too heavy for find-file-at-point diff --git a/modules/completion/ivy/autoload/ivy.el b/modules/completion/ivy/autoload/ivy.el index eef638f21..89ce56db5 100644 --- a/modules/completion/ivy/autoload/ivy.el +++ b/modules/completion/ivy/autoload/ivy.el @@ -116,9 +116,9 @@ If ARG (universal argument), open selection in other-window." "\\):?\\s-*\\(.+\\)") x) (error - (message! (red "Error matching task in file: (%s) %s" - (error-message-string ex) - (car (split-string x ":")))) + (print! (red "Error matching task in file: (%s) %s" + (error-message-string ex) + (car (split-string x ":")))) nil)) collect `((type . ,(match-string 3 x)) (desc . ,(match-string 4 x)) diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index 51434fb26..9d3f3f705 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -24,7 +24,8 @@ immediately runs it on the current candidate (ending the ivy session)." ;; (def-package! ivy - :defer (pre-command-hook . 1) + :defer 1 + :after-call pre-command-hook :config (setq ivy-height 12 ivy-do-completion-in-region nil @@ -184,7 +185,7 @@ immediately runs it on the current candidate (ending the ivy session)." (def-package! wgrep - :commands (wgrep-setup wgrep-change-to-wgrep-mode) + :commands wgrep-change-to-wgrep-mode :config (setq wgrep-auto-save-buffer t)) diff --git a/modules/config/default/config.el b/modules/config/default/config.el index 6d5ba386b..12bd8c5ec 100644 --- a/modules/config/default/config.el +++ b/modules/config/default/config.el @@ -35,6 +35,15 @@ (sp-pair "'" nil :unless unless-list) (sp-pair "\"" nil :unless unless-list)) + ;; Major-mode specific fixes + (sp-local-pair 'ruby-mode "{" "}" + :pre-handlers '(:rem sp-ruby-prehandler) + :post-handlers '(:rem sp-ruby-posthandler)) + ;; sp's default rules for these modes are obnoxious, so disable them + (provide 'smartparens-latex) + (provide 'smartparens-elixir) + (provide 'smartparens-lua) + ;; Expand {|} => { | } ;; Expand {|} => { ;; | diff --git a/modules/feature/debugger/config.el b/modules/feature/debugger/config.el index 1b7ef587d..78660ffa8 100644 --- a/modules/feature/debugger/config.el +++ b/modules/feature/debugger/config.el @@ -3,7 +3,8 @@ (def-package! realgud :commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb) :config - (set! :popup "^\\*\\(?trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)" '((size . 20))) + (set! :popup "^\\*\\(?trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)" + '((size . 20))) ;; TODO Temporary Ex commands for the debugger ;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off diff --git a/modules/feature/eval/config.el b/modules/feature/eval/config.el index 72b086d15..1549eacb8 100644 --- a/modules/feature/eval/config.el +++ b/modules/feature/eval/config.el @@ -10,12 +10,7 @@ ;; (def-package! quickrun - :commands (quickrun - quickrun-region - quickrun-with-arg - quickrun-shell - quickrun-compile-only - quickrun-replace-region) + :defer t :init (unless (boundp 'display-line-numbers) (add-hook 'quickrun--mode-hook #'nlinum-mode)) diff --git a/modules/feature/evil/autoload/evil.el b/modules/feature/evil/autoload/evil.el index f1c41106d..a04891154 100644 --- a/modules/feature/evil/autoload/evil.el +++ b/modules/feature/evil/autoload/evil.el @@ -1,6 +1,21 @@ ;; feature/evil/autoload/evil.el -*- lexical-binding: t; -*- ;;;###if (featurep! :feature evil) +;;;###autoload +(def-setting! :evil-state (modes state) + "Set the initialize STATE of MODE using `evil-set-initial-state'." + (let ((unquoted-modes (doom-unquote modes))) + (if (listp unquoted-modes) + `(progn + ,@(cl-loop for mode in unquoted-modes + collect `(evil-set-initial-state ',mode ,state))) + `(evil-set-initial-state ,modes ,state)))) + + +;; +;; Commands +;; + ;;;###autoload (defun +evil/visual-indent () "vnoremap < " evil-args-closers))) -(def-package! evil-indent-plus - :commands (evil-indent-plus-i-indent - evil-indent-plus-a-indent - evil-indent-plus-i-indent-up - evil-indent-plus-a-indent-up - evil-indent-plus-i-indent-up-down - evil-indent-plus-a-indent-up-down)) - - -(def-package! evil-textobj-anyblock - :commands (evil-textobj-anyblock-inner-block evil-textobj-anyblock-a-block)) - - ;; ;; Multiple cursors compatibility (for the plugins that use it) ;; diff --git a/modules/feature/lookup/autoload/devdocs.el b/modules/feature/lookup/autoload/devdocs.el new file mode 100644 index 000000000..2b2c4a514 --- /dev/null +++ b/modules/feature/lookup/autoload/devdocs.el @@ -0,0 +1,11 @@ +;;; feature/lookup/autoload/devdocs.el -*- lexical-binding: t; -*- +;;;###if (featurep! +devdocs) + +;;;###autoload +(def-setting! :devdocs (modes docset) + "Map major MODES (one major-mode symbol or a list of them) to a devdocs +DOCSET (a string). + +See `devdocs-alist' for the defaults. " + `(dolist (mode ',modes) + (push (cons mode ,docset) devdocs-alist))) diff --git a/modules/feature/lookup/autoload/docsets.el b/modules/feature/lookup/autoload/docsets.el new file mode 100644 index 000000000..89fef163c --- /dev/null +++ b/modules/feature/lookup/autoload/docsets.el @@ -0,0 +1,40 @@ +;;; feature/lookup/autoload/docsets.el -*- lexical-binding: t; -*- +;;;###if (featurep! +docsets) + +;;;###autoload +(def-setting! :docset (modes &rest docsets) + "Registers a list of DOCSETS (strings) for MODES (either one major mode +symbol or a list of them). + +If MODES is a minor mode, you can use :add or :remove as the first element of +DOCSETS, to instruct it to append (or remove) those from the docsets already set +by a major-mode, if any. + +Used by `+lookup/in-docsets' and `+lookup/documentation'." + (let* ((modes (doom-unquote modes)) + (ivy-p (featurep! :completion ivy)) + (hook-sym (intern (format "+lookup|%s-docsets--%s" + (cond ((eq ',(car docsets) :add) 'add) + ((eq ',(car docsets) :remove) 'remove) + ('set)) + (string-join docsets "-")))) + (var-sym (if ivy-p 'counsel-dash-docsets 'helm-dash-docsets))) + `(progn + (defun ,hook-sym () + (make-variable-buffer-local ',var-sym) + ,(cond ((eq ',(car docsets) :add) + `(setq ,var-sym (append ,var-sym (list ,@(cdr docsets))))) + ((eq ',(car docsets) :remove) + `(setq ,var-sym + (cl-loop with to-delete = (list ,@(cdr docsets)) + for docset in ,var-sym + unless (member docset to-delete) + collect docset))) + (`(setq ,var-sym (list ,@docsets))))) + (add-hook! ,modes #',hook-sym)))) + +;;;###autoload +(autoload 'helm-dash-installed-docsets "helm-dash") + +;;;###autoload +(autoload 'helm-dash-docset-installed-p "helm-dash") diff --git a/modules/feature/lookup/config.el b/modules/feature/lookup/config.el index b693f44bc..bbabb689a 100644 --- a/modules/feature/lookup/config.el +++ b/modules/feature/lookup/config.el @@ -122,33 +122,29 @@ ones." ;; (def-package! dumb-jump - :commands (dumb-jump-go dumb-jump-quick-look - dumb-jump-back dumb-jump-result-follow) + :commands dumb-jump-result-follow :config (setq dumb-jump-default-project doom-emacs-dir dumb-jump-aggressive nil dumb-jump-selector (cond ((featurep! :completion ivy) 'ivy) ((featurep! :completion helm) 'helm) - (t 'popup)))) + ('popup)))) ;; ;; xref ;; -(def-package! xref - :commands (xref-backend-identifier-at-point xref-find-definitions xref-find-references) - :config - ;; By default, `etags--xref-backend' is the default xref backend. No need. - ;; We'll set these up ourselves in other modules. - (setq-default xref-backend-functions '(t)) +;; By default, `etags--xref-backend' is the default xref backend. No need. We'll +;; set these up ourselves in other modules. +(setq-default xref-backend-functions '(t)) - ;; ...however, it breaks `projectile-find-tag', unless we put it back. - (defun +lookup*projectile-find-tag (orig-fn) - (let ((xref-backend-functions '(etags--xref-backend t))) - (funcall orig-fn))) - (advice-add #'projectile-find-tag :around #'+lookup*projectile-find-tag)) +;; ...however, it breaks `projectile-find-tag', unless we put it back. +(defun +lookup*projectile-find-tag (orig-fn) + (let ((xref-backend-functions '(etags--xref-backend t))) + (funcall orig-fn))) +(advice-add #'projectile-find-tag :around #'+lookup*projectile-find-tag) (def-package! ivy-xref @@ -168,41 +164,9 @@ ones." ;; (when (featurep! +docsets) - (def-setting! :docset (modes &rest docsets) - "Registers a list of DOCSETS (strings) for MODES (either one major mode -symbol or a list of them). - -If MODES is a minor mode, you can use :add or :remove as the first element of -DOCSETS, to instruct it to append (or remove) those from the docsets already set -by a major-mode, if any. - -Used by `+lookup/in-docsets' and `+lookup/documentation'." - (let* ((modes (doom-unquote modes)) - (ivy-p (featurep! :completion ivy)) - (hook-sym (intern (format "+lookup|%s-docsets--%s" - (cond ((eq ',(car docsets) :add) 'add) - ((eq ',(car docsets) :remove) 'remove) - ('set)) - (string-join docsets "-")))) - (var-sym (if ivy-p 'counsel-dash-docsets 'helm-dash-docsets))) - `(progn - (defun ,hook-sym () - (make-variable-buffer-local ',var-sym) - ,(cond ((eq ',(car docsets) :add) - `(setq ,var-sym (append ,var-sym (list ,@(cdr docsets))))) - ((eq ',(car docsets) :remove) - `(setq ,var-sym - (cl-loop with to-delete = (list ,@(cdr docsets)) - for docset in ,var-sym - unless (member docset to-delete) - collect docset))) - (`(setq ,var-sym (list ,@docsets))))) - (add-hook! ,modes #',hook-sym)))) - ;; Both packages depend on helm-dash (def-package! helm-dash - :commands (helm-dash helm-dash-install-docset helm-dash-at-point - helm-dash-docset-installed-p helm-dash-installed-docsets) + :defer t :init (setq helm-dash-enable-debugging doom-debug-mode helm-dash-browser-func #'eww) @@ -214,7 +178,7 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'." (def-package! counsel-dash :when (featurep! :completion ivy) - :commands (counsel-dash counsel-dash-install-docset) + :commands counsel-dash-install-docset :config (setq counsel-dash-min-length 2))) @@ -223,20 +187,11 @@ Used by `+lookup/in-docsets' and `+lookup/documentation'." ;; (when (featurep! +devdocs) - (def-setting! :devdocs (modes docset) - "Map major MODES (one major-mode symbol or a list of them) to a devdocs -DOCSET (a string). - -See `devdocs-alist' for the defaults. " - `(dolist (mode ',modes) - (push (cons mode ,docset) devdocs-alist))) - - (def-package! devdocs-lookup - :commands (devdocs-setup devdocs-lookup) - :config - (setq devdocs-subjects - (append '(("SCSS" "scss") - ("GFM" "markdown") - ("Typescript" "typescript")) - devdocs-subjects)))) + (after! devdocs-lookup + (unless (assoc "SCSS" devdocs-subjects) + (setq devdocs-subjects + (append '(("SCSS" "scss") + ("GFM" "markdown") + ("Typescript" "typescript")) + devdocs-subjects))))) diff --git a/modules/feature/snippets/config.el b/modules/feature/snippets/config.el index a9acfadd6..33757e31e 100644 --- a/modules/feature/snippets/config.el +++ b/modules/feature/snippets/config.el @@ -1,9 +1,16 @@ ;;; feature/snippets/config.el -*- lexical-binding: t; -*- +(defvar +snippets-dir (expand-file-name "snippets/" doom-private-dir) + "Directory where `yasnippet' will search for your private snippets.") + + +;; +;; Plugins +;; + (def-package! yasnippet - :commands (yas-minor-mode yas-minor-mode-on yas-expand yas-expand-snippet - yas-lookup-snippet yas-insert-snippet yas-new-snippet - yas-visit-snippet-file snippet-mode) + :commands (yas-minor-mode-on yas-expand yas-expand-snippet yas-lookup-snippet + yas-insert-snippet yas-new-snippet yas-visit-snippet-file) :preface (defvar yas-minor-mode-map (let ((map (make-sparse-keymap))) @@ -23,28 +30,25 @@ (setq yas-verbosity (if doom-debug-mode 3 0) yas-also-auto-indent-first-line t yas-prompt-functions (delq #'yas-dropdown-prompt yas-prompt-functions) - ;; Allow nested snippets - yas-triggers-in-field t) + yas-triggers-in-field t) ; Allow nested snippets - (cl-pushnew (expand-file-name "snippets/" doom-private-dir) yas-snippet-dirs - :test #'string=) + (add-to-list 'yas-snippet-dirs '+snippets-dir nil #'eq) (defun +snippets|enable-project-modes (mode &rest _) - "Enable snippets for project modes." + "Automatically enable snippet libraries for project minor modes defined with +`def-project-mode!'." (if (symbol-value mode) (yas-activate-extra-mode mode) (yas-deactivate-extra-mode mode))) (add-hook 'doom-project-hook #'+snippets|enable-project-modes) - ;; fix an error caused by smartparens interfering with yasnippet bindings - (advice-add #'yas-expand :before #'sp-remove-active-pair-overlay) - ;; Exit snippets on ESC from normal mode - (add-hook 'doom-escape-hook #'yas-abort-snippet)) + (add-hook 'doom-escape-hook #'yas-abort-snippet) + + (after! smartparens + ;; fix an error caused by smartparens interfering with yasnippet bindings + (advice-add #'yas-expand :before #'sp-remove-active-pair-overlay))) -(def-package! auto-yasnippet - :commands (aya-create aya-expand aya-open-line aya-persist-snippet) - :config +(after! auto-yasnippet (setq aya-persist-snippets-dir (concat doom-local-dir "auto-snippets/"))) - diff --git a/modules/feature/snippets/doctor.el b/modules/feature/snippets/doctor.el deleted file mode 100644 index 8ba004a36..000000000 --- a/modules/feature/snippets/doctor.el +++ /dev/null @@ -1,7 +0,0 @@ -;; -*- lexical-binding: t; no-byte-compile: t; -*- -;;; feature/snippets/doctor.el - -(require 'yasnippet) -(unless (ignore-errors (yas-reload-all) - (yas--get-snippet-tables)) - (warn! "Couldn't find any snippets in any of these directories: %s" yas-snippet-dirs)) diff --git a/modules/feature/spellcheck/config.el b/modules/feature/spellcheck/config.el index c1f8b3bb6..2cc8dadb6 100644 --- a/modules/feature/spellcheck/config.el +++ b/modules/feature/spellcheck/config.el @@ -8,7 +8,7 @@ Since spellchecking can be slow in some buffers, this can be disabled with: (setq-hook! 'LaTeX-mode-hook +spellcheck-immediately nil)") (def-package! flyspell ; built-in - :commands flyspell-mode + :defer t :init (add-hook 'flyspell-mode-hook #'+spellcheck|immediately) :config diff --git a/modules/feature/spellcheck/packages.el b/modules/feature/spellcheck/packages.el index bb01a00ba..97172953f 100644 --- a/modules/feature/spellcheck/packages.el +++ b/modules/feature/spellcheck/packages.el @@ -1,11 +1,11 @@ ;; -*- no-byte-compile: t; -*- ;;; feature/spellcheck/packages.el -(package! flyspell-correct) -(cond ((featurep! :completion ivy) - (package! flyspell-correct-ivy)) - ((featurep! :completion helm) - (package! flyspell-correct-helm)) - (t - (package! flyspell-correct-popup))) +(when (package! flyspell-correct) + (cond ((featurep! :completion ivy) + (package! flyspell-correct-ivy)) + ((featurep! :completion helm) + (package! flyspell-correct-helm)) + (t + (package! flyspell-correct-popup)))) diff --git a/modules/feature/syntax-checker/config.el b/modules/feature/syntax-checker/config.el index 29048618e..9bdc0b5fa 100644 --- a/modules/feature/syntax-checker/config.el +++ b/modules/feature/syntax-checker/config.el @@ -1,18 +1,11 @@ ;;; feature/syntax-checker/config.el -*- lexical-binding: t; -*- -;; Since Doom doesn't use `package-initialize', pkg-info won't get autoloaded -;; when `flycheck-version' needs it, so we need this: -(autoload 'pkg-info-version-info "pkg-info") - (def-package! flycheck - :commands (flycheck-mode flycheck-list-errors flycheck-buffer) + :commands (flycheck-list-errors flycheck-buffer) :config ;; Emacs feels snappier without checks on newline (setq flycheck-check-syntax-automatically '(save idle-change mode-enabled)) - ;; Popup - (add-hook 'flycheck-mode-hook #'+syntax-checker-popup-mode) - (after! evil (defun +syntax-checkers|flycheck-buffer () "Flycheck buffer on ESC in normal mode." @@ -20,21 +13,16 @@ (ignore-errors (flycheck-buffer)) nil)) (add-hook 'doom-escape-hook #'+syntax-checkers|flycheck-buffer t) - (add-hook 'evil-insert-state-exit-hook #'+syntax-checkers|flycheck-buffer) - - ;; With the option of flychecking the buffer on escape or leaving insert - ;; mode, we don't need auto-flychecking on idle-change (which can feel slow, - ;; esp on computers without SSDs). - (delq 'idle-change flycheck-check-syntax-automatically))) + (add-hook 'evil-insert-state-exit-hook #'+syntax-checkers|flycheck-buffer))) (def-package! flycheck-popup-tip - :commands (flycheck-popup-tip-show-popup flycheck-popup-tip-delete-popup)) + :commands (flycheck-popup-tip-show-popup flycheck-popup-tip-delete-popup) + :init (add-hook 'flycheck-mode-hook #'+syntax-checker-popup-mode)) (def-package! flycheck-posframe - :when EMACS26+ - :when (featurep! +childframe) + :when (and EMACS26+ (featurep! +childframe)) :commands flycheck-posframe-show-posframe :config (setq flycheck-posframe-warning-prefix "⚠ " diff --git a/modules/feature/version-control/+git.el b/modules/feature/version-control/+git.el index 88d610089..8488f9076 100644 --- a/modules/feature/version-control/+git.el +++ b/modules/feature/version-control/+git.el @@ -1,10 +1,5 @@ ;;; feature/version-control/+git.el -*- lexical-binding: t; -*- -;; These don't need `def-package!' blocks because they've already been set up by -;; `doom-initialize'. -(autoload 'gitconfig-mode "gitconfig-mode" nil t) -(autoload 'gitignore-mode "gitignore-mode" nil t) - (when (featurep! :feature evil) (add-hook 'git-commit-mode-hook #'evil-insert-state)) @@ -59,7 +54,7 @@ (def-package! git-timemachine - :commands (git-timemachine git-timemachine-toggle) + :defer t :config ;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of ;; showing revision details in the minibuffer, show them in @@ -67,10 +62,6 @@ (setq git-timemachine-show-minibuffer-details t) (advice-add #'git-timemachine--show-minibuffer-details :override #'+vcs*update-header-line) - ;; Force evil to rehash keybindings for the current state - (add-hook 'git-timemachine-mode-hook #'evil-force-normal-state)) - - -(def-package! git-link - :commands (git-link git-link-commit git-link-homepage)) - + (after! evil + ;; Force evil to rehash keybindings for the current state + (add-hook 'git-timemachine-mode-hook #'evil-force-normal-state))) diff --git a/modules/feature/workspaces/config.el b/modules/feature/workspaces/config.el index 4b6d1f4b4..bc1467bcf 100644 --- a/modules/feature/workspaces/config.el +++ b/modules/feature/workspaces/config.el @@ -27,7 +27,7 @@ new project directory.") stored in `persp-save-dir'.") (defun +workspaces-restore-last-session (&rest _) - (add-hook 'emacs-startup-hook #'+workspace/load-session 'append)) + (add-hook 'doom-post-init-hook #'+workspace/load-session 'append)) (map-put command-switch-alist '"--restore" #'+workspaces-restore-last-session) diff --git a/modules/feature/workspaces/test/autoload-workspaces.el b/modules/feature/workspaces/test/autoload-workspaces.el index e7cc2e9bd..6367400ed 100644 --- a/modules/feature/workspaces/test/autoload-workspaces.el +++ b/modules/feature/workspaces/test/autoload-workspaces.el @@ -2,6 +2,7 @@ ;;; feature/workspaces/test/autoload-workspaces.el (require! :feature workspaces) +(doom|init-custom-hooks) (defmacro with-workspace!! (buffer-args &rest body) (declare (indent defun)) diff --git a/modules/lang/assembly/autoload.el b/modules/lang/assembly/autoload.el new file mode 100644 index 000000000..38b582a66 --- /dev/null +++ b/modules/lang/assembly/autoload.el @@ -0,0 +1,4 @@ +;;; lang/assembly/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(map-put auto-mode-alist "\\.hax\\'" 'haxor-mode) diff --git a/modules/lang/assembly/config.el b/modules/lang/assembly/config.el deleted file mode 100644 index 98b879b24..000000000 --- a/modules/lang/assembly/config.el +++ /dev/null @@ -1,8 +0,0 @@ -;;; lang/assembly/config.el -*- lexical-binding: t; -*- - -(def-package! mips-mode :mode "\\.mips$") - -(def-package! haxor-mode :mode "\\.hax$") - -(def-package! nasm-mode :commands nasm-mode) - diff --git a/modules/lang/cc/autoload.el b/modules/lang/cc/autoload.el index cf6580425..f063cf11c 100644 --- a/modules/lang/cc/autoload.el +++ b/modules/lang/cc/autoload.el @@ -89,13 +89,6 @@ compilation dbs." nconc (list "-I" path))) (doom-project-root))))) -;;;###autoload -(defun +cc|init-rtags () - "Start an rtags server in c-mode and c++-mode buffers." - (when (and (memq major-mode '(c-mode c++-mode)) - (rtags-executable-find "rtags")) - (rtags-start-process-unless-running))) - ;;;###autoload (defun +cc|cleanup-rtags () "Kill rtags server(s) if there are no C/C++ buffers open." diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 0077083c1..cb02a6558 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -55,10 +55,10 @@ compilation database is present in the project.") :config (set! :electric '(c-mode c++-mode objc-mode java-mode) - :chars '(?\n ?\})) + :chars '(?\n ?\})) (set! :company-backend - '(c-mode c++-mode objc-mode) - '(company-irony-c-headers company-irony)) + '(c-mode c++-mode objc-mode) + '(company-irony-c-headers company-irony)) ;;; Style/formatting ;; C/C++ style settings @@ -101,8 +101,8 @@ compilation database is present in the project.") (label . 0)))) ;;; Keybindings - ;; Completely disable electric keys because it interferes with smartparens and - ;; custom bindings. We'll do this ourselves. + ;; Disable electric keys because it interferes with smartparens and custom + ;; bindings. We'll do it ourselves (mostly). (setq c-tab-always-indent nil c-electric-flag nil) (dolist (key '("#" "}" "/" "*" ";" "," ":" "(" ")" "\177")) @@ -129,6 +129,7 @@ compilation database is present in the project.") (def-package! irony + :when (featurep! +irony) :commands (irony-install-server irony-mode) :preface (setq irony-server-install-prefix (concat doom-etc-dir "irony-server/")) @@ -172,23 +173,13 @@ compilation database is present in the project.") ;; (def-package! cmake-mode - :mode "/CMakeLists\\.txt$" - :mode "\\.cmake\\$" + :defer t :config (set! :company-backend 'cmake-mode '(company-cmake company-yasnippet))) -(def-package! cuda-mode :mode "\\.cuh?$") +(def-package! opencl-mode :mode "\\.cl\\'") -(def-package! opencl-mode :mode "\\.cl$") - -(def-package! demangle-mode - :hook llvm-mode) - -(def-package! glsl-mode - :mode "\\.glsl$" - :mode "\\.vert$" - :mode "\\.frag$" - :mode "\\.geom$") +(def-package! demangle-mode :hook llvm-mode) ;; @@ -213,7 +204,12 @@ compilation database is present in the project.") (def-package! rtags :commands rtags-executable-find :init - (add-hook! (c-mode c++-mode) #'+cc|init-rtags) + (defun +cc|init-rtags () + "Start an rtags server in c-mode and c++-mode buffers." + (when (and (memq major-mode '(c-mode c++-mode)) + (rtags-executable-find "rtags")) + (rtags-start-process-unless-running))) + (add-hook 'c-mode-common-hook #'+cc|init-rtags) :config (setq rtags-autostart-diagnostics t rtags-use-bookmarks nil diff --git a/modules/lang/cc/doctor.el b/modules/lang/cc/doctor.el index 442798ce4..5f9799ecf 100644 --- a/modules/lang/cc/doctor.el +++ b/modules/lang/cc/doctor.el @@ -7,9 +7,9 @@ (warn! "Couldn't find the rtag client and/or server programs %s. Disabling rtags support" bins))) ;; irony server -(require 'irony) -(unless (file-directory-p irony-server-install-prefix) - (warn! "Irony server isn't installed. Run M-x irony-install-server")) +(when (require 'irony nil t) + (unless (file-directory-p irony-server-install-prefix) + (warn! "Irony server isn't installed. Run M-x irony-install-server"))) (when (featurep! :completion company) ;; glslangValidator diff --git a/modules/lang/clojure/config.el b/modules/lang/clojure/config.el index 53a18eded..e78813ef5 100644 --- a/modules/lang/clojure/config.el +++ b/modules/lang/clojure/config.el @@ -1,13 +1,7 @@ ;;; lang/clojure/config.el -*- lexical-binding: t; -*- -(def-package! clojure-mode - :mode "\\.clj$" - :mode "\\.edn$" - :mode "\\(?:build\\|profile\\)\\.boot$" - :mode ("\\.cljs$" . clojurescript-mode) - :mode ("\\.cljc$" . clojurec-mode) - :config - (add-hook 'clojure-mode #'rainbow-delimiters-mode)) +;; `clojure-mode' +(add-hook 'clojure-mode #'rainbow-delimiters-mode) (def-package! clj-refactor diff --git a/modules/lang/crystal/config.el b/modules/lang/crystal/config.el index f1b765e72..717a4137c 100644 --- a/modules/lang/crystal/config.el +++ b/modules/lang/crystal/config.el @@ -1,8 +1,7 @@ ;;; lang/crystal/config.el -*- lexical-binding: t; -*- (def-package! crystal-mode - :mode "\\.cr$" - :interpreter "crystal" + :defer t :config (set! :lookup 'crystal-mode :definition #'crystal-def-jump @@ -19,5 +18,4 @@ :config (add-hook 'crystal-mode-hook #'flycheck-mode)) -(def-package! inf-crystal - :commands (inf-crystal crystal-switch-to-inf)) +(def-package! inf-crystal :commands crystal-switch-to-inf) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index 306f93b12..c7ecabe28 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -1,17 +1,16 @@ ;;; lang/csharp/config.el -*- lexical-binding: t; -*- -(def-package! csharp-mode :mode "\\.cs$") - -(def-package! shader-mode :mode "\\.shader$") ; unity shaders +(add-to-list 'auto-mode-alist '("\\.shader$" . shader-mode)) ; unity shaders (def-package! omnisharp - :after csharp-mode + :hook (csharp-mode . omnisharp-mode) + :commands omnisharp-install-server :preface (setq omnisharp-auto-complete-want-documentation nil omnisharp-cache-directory (concat doom-cache-dir "omnisharp")) :config - (add-hook! csharp-mode #'(flycheck-mode omnisharp-mode)) + (add-hook 'csharp-mode-hook #'flycheck-mode) (defun +csharp|cleanup-omnisharp-server () "Clean up the omnisharp server once you kill the last csharp-mode buffer." diff --git a/modules/lang/data/config.el b/modules/lang/data/config.el index 60b1af9b2..77e9723de 100644 --- a/modules/lang/data/config.el +++ b/modules/lang/data/config.el @@ -1,47 +1,30 @@ ;;; lang/data/config.el -*- lexical-binding: t; -*- -(push '("/sxhkdrc" . conf-mode) auto-mode-alist) +;; Built in plugins +(dolist (spec '(("/sxhkdrc\\'" . conf-mode) + ("\\.\\(?:hex\\|nes\\)\\'" . hexl-mode) + ("\\.plist\\'" . nxml-mode))) + (map-put auto-mode-alist (car spec) (cdr spec))) + +(set! :company-backend 'nxml-mode '(company-nxml company-yasnippet)) -(def-package! dockerfile-mode - :mode "/Dockerfile$") - +;; +;; Third-party plugins +;; (def-package! graphql-mode - :mode "\\.g\\(?:raph\\)?ql$") - - -(def-package! hexl ; For ROM hacking or debugging - :mode ("\\.hex$" . hexl-mode) - :mode ("\\.nes$" . hexl-mode)) - + :mode "\\.gql\\'") (def-package! json-mode - :mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)$" + :mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)\\'" :config (when (featurep! :feature syntax-checker) (add-hook 'json-mode-hook #'flycheck-mode)) (set! :electric 'json-mode :chars '(?\n ?: ?{ ?}))) - -(def-package! nxml-mode - :mode "\\.plist$" - :config - (set! :company-backend 'nxml-mode '(company-nxml company-yasnippet))) - - -(def-package! toml-mode - :mode "\\.toml$") - - (def-package! vimrc-mode - :mode "/\\.?g?vimrc$" - :mode "\\.vimp?$" - :mode "\\.?vimperatorrc$") - - -(def-package! yaml-mode - :mode "\\.ya?ml$") + :mode "\\.?vimperatorrc\\'") ;; diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index 590bb545a..6afd25471 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -1,21 +1,18 @@ ;;; lang/elixir/config.el -*- lexical-binding: t; -*- (def-package! elixir-mode - :mode "\\.exs?\\'" - :mode "\\.elixir2\\'" - :init - ;; sp's default elixir rules are obnoxious, so disable them - (provide 'smartparens-elixir) + :defer t :config ;; ...and only complete the basics - (sp-with-modes 'elixir-mode - (sp-local-pair "do" "end" - :when '(("RET" "")) - :unless '(sp-in-comment-p sp-in-string-p) - :skip-match 'sp-elixir-skip-def-p - :post-handlers '("||\n[i]")) - (sp-local-pair "do " " end" :unless '(sp-in-comment-p sp-in-string-p)) - (sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p)))) + (after! smartparens + (sp-with-modes 'elixir-mode + (sp-local-pair "do" "end" + :when '(("RET" "")) + :unless '(sp-in-comment-p sp-in-string-p) + :skip-match 'sp-elixir-skip-def-p + :post-handlers '("||\n[i]")) + (sp-local-pair "do " " end" :unless '(sp-in-comment-p sp-in-string-p)) + (sp-local-pair "fn " " end" :unless '(sp-in-comment-p sp-in-string-p))))) (def-package! alchemist @@ -30,13 +27,13 @@ (def-package! alchemist-company :when (featurep! :completion company) - :after elixir-mode + :commands alchemist-company + :init + (set! :company-backend 'elixir-mode '(alchemist-company company-yasnippet)) :config ;; Alchemist doesn't use hook symbols to add these backends, so we have to use ;; the entire closure to get rid of it. (let ((fn (byte-compile (lambda () (add-to-list (make-local-variable 'company-backends) 'alchemist-company))))) (remove-hook 'alchemist-mode-hook fn) - (remove-hook 'alchemist-iex-mode-hook fn)) - - (set! :company-backend 'elixir-mode '(alchemist-company company-yasnippet))) + (remove-hook 'alchemist-iex-mode-hook fn))) diff --git a/modules/lang/elm/config.el b/modules/lang/elm/config.el index 6bc5f9c00..6cf23914d 100644 --- a/modules/lang/elm/config.el +++ b/modules/lang/elm/config.el @@ -1,13 +1,12 @@ ;;; lang/elm/config.el -*- lexical-binding: t; -*- -(def-package! elm-mode - :mode "\\.elm$" - :config - (load "elm-mode-autoloads" nil t) - (add-hook! 'elm-mode-hook #'(flycheck-mode rainbow-delimiters-mode)) - (set! :company-backend 'elm-mode '(company-elm)) - (set! :repl 'elm-mode #'run-elm-interactive) - (setq elm-format-on-save t)) +;; `elm-mode' +(setq elm-format-on-save t) + +(add-hook! 'elm-mode-hook #'(flycheck-mode rainbow-delimiters-mode)) + +(set! :company-backend 'elm-mode 'company-elm) +(set! :repl 'elm-mode #'run-elm-interactive) (def-package! flycheck-elm diff --git a/modules/lang/emacs-lisp/autoload.el b/modules/lang/emacs-lisp/autoload.el index 05e3b6e96..4071df3f1 100644 --- a/modules/lang/emacs-lisp/autoload.el +++ b/modules/lang/emacs-lisp/autoload.el @@ -1,5 +1,13 @@ ;;; lang/emacs-lisp/autoload.el -*- lexical-binding: t; -*- +;;;###autoload +(autoload 'overseer-test "overseer" nil t) + + +;; +;; Library +;; + ;;;###autoload (defun +emacs-lisp/repl () "Open the Emacs Lisp REPL (`ielm')." diff --git a/modules/lang/emacs-lisp/config.el b/modules/lang/emacs-lisp/config.el index 20033e171..97172e8b6 100644 --- a/modules/lang/emacs-lisp/config.el +++ b/modules/lang/emacs-lisp/config.el @@ -67,27 +67,17 @@ ;; Plugins ;; -(def-package! auto-compile - :commands auto-compile-on-save-mode - :config - (setq auto-compile-display-buffer nil - auto-compile-use-mode-line nil)) +;; `auto-compile' +(setq auto-compile-display-buffer nil + auto-compile-use-mode-line nil) -(def-package! highlight-quoted - :commands highlight-quoted-mode) +;; `slime' +(setq inferior-lisp-program "clisp") +(after! slime (require 'slime-fuzzy)) -(def-package! slime - :defer t - :config - (setq inferior-lisp-program "clisp") - (require 'slime-fuzzy)) - - -(def-package! macrostep - :commands macrostep-expand - :config +(after! macrostep (map! :map macrostep-keymap :n "RET" #'macrostep-expand :n "e" #'macrostep-expand @@ -104,6 +94,7 @@ :n "q" #'macrostep-collapse-all :n "C" #'macrostep-collapse-all) + ;; `evil-normalize-keymaps' seems to be required for macrostep or it won't ;; apply for the very first invocation (add-hook 'macrostep-mode-hook #'evil-normalize-keymaps)) @@ -111,18 +102,14 @@ (def-package! flycheck-cask :when (featurep! :feature syntax-checker) - :commands flycheck-cask-setup + :defer t :init (add-hook! 'emacs-lisp-mode-hook (add-hook 'flycheck-mode-hook #'flycheck-cask-setup nil t))) -(def-package! overseer - :commands overseer-test) - - -;; ;; +;; Project modes ;; (def-project-mode! +emacs-lisp-ert-mode diff --git a/modules/lang/erlang/config.el b/modules/lang/erlang/config.el index 8a180d37a..933c455f4 100644 --- a/modules/lang/erlang/config.el +++ b/modules/lang/erlang/config.el @@ -1,20 +1,19 @@ ;;; private/erlang/config.el -*- lexical-binding: t; -*- -(def-package! erlang - ;; customizations - :mode "\\.erlang$" - ;; rebar files - :mode "/rebar\\.config\\(?:\\.script\\)?$" - ;; erlang configs - :mode "/\\(?:app\\|sys\\)\\.config$") +(dolist (regexp '("\\.erlang$" + ;; rebar files + "/rebar\\.config\\(?:\\.script\\)?$" + ;; erlang configs + "/\\(?:app\\|sys\\)\\.config$")) + (map-put auto-mode-alist regexp 'erlang-mode)) + (def-package! flycheck-rebar3 :when (featurep! :feature syntax-checker) - :after erlang - :config - (flycheck-rebar3-setup)) + :after flycheck + :config (flycheck-rebar3-setup)) + -;; Completion via Ivy (def-package! ivy-erlang-complete :when (featurep! :completion ivy) :hook (erlang-mode . ivy-erlang-complete-init) @@ -23,7 +22,6 @@ (add-hook 'after-save-hook #'ivy-erlang-complete-reparse nil t))) -;; Completion via Company (def-package! company-erlang :when (featurep! :completion company) :hook (erlang-mode . company-erlang-init)) diff --git a/modules/lang/ess/config.el b/modules/lang/ess/config.el index e08657a08..a1fc837b2 100644 --- a/modules/lang/ess/config.el +++ b/modules/lang/ess/config.el @@ -79,6 +79,6 @@ :n "cn" #'ess-noweb-next-chunk)))) -(def-package! ess-smart-equals - :hook ((ess-mode . ess-smart-equals-mode) - (inferior-ess-mode . ess-smart-equals-mode))) +;; `ess-smart-equals-mode' +(add-hook! (ess-mode inferior-ess) + #'ess-smart-equals-mode) diff --git a/modules/lang/go/config.el b/modules/lang/go/config.el index 34e4d57d5..f8e8c6050 100644 --- a/modules/lang/go/config.el +++ b/modules/lang/go/config.el @@ -4,10 +4,7 @@ ;; Plugins ;; -(def-package! go-mode - :mode "\\.go$" - :interpreter "go" - :config +(after! go-mode (set! :env "GOPATH" "GOROOT") (set! :repl 'go-mode #'gorepl-run) (set! :lookup 'go-mode @@ -15,11 +12,12 @@ :references #'go-guru-referrers :documentation #'godoc-at-point) - (when (executable-find "goimports") - (setq gofmt-command "goimports")) + (when-let* ((goimports (executable-find "goimports"))) + (setq gofmt-command goimports)) (setq gofmt-show-errors nil) ; Leave it to flycheck - (add-hook 'go-mode-hook #'flycheck-mode) + + (add-hook! 'go-mode-hook #'(flycheck-mode go-eldoc-setup)) (add-hook! go-mode (add-hook 'before-save-hook #'gofmt-before-save nil t)) @@ -70,25 +68,13 @@ :v "r" #'go-play-region)) -(def-package! go-eldoc - :hook (go-mode . go-eldoc-setup)) - - -(def-package! go-guru - :commands (go-guru-describe go-guru-freevars go-guru-implements go-guru-peers - go-guru-referrers go-guru-definition go-guru-pointsto - go-guru-callstack go-guru-whicherrs go-guru-callers go-guru-callees - go-guru-expand-region)) - - (def-package! gorepl-mode - :commands (gorepl-run gorepl-run-load-current-file)) + :commands gorepl-run-load-current-file) (def-package! company-go :when (featurep! :completion company) - :init (setq command-go-gocode-command "gocode") :after go-mode :config - (setq company-go-show-annotation t) - (set! :company-backend 'go-mode '(company-go))) + (set! :company-backend 'go-mode 'company-go) + (setq company-go-show-annotation t)) diff --git a/modules/lang/haskell/config.el b/modules/lang/haskell/config.el index a97fa9bff..559b244aa 100644 --- a/modules/lang/haskell/config.el +++ b/modules/lang/haskell/config.el @@ -8,18 +8,7 @@ ;; Common plugins ;; -(def-package! haskell-mode - :mode "\\.hs$" - :mode ("\\.ghci$" . ghci-script-mode) - :mode ("\\.cabal$" . haskell-cabal-mode) - :interpreter (("runghc" . haskell-mode) - ("runhaskell" . haskell-mode)) - :config - (load "haskell-mode-autoloads" nil t) +(after! haskell-mode (set! :repl 'haskell-mode #'switch-to-haskell) - (push ".hi" completion-ignored-extensions) - - (autoload 'switch-to-haskell "inf-haskell" nil t) - (after! inf-haskell - (map! :map inferior-haskell-mode-map "ESC ESC" #'+popup/close))) + (add-to-list 'completion-ignored-extensions ".hi")) diff --git a/modules/lang/hy/config.el b/modules/lang/hy/config.el index bc106c784..bd24be0da 100644 --- a/modules/lang/hy/config.el +++ b/modules/lang/hy/config.el @@ -1,8 +1,8 @@ ;;; lang/hy/config.el -*- lexical-binding: t; -*- (def-package! hy-mode - :mode "\\.hy$" + :mode "\\.hy\\'" :interpreter "hy" :config (set! :repl 'hy-mode #'hy-shell-start-or-switch-to-shell) - (set! :company-backend 'hy-mode '(company-hy))) + (set! :company-backend 'hy-mode 'company-hy)) diff --git a/modules/lang/java/config.el b/modules/lang/java/config.el index 8be32f44c..5ace2680a 100644 --- a/modules/lang/java/config.el +++ b/modules/lang/java/config.el @@ -3,8 +3,8 @@ (add-hook 'java-mode-hook #'rainbow-delimiters-mode) (cond ((featurep! +meghanada) (load! +meghanada)) - ;; TODO lang/java +eclim - ;; ((featurep! +eclim) (load! +eclim)) + ;; TODO lang/java +lsp (lsp-java?) + ;; ((featurep! +lsp) (load! +lsp)) ) diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index ff5991288..c5721ff22 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -22,6 +22,7 @@ (add-hook! 'js2-mode-hook #'(flycheck-mode rainbow-delimiters-mode)) (set! :electric 'js2-mode :chars '(?\} ?\) ?. ?:)) + (set! :repl 'js2-mode #'+javascript/repl) ;; Conform switch-case indentation to js2 normal indent (defvaralias 'js-switch-indent-offset 'js2-basic-offset) @@ -31,19 +32,10 @@ (map! :map js2-mode-map :localleader - :n "S" #'+javascript/skewer-this-buffer)) - - -(def-package! typescript-mode - :commands typescript-mode - :config - (add-hook! 'typescript-mode-hook #'(flycheck-mode rainbow-delimiters-mode)) - (set! :electric 'typescript-mode - :chars '(?\} ?\)) :words '("||" "&&"))) + :n "S" #'+javascript/skewer-this-buffer)) (def-package! rjsx-mode - :commands rjsx-mode :mode "components/.+\\.js$" :init (defun +javascript-jsx-file-p () @@ -54,8 +46,7 @@ magic-mode-regexp-match-limit t) (progn (goto-char (match-beginning 1)) (not (sp-point-in-string-or-comment))))) - - (push '(+javascript-jsx-file-p . rjsx-mode) magic-mode-alist) + (map-put magic-mode-alist #'+javascript-jsx-file-p 'rjsx-mode) :config (set! :electric 'rjsx-mode :chars '(?\} ?\) ?. ?>)) (add-hook! 'rjsx-mode-hook @@ -67,14 +58,19 @@ ;; However, the parser doesn't run immediately, so a fast typist can outrun ;; it, causing issues, so force it to parse. (defun +javascript|reparse (n) - ;; if n != 1, then rjsx-maybe-reparse will be run elsewhere + ;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself (if (= n 1) (rjsx-maybe-reparse))) (advice-add #'rjsx-electric-gt :before #'+javascript|reparse)) -(def-package! coffee-mode - :defer t ; file extensions registered by autoloads file - :init (setq coffee-indent-like-python-mode t)) +(after! typescript-mode + (add-hook! 'typescript-mode-hook #'(flycheck-mode rainbow-delimiters-mode)) + (set! :electric 'typescript-mode + :chars '(?\} ?\)) :words '("||" "&&"))) + + +;; `coffee-mode' +(setq coffee-indent-like-python-mode t) ;; @@ -86,6 +82,7 @@ :hook (typescript-mode . tide-setup) :init (defun +javascript|init-tide-in-web-mode () + "Enable `tide-mode' if in a *.tsx file." (when (string= (file-name-extension (or buffer-file-name "")) "tsx") (tide-setup))) (add-hook 'web-mode-hook #'+javascript|init-tide-in-web-mode) @@ -156,12 +153,6 @@ :init (set! :lookup 'js2-mode :xref-backend #'xref-js2-xref-backend)) -(def-package! nodejs-repl - :commands nodejs-repl - :init - (set! :repl 'js2-mode #'+javascript/repl)) - - (def-package! js2-refactor :commands (js2r-extract-function js2r-extract-method js2r-introduce-parameter @@ -174,51 +165,38 @@ js2r-debug-this js2r-forward-slurp js2r-forward-barf)) -(def-package! web-beautify - :commands web-beautify-js - :init - (map! :map* (json-mode js2-mode-map) :n "gQ" #'web-beautify-js)) - - (def-package! eslintd-fix - :commands (eslintd-fix-mode eslintd-fix) + :commands eslintd-fix :config (defun +javascript|set-flycheck-executable-to-eslint () (setq flycheck-javascript-eslint-executable eslintd-fix-executable)) (add-hook 'eslintd-fix-mode-hook #'+javascript|set-flycheck-executable-to-eslint)) -(def-package! skewer-mode - :commands (skewer-mode run-skewer) - :config - (map! :map skewer-mode-map +;; `skewer-mode' +(map! (:after skewer-mode + :map skewer-mode-map :localleader :n "sE" #'skewer-eval-last-expression :n "se" #'skewer-eval-defun - :n "sf" #'skewer-load-buffer)) + :n "sf" #'skewer-load-buffer) - -(def-package! skewer-css ; in skewer-mode - :commands skewer-css-mode - :config - (map! :map skewer-css-mode-map + (:after skewer-css + :map skewer-css-mode-map :localleader :n "se" #'skewer-css-eval-current-declaration :n "sr" #'skewer-css-eval-current-rule :n "sb" #'skewer-css-eval-buffer - :n "sc" #'skewer-css-clear-all)) + :n "sc" #'skewer-css-clear-all) - -(def-package! skewer-html ; in skewer-mode - :commands skewer-html-mode - :config - (map! :map skewer-html-mode-map + (:after skewer-html + :map skewer-html-mode-map :localleader :n "se" #'skewer-html-eval-tag)) -(def-package! skewer-repl - :commands skewer-repl) +;; `web-beautify' +(map! :map* (json-mode-map js2-mode-map) :n "gQ" #'web-beautify-js) ;; @@ -226,7 +204,7 @@ ;; (def-project-mode! +javascript-screeps-mode - :match "/screeps\\(-ai\\)?/.+$" + :match "/screeps\\(?:-ai\\)?/.+$" :modes (+javascript-npm-mode) :add-hooks (+javascript|init-screeps-mode) :on-load (load! +screeps)) diff --git a/modules/lang/julia/config.el b/modules/lang/julia/config.el index 2656fd4c8..c7be5a650 100644 --- a/modules/lang/julia/config.el +++ b/modules/lang/julia/config.el @@ -1,7 +1,6 @@ ;;; lang/julia/config.el -*- lexical-binding: t; -*- (use-package julia-mode - :mode "\\.jl$" :interpreter "julia" :config (set! :repl 'julia-mode #'+julia/repl) diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index 29ecefa08..dd33daf0f 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -18,9 +18,6 @@ "Sets the directory where AUCTeX will search for PDFs associated to BibTeX references." `(setq +latex-bibtex-dir ,dir)) -;; sp's default latex rules are obnoxious, so disable them -(provide 'smartparens-latex) - ;; ;; Plugins diff --git a/modules/lang/ledger/config.el b/modules/lang/ledger/config.el index 5db4e7c71..0df0dbc5f 100644 --- a/modules/lang/ledger/config.el +++ b/modules/lang/ledger/config.el @@ -1,8 +1,7 @@ ;;; lang/ledger/config.el -*- lexical-binding: t; -*- -(def-package! ledger-mode - :mode "\\.ledger$" - :config (setq ledger-clear-whole-transactions 1)) +;; `ledger-mode' +(setq ledger-clear-whole-transactions 1) (def-package! evil-ledger @@ -12,4 +11,5 @@ (def-package! flycheck-ledger :when (featurep! :feature syntax-checker) - :init (add-hook 'ledger-mode-hook #'flycheck-mode)) + :after ledger-mode + :config (add-hook 'ledger-mode-hook #'flycheck-mode)) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index 9a2dece5a..d8557f3b3 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -1,18 +1,12 @@ ;;; lang/lua/config.el -*- lexical-binding: t; -*- -(def-package! lua-mode - :mode "\\.lua$" - :interpreter "lua" - :init - ;; sp's default lua rules are obnoxious, so disable them. Use snippets - ;; instead! - (provide 'smartparens-lua) - :config +(after! lua-mode (add-hook 'lua-mode-hook #'flycheck-mode) (set! :lookup 'lua-mode :documentation 'lua-search-documentation) (set! :electric 'lua-mode :words '("else" "end")) (set! :repl 'lua-mode #'+lua/repl) + (set! :company-backend 'lua-mode '(company-lua company-yasnippet)) (def-menu! +lua/build-menu "Build/compilation commands for `lua-mode' buffers." @@ -24,15 +18,8 @@ :n "b" #'+lua/build-menu)) -(def-package! company-lua - :after (:all company lua-mode) - :config - (set! :company-backend 'lua-mode '(company-lua company-yasnippet))) - - -(def-package! moonscript - :mode ("\\.moon$" . moonscript-mode) - :config (defvaralias 'moonscript-indent-offset 'tab-width)) +(after! moonscript + (defvaralias 'moonscript-indent-offset 'tab-width)) ;; diff --git a/modules/lang/markdown/config.el b/modules/lang/markdown/config.el index b45cbe084..0438171e0 100644 --- a/modules/lang/markdown/config.el +++ b/modules/lang/markdown/config.el @@ -1,9 +1,7 @@ ;;; lang/markdown/config.el -*- lexical-binding: t; -*- (def-package! markdown-mode - :mode "/README$" - :mode ("/README\\.md$" . gfm-mode) - :mode "\\.m\\(?:d\\|arkdown\\)$" + :mode ("/README\\(?:\\.\\(?:markdown\\|md\\)\\)?\\'" . gfm-mode) :init (setq markdown-enable-wiki-links t markdown-enable-math t diff --git a/modules/lang/nim/config.el b/modules/lang/nim/config.el index 4beffb199..c43aab0aa 100644 --- a/modules/lang/nim/config.el +++ b/modules/lang/nim/config.el @@ -1,32 +1,20 @@ ;;; lang/nim/config.el -*- lexical-binding: t; -*- -(def-package! nim-mode - :mode "\\.nim\\'" - :mode ("\\.nim\\(ble\\|s\\)\\'" . nimscript-mode) - :config - (load "nim-mode-autoloads" nil t) - ;; NOTE nim-mode autoloads sets up xref - +(after! nim-mode (defun +nim|init-nimsuggest-mode () "Conditionally load `nimsuggest-mode', instead of clumsily erroring out if nimsuggest isn't installed." - (when (executable-find "nimsuggest") + (when (file-executable-p nimsuggest-path) (nimsuggest-mode))) (add-hook 'nim-mode-hook #'+nim|init-nimsuggest-mode) (map! :map nim-mode-map :localleader - :n "b" #'+nim/build-menu) - - (def-menu! +nim/build-menu - "Building commands for `nim-mode' buffers." - '(("Build & run" :exec nim-compile)) - :prompt "Build")) + :n "b" #'nim-compile)) (def-package! flycheck-nim :when (featurep! :feature syntax-checker) :after nim-mode - :config - (add-hook 'nimsuggest-mode-hook #'flycheck-mode)) + :config (add-hook 'nimsuggest-mode-hook #'flycheck-mode)) diff --git a/modules/lang/nix/config.el b/modules/lang/nix/config.el deleted file mode 100644 index e9d090fc3..000000000 --- a/modules/lang/nix/config.el +++ /dev/null @@ -1,4 +0,0 @@ -;;; lang/nix/config.el -*- lexical-binding: t; -*- - -(def-package! nix-mode - :mode "\\.nix$") diff --git a/modules/lang/ocaml/config.el b/modules/lang/ocaml/config.el index 22067cffb..bdd4974d2 100644 --- a/modules/lang/ocaml/config.el +++ b/modules/lang/ocaml/config.el @@ -1,9 +1,13 @@ ;;; lang/ocaml/config.el -*- lexical-binding: t; -*- (def-package! tuareg - :mode ("\\.ml[4ilpy]?$" . tuareg-mode)) + :mode ("\\.ml[4ilpy]?\\'" . tuareg-mode)) (def-package! merlin :after tuareg - :hook (tuareg-mode . merlin-mode)) + :hook (tuareg-mode . merlin-mode) + :config + (set! :company-backend 'tuareg-mode 'merlin-compand-backend) + (after! company + (remove-hook 'company-backends 'merlin-compand-backend))) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index a2c17bb28..ba5449039 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -16,12 +16,8 @@ ;; Plugins ;; -(def-package! toc-org - :commands toc-org-enable - :config (setq toc-org-hrefify-default "org")) - -(def-package! org-bullets - :commands org-bullets-mode) +;; `toc-org' +(setq toc-org-hrefify-default "org") (def-package! evil-org :when (featurep! :feature evil) diff --git a/modules/lang/plantuml/config.el b/modules/lang/plantuml/config.el index cb66d1495..a60b92e92 100644 --- a/modules/lang/plantuml/config.el +++ b/modules/lang/plantuml/config.el @@ -1,7 +1,7 @@ ;;; lang/plantuml/config.el -*- lexical-binding: t; -*- (def-package! plantuml-mode - :mode "\\.p\\(?:lant\\)?uml$" + :defer t :init (setq plantuml-jar-path (concat doom-etc-dir "plantuml.jar") org-plantuml-jar-path plantuml-jar-path) diff --git a/modules/lang/purescript/config.el b/modules/lang/purescript/config.el index 39eafd64c..579391e8e 100644 --- a/modules/lang/purescript/config.el +++ b/modules/lang/purescript/config.el @@ -1,16 +1,18 @@ ;;; lang/purescript/config.el -*- lexical-binding: t; -*- -(def-package! purescript-mode - :mode "\\.purs$" - :config +(after! purescript-mode (add-hook! 'purescript-mode-hook - #'(flycheck-mode purescript-indentation-mode rainbow-delimiters-mode))) + #'(flycheck-mode + purescript-indentation-mode + rainbow-delimiters-mode))) + ;; (def-package! flycheck-purescript ;; :after purescript-mode ;; :config ;; (add-hook 'flycheck-mode-hook #'flycheck-purescript-setup)) + (def-package! psc-ide :hook (purescript-mode . psc-ide-mode)) diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 4c6fe44f1..4e129b9d3 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -16,7 +16,7 @@ is loaded.") ;; (def-package! python - :commands python-mode + :defer t :init (setq python-environment-directory doom-cache-dir python-indent-guess-indent-offset-verbose nil @@ -73,7 +73,6 @@ environment variables." (def-package! anaconda-mode - :after python :hook python-mode :init (setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/") diff --git a/modules/lang/rest/config.el b/modules/lang/rest/config.el index c3781d2b1..117908050 100644 --- a/modules/lang/rest/config.el +++ b/modules/lang/rest/config.el @@ -1,8 +1,7 @@ ;;; lang/rest/config.el -*- lexical-binding: t; -*- (def-package! restclient - :commands restclient-mode - :mode ("\\.http$" . restclient-mode) + :mode ("\\.http\\'" . restclient-mode) :config (set! :popup "^\\*HTTP Response" '((size . 0.4)) '((quit . other))) (map! :mode restclient-mode @@ -16,4 +15,4 @@ (def-package! company-restclient :when (featurep! :completion company) :after restclient - :config (set! :company-backend 'restclient-mode '(company-restclient))) + :config (set! :company-backend 'restclient-mode 'company-restclient)) diff --git a/modules/lang/ruby/config.el b/modules/lang/ruby/config.el index 3d4fd3ae3..5eb32b4fc 100644 --- a/modules/lang/ruby/config.el +++ b/modules/lang/ruby/config.el @@ -12,15 +12,12 @@ ;; (def-package! ruby-mode - :mode "\\.rb$" - :mode "\\.rake$" - :mode "\\.gemspec$" - :mode "\\.\\(?:pry\\|irb\\)rc$" - :mode "/\\(?:Gem\\|Cap\\|Vagrant\\|Rake\\|Pod\\|Puppet\\|Berks\\)file$" - :interpreter "ruby" + :mode "\\.\\(?:pry\\|irb\\)rc\\'" :config - (set! :company-backend 'ruby-mode '(company-dabbrev-code)) + (set! :company-backend 'ruby-mode 'company-dabbrev-code) (set! :electric 'ruby-mode :words '("else" "end" "elseif")) + (set! :env "RBENV_ROOT") + (set! :repl 'ruby-mode #'inf-ruby) ; `inf-ruby' (setq ruby-deep-indent-paren t) ;; Don't interfere with my custom RET behavior (define-key ruby-mode-map [?\n] nil) @@ -74,10 +71,8 @@ environment variables." (def-package! rspec-mode - :mode ("/\\.rspec$" . text-mode) + :mode ("/\\.rspec\\'" . text-mode) :init - (associate! rspec-mode :match "/\\.rspec$") - (associate! rspec-mode :modes (ruby-mode yaml-mode) :files ("/spec/")) (defvar rspec-mode-verifiable-map (make-sparse-keymap)) (defvar evilmi-ruby-match-tags '((("unless" "if") ("elsif" "else") "end") @@ -96,18 +91,12 @@ environment variables." :n "v" #'rspec-verify)) -(def-package! inf-ruby - :commands (inf-ruby inf-ruby-console-auto) - :init (set! :repl 'ruby-mode 'inf-ruby)) - - (def-package! company-inf-ruby :when (featurep! :completion company) :after inf-ruby - :config (set! :company-backend 'inf-ruby-mode '(company-inf-ruby))) + :config (set! :company-backend 'inf-ruby-mode 'company-inf-ruby)) -(def-package! rake - :commands (rake rake-find-task rake-rerun) - :config (setq rake-completion-system 'default)) +;; `rake' +(setq rake-completion-system 'default) diff --git a/modules/lang/rust/config.el b/modules/lang/rust/config.el index 9a45ae71e..cd216273f 100644 --- a/modules/lang/rust/config.el +++ b/modules/lang/rust/config.el @@ -1,12 +1,6 @@ ;;; lang/rust/config.el -*- lexical-binding: t; -*- -;; -;; Plugins -;; - -(def-package! rust-mode - :mode "\\.rs$" - :config +(after! rust-mode (set! :env "RUST_SRC_PATH") (set! :docset 'rust-mode "Rust") (setq rust-indent-method-chain t) @@ -14,6 +8,7 @@ (map! :map rust-mode-map :localleader :n "b" #'+rust/build-menu) + (def-menu! +rust/build-menu "TODO" '(("cargo run" :exec "cargo run --color always") @@ -40,6 +35,5 @@ (def-package! flycheck-rust :when (featurep! :feature syntax-checker) :after rust-mode - :hook (flycheck-mode . flycheck-rust-setup) - :init (add-hook 'rust-mode-hook #'flycheck-mode)) + :config (add-hook! 'rust-mode-hook #'(flycheck-mode flycheck-rust-setup))) diff --git a/modules/lang/scala/config.el b/modules/lang/scala/config.el index b5a2a1bf0..44a39ced9 100644 --- a/modules/lang/scala/config.el +++ b/modules/lang/scala/config.el @@ -1,26 +1,24 @@ ;;; lang/scala/config.el -*- lexical-binding: t; -*- -(def-package! scala-mode - :mode "\\.s\\(?:cala\\|bt\\)$" - :config (setq scala-indent:align-parameters t)) +(after! scala-mode + (setq scala-indent:align-parameters t) + (add-to-list 'dtrt-indent-hook-mapping-list '(scala-mode c/c++/java scala-indent:step))) -(def-package! sbt-mode :after scala-mode) - - -(def-package! ensime - :commands (ensime ensime-scala-mode-hook) - :hook (scala-mode . ensime-mode) - :config - (set! :company-backend 'scala-mode '(ensime-company company-yasnippet)) - +(after! ensime (setq ensime-startup-snapshot-notification nil ensime-startup-notification nil ensime-eldoc-hints 'all ;; let DOOM handle company setup ensime-completion-style nil) + (set! :company-backend 'scala-mode '(ensime-company company-yasnippet)) + ;; Fix void-variable imenu-auto-rescan error caused by `ensime--setup-imenu' ;; trying to make imenu variables buffer local before imenu is loaded. (require 'imenu)) + +(def-package! sbt-mode + :after scala-mode + :config (set! :repl 'scala-mode #'run-scala)) diff --git a/modules/lang/sh/config.el b/modules/lang/sh/config.el index d100a8c86..21444fb91 100644 --- a/modules/lang/sh/config.el +++ b/modules/lang/sh/config.el @@ -12,21 +12,19 @@ ;; (def-package! sh-script ; built-in - :mode ("\\.zsh$" . sh-mode) - :mode ("\\.zunit$" . sh-mode) - :mode ("/bspwmrc$" . sh-mode) - :init - (add-hook! sh-mode #'(flycheck-mode highlight-numbers-mode)) + :mode ("\\.zunit\\'" . sh-mode) + :mode ("/bspwmrc\\'" . sh-mode) :config + (add-hook! sh-mode #'(flycheck-mode highlight-numbers-mode)) (set! :electric 'sh-mode :words '("else" "elif" "fi" "done" "then" "do" "esac" ";;")) (set! :repl 'sh-mode #'+sh/repl) (setq sh-indent-after-continuation 'always) ;; recognize function names with dashes in them - (push '((sh . ((nil "^\\s-*function\\s-+\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*\\(?:()\\)?" 1) - (nil "^\\s-*\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*()" 1)))) - sh-imenu-generic-expression) + (map-put sh-imenu-generic-expression + 'sh '((nil "^\\s-*function\\s-+\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*\\(?:()\\)?" 1) + (nil "^\\s-*\\([[:alpha:]_-][[:alnum:]_-]*\\)\\s-*()" 1))) ;; `sh-set-shell' is chatty about setting up indentation rules (advice-add #'sh-set-shell :around #'doom*shut-up) diff --git a/modules/lang/swift/config.el b/modules/lang/swift/config.el index 9daae8f3a..6ba19cf0e 100644 --- a/modules/lang/swift/config.el +++ b/modules/lang/swift/config.el @@ -1,13 +1,14 @@ ;;; lang/swift/config.el -*- lexical-binding: t; -*- -;; TODO Set up emacs task runners for fruitstrap +;; `swift-mode' +(set! :repl 'swift-mode #'run-swift) -(def-package! swift-mode - :mode "\\.swift$" - :config - (add-hook 'swift-mode-hook #'flycheck-mode) - (set! :repl 'swift-mode #'swift-mode-run-repl) ; TODO test this - (push 'swift flycheck-checkers)) + +(def-package! flycheck-swift + :when (featurep! :feature syntax-checker) + :after swift-mode + :init (add-hook 'swift-mode-hook #'flycheck-mode) + :config (flycheck-swift-setup)) (def-package! company-sourcekit diff --git a/modules/lang/swift/packages.el b/modules/lang/swift/packages.el index a9cc3a778..73e74da91 100644 --- a/modules/lang/swift/packages.el +++ b/modules/lang/swift/packages.el @@ -5,3 +5,6 @@ (when (featurep! :completion company) (package! company-sourcekit)) + +(when (featurep! :feature syntax-checker) + (package! flycheck-swift)) diff --git a/modules/lang/web/+css.el b/modules/lang/web/+css.el index d49d19292..834a2ae6e 100644 --- a/modules/lang/web/+css.el +++ b/modules/lang/web/+css.el @@ -1,10 +1,5 @@ ;;; lang/web/+css.el -*- lexical-binding: t; -*- -;; css-mode hooks apply to scss and less-css modes -(add-hook 'css-mode-hook #'rainbow-delimiters-mode) -(add-hook! (css-mode sass-mode stylus-mode) - #'(yas-minor-mode-on flycheck-mode highlight-numbers-mode)) - ;; An improved newline+continue comment function (setq-hook! css-mode comment-indent-function #'+css/comment-indent-new-line) @@ -13,29 +8,36 @@ (sp-local-pair "/*" "*/" :post-handlers '(("||\n[i]" "RET") ("| " "SPC"))))) (map! :map* (css-mode-map scss-mode-map less-css-mode-map) - :n "M-R" #'+css/web-refresh-browser - (:localleader - :n "rb" #'+css/toggle-inline-or-block)) + :localleader + :n "rb" #'+css/toggle-inline-or-block) ;; ;; Packages ;; +;; css-mode hooks apply to scss and less-css modes +(add-hook 'css-mode-hook #'rainbow-delimiters-mode) +(add-hook! (css-mode sass-mode stylus-mode) + #'(yas-minor-mode-on + flycheck-mode + highlight-numbers-mode + rainbow-mode)) + + (def-package! counsel-css :when (featurep! :completion ivy) - :commands (counsel-css counsel-css-imenu-setup) + :commands counsel-css :hook (css-mode . counsel-css-imenu-setup) :init (map! :map* (css-mode-map scss-mode-map less-css-mode-map) :localleader :n ";" #'counsel-css)) -(def-package! rainbow-mode - :hook (css-mode sass-mode)) - - -(after! css-mode ; contains both css-mode & scss-mode +(def-package! css-mode ; built-in + :defer t + :config + ;; contains both css-mode & scss-mode (set! :docset 'css-mode "CSS") (set! :docset 'scss-mode "Sass") (unless EMACS26+ @@ -45,7 +47,7 @@ (def-package! sass-mode - :commands sass-mode + :defer t :config (set! :docset 'sass-mode "Sass") (set! :company-backend 'sass-mode 'company-css) diff --git a/modules/lang/web/+html.el b/modules/lang/web/+html.el index a01979605..4a27bd0ed 100644 --- a/modules/lang/web/+html.el +++ b/modules/lang/web/+html.el @@ -14,7 +14,6 @@ :mode "wp-content/themes/.+/.+\\.php$" :mode "templates/.+\\.php$" :config - (set! :company-backend 'web-mode '(company-web-html company-yasnippet)) (setq web-mode-enable-html-entities-fontification t web-mode-enable-auto-quoting nil) @@ -91,10 +90,7 @@ :nv "[T" #'web-mode-element-parent)) -(def-package! company-web - :when (featurep! :completion company) - :after web-mode) - - -;; `pug-mode' -(set! :company-backend 'pug-mode '(company-yasnippet)) +;; +(set! :company-backend 'pug-mode 'company-web-jade) +(set! :company-backend 'web-mode 'company-web-html) +(set! :company-backend 'slim-mode 'company-web-slim) diff --git a/modules/lang/web/packages.el b/modules/lang/web/packages.el index f89e975d7..9a864d1bc 100644 --- a/modules/lang/web/packages.el +++ b/modules/lang/web/packages.el @@ -13,9 +13,9 @@ (package! haml-mode) (package! pug-mode) (package! slim-mode) -(package! web-mode) -(when (featurep! :completion company) - (package! company-web)) +(when (package! web-mode) + (when (featurep! :completion company) + (package! company-web))) ;; +css.el (package! less-css-mode) diff --git a/modules/tools/editorconfig/config.el b/modules/tools/editorconfig/config.el index 2e5d98795..c458b8a2e 100644 --- a/modules/tools/editorconfig/config.el +++ b/modules/tools/editorconfig/config.el @@ -3,7 +3,8 @@ ;; Handles whitespace (tabs/spaces) settings externally. This way projects can ;; specify their own formatting rules. (def-package! editorconfig - :hook (doom-init . editorconfig-mode) + :defer 2 + :after-call doom-before-switch-buffer :config ;; Register missing indent variables (setq editorconfig-indentation-alist @@ -49,9 +50,7 @@ extension, try to guess one." ;; editorconfig to ignore indentation there. I prefer dynamic indentation ;; support built into Emacs. (dolist (mode '(emacs-lisp-mode lisp-mode)) - (map-delete editorconfig-indentation-alist mode))) - - -(def-package! editorconfig-conf-mode - :mode "\\.?editorconfig$") + (map-delete editorconfig-indentation-alist mode)) + ;; + (editorconfig-mode +1)) diff --git a/modules/tools/ein/autoload.el b/modules/tools/ein/autoload.el index d30f5119e..303deb947 100644 --- a/modules/tools/ein/autoload.el +++ b/modules/tools/ein/autoload.el @@ -1,9 +1,29 @@ ;;; tools/ein/autoload.el -*- lexical-binding: t; -*- +;;;###autoload +(def-setting! :ein-notebook-dir (dir) + "Set the default directory from where to open Jupyter notebooks." + `(setq ein:jupyter-default-notebook-directory ,dir)) + + +;; +;; Library +;; + +(defun +ein--collect-ein-buffer-links () + (let ((end (window-end)) + points) + (save-excursion + (goto-char (window-start)) + (while (re-search-forward "~?/.+\\|\s\\[" end t) + (push (+ (match-beginning 0) 1) points)) + (nreverse points)))) + ;;;###autoload (defun +ein/ace-link-ein () "Ace jump to links in ein notebooklist." (interactive) + (require 'avy) (let ((res (avy-with +ein/ace-link-ein (avy--process (+ein--collect-ein-buffer-links) @@ -13,14 +33,4 @@ (goto-char (1+ res)) (widget-button-press (point))))) -;;;###autoload -(defun +ein--collect-ein-buffer-links () - (interactive) - (let ((end (window-end)) - points) - (save-excursion - (goto-char (window-start)) - (while (re-search-forward "~?/.+\\|\s\\[" end t) - (push (+ (match-beginning 0) 1) points)) - (nreverse points)))) diff --git a/modules/tools/ein/config.el b/modules/tools/ein/config.el index 812e815a5..e3b469254 100644 --- a/modules/tools/ein/config.el +++ b/modules/tools/ein/config.el @@ -3,47 +3,49 @@ (defvar +ein-notebook-dir "~/" "Default directory from where Jupyter notebooks are to be opened.") -(def-setting! :ein-notebook-dir (dir) - "Set the default directory from where to open Jupyter notebooks." - `(setq +ein-notebook-dir ,dir)) +;; +;; Plugins +;; (def-package! ein - :commands (ein:notebooklist-open ein:notebooklist-login ein:jupyter-server-start) + :defer t :init - (push (lambda (buf) (string-match-p "^\\*ein: .*" (buffer-name buf))) - doom-real-buffer-functions) (set! :popup "\\*ein: .*" :ignore) - (set! :popup "\\*ein:tb .*" '((side . bottom) (size . 0.3)) '((quit . t) (transient) (select))) - (set! :popup "\\*ein:notebooklist *" '((side . left) (size . 50)) '((select))) - ;; Ace-link on notebook list buffers - (add-hook! 'ein:notebooklist-mode-hook - (map! :map ein:notebooklist-mode-map - "o" #'+ein/ace-link-ein)) - ;; Ein uses request to store http cookies. Store them in the cache dir. - (setq request-storage-directory (concat doom-cache-dir "/request")) + (set! :popup "\\*ein:tb .*" + '((side . bottom) (size . 0.3)) + '((quit . t) (transient) (select))) + (set! :popup "\\*ein:notebooklist *" + '((side . left) (size . 50)) + '((select))) + ;; Auto complete with company (when (featurep! :completion company) (setq ein:completion-backend 'ein:use-company-backend) - (set! :company-backend - '(ein:notebook-multilang-mode - ein:notebook-python-mode - ein:notebook-plain-mode) + (set! :company-backend '(ein:notebook-multilang-mode + ein:notebook-python-mode + ein:notebook-plain-mode) 'ein:company-backend)) :config - ;; Manually load the autoloads of EIN. This takes time... - (load "ein-loaddefs.el" nil t t) - (setq - ;; Slice images into rows so that we can navigate buffers with images more easily - ein:slice-image t - ein:jupyter-default-notebook-directory +ein-notebook-dir - ein:jupyter-default-server-command "jupyter" - ein:jupyter-server-args '("--no-browser") - ein:notebook-modes - '(ein:notebook-multilang-mode ein:notebook-python-mode ein:notebook-plain-mode)) - ;; Avy is required for showing links in the notebook list with ace-link. - (require 'avy) + (setq ein:jupyter-server-args '("--no-browser") + ein:notebook-modes + '(ein:notebook-multilang-mode ein:notebook-python-mode ein:notebook-plain-mode) + ;; Slice images into rows; easier to navigate around images + ein:slice-image t) + + (unless ein:jupyter-default-notebook-directory + (setq ein:jupyter-default-notebook-directory "~/")) + + (defun +ein-buffer-p (buf) + (string-match-p "^\\*ein: .*" (buffer-name buf))) + (add-to-list 'doom-real-buffer-functions #'+ein-buffer-p nil #'eq) + + ;; Ace-link on notebook list buffers + (map! :after ein-notebooklist + :map ein:notebooklist-mode-map + "o" #'+ein/ace-link-ein) + ;; add hydra (defhydra +ein/hydra (:hint t :color red) " diff --git a/modules/tools/electric-indent/config.el b/modules/tools/electric-indent/config.el index 809b07800..01a1f3f86 100644 --- a/modules/tools/electric-indent/config.el +++ b/modules/tools/electric-indent/config.el @@ -8,16 +8,6 @@ (defvar-local doom-electric-indent-words '() "TODO") -(setq-default electric-indent-chars '(?\n ?\^?)) - -(defun +electric-indent|char (_c) - (when (and (eolp) doom-electric-indent-words) - (save-excursion - (backward-word) - (looking-at-p - (concat "\\<" (regexp-opt doom-electric-indent-words)))))) -(push #'+electric-indent|char electric-indent-functions) - (def-setting! :electric (modes &rest plist) "Declare :words (list of strings) or :chars (lists of chars) in MODES that trigger electric indentation." @@ -34,3 +24,15 @@ trigger electric indentation." ,@(if words `((setq doom-electric-indent-words ',words)))) (add-hook! ,modes #',fn-name)))))) +;; +(after! electric + (setq-default electric-indent-chars '(?\n ?\^?)) + + (defun +electric-indent|char (_c) + (when (and (eolp) doom-electric-indent-words) + (save-excursion + (backward-word) + (looking-at-p + (concat "\\<" (regexp-opt doom-electric-indent-words)))))) + (add-to-list 'electric-indent-functions #'+electric-indent|char)) + diff --git a/modules/tools/eshell/config.el b/modules/tools/eshell/config.el index 26f919bd9..9c522e699 100644 --- a/modules/tools/eshell/config.el +++ b/modules/tools/eshell/config.el @@ -1,7 +1,5 @@ ;;; tools/eshell/config.el -*- lexical-binding: t; -*- -;; This is highly experimental. I don't use eshell often, so this may need work. - ;; see: ;; + `+eshell/open': open in current buffer ;; + `+eshell/open-popup': open in a popup @@ -9,7 +7,7 @@ ;; workspaces) (def-package! eshell ; built-in - :commands eshell-mode + :defer t :init (setq eshell-directory-name (let ((dir (concat doom-private-dir "eshell"))) diff --git a/modules/tools/gist/config.el b/modules/tools/gist/config.el index 46473990a..3e563de26 100644 --- a/modules/tools/gist/config.el +++ b/modules/tools/gist/config.el @@ -4,9 +4,7 @@ ;; errors. If that happens, try `+gist/kill-cache'. You may have to restart ;; Emacs. -(def-package! gist - :commands (gist-list gist-region-or-buffer-private gist-region-or-buffer) - :config +(after! gist (set! :evil-state 'gist-list-mode 'normal) (defun +gist*list-render (orig-fn &rest args) diff --git a/modules/tools/imenu/config.el b/modules/tools/imenu/config.el index 58628197d..577476ab9 100644 --- a/modules/tools/imenu/config.el +++ b/modules/tools/imenu/config.el @@ -1,13 +1,10 @@ ;;; tools/imenu/config.el -*- lexical-binding: t; -*- -(def-package! imenu-anywhere - :commands (ido-imenu-anywhere ivy-imenu-anywhere helm-imenu-anywhere) - :config (setq imenu-anywhere-delimiter ": ")) +;; `imenu-anywhere' +(setq imenu-anywhere-delimiter ": ") -(def-package! imenu-list - :commands (imenu-list-minor-mode imenu-list-smart-toggle) - :config +(after! imenu-list (setq imenu-list-idle-update-delay 0.5) (set! :popup "^\\*Ilist" diff --git a/modules/tools/magit/config.el b/modules/tools/magit/config.el index db32ca8d1..f5be64dc6 100644 --- a/modules/tools/magit/config.el +++ b/modules/tools/magit/config.el @@ -2,8 +2,6 @@ (def-package! magit :defer t - :init - (load "magit-autoloads" nil t) :config (setq magit-completing-read-function (if (featurep! :completion ivy) @@ -18,13 +16,11 @@ (map! :map magit-status-mode-map [remap magit-mode-bury-buffer] #'+magit/quit)) -(def-package! magit-blame - :commands magit-blame - :after git-timemachine) +(def-package! magit-blame :after git-timemachine) (def-package! magithub - :commands (magithub-clone magithub-feature-autoinject) + :commands magithub-feature-autoinject :after magit :preface (setq magithub-dir (concat doom-etc-dir "magithub/")) @@ -32,7 +28,6 @@ (setq magithub-clone-default-directory "~/" magithub-preferred-remote-method 'clone_url) :config - (load "magithub-autoloads" nil t) (magithub-feature-autoinject t)) diff --git a/modules/tools/password-store/config.el b/modules/tools/password-store/config.el index f57b69c8d..4fac1bb32 100644 --- a/modules/tools/password-store/config.el +++ b/modules/tools/password-store/config.el @@ -11,17 +11,18 @@ ;; Plugins ;; -(def-package! password-store +;; `password-store' +(setq password-store-password-length 12) + + +;; `pass' +(def-package! pass :defer t :config - (setq password-store-password-length 12)) - - -(def-package! pass - :commands pass - :config (set! :evil-state 'pass-mode 'emacs) - (set! :popup "^\\*Password-Store" '((side . left) (size . 0.25)) '((quit))) + (set! :popup "^\\*Password-Store" + '((side . left) (size . 0.25)) + '((quit))) (map! :map pass-mode-map "j" #'pass-next-entry "k" #'pass-prev-entry @@ -30,12 +31,6 @@ "C-k" #'pass-next-directory)) -(def-package! helm-pass - :when (featurep! :completion helm) - :commands helm-pass) - - ;; Is built into Emacs 26+ -(def-package! auth-source-pass - :when (featurep! +auth) - :config (auth-source-pass-enable)) +(when (and EMACS26+ (featurep! +auth)) + (auth-source-pass-enable)) diff --git a/modules/tools/password-store/packages.el b/modules/tools/password-store/packages.el index 6827fc23e..dbc5f2afd 100644 --- a/modules/tools/password-store/packages.el +++ b/modules/tools/password-store/packages.el @@ -4,7 +4,7 @@ (package! pass) (package! password-store) -(when (featurep! +auth) +(when (and EMACS26+ (featurep! +auth)) (package! auth-source-pass)) (when (featurep! :completion helm) diff --git a/modules/tools/pdf/config.el b/modules/tools/pdf/config.el index 0dd7c0fc9..100246093 100644 --- a/modules/tools/pdf/config.el +++ b/modules/tools/pdf/config.el @@ -1,8 +1,7 @@ ;;; tools/pdf/config.el -*- lexical-binding: t; -*- (def-package! pdf-tools - :mode ("\\.pdf$" . pdf-view-mode) - :init (load "pdf-tools-autoloads" nil t) + :mode ("\\.pdf\\'" . pdf-view-mode) :config (unless noninteractive (pdf-tools-install)) diff --git a/modules/tools/prodigy/autoload.el b/modules/tools/prodigy/autoload.el index 88781dd3d..6f27d40df 100644 --- a/modules/tools/prodigy/autoload.el +++ b/modules/tools/prodigy/autoload.el @@ -1,5 +1,11 @@ ;;; tools/prodigy/autoload.el -*- lexical-binding: t; -*- +;;;###autoload +(def-setting! :service (&rest plist) + "TODO" + `(after! prodigy + (prodigy-define-service ,@plist))) + ;;;###autoload (defun +prodigy/create () "Interactively create a new prodigy service." @@ -32,3 +38,17 @@ (file-directory-p (plist-get service :project))) collect service into services finally do (setq prodigy-service services))) + +;;;###autoload +(defun +prodigy*services (orig-fn &rest args) + "Adds a new :project property to prodigy services, which hides the service +unless invoked from the relevant project." + (let ((project-root (downcase (doom-project-root))) + (services (apply orig-fn args))) + (if current-prefix-arg + services + (cl-remove-if-not (lambda (service) + (let ((project (plist-get service :project))) + (or (not project) + (file-in-directory-p project-root project)))) + services)))) diff --git a/modules/tools/prodigy/config.el b/modules/tools/prodigy/config.el index 8763db6a3..e9ba7ca32 100644 --- a/modules/tools/prodigy/config.el +++ b/modules/tools/prodigy/config.el @@ -1,38 +1,13 @@ ;;; tools/prodigy/config.el -*- lexical-binding: t; -*- -(def-setting! :service (&rest plist) - "TODO" - `(after! prodigy - (prodigy-define-service ,@plist))) - - -;; -;; Plugins -;; - -(def-package! prodigy - :commands (prodigy prodigy-view-mode prodigy-add-filter) - :config +(after! prodigy (set! :evil-state 'prodigy-mode 'emacs) ;; Make services, etc persistent between Emacs sessions (doom-cache-persist :prodigy '(prodigy-services prodigy-tags prodigy-filters)) - (defun +prodigy*services (orig-fn &rest args) - "Adds a new :project property to prodigy services, which hides the service -unless invoked from the relevant project." - (let ((project-root (downcase (doom-project-root))) - (services (apply orig-fn args))) - (if current-prefix-arg - services - (cl-remove-if-not (lambda (service) - (let ((project (plist-get service :project))) - (or (not project) - (file-in-directory-p project-root project)))) - services)))) (advice-add #'prodigy-services :around #'+prodigy*services) - ;; Keybindings (map! :map prodigy-mode-map "d" #'+prodigy/delete)) diff --git a/modules/tools/rgb/config.el b/modules/tools/rgb/config.el index ffab008eb..08a93d06a 100644 --- a/modules/tools/rgb/config.el +++ b/modules/tools/rgb/config.el @@ -4,9 +4,6 @@ ;; Plugins ;; -(def-package! rainbow-mode) - - (def-package! kurecolor :after rainbow-mode :config diff --git a/modules/tools/rotate-text/autoload.el b/modules/tools/rotate-text/autoload.el new file mode 100644 index 000000000..1cae4ba58 --- /dev/null +++ b/modules/tools/rotate-text/autoload.el @@ -0,0 +1,17 @@ +;;; tools/rotate-text/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(def-setting! :rotate (modes &rest plist) + "Declare :symbols, :words or :patterns (all lists of strings) that +`rotate-text' will cycle through." + (declare (indent 1)) + (let* ((modes (doom-enlist (doom-unquote modes))) + (fn-name (intern (format "doom--rotate-%s" (mapconcat #'symbol-name modes "-"))))) + `(progn + (defun ,fn-name () + (require 'rotate-text) + (let ((plist (list ,@plist))) + (setq rotate-text-local-symbols (plist-get plist :symbols) + rotate-text-local-words (plist-get plist :words) + rotate-text-local-patterns (plist-get plist :patterns)))) + (add-hook! ,modes #',fn-name)))) diff --git a/modules/tools/rotate-text/config.el b/modules/tools/rotate-text/config.el index 5fb81df5a..df310e3a5 100644 --- a/modules/tools/rotate-text/config.el +++ b/modules/tools/rotate-text/config.el @@ -1,22 +1,4 @@ ;;; tools/rotate-text/config.el -*- lexical-binding: t; -*- -(def-package! rotate-text - :commands (rotate-text rotate-text-backward) - :config - (push '("true" "false") rotate-text-words)) - - -(def-setting! :rotate (modes &rest plist) - "Declare :symbols, :words or :patterns (all lists of strings) that -`rotate-text' will cycle through." - (declare (indent 1)) - (let* ((modes (doom-enlist (doom-unquote modes))) - (fn-name (intern (format "doom--rotate-%s" (mapconcat #'symbol-name modes "-"))))) - `(progn - (defun ,fn-name () - (let ((plist (list ,@plist))) - (setq rotate-text-local-symbols (plist-get plist :symbols) - rotate-text-local-words (plist-get plist :words) - rotate-text-local-patterns (plist-get plist :patterns)))) - (add-hook! ,modes #',fn-name)))) - +(after! rotate-text + (add-to-list 'rotate-text-words '("true" "false"))) diff --git a/modules/tools/term/config.el b/modules/tools/term/config.el index adb1d470b..3263ddcb6 100644 --- a/modules/tools/term/config.el +++ b/modules/tools/term/config.el @@ -1,8 +1,14 @@ ;;; tools/term/config.el -*- lexical-binding: t; -*- -(def-package! multi-term - :commands (multi-term multi-term-next multi-term-prev) - :config - (setq multi-term-program (getenv "SHELL") - multi-term-dedicated-window-height 20 - multi-term-switch-after-close 'PREVIOUS)) +;; `multi-term' +(setq multi-term-dedicated-window-height 20 + multi-term-switch-after-close 'PREVIOUS) + +;; `term' (built-in) +(after! term + (set! :env "SHELL") + + ;; Consider term buffers real + (defun +term-p (buf) + (eq (buffer-local-value 'major-mode buf) 'term-mode)) + (add-to-list 'doom-real-buffer-functions #'+eshell-p #'eq)) diff --git a/modules/ui/doom-dashboard/config.el b/modules/ui/doom-dashboard/config.el index 841235faf..acde3ad25 100644 --- a/modules/ui/doom-dashboard/config.el +++ b/modules/ui/doom-dashboard/config.el @@ -114,16 +114,17 @@ Possible values: (defun +doom-dashboard|init () "Initializes Doom's dashboard." - (add-hook 'window-configuration-change-hook #'+doom-dashboard|resize) - (add-hook 'window-size-change-functions #'+doom-dashboard|resize) - (add-hook 'kill-buffer-query-functions #'+doom-dashboard|reload-on-kill) - (add-hook 'doom-after-switch-buffer-hook #'+doom-dashboard|reload-on-kill) - (unless (daemonp) - (add-hook 'after-make-frame-functions #'+doom-dashboard|make-frame)) - ;; `persp-mode' integration: update `default-directory' when switching - (add-hook 'persp-created-functions #'+doom-dashboard|record-project) - (add-hook 'persp-activated-functions #'+doom-dashboard|detect-project) - (add-hook 'persp-before-switch-functions #'+doom-dashboard|record-project) + (unless noninteractive + (add-hook 'window-configuration-change-hook #'+doom-dashboard|resize) + (add-hook 'window-size-change-functions #'+doom-dashboard|resize) + (add-hook 'kill-buffer-query-functions #'+doom-dashboard|reload-on-kill) + (add-hook 'doom-after-switch-buffer-hook #'+doom-dashboard|reload-on-kill) + (unless (daemonp) + (add-hook 'after-make-frame-functions #'+doom-dashboard|make-frame)) + ;; `persp-mode' integration: update `default-directory' when switching + (add-hook 'persp-created-functions #'+doom-dashboard|record-project) + (add-hook 'persp-activated-functions #'+doom-dashboard|detect-project) + (add-hook 'persp-before-switch-functions #'+doom-dashboard|record-project)) (+doom-dashboard-reload t)) (defun +doom-dashboard|reload-on-kill () diff --git a/modules/ui/doom-modeline/config.el b/modules/ui/doom-modeline/config.el index f35a3a478..759132f89 100644 --- a/modules/ui/doom-modeline/config.el +++ b/modules/ui/doom-modeline/config.el @@ -4,11 +4,7 @@ ;; mode-line. (def-package! anzu - :commands (anzu-mode global-anzu-mode - anzu-query-replace anzu-query-replace-regexp - anzu-query-replace-at-cursor anzu-replace-at-cursor-thing) - :init - (add-transient-hook! #'isearch-mode (require 'anzu)) + :after-call isearch-mode :config (setq anzu-cons-mode-line-p nil anzu-minimum-input-length 1 @@ -35,10 +31,7 @@ (def-package! evil-anzu - :defer t - :init - (add-transient-hook! #'evil-ex-start-search (require 'evil-anzu)) - (add-transient-hook! #'evil-ex-start-word-search (require 'evil-anzu))) + :after-call (evil-ex-start-search evil-ex-start-word-search)) ;; fish-style modeline diff --git a/modules/ui/doom/config.el b/modules/ui/doom/config.el index 3f8561302..b68313bef 100644 --- a/modules/ui/doom/config.el +++ b/modules/ui/doom/config.el @@ -22,10 +22,11 @@ ;; (def-package! doom-themes - :config + :defer t + :init (unless doom-theme (setq doom-theme 'doom-one)) - + :config ;; Reload common faces when reloading doom-themes live (defun +doom*reload-common (&rest _) (load "doom-themes-common.el" nil t)) (advice-add #'doom//reload-theme :before #'+doom*reload-common) @@ -41,7 +42,7 @@ (def-package! solaire-mode - :commands (solaire-mode turn-on-solaire-mode solaire-mode-swap-bg) + :defer t :init (defun +doom|solaire-mode-swap-bg-maybe () (when-let* ((rule (assq doom-theme +doom-solaire-themes))) diff --git a/modules/ui/evil-goggles/config.el b/modules/ui/evil-goggles/config.el index 1a17d0ebe..e48f8a08a 100644 --- a/modules/ui/evil-goggles/config.el +++ b/modules/ui/evil-goggles/config.el @@ -2,7 +2,7 @@ (def-package! evil-goggles :when (featurep! :feature evil) - :defer pre-command-hook + :after-call pre-command-hook :init (setq evil-goggles-duration 0.05 evil-goggles-pulse nil ; too slow diff --git a/modules/ui/nav-flash/config.el b/modules/ui/nav-flash/config.el index a1519f993..3ab42ec28 100644 --- a/modules/ui/nav-flash/config.el +++ b/modules/ui/nav-flash/config.el @@ -1,7 +1,7 @@ ;;; ui/nav-flash/config.el -*- lexical-binding: t; -*- (def-package! nav-flash - :commands nav-flash-show + :defer t :init ;; NOTE In :feature lookup `recenter' is hooked to a bunch of jumping ;; commands, which will trigger nav-flash. diff --git a/modules/ui/popup/autoload.el b/modules/ui/popup/autoload.el index 844e3d1ef..c1e318514 100644 --- a/modules/ui/popup/autoload.el +++ b/modules/ui/popup/autoload.el @@ -1,5 +1,73 @@ ;;; ui/popup/autoload.el -*- lexical-binding: t; -*- +;;;###autoload +(defvar +popup--display-buffer-alist nil) + +;;;###autoload +(def-setting! :popup (condition &optional alist parameters) + "Register a popup rule. + +CONDITION can be a regexp string or a function. See `display-buffer' for a list +of possible entries for ALIST, which tells the display system how to initialize +the popup window. PARAMETERS is an alist of window parameters. See +`+popup-window-parameters' for a list of custom parameters provided by the popup +module. + +ALIST supports one custom parameter: `size', which will resolve to +`window-height' or `window-width' depending on `side'." + `(progn + (+popup-define ,condition ,alist ,parameters) + (when (bound-and-true-p +popup-mode) + (setq display-buffer-alist +popup--display-buffer-alist)) + +popup--display-buffer-alist)) + +;;;###autoload +(def-setting! :popups (&rest rules) + "Register multiple popup rules with :popup setting (`doom--set:popup'). For +example: + + (set! :popups + (\"^ \\*\" '((slot . 1) (vslot . -1) (size . +popup-shrink-to-fit))) + (\"^\\*\" '((slot . 1) (vslot . -1)) '((select . t))))" + `(progn + ,@(cl-loop for rule in rules collect `(+popup-define ,@rule)) + (when (bound-and-true-p +popup-mode) + (setq display-buffer-alist +popup--display-buffer-alist)) + +popup--display-buffer-alist)) + +;;;###autoload +(defsubst +popup-define (condition &optional alist parameters) + "Define a popup rule. + +The buffers of new windows displayed by `pop-to-buffer' and `display-buffer' +will be tested against CONDITION, which is either a) a regexp string (which is +matched against the buffer's name) or b) a function that takes no arguments and +returns a boolean. + +If CONDITION is met, the buffer will be displayed in a popup window with ALIST +and window PARAMETERS. See `display-buffer-alist' for details on what ALIST may +contain and `+popup-window-parameters' for what window parameters that the popup +module supports. + +ALIST also supports the `size' parameter, which will be translated to +`window-width' or `window-height' depending on `side'. + +If certain attributes/parameters are omitted, the ones from +`+popup-default-alist' and `+popup-default-parameters' will be used." + (declare (indent 1)) + (push (if (eq alist :ignore) + (list condition nil) + `(,condition + (+popup-buffer) + ,@alist + (window-parameters ,@parameters))) + +popup--display-buffer-alist)) + + +;; +;; Library +;; + (defvar +popup--populate-wparams (not EMACS26+)) (defvar +popup--inhibit-transient nil) (defvar +popup--inhibit-select nil) diff --git a/modules/ui/popup/init.el b/modules/ui/popup/init.el deleted file mode 100644 index 8b6b99f16..000000000 --- a/modules/ui/popup/init.el +++ /dev/null @@ -1,61 +0,0 @@ -;;; ui/popup/init.el -*- lexical-binding: t; -*- - -(defvar +popup--display-buffer-alist nil) - -(defun +popup-define (condition &optional alist parameters) - "Define a popup rule. - -The buffers of new windows displayed by `pop-to-buffer' and `display-buffer' -will be tested against CONDITION, which is either a) a regexp string (which is -matched against the buffer's name) or b) a function that takes no arguments and -returns a boolean. - -If CONDITION is met, the buffer will be displayed in a popup window with ALIST -and window PARAMETERS. See `display-buffer-alist' for details on what ALIST may -contain and `+popup-window-parameters' for what window parameters that the popup -module supports. - -ALIST also supports the `size' parameter, which will be translated to -`window-width' or `window-height' depending on `side'. - -If certain attributes/parameters are omitted, the ones from -`+popup-default-alist' and `+popup-default-parameters' will be used." - (declare (indent 1)) - (push (if (eq alist :ignore) - (list condition nil) - `(,condition - (+popup-buffer) - ,@alist - (window-parameters ,@parameters))) - +popup--display-buffer-alist)) - -;; -(def-setting! :popup (condition &optional alist parameters) - "Register a popup rule. - -CONDITION can be a regexp string or a function. See `display-buffer' for a list -of possible entries for ALIST, which tells the display system how to initialize -the popup window. PARAMETERS is an alist of window parameters. See -`+popup-window-parameters' for a list of custom parameters provided by the popup -module. - -ALIST supports one custom parameter: `size', which will resolve to -`window-height' or `window-width' depending on `side'." - `(progn - (+popup-define ,condition ,alist ,parameters) - (when (bound-and-true-p +popup-mode) - (setq display-buffer-alist +popup--display-buffer-alist)) - +popup--display-buffer-alist)) - -(def-setting! :popups (&rest rules) - "Register multiple popup rules with :popup setting (`doom--set:popup'). For -example: - - (set! :popups - (\"^ \\*\" '((slot . 1) (vslot . -1) (size . +popup-shrink-to-fit))) - (\"^\\*\" '((slot . 1) (vslot . -1)) '((select . t))))" - `(progn - ,@(cl-loop for rule in rules collect `(+popup-define ,@rule)) - (when (bound-and-true-p +popup-mode) - (setq display-buffer-alist +popup--display-buffer-alist)) - +popup--display-buffer-alist)) diff --git a/modules/ui/unicode/autoload.el b/modules/ui/unicode/autoload.el new file mode 100644 index 000000000..1af675c04 --- /dev/null +++ b/modules/ui/unicode/autoload.el @@ -0,0 +1,23 @@ +;;; ui/unicode/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(add-hook 'doom-post-init-hook #'+unicode|init-fonts) + +;;;###autoload +(defun +unicode|init-fonts () + "Set up `unicode-fonts' to eventually run; accomodating the daemon, if +necessary." + (setq-default bidi-display-reordering t + doom-unicode-font nil) + (if initial-window-system + (+unicode|setup-fonts (selected-frame)) + (add-hook 'after-make-frame-functions #'+unicode|setup-fonts))) + +;;;###autoload +(defun +unicode|setup-fonts (&optional frame) + "Initialize `unicode-fonts', if in a GUI session." + (when (and frame (display-graphic-p frame)) + (with-selected-frame frame + (require 'unicode-fonts) + ;; NOTE will impact startup time on first run + (unicode-fonts-setup)))) diff --git a/modules/ui/unicode/config.el b/modules/ui/unicode/config.el deleted file mode 100644 index a41ae6554..000000000 --- a/modules/ui/unicode/config.el +++ /dev/null @@ -1,19 +0,0 @@ -;;; ui/unicode/config.el -*- lexical-binding: t; -*- - -(def-package! unicode-fonts - :init - (setq-default bidi-display-reordering t - doom-unicode-font nil) - - (defun +unicode|init-fonts (&optional frame) - "Initialize `unicode-fonts', if in a GUI session." - (when (and frame (display-graphic-p frame)) - (with-selected-frame frame - (require 'unicode-fonts) - ;; NOTE will impact startup time on first run - (unicode-fonts-setup)))) - - (add-hook! 'after-init-hook - (if initial-window-system - (+unicode|init-fonts (selected-frame)) - (add-hook 'after-make-frame-functions #'+unicode|init-fonts)))) diff --git a/modules/ui/vi-tilde-fringe/autoload.el b/modules/ui/vi-tilde-fringe/autoload.el new file mode 100644 index 000000000..ab9029cfc --- /dev/null +++ b/modules/ui/vi-tilde-fringe/autoload.el @@ -0,0 +1,4 @@ +;;; ui/vi-tilde-fringe/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(add-hook! (prog-mode text-mode conf-mode) #'vi-tilde-fringe-mode) diff --git a/modules/ui/vi-tilde-fringe/config.el b/modules/ui/vi-tilde-fringe/config.el deleted file mode 100644 index 1f099b7aa..000000000 --- a/modules/ui/vi-tilde-fringe/config.el +++ /dev/null @@ -1,6 +0,0 @@ -;;; ui/vi-tilde-fringe/config.el -*- lexical-binding: t; -*- - -;; indicators for empty lines past EOF -(def-package! vi-tilde-fringe - :hook ((prog-mode text-mode conf-mode) . vi-tilde-fringe-mode)) - diff --git a/modules/ui/window-select/config.el b/modules/ui/window-select/config.el index b055bb779..3989310e3 100644 --- a/modules/ui/window-select/config.el +++ b/modules/ui/window-select/config.el @@ -2,9 +2,7 @@ (def-package! switch-window :when (featurep! +switch-window) - :commands (switch-window switch-window-then-maximize switch-window-then-split-below - switch-window-then-split-right switch-window-then-delete - switch-window-then-swap-buffer) + :defer t :init (define-key global-map [remap other-window] #'switch-window) :config @@ -14,8 +12,7 @@ (def-package! ace-window :unless (featurep! +switch-window) - :commands (ace-window ace-swap-window ace-delete-window - ace-select-window ace-delete-other-windows) + :defer t :init (define-key global-map [remap other-window] #'ace-window) :config From 887e3e11af213bbdc96f445aecd0a5699267a8ba Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:49:03 +0200 Subject: [PATCH 096/132] Remove unused printerr! macro --- core/autoload/message.el | 10 ---------- core/autoload/modules.el | 1 - 2 files changed, 11 deletions(-) diff --git a/core/autoload/message.el b/core/autoload/message.el index 8aba7b918..3fcdc86a9 100644 --- a/core/autoload/message.el +++ b/core/autoload/message.el @@ -75,16 +75,6 @@ into faces or ANSI codes depending on the type of sesssion we're in." (apply #'doom-ansi-apply code format args)))) (format ,message ,@args))) -;;;###autoload -(defmacro printerr! (message &rest args) - "Uses `warn' in interative sessions and `message' otherwise (prints to -standard error). - -Can be colored using (color ...) blocks. See `print!' for details." - `(if noninteractive - (message (format! ,message ,@args)) - (warn ,message ,@args))) - ;;;###autoload (defmacro print! (message &rest args) "Uses `message' in interactive sessions and `princ' otherwise (prints to diff --git a/core/autoload/modules.el b/core/autoload/modules.el index 462cf6411..f7a4e529d 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -1,7 +1,6 @@ ;;; core/autoload/modules.el -*- lexical-binding: t; -*- (autoload 'print! "autoload/message" nil 'macro) -(autoload 'printerr! "autoload/message" nil 'macro) (defun doom--server-eval (body) (require 'server) From 852193dfc54906748131c6ccb3cae6c16ef3c579 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:49:21 +0200 Subject: [PATCH 097/132] completion/helm: update command remappings --- modules/completion/helm/config.el | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/modules/completion/helm/config.el b/modules/completion/helm/config.el index 702208166..ec0c9a550 100644 --- a/modules/completion/helm/config.el +++ b/modules/completion/helm/config.el @@ -75,18 +75,19 @@ (map! :map global-map [remap apropos] #'helm-apropos - [remap find-file] #'helm-find-files - [remap recentf-open-files] #'helm-recentf - [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer - [remap projectile-recentf] #'helm-projectile-recentf - [remap projectile-find-file] #'helm-projectile-find-file - [remap imenu] #'helm-semantic-or-imenu [remap bookmark-jump] #'helm-bookmarks - [remap noop-show-kill-ring] #'helm-show-kill-ring - [remap projectile-switch-project] #'helm-projectile-switch-project - [remap projectile-find-file] #'helm-projectile-find-file + [remap bookmark-jump] #'helm-bookmarks + [remap execute-extended-command] #'helm-M-x + [remap find-file] #'helm-find-files [remap imenu-anywhere] #'helm-imenu-anywhere - [remap execute-extended-command] #'helm-M-x)) + [remap imenu-anywhere] #'helm-imenu-anywhere + [remap imenu] #'helm-semantic-or-imenu + [remap noop-show-kill-ring] #'helm-show-kill-ring + [remap projectile-find-file] #'helm-projectile-find-file + [remap projectile-recentf] #'helm-projectile-recentf + [remap projectile-switch-project] #'helm-projectile-switch-project + [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer + [remap recentf-open-files] #'helm-recentf)) (def-package! helm-locate From 55a3aeec9add75683c790db43abd74c540889ff5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:50:24 +0200 Subject: [PATCH 098/132] completion/ivy: don't pre-fill ag/rg/pt/grep searches w/ last search --- modules/completion/ivy/autoload/ivy.el | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/completion/ivy/autoload/ivy.el b/modules/completion/ivy/autoload/ivy.el index 89ce56db5..1ef711277 100644 --- a/modules/completion/ivy/autoload/ivy.el +++ b/modules/completion/ivy/autoload/ivy.el @@ -202,7 +202,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for." ;; File searching ;; -(defvar +ivy--file-last-search nil) (defvar +ivy--file-search-recursion-p t) (defvar +ivy--file-search-all-files-p nil) @@ -220,8 +219,7 @@ search current file. See `+ivy-task-tags' to customize what this searches for." (let ((beg (or (bound-and-true-p evil-visual-beginning) (region-beginning))) (end (or (bound-and-true-p evil-visual-end) (region-end)))) (when (> (abs (- end beg)) 1) - (rxt-quote-pcre (buffer-substring-no-properties beg end))))) - +ivy--file-last-search)) + (rxt-quote-pcre (buffer-substring-no-properties beg end))))))) (prompt (format "%s%%s %s" (symbol-name engine) @@ -232,7 +230,6 @@ search current file. See `+ivy-task-tags' to customize what this searches for." (t (file-relative-name directory project-root))))) (default-directory directory)) - (setq +ivy--file-last-search query) (require 'counsel) (cl-letf (((symbol-function 'counsel-ag-function) (symbol-function '+ivy*counsel-ag-function)) From b36eca2ae7c2b7d62f1fac49e8b08b54fe6a2497 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:50:33 +0200 Subject: [PATCH 099/132] completion/ivy: ivy-height = 15 --- modules/completion/ivy/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index 9d3f3f705..a37ea4baf 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -27,7 +27,7 @@ immediately runs it on the current candidate (ending the ivy session)." :defer 1 :after-call pre-command-hook :config - (setq ivy-height 12 + (setq ivy-height 15 ivy-do-completion-in-region nil ivy-wrap t ivy-fixed-height-minibuffer t From 9011593e38b4d0f8dd3ba94a5deb76a9ed307883 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:50:52 +0200 Subject: [PATCH 100/132] feature/workspaces: fix tests --- modules/feature/workspaces/test/autoload-workspaces.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/feature/workspaces/test/autoload-workspaces.el b/modules/feature/workspaces/test/autoload-workspaces.el index 6367400ed..acd647ba9 100644 --- a/modules/feature/workspaces/test/autoload-workspaces.el +++ b/modules/feature/workspaces/test/autoload-workspaces.el @@ -14,7 +14,8 @@ (require 'persp-mode) (let (noninteractive) (persp-mode +1)) - (+workspace-switch +workspaces-main t) + (let (persp-before-switch-functions persp-activated-functions) + (+workspace-switch +workspaces-main t)) (let* (,@buffers) (cl-loop with persp = (get-current-persp) for buf in (list ,@(mapcar #'car buffers)) From fd87a0bd9eb84777b3c84eaf028f533a8ba596a7 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:51:15 +0200 Subject: [PATCH 101/132] lang/org: add ]h/[h keybinds; correct bind motion keys to motion map --- modules/lang/org/config.el | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index ba5449039..13f12f7bb 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -274,12 +274,14 @@ between the two." :ni [M-return] (λ! (+org/insert-item 'below)) :ni [S-M-return] (λ! (+org/insert-item 'above)) ;; more org-ish vim motion keys - :n "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line)) - :n "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line)) - :n "]l" #'org-next-link - :n "[l" #'org-previous-link - :n "]s" #'org-babel-next-src-block - :n "[s" #'org-babel-previous-src-block + :m "]]" (λ! (org-forward-heading-same-level nil) (org-beginning-of-line)) + :m "[[" (λ! (org-backward-heading-same-level nil) (org-beginning-of-line)) + :m "]h" #'org-next-visible-heading + :m "[h" #'org-previous-visible-heading + :m "]l" #'org-next-link + :m "[l" #'org-previous-link + :m "]s" #'org-babel-next-src-block + :m "[s" #'org-babel-previous-src-block :m "^" #'evil-org-beginning-of-line :m "0" (λ! (let ((visual-line-mode)) (org-beginning-of-line))) :n "gQ" #'org-fill-paragraph From 5472cd4a37422b0dcf4191c0371c327ae8c08c46 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:51:34 +0200 Subject: [PATCH 102/132] lang/org: set org-clock variables sooner --- modules/lang/org/config.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 13f12f7bb..a0c0e61b5 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -346,10 +346,11 @@ between the two." (def-package! org-clock :commands org-clock-save :hook (org-mode . org-clock-load) - :config + :init (setq org-clock-persist 'history org-clock-persist-file (concat doom-etc-dir "org-clock-save.el")) - (add-hook 'kill-emacs-hook 'org-clock-save)) + :config + (add-hook 'kill-emacs-hook #'org-clock-save)) ;; (when (featurep 'org) From ae95b9e8d5384bcb9032e65741f347c0e9d12b24 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:52:37 +0200 Subject: [PATCH 103/132] lang/sh: improve zsh shebang detection regexp --- modules/lang/sh/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lang/sh/config.el b/modules/lang/sh/config.el index 21444fb91..d705509da 100644 --- a/modules/lang/sh/config.el +++ b/modules/lang/sh/config.el @@ -50,7 +50,7 @@ (string-match-p "\\.zsh\\'" buffer-file-name)) (save-excursion (goto-char (point-min)) - (looking-at-p "^#!.+zsh[$\\s-]"))) + (looking-at-p "^#!.+/zsh[$ ]"))) (sh-set-shell "zsh"))) (add-hook 'sh-mode-hook #'+sh|detect-zsh)) From be9a06b126b0a820cfbd2d8072b562b45b3613c9 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:53:04 +0200 Subject: [PATCH 104/132] tools/magit: add magit-gitflow --- modules/tools/magit/config.el | 4 ++++ modules/tools/magit/packages.el | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/tools/magit/config.el b/modules/tools/magit/config.el index f5be64dc6..2d1d810f8 100644 --- a/modules/tools/magit/config.el +++ b/modules/tools/magit/config.el @@ -31,6 +31,10 @@ (magithub-feature-autoinject t)) +(def-package! magit-gitflow + :hook (magit-mode . turn-on-magit-gitflow)) + + (def-package! evil-magit :when (featurep! :feature evil) :after magit diff --git a/modules/tools/magit/packages.el b/modules/tools/magit/packages.el index 132e1fc30..d510a8977 100644 --- a/modules/tools/magit/packages.el +++ b/modules/tools/magit/packages.el @@ -1,7 +1,8 @@ ;; -*- no-byte-compile: t; -*- ;;; tools/magit/packages.el -(package! magit) -(package! magithub) -(when (featurep! :feature evil) - (package! evil-magit)) +(when (package! magit) + (package! magithub) + (package! magit-gitflow) + (when (featurep! :feature evil) + (package! evil-magit))) From cf3c0d808dea51a0b4c046decfa33d27aca9e3cc Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:53:46 +0200 Subject: [PATCH 105/132] tools/tmux: minor refactor of +tmux/rerun --- modules/tools/tmux/autoload/tmux.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tools/tmux/autoload/tmux.el b/modules/tools/tmux/autoload/tmux.el index fdfaa6c5e..9508172a2 100644 --- a/modules/tools/tmux/autoload/tmux.el +++ b/modules/tools/tmux/autoload/tmux.el @@ -63,7 +63,7 @@ but do not execute them." (interactive "P") (unless +tmux-last-command (user-error "No last command to run")) - (apply #'+tmux (car +tmux-last-command) (cdr +tmux-last-command))) + (apply #'+tmux +tmux-last-command)) ;;;###autoload (defun +tmux/cd (&optional arg directory) From 2f83757018deb2b1994880feb3ba9f4dfbf9d844 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:54:05 +0200 Subject: [PATCH 106/132] ui/doom-dashboard: more robust feature detection In case you aren't using those modules, but have other means of loading those packages. --- modules/ui/doom-dashboard/config.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ui/doom-dashboard/config.el b/modules/ui/doom-dashboard/config.el index acde3ad25..a446f2d8a 100644 --- a/modules/ui/doom-dashboard/config.el +++ b/modules/ui/doom-dashboard/config.el @@ -330,11 +330,11 @@ controlled by `+doom-dashboard-pwd-policy'." "\n\n")))) `(("Homepage" "mark-github" (browse-url "https://github.com/hlissner/doom-emacs")) - ,(when (and (featurep! :feature workspaces) + ,(when (and (bound-and-true-p persp-mode) (file-exists-p (expand-file-name persp-auto-save-fname persp-save-dir))) '("Reload last session" "history" (+workspace/load-session))) - ,(when (featurep! :lang org) + ,(when (fboundp 'org-agenda-list) '("See agenda for this week" "calendar" (call-interactively #'org-agenda-list))) ("Recently opened files" "file-text" From 643ff130532477d889eda890c0493a6e36ded18e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:55:03 +0200 Subject: [PATCH 107/132] ui/doom: make solaire-mode a little pickier Instead of only activating in buffers that a real (which is more selective), simply activate in buffers that are file-visiting (this means that real buffers that aren't highlighted can exist, particularly term/eshell buffers). --- modules/ui/doom/config.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ui/doom/config.el b/modules/ui/doom/config.el index b68313bef..98edef3da 100644 --- a/modules/ui/doom/config.el +++ b/modules/ui/doom/config.el @@ -50,8 +50,7 @@ (if (cdr rule) (solaire-mode-swap-bg)))) (add-hook 'doom-load-theme-hook #'+doom|solaire-mode-swap-bg-maybe t) :config - (add-hook 'after-change-major-mode-hook #'turn-on-solaire-mode) - (setq solaire-mode-real-buffer-fn #'doom-real-buffer-p) + (add-hook 'change-major-mode-after-body-hook #'turn-on-solaire-mode) ;; fringe can become unstyled when deleting or focusing frames (add-hook 'focus-in-hook #'solaire-mode-reset) ;; Prevent color glitches when reloading either DOOM or loading a new theme From 1e4f108655f6cc46bb84a0a343d69bfe727cc5e7 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:56:15 +0200 Subject: [PATCH 108/132] ui/neotree: non-capturing groups in neo-hidden-regexp-list Slight optimization. --- modules/ui/neotree/config.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/ui/neotree/config.el b/modules/ui/neotree/config.el index 2723ab273..f7c8847db 100644 --- a/modules/ui/neotree/config.el +++ b/modules/ui/neotree/config.el @@ -24,13 +24,14 @@ neo-show-hidden-files t neo-hidden-regexp-list '(;; vcs folders - "^\\.\\(git\\|hg\\|svn\\)$" + "^\\.\\(?:git\\|hg\\|svn\\)$" ;; compiled files - "\\.\\(pyc\\|o\\|elc\\|lock\\|css.map\\|class\\)$" + "\\.\\(?:pyc\\|o\\|elc\\|lock\\|css.map\\|class\\)$" ;; generated files, caches or local pkgs - "^\\(node_modules\\|vendor\\|.\\(project\\|cask\\|yardoc\\|sass-cache\\)\\)$" + "^\\(?:node_modules\\|vendor\\|.\\(project\\|cask\\|yardoc\\|sass-cache\\)\\)$" ;; org-mode folders - "^\\.\\(sync\\|export\\|attach\\)$" + "^\\.\\(?:sync\\|export\\|attach\\)$" + ;; temp files "~$" "^#.*#$")) From 6b7083138699b3520755f0b14ff89d999669104d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:56:34 +0200 Subject: [PATCH 109/132] ui/evil-goggles: evil-goggles-enable-delete = nil --- modules/ui/evil-goggles/config.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ui/evil-goggles/config.el b/modules/ui/evil-goggles/config.el index e48f8a08a..3d1f65fe2 100644 --- a/modules/ui/evil-goggles/config.el +++ b/modules/ui/evil-goggles/config.el @@ -6,7 +6,9 @@ :init (setq evil-goggles-duration 0.05 evil-goggles-pulse nil ; too slow - evil-goggles-enable-delete t + ;; evil-goggles provides a good indicator of what has been affected. + ;; delete/change is obvious, so I'd rather disable it for these. + evil-goggles-enable-delete nil evil-goggles-enable-change nil) :config (evil-goggles-mode +1)) From cce30367bb07393ab36b0ac78d0e97992002c99f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 00:58:09 +0200 Subject: [PATCH 110/132] tools/eshell: fix naive path concatenation for eshell-directory-name --- modules/tools/eshell/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tools/eshell/config.el b/modules/tools/eshell/config.el index 9c522e699..75870835a 100644 --- a/modules/tools/eshell/config.el +++ b/modules/tools/eshell/config.el @@ -10,7 +10,7 @@ :defer t :init (setq eshell-directory-name - (let ((dir (concat doom-private-dir "eshell"))) + (let ((dir (expand-file-name "eshell" doom-private-dir))) (if (file-directory-p dir) dir "~/.eshell")) From 0348686ccee2c0a665edef6adbb664a99b058df4 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:00:04 +0200 Subject: [PATCH 111/132] tools/eshell: change split behavior to open non-eshell window --- modules/tools/eshell/autoload/eshell.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/tools/eshell/autoload/eshell.el b/modules/tools/eshell/autoload/eshell.el index 57da503c8..059d0fba4 100644 --- a/modules/tools/eshell/autoload/eshell.el +++ b/modules/tools/eshell/autoload/eshell.el @@ -175,14 +175,14 @@ delete." "Create a new eshell window below the current one." (interactive) (select-window (split-window-vertically)) - (+eshell/open)) + (bury-buffer)) ;;;###autoload (defun +eshell/split-right () "Create a new eshell window to the right of the current one." (interactive) (select-window (split-window-horizontally)) - (+eshell/open)) + (bury-buffer)) ;; `make-ring' ;; `ring-ref' From 9a8b6a82e2b37c2be50f9e5dae2b9da7d3caf7a5 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:01:22 +0200 Subject: [PATCH 112/132] lang/web: add doctor.el --- modules/lang/web/doctor.el | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 modules/lang/web/doctor.el diff --git a/modules/lang/web/doctor.el b/modules/lang/web/doctor.el new file mode 100644 index 000000000..c351f0c73 --- /dev/null +++ b/modules/lang/web/doctor.el @@ -0,0 +1,8 @@ +;;; lang/web/doctor.el -*- lexical-binding: t; -*- + +(unless (executable-find "js-beautify") + (warn! "Couldn't find js-beautify. Code formatting in JS/CSS/HTML modes will not work.")) + +(unless (executable-find "stylelint") + (warn! "Couldn't find stylelint. Linting for CSS modes will not work.")) + From 59f70c2a8721a403bd63632eef0f8f3e170244ac Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:11:53 +0200 Subject: [PATCH 113/132] Soft-fail if doom-module-table can't find your private init.el --- core/core-packages.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 5f70d6396..7788a1051 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -465,16 +465,17 @@ added, if the file exists." :size (if modules (length modules) 100) :rehash-threshold 1.0))) (when (null modules) - (let ((init-file (expand-file-name "init.el" doom-private-dir))) + (let ((init-file (expand-file-name "init.el" doom-private-dir)) + (short-init-file (abbreviate-file-name init-file))) (if (not (file-exists-p init-file)) - (error "%s doesn't exist" (abbreviate-file-name init-file)) + (warn "%s doesn't exist" short-init-file) (with-temp-buffer (insert-file-contents init-file) (when (re-search-forward "^\\s-*\\((doom! \\)" nil t) (goto-char (match-beginning 1)) (setq modules (cdr (sexp-at-point)))))) - (unless modules - (error "Couldn't gather module list from %s" init-file)))) + (unless (or modules noninteractive) + (warn "Couldn't gather module list from %s" short-init-file)))) (if (eq modules t) (setq modules nil)) (let (category) (dolist (m modules) From 11705d0920bf947a2dbf294d7cb11564a9833627 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:13:28 +0200 Subject: [PATCH 114/132] Fix void-variable error (let -> let*) --- core/core-packages.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 7788a1051..9143cf8d9 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -465,8 +465,8 @@ added, if the file exists." :size (if modules (length modules) 100) :rehash-threshold 1.0))) (when (null modules) - (let ((init-file (expand-file-name "init.el" doom-private-dir)) - (short-init-file (abbreviate-file-name init-file))) + (let* ((init-file (expand-file-name "init.el" doom-private-dir)) + (short-init-file (abbreviate-file-name init-file))) (if (not (file-exists-p init-file)) (warn "%s doesn't exist" short-init-file) (with-temp-buffer From a390ef8debedd0374e8bdd7d1318e8ae97f3358d Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:17:01 +0200 Subject: [PATCH 115/132] Reduce doom-module-table calls significantly --- core/core-packages.el | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/core/core-packages.el b/core/core-packages.el index 9143cf8d9..124169d27 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -309,8 +309,7 @@ Use this before any of package.el, quelpa or Doom's package management's API to ensure all the necessary package metadata is initialized and available for them." (with-temp-buffer ; prevent buffer-local settings from propagating - (let ((load-prefer-newer t) ; reduce stale code issues - (doom-modules (doom-module-table))) + (let ((load-prefer-newer t)) ; reduce stale code issues ;; package.el and quelpa handle themselves if their state changes during ;; the current session, but if you change an packages.el file in a module, ;; there's no non-trivial way to detect that, so we give you a way to @@ -338,26 +337,27 @@ them." (error "Could not initialize quelpa")))) (when (or force-p (not doom-packages)) - (setq doom-packages nil) - (cl-flet - ((_load - (file &optional noerror interactive) - (condition-case-unless-debug ex - (let ((noninteractive (not interactive))) - (load file noerror 'nomessage 'nosuffix)) - ('error - (lwarn 'doom-initialize-packages :warning - "%s in %s: %s" - (car ex) - (file-relative-name file doom-emacs-dir) - (error-message-string ex)))))) - (let ((doom--stage 'packages)) - (_load (expand-file-name "packages.el" doom-core-dir)) - (cl-loop for key being the hash-keys of doom-modules - for path = (doom-module-path (car key) (cdr key) "packages.el") - do (let ((doom--current-module key)) (_load path t))) - (cl-loop for dir in doom-psuedo-module-dirs - do (_load (expand-file-name "packages.el" dir) t)))))))) + (let ((doom-modules (doom-module-table))) + (setq doom-packages nil) + (cl-flet + ((_load + (file &optional noerror interactive) + (condition-case-unless-debug ex + (let ((noninteractive (not interactive))) + (load file noerror 'nomessage 'nosuffix)) + ('error + (lwarn 'doom-initialize-packages :warning + "%s in %s: %s" + (car ex) + (file-relative-name file doom-emacs-dir) + (error-message-string ex)))))) + (let ((doom--stage 'packages)) + (_load (expand-file-name "packages.el" doom-core-dir)) + (cl-loop for key being the hash-keys of doom-modules + for path = (doom-module-path (car key) (cdr key) "packages.el") + do (let ((doom--current-module key)) (_load path t))) + (cl-loop for dir in doom-psuedo-module-dirs + do (_load (expand-file-name "packages.el" dir) t))))))))) ;; From 843c4d085fd0fc2adb5b047810069af772fa08ab Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:25:54 +0200 Subject: [PATCH 116/132] bin/doom: fix doom run --- bin/doom | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/doom b/bin/doom index 1e455534a..53e55de43 100755 --- a/bin/doom +++ b/bin/doom @@ -56,7 +56,6 @@ (setq doom-auto-accept t)))) ;; Bootstrap Doom - (setq noninteractive 'doom) (load (expand-file-name "init" emacs-dir) nil 'nomessage) @@ -68,6 +67,7 @@ ((not args) (error "Expecting a command")) ((let ((default-directory user-emacs-directory)) - (setq argv nil) + (setq argv nil + noninteractive 'doom) (doom-dispatch args))))) From 2990d5bd586f6367f094321c99c2d3b8807a2765 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:26:24 +0200 Subject: [PATCH 117/132] Fix hash-table-p and format type errors on blank startup --- core/core-packages.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-packages.el b/core/core-packages.el index 124169d27..d939135c9 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -155,7 +155,7 @@ If RETURN-P, return the message as a string instead of displaying it." ;; load-path are concerned, but I don't mind a [small] margin of ;; error in the plugin count in exchange for faster startup. (- (length load-path) (length doom-site-load-path)) - (hash-table-count doom-modules) + (if doom-modules (hash-table-count doom-modules) 0) (or doom-init-time (setq doom-init-time (float-time (time-subtract (current-time) before-init-time)))))) From 6e82e6fa19dee8bf0a747080fa6cac51b83e1824 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 01:59:15 +0200 Subject: [PATCH 118/132] tools/term: fix void-function error due to misplaced reference to +eshell-p --- modules/tools/term/config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tools/term/config.el b/modules/tools/term/config.el index 3263ddcb6..3aaad2453 100644 --- a/modules/tools/term/config.el +++ b/modules/tools/term/config.el @@ -11,4 +11,4 @@ ;; Consider term buffers real (defun +term-p (buf) (eq (buffer-local-value 'major-mode buf) 'term-mode)) - (add-to-list 'doom-real-buffer-functions #'+eshell-p #'eq)) + (add-to-list 'doom-real-buffer-functions #'+term-p #'eq)) From d9894f0b747e09270c3588d2810ff582ae4ce239 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:16:19 +0200 Subject: [PATCH 119/132] Fix package install not retrying after a 'bad request' error --- core/autoload/packages.el | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index a94da7b7f..09cc577fb 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -423,20 +423,17 @@ calls." (print! "Installing %s" (car pkg)) (doom--condition-case! (print! "%s%s" - (if (and (package-installed-p (car pkg)) - (not (doom-package-different-backend-p (car pkg))) - (not (doom-package-different-recipe-p (car pkg)))) - (dark (white "⚠ ALREADY INSTALLED")) - (condition-case e - (if (doom-install-package (car pkg) (cdr pkg)) - (prog1 (green "✓ DONE") - (setq success t)) - (red "✕ FAILED")) - (error - (red "✕ ERROR (%s)" e)))) - (if (plist-member (cdr pkg) :pin) - (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) - "")))) + (cond ((and (package-installed-p (car pkg)) + (not (doom-package-different-backend-p (car pkg))) + (not (doom-package-different-recipe-p (car pkg)))) + (dark (white "⚠ ALREADY INSTALLED"))) + ((doom-install-package (car pkg) (cdr pkg)) + (setq success t) + (green "✓ DONE")) + ((red "✕ FAILED"))) + (if (plist-member (cdr pkg) :pin) + (format " [pinned: %s]" (plist-get (cdr pkg) :pin)) + "")))) (print! (bold (green "Finished!"))) (if success (doom-delete-autoloads-file doom-package-autoload-file)) success))))) From 0bdf638813f5af21aa9d17be8cf7ad5480a07e3a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:18:29 +0200 Subject: [PATCH 120/132] lang/latex: refactor package loading mechanism --- modules/lang/latex/config.el | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index dd33daf0f..758f703a7 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -23,13 +23,7 @@ ;; Plugins ;; -(def-package! tex-site - :init - ;; Manually load the AUCTEX autoloads. This is normally done by - ;; package-initialize, ... which we do not use. - (load "auctex.el" nil t t) - (load "auctex-autoloads.el" nil t t) - :config +(after! tex-site ;; Set some varibles to fontify common LaTeX commands. (load! +fontification) (setq ;; Enable parse on load. @@ -179,7 +173,6 @@ (def-package! bibtex :defer t - :mode ("\\.bib\\'" . bibtex-mode) :config (setq bibtex-dialect 'biblatex bibtex-align-at-equal-sign t From 0aa7bf2d4a5618c02c5604f4347ce32f8d9b51a6 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:18:52 +0200 Subject: [PATCH 121/132] Insert package state before package autoloads in autoloads file Prevents issues where autoloads will try to load packages but `load-path` isn't initialized yet, causing "Cannot open load file" errors. --- core/autoload/modules.el | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index f7a4e529d..f3b189a64 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -208,8 +208,18 @@ This should be run whenever your `doom!' block or update your packages." (with-temp-file doom-package-autoload-file (insert ";;; -*- lexical-binding:t -*-\n" ";; This file is autogenerated by `doom//reload-package-autoloads', DO NOT EDIT !!\n\n") - ;; insert package autoloads (save-excursion + ;; Cache the important and expensive-to-initialize state here. + (doom-initialize-packages 'internal) + (prin1 `(setq load-path ',load-path + auto-mode-alist ',auto-mode-alist + Info-directory-list ',Info-directory-list + doom-disabled-packages ',doom-disabled-packages + package-activated-list ',package-activated-list) + (current-buffer)) + (print! (green "✓ Cached package state")) + + ;; insert package autoloads (dolist (spec package-alist) (cl-destructuring-bind (pkg desc) spec (unless (memq pkg doom-autoload-excluded-packages) @@ -223,17 +233,8 @@ This should be run whenever your `doom!' block or update your packages." (unless (nth 8 (syntax-ppss)) (replace-match "" t t))) (unless (bolp) (insert "\n")) - (insert ")\n")))))) - (print! (green "✓ Package autoloads included")) - ;; Cache the important and expensive-to-initialize state here. - (doom-initialize-packages 'internal) - (prin1 `(setq load-path ',load-path - auto-mode-alist ',auto-mode-alist - Info-directory-list ',Info-directory-list - doom-disabled-packages ',doom-disabled-packages - package-activated-list ',package-activated-list) - (current-buffer)) - (print! (green "✓ Cached package state"))) + (insert ")\n"))))))) + (print! (green "✓ Package autoloads included")) ;; Remove `load-path' and `auto-mode-alist' modifications (most of them, ;; at least); they are cached later, so all those membership checks are ;; unnecessary overhead. From ef9cea4d119152848b42b8a3650cca5f81f3580a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:20:28 +0200 Subject: [PATCH 122/132] More aggressive autoloads reloading on install, autoremove, update & refresh --- core/core-dispatcher.el | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index 861e58958..0128702c5 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -128,19 +128,19 @@ exists." "Installs requested plugins that aren't installed." (doom//reload-doom-autoloads) (when (doom//packages-install doom-auto-accept) - (doom//reload))) + (doom//reload-package-autoloads))) (def-dispatcher! (update u) "Checks for and updates outdated plugins." (doom//reload-doom-autoloads) (when (doom//packages-update doom-auto-accept) - (doom//reload))) + (doom//reload-package-autoloads))) (def-dispatcher! (autoremove r) "Removes orphaned plugins." (doom//reload-doom-autoloads) (when (doom//packages-autoremove doom-auto-accept) - (doom//reload))) + (doom//reload-package-autoloads))) (def-dispatcher! (autoloads a) "Regenerates Doom's autoloads file. @@ -196,12 +196,10 @@ recompile. Run this whenever you: 2. Add or remove `package!' blocks to your config, 3. Add or remove autoloaded functions in module autoloaded files. 4. Update Doom outside of Doom (e.g. with git)" - (if (let* ((doom--inhibit-reload t) - (autoremove-p (with-demoted-errors "%s" (doom//packages-autoremove))) - (install-p (with-demoted-errors "%s" (doom//packages-install)))) - (or autoremove-p install-p)) - (doom//reload) - (doom//reload-autoloads)) + (let ((doom--inhibit-reload t)) + (with-demoted-errors "%s" (doom//packages-autoremove)) + (with-demoted-errors "%s" (doom//packages-install))) + (doom//reload-autoloads) (doom//byte-compile nil 'recompile)) From 0368e8f84bbb69b48f78d6a72ca816d6774aa278 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:41:23 +0200 Subject: [PATCH 123/132] Ensure package state is initialized before package management --- core/autoload/packages.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 09cc577fb..96aa9f6f3 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -387,7 +387,7 @@ calls." (defun doom//packages-install (&optional auto-accept-p) "Interactive command for installing missing packages." (interactive "P") - (doom-initialize-packages) + (doom-initialize-packages 'internal) (print! "Looking for packages to install...") (let ((packages (reverse (doom-get-missing-packages)))) (cond ((not packages) @@ -442,7 +442,7 @@ calls." (defun doom//packages-update (&optional auto-accept-p) "Interactive command for updating packages." (interactive "P") - (doom-initialize-packages) + (doom-initialize-packages 'internal) (print! "Looking for outdated packages...") (doom-refresh-packages-maybe doom-debug-mode) (let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp @@ -486,7 +486,7 @@ calls." (defun doom//packages-autoremove (&optional auto-accept-p) "Interactive command for auto-removing orphaned packages." (interactive "P") - (doom-initialize-packages) + (doom-initialize-packages 'internal) (print! "Looking for orphaned packages...") (let ((packages (doom-get-orphaned-packages))) (cond ((not packages) From 7f31f4a1bd93c88c7b3e83844040d24a04c1709e Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:53:48 +0200 Subject: [PATCH 124/132] Adjust package state initialization strategies --- core/autoload/packages.el | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/core/autoload/packages.el b/core/autoload/packages.el index 96aa9f6f3..8b3be26c2 100644 --- a/core/autoload/packages.el +++ b/core/autoload/packages.el @@ -140,7 +140,7 @@ Warning: this function is expensive; it re-evaluates all of doom's config files. Be careful not to use it in a loop. If INSTALLED-ONLY-P, only return packages that are installed." - (doom-initialize-packages (not noninteractive)) + (doom-initialize-packages t) (cl-loop with packages = (append doom-core-packages (mapcar #'car doom-packages)) for sym in (cl-delete-duplicates packages) if (and (or (not installed-only-p) @@ -173,7 +173,8 @@ containing (PACKAGE-SYMBOL OLD-VERSION-LIST NEW-VERSION-LIST). If INCLUDE-FROZEN-P is non-nil, check frozen packages as well. Used by `doom//packages-update'." - (doom-initialize-packages (not noninteractive)) + (doom-initialize-packages t) + (doom-refresh-packages-maybe doom-debug-mode) (require 'async) (let (quelpa-pkgs elpa-pkgs) ;; Separate quelpa from elpa packages @@ -221,7 +222,7 @@ Used by `doom//packages-update'." depended on. Used by `doom//packages-autoremove'." - (doom-initialize-packages (not noninteractive)) + (doom-initialize-packages t) (let ((package-selected-packages (append (mapcar #'car doom-packages) doom-core-packages))) (append (package--removable-packages) @@ -241,7 +242,6 @@ If INCLUDE-IGNORED-P is non-nil, includes missing packages that are ignored, i.e. they have an :ignore property. Used by `doom//packages-install'." - (doom-initialize-packages (not noninteractive)) (cl-loop for desc in (doom-get-packages) for (name . plist) = desc if (and (or include-ignored-p @@ -387,7 +387,6 @@ calls." (defun doom//packages-install (&optional auto-accept-p) "Interactive command for installing missing packages." (interactive "P") - (doom-initialize-packages 'internal) (print! "Looking for packages to install...") (let ((packages (reverse (doom-get-missing-packages)))) (cond ((not packages) @@ -442,9 +441,7 @@ calls." (defun doom//packages-update (&optional auto-accept-p) "Interactive command for updating packages." (interactive "P") - (doom-initialize-packages 'internal) (print! "Looking for outdated packages...") - (doom-refresh-packages-maybe doom-debug-mode) (let ((packages (cl-sort (cl-copy-list (doom-get-outdated-packages)) #'string-lessp :key #'car))) (cond ((not packages) @@ -486,7 +483,6 @@ calls." (defun doom//packages-autoremove (&optional auto-accept-p) "Interactive command for auto-removing orphaned packages." (interactive "P") - (doom-initialize-packages 'internal) (print! "Looking for orphaned packages...") (let ((packages (doom-get-orphaned-packages))) (cond ((not packages) From 2b8efd67832dd3e6e26dc4778d92e6e9fc9bbd42 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 02:54:16 +0200 Subject: [PATCH 125/132] Error of private init.el doesn't exist (it really should!) --- core/core-packages.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/core-packages.el b/core/core-packages.el index d939135c9..d73f14174 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -468,7 +468,7 @@ added, if the file exists." (let* ((init-file (expand-file-name "init.el" doom-private-dir)) (short-init-file (abbreviate-file-name init-file))) (if (not (file-exists-p init-file)) - (warn "%s doesn't exist" short-init-file) + (error "%s doesn't exist" short-init-file) (with-temp-buffer (insert-file-contents init-file) (when (re-search-forward "^\\s-*\\((doom! \\)" nil t) From d7a5f3b99723f6099c472cdaadcd73a6061f0fa8 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 03:07:19 +0200 Subject: [PATCH 126/132] Fix doom-module-table failing to fetch module list ...because sexp-at-point needs a valid syntax table, and fundamental mode ain't got one. --- core/core-packages.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/core-packages.el b/core/core-packages.el index d73f14174..faca27409 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -470,7 +470,8 @@ added, if the file exists." (if (not (file-exists-p init-file)) (error "%s doesn't exist" short-init-file) (with-temp-buffer - (insert-file-contents init-file) + (delay-mode-hooks (emacs-lisp-mode)) + (insert-file-contents-literally init-file) (when (re-search-forward "^\\s-*\\((doom! \\)" nil t) (goto-char (match-beginning 1)) (setq modules (cdr (sexp-at-point)))))) From e99d5c662434f56220d6002eb57e990a8a08b125 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 11:49:59 +0200 Subject: [PATCH 127/132] completion/helm: refactor how helm packages are loaded; fix command remaps --- modules/completion/helm/config.el | 66 ++++++++++++------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/modules/completion/helm/config.el b/modules/completion/helm/config.el index ec0c9a550..7caa3e8a4 100644 --- a/modules/completion/helm/config.el +++ b/modules/completion/helm/config.el @@ -13,6 +13,22 @@ (def-package! helm-mode :defer 1 :after-call pre-command-hook + :init + (map! :map global-map + [remap apropos] #'helm-apropos + [remap bookmark-jump] #'helm-bookmarks + [remap bookmark-jump] #'helm-bookmarks + [remap execute-extended-command] #'helm-M-x + [remap find-file] #'helm-find-files + [remap imenu-anywhere] #'helm-imenu-anywhere + [remap imenu-anywhere] #'helm-imenu-anywhere + [remap imenu] #'helm-semantic-or-imenu + [remap noop-show-kill-ring] #'helm-show-kill-ring + [remap projectile-find-file] #'helm-projectile-find-file + [remap projectile-recentf] #'helm-projectile-recentf + [remap projectile-switch-project] #'helm-projectile-switch-project + [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer + [remap recentf-open-files] #'helm-recentf) :config (helm-mode +1) ;; helm is too heavy for find-file-at-point @@ -41,7 +57,6 @@ helm-move-to-line-cycle-in-source t) :config - (load "helm-autoloads" nil t) (setq projectile-completion-system 'helm) (defvar helm-projectile-find-file-map (make-sparse-keymap)) @@ -73,21 +88,7 @@ (setq-local cursor-type nil)))) (add-hook 'helm-minibuffer-set-up-hook #'+helm*hide-minibuffer-maybe) - (map! :map global-map - [remap apropos] #'helm-apropos - [remap bookmark-jump] #'helm-bookmarks - [remap bookmark-jump] #'helm-bookmarks - [remap execute-extended-command] #'helm-M-x - [remap find-file] #'helm-find-files - [remap imenu-anywhere] #'helm-imenu-anywhere - [remap imenu-anywhere] #'helm-imenu-anywhere - [remap imenu] #'helm-semantic-or-imenu - [remap noop-show-kill-ring] #'helm-show-kill-ring - [remap projectile-find-file] #'helm-projectile-find-file - [remap projectile-recentf] #'helm-projectile-recentf - [remap projectile-switch-project] #'helm-projectile-switch-project - [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer - [remap recentf-open-files] #'helm-recentf)) + ) (def-package! helm-locate @@ -96,40 +97,28 @@ :config (set-keymap-parent helm-generic-files-map helm-map)) -(def-package! helm-bookmark - :commands helm-bookmark - :config (setq-default helm-bookmark-show-location t)) +(after! helm-bookmark + (setq-default helm-bookmark-show-location t)) -(def-package! helm-files - :defer t - :config +(after! helm-files (setq helm-boring-file-regexp-list (append (list "\\.projects$" "\\.DS_Store$") helm-boring-file-regexp-list))) -(def-package! helm-ag - :defer t - :config - (map! :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort)) +;; `helm-ag' +(map! :after helm-ag + :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort) -(def-package! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss - :commands (helm-css-scss - helm-css-scss-multi - helm-css-scss-insert-close-comment) - :config +(after! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss (setq helm-css-scss-split-direction #'split-window-vertically helm-css-scss-split-with-multiple-windows t)) -(def-package! helm-for-files - :commands (helm-for-files helm-recentf helm-multi-files)) - - (def-package! helm-swoop ; https://github.com/ShingoFukuyama/helm-swoop - :commands (helm-swoop helm-multi-swoop helm-multi-swoop-all) + :commands helm-multi-swoop-all :config (setq helm-swoop-use-line-number-face t helm-swoop-candidate-number-limit 200 @@ -137,9 +126,6 @@ helm-swoop-pre-input-function (lambda () ""))) -(def-package! helm-describe-modes :commands helm-describe-modes) - - (def-package! wgrep - :commands (wgrep-setup wgrep-change-to-wgrep-mode) + :commands wgrep-change-to-wgrep-mode :config (setq wgrep-auto-save-buffer t)) From 81d3fe4a82931d4dff899ba6724411bbec4493d0 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 11:54:49 +0200 Subject: [PATCH 128/132] config/default: fix missing +ivy-do-action! error when ivy module is disabled --- modules/config/default/+bindings.el | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 9b2ef077d..b4033b14a 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -393,11 +393,12 @@ [escape] #'company-search-abort)) ;; counsel - (:after counsel - (:map counsel-ag-map - [backtab] #'+ivy/wgrep-occur ; search/replace on results - "C-SPC" #'ivy-call-and-recenter ; preview - "M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action))) + (:when (featurep! :completion ivy) + (:after counsel + (:map counsel-ag-map + [backtab] #'+ivy/wgrep-occur ; search/replace on results + "C-SPC" #'ivy-call-and-recenter ; preview + "M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action)))) ;; easymotion :m "gs" #'+default/easymotion ; lazy-load `evil-easymotion' From d7d9da2210dab92a924e25179a46624ccbdc5518 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 11:55:57 +0200 Subject: [PATCH 129/132] Appease byte-compiler san kun chan sama sensei de gozaru --- modules/feature/lookup/autoload/lookup.el | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/feature/lookup/autoload/lookup.el b/modules/feature/lookup/autoload/lookup.el index 56203adf5..167e12811 100644 --- a/modules/feature/lookup/autoload/lookup.el +++ b/modules/feature/lookup/autoload/lookup.el @@ -160,6 +160,7 @@ Goes down a list of possible backends: identifier (+lookup--online-provider (not current-prefix-arg)))))) +(defvar ffap-file-finder) ;;;###autoload (defun +lookup/file (path) "Figure out PATH from whatever is at point and open it. From 73045f9950569677c357ac962ef832a18830fb94 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 12:49:23 +0200 Subject: [PATCH 130/132] Fix doom//quickstart & improve feedback (make quickstart) --- core/autoload/debug.el | 11 +++-------- core/core-dispatcher.el | 29 ++++++++++++++++++----------- core/templates/QUICKSTART_INTRO | 30 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 core/templates/QUICKSTART_INTRO diff --git a/core/autoload/debug.el b/core/autoload/debug.el index f53e5b33d..2662128e5 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -1,15 +1,10 @@ ;;; core/autoload/debug.el -*- lexical-binding: t; -*- -(defun doom-template-exists-p (template) - "TODO" - (file-exists-p - (expand-file-name (format "templates/%s" template) - doom-core-dir))) - (defun doom-template-insert (template) "TODO" - (let ((dir (expand-file-name "templates/" doom-core-dir))) - (insert-file-contents (expand-file-name template dir)))) + (let ((file (expand-file-name (format "templates/%s" template) doom-core-dir))) + (when (file-exists-p file) + (insert-file-contents file)))) ;;;###autoload (defun doom-info () diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index 0128702c5..6919d4878 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -122,7 +122,7 @@ with the -p option, e.g. This command will refuse to overwrite the private directory if it already exists." - (doom//quickstart args)) + (doom//quickstart)) (def-dispatcher! (install i) "Installs requested plugins that aren't installed." @@ -252,27 +252,34 @@ recompile. Run this whenever you: This deploys a barebones config to `doom-private-dir', installs all missing packages and regenerates the autoloads file." - (declare (interactive-only t)) (interactive) (let ((short-private-dir (abbreviate-file-name doom-private-dir))) - (unless (file-directory-p doom-private-dir) + (if (file-directory-p doom-private-dir) + (print! (yellow "%s directory already exists. Skipping." short-private-dir)) (print! "Creating %s" short-private-dir) - (make-directory doom-private-dir t)) + (make-directory doom-private-dir t) + (print! (green "Done!"))) (let ((init-file (expand-file-name "init.el" doom-private-dir))) (if (file-exists-p init-file) - (print! "%sinit.el already exists. Skipping." short-private-dir) + (print! (yellow "%sinit.el already exists. Skipping." short-private-dir)) (print! "Copying init.example.el to %s" short-private-dir) (copy-file (expand-file-name "init.example.el" doom-emacs-dir) - init-file))) + init-file) + (print! (green "Done!")))) (let ((config-file (expand-file-name "config.el" doom-private-dir))) (if (file-exists-p config-file) (print! "%sconfig.el already exists. Skipping." short-private-dir) - (with-temp-file config-file (insert ""))))) - (print! "Installing plugins & generating autoloads file, if necessary") + (print! "Deploying empty config.el file in %s" short-private-dir) + (with-temp-file config-file (insert "")) + (print! (green "Done!"))))) + (print! "Installing plugins") (doom//packages-install) - (doom//reload-autoloads) - (print! "\n\nDone! Doom Emacs is ready.\n") - (print! "Remember to run M-x all-the-icons-install-fonts after starting Emacs for the first time.")) + (print! "Regenerating autoloads files") + (doom//reload-autoloads nil 'force-p) + (print! (bold (green "\nFinished! Doom is ready to go!\n"))) + (with-temp-buffer + (doom-template-insert "QUICKSTART_INTRO") + (print! (buffer-string)))) (provide 'core-dispatcher) ;;; core-dispatcher.el ends here diff --git a/core/templates/QUICKSTART_INTRO b/core/templates/QUICKSTART_INTRO new file mode 100644 index 000000000..61a8af0ec --- /dev/null +++ b/core/templates/QUICKSTART_INTRO @@ -0,0 +1,30 @@ +Before you doom yourself, there are a few things you should know: + +1. If you use GUI Emacs, run `M-x all-the-icons-install-fonts` so you don't get + weird symbols all over the place. + +2. When you edit ~/.doom.d/init.el or modify modules, run: + + bin/doom refresh + + This will ensure all needed packages are installed, all orphaned packages are + removed, and your autoloads files are up to date. This is important! If you + forget to do this you will get errors! + +3. If something inexplicably goes wrong, it's a good idea to try: + + bin/doom doctor + + It will diagnose common issues with your environment and setup, and may give + you clues about what is wrong. + +4. To update doom, run + + bin/doom upgrade + + Doing it any other way will require you run `bin/doom refresh` otherwise, + +5. Check out `bin/doom help` to see what else it can do (it is also safe to add + ~/.emacs.d/bin to your PATH). + +Have fun! From 4aacd831b528926644091e721d7b98fcee8aa560 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 12:49:34 +0200 Subject: [PATCH 131/132] Fix doom//upgrade (make upgrade) --- core/core-dispatcher.el | 1 + 1 file changed, 1 insertion(+) diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index 6919d4878..d52f9a13b 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -214,6 +214,7 @@ recompile. Run this whenever you: (defun doom//upgrade () "Upgrade Doom to the latest version." (interactive) + (require 'vc-git) (let ((core-file (expand-file-name "init.el" doom-core-dir)) (branch (vc-git--symbolic-ref core-file)) (default-directory doom-emacs-dir)) From 27cee0bf5ab21fa34c882d5e82455c6860ed1cc3 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Fri, 25 May 2018 18:33:30 +0200 Subject: [PATCH 132/132] Remove redundant hexl-mode block --- modules/lang/data/config.el | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/lang/data/config.el b/modules/lang/data/config.el index 4111c5972..80134d84d 100644 --- a/modules/lang/data/config.el +++ b/modules/lang/data/config.el @@ -27,10 +27,6 @@ (def-package! graphql-mode :mode "\\.gql\\'") -(def-package! hexl ; For ROM hacking or debugging - :mode ("\\.hex$" . hexl-mode) - :mode ("\\.nes$" . hexl-mode)) - (def-package! json-mode :mode "\\.js\\(?:on\\|[hl]int\\(rc\\)?\\)\\'" :config