2018-05-20 12:21:13 +02:00
|
|
|
;;; -*- lexical-binding: t; no-byte-compile: t; -*-
|
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
;; 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).
|
2018-05-27 12:44:22 +02:00
|
|
|
(load! "autoload/packages")
|
|
|
|
(load! "autoload/debug")
|
|
|
|
(load! "autoload/message")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
;;
|
2018-05-24 19:03:36 +02:00
|
|
|
;; Dispatcher API
|
2018-05-20 12:21:13 +02:00
|
|
|
;;
|
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
(defvar doom-auto-accept (getenv "YES")
|
|
|
|
"If non-nil, Doom will auto-accept any confirmation prompts during batch
|
2018-06-17 21:35:58 +02:00
|
|
|
commands like `doom-packages-install', `doom-packages-update' and
|
|
|
|
`doom-packages-autoremove'.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
(defconst doom--dispatch-command-alist ())
|
|
|
|
(defconst doom--dispatch-alias-alist ())
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
(defun doom--dispatch-format (desc &optional short)
|
2018-06-05 11:19:34 +02:00
|
|
|
(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)))))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
(defun doom--dispatch-help (&optional command desc &rest args)
|
2018-05-24 19:03:36 +02:00
|
|
|
"Display help documentation for a dispatcher command. If COMMAND and DESC are
|
|
|
|
omitted, show all available commands, their aliases and brief descriptions."
|
2018-05-20 12:21:13 +02:00
|
|
|
(if command
|
|
|
|
(princ (doom--dispatch-format desc))
|
|
|
|
(print! (bold "%-10s\t%s\t%s" "Command:" "Alias" "Description"))
|
2018-06-19 16:43:08 +02:00
|
|
|
(dolist (spec (cl-sort doom--dispatch-command-alist #'string-lessp
|
|
|
|
:key #'car))
|
2018-05-20 12:21:13 +02:00
|
|
|
(cl-destructuring-bind (command &key desc _body) spec
|
2018-05-24 19:03:36 +02:00
|
|
|
(let ((aliases (cl-loop for (alias . cmd) in doom--dispatch-alias-alist
|
|
|
|
if (eq cmd command)
|
|
|
|
collect (symbol-name alias))))
|
2018-05-20 12:21:13 +02:00
|
|
|
(print! " %-10s\t%s\t%s"
|
2018-05-24 19:03:36 +02:00
|
|
|
command (if aliases (string-join aliases ",") "")
|
2018-05-20 12:21:13 +02:00
|
|
|
(doom--dispatch-format desc t)))))))
|
|
|
|
|
|
|
|
(defun doom-dispatch (args)
|
2018-05-24 19:03:36 +02:00
|
|
|
"Invoke a dispatcher command and pass ARGS to it."
|
2018-05-20 12:21:13 +02:00
|
|
|
(let ((help (equal (car args) "help")))
|
|
|
|
(if help (pop args))
|
|
|
|
(cl-destructuring-bind (command &key desc body)
|
|
|
|
(let ((sym (intern (car args))))
|
2018-05-24 19:03:36 +02:00
|
|
|
(or (assq sym doom--dispatch-command-alist)
|
2018-06-19 20:55:44 +02:00
|
|
|
(assq (cdr (assq sym doom--dispatch-alias-alist))
|
|
|
|
doom--dispatch-command-alist)
|
2018-05-20 12:21:13 +02:00
|
|
|
(error "Invalid command: %s" (car args))))
|
|
|
|
(if help
|
|
|
|
(apply #'doom--dispatch-help command desc (cdr args))
|
|
|
|
(funcall body (cdr args))))))
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(defmacro dispatcher! (command form &optional docstring)
|
2018-05-24 19:03:36 +02:00
|
|
|
"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."
|
2018-06-17 21:38:30 +02:00
|
|
|
(declare (doc-string 3))
|
2018-06-19 20:55:44 +02:00
|
|
|
(cl-destructuring-bind (cmd &rest aliases)
|
|
|
|
(doom-enlist command)
|
2018-06-19 16:43:08 +02:00
|
|
|
(macroexp-progn
|
|
|
|
(append
|
|
|
|
(when aliases
|
|
|
|
`((dolist (alias ',aliases)
|
2018-06-23 16:48:58 +02:00
|
|
|
(setf (alist-get alias doom--dispatch-alias-alist) ',cmd))))
|
|
|
|
`((setf (alist-get ',cmd doom--dispatch-command-alist)
|
|
|
|
(list :desc ,docstring
|
|
|
|
:body (lambda (args) ,form))))))))
|
2018-05-24 19:03:36 +02:00
|
|
|
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
;;
|
2018-05-24 19:03:36 +02:00
|
|
|
;; Dispatch commands
|
|
|
|
;;
|
|
|
|
|
|
|
|
;; Dummy dispatchers (no-op because they're handled especially)
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! run :noop
|
2018-05-20 12:21:13 +02:00
|
|
|
"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
|
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
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.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (doctor doc) :noop
|
2018-05-21 15:42:27 +02:00
|
|
|
"Checks for issues with your current Doom config.")
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (help h) :noop
|
2018-05-21 15:42:27 +02:00
|
|
|
"Look up additional information about a command.")
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
|
2018-05-24 19:03:36 +02:00
|
|
|
;; Real dispatchers
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (quickstart qs) (doom-quickstart)
|
2018-05-24 19:03:36 +02:00
|
|
|
"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
|
2018-06-17 21:38:30 +02:00
|
|
|
exists.")
|
|
|
|
|
|
|
|
(dispatcher! (install i) (doom--do 'doom-packages-install)
|
|
|
|
"Installs requested plugins that aren't installed.")
|
|
|
|
|
|
|
|
(dispatcher! (update u) (doom--do 'doom-packages-update)
|
|
|
|
"Installs requested plugins that aren't installed.")
|
|
|
|
|
|
|
|
(dispatcher! (autoremove r) (doom--do 'doom-packages-autoremove)
|
|
|
|
"Installs requested plugins that aren't installed.")
|
|
|
|
|
|
|
|
(dispatcher! (autoloads a) (doom-reload-autoloads nil 'force)
|
2018-05-20 12:21:13 +02:00
|
|
|
"Regenerates Doom's autoloads file.
|
|
|
|
|
|
|
|
This file tells Emacs where to find your module's autoloaded functions and
|
2018-06-17 21:38:30 +02:00
|
|
|
plugins.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (upgrade up) (doom-upgrade)
|
|
|
|
"Checks out the latest Doom on this branch.")
|
|
|
|
|
|
|
|
(dispatcher! (compile c) (doom-byte-compile args)
|
2018-05-20 12:21:13 +02:00
|
|
|
"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,
|
2018-06-17 21:38:30 +02:00
|
|
|
respectively.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (compile c) (doom-byte-compile args)
|
|
|
|
"Byte-compiles your config or selected modules.
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
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.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! (recompile rc) (doom-byte-compile args 'recompile)
|
|
|
|
"Re-byte-compiles outdated *.elc files.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! clean (doom-clean-byte-compiled-files)
|
|
|
|
"Delete all *.elc files.")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(dispatcher! test
|
|
|
|
(progn (require 'core-tests)
|
|
|
|
(doom-run-tests args))
|
|
|
|
"Run Doom unit tests.")
|
|
|
|
|
|
|
|
(dispatcher! info (doom/info)
|
|
|
|
"Output system info in markdown for bug reports.")
|
|
|
|
|
|
|
|
(dispatcher! (version v) (doom/version)
|
|
|
|
"Reports the version of Doom and Emacs.")
|
|
|
|
|
2018-06-26 17:14:29 +02:00
|
|
|
(dispatcher! (refresh re) (doom-refresh 'force)
|
2018-05-24 19:03:36 +02:00
|
|
|
"Refresh Doom. Same as autoremove+install+autoloads.
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
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.
|
2018-06-17 21:38:30 +02:00
|
|
|
4. Update Doom outside of Doom (e.g. with git)")
|
2018-05-20 12:21:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
;; Quality of Life Commands
|
|
|
|
;;
|
|
|
|
|
2018-05-26 23:25:06 +02:00
|
|
|
(defvar doom-repo-url "https://github.com/hlissner/doom-emacs"
|
|
|
|
"TODO")
|
2018-05-28 12:19:58 +02:00
|
|
|
(defvar doom-repo-remote "_upgrade"
|
2018-05-20 12:21:13 +02:00
|
|
|
"TODO")
|
|
|
|
|
2018-05-28 12:19:58 +02:00
|
|
|
(defun doom--working-tree-dirty-p (dir)
|
|
|
|
(with-temp-buffer
|
|
|
|
(let ((default-directory dir))
|
|
|
|
(if (zerop (process-file "git" nil (current-buffer) nil
|
2018-06-01 11:25:47 +02:00
|
|
|
"status" "--porcelain" "-uno"))
|
2018-05-28 12:19:58 +02:00
|
|
|
(string-match-p "[^ \t\n]" (buffer-string))
|
|
|
|
(error "Failed to check working tree in %s" dir)))))
|
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-refresh (&optional force-p)
|
2018-05-30 11:42:35 +02:00
|
|
|
"Ensure Doom is in a working state by checking autoloads and packages, and
|
|
|
|
recompiling any changed compiled files. This is the shotgun solution to most
|
|
|
|
problems with doom."
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom-reload-doom-autoloads force-p)
|
2018-05-30 11:42:35 +02:00
|
|
|
(unwind-protect
|
2018-06-19 16:43:08 +02:00
|
|
|
(progn
|
|
|
|
(ignore-errors
|
|
|
|
(doom-packages-autoremove doom-auto-accept))
|
|
|
|
(ignore-errors
|
|
|
|
(doom-packages-install doom-auto-accept)))
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom-reload-package-autoloads force-p)
|
|
|
|
(doom-byte-compile nil 'recompile)))
|
2018-05-30 11:42:35 +02:00
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-upgrade ()
|
2018-06-02 13:56:39 +02:00
|
|
|
"Upgrade Doom to the latest version non-destructively."
|
2018-05-25 12:49:34 +02:00
|
|
|
(require 'vc-git)
|
2018-05-26 23:25:06 +02:00
|
|
|
(let* ((gitdir (expand-file-name ".git" doom-emacs-dir))
|
|
|
|
(branch (vc-git--symbolic-ref doom-emacs-dir))
|
2018-05-25 16:15:58 +02:00
|
|
|
(default-directory doom-emacs-dir))
|
2018-05-26 23:25:06 +02:00
|
|
|
(unless (file-exists-p gitdir)
|
2018-06-02 13:56:39 +02:00
|
|
|
(error "Couldn't find %s. Was Doom cloned properly?"
|
2018-05-26 23:25:06 +02:00
|
|
|
(abbreviate-file-name gitdir)))
|
2018-05-20 12:21:13 +02:00
|
|
|
(unless branch
|
2018-06-02 13:56:39 +02:00
|
|
|
(error "Couldn't detect what branch you're using. Is Doom detached?"
|
2018-05-20 12:21:13 +02:00
|
|
|
(abbreviate-file-name doom-emacs-dir)))
|
2018-05-28 12:19:58 +02:00
|
|
|
(when (doom--working-tree-dirty-p doom-emacs-dir)
|
2018-05-26 23:25:06 +02:00
|
|
|
(user-error "Refusing to upgrade because Doom has been modified. Stash or undo your changes"))
|
2018-05-20 12:21:13 +02:00
|
|
|
(with-temp-buffer
|
|
|
|
(let ((buf (current-buffer)))
|
2018-06-02 13:56:39 +02:00
|
|
|
(condition-case e
|
|
|
|
(progn
|
|
|
|
(process-file "git" nil buf nil "remote" "remove" doom-repo-remote)
|
|
|
|
(unless (zerop (process-file "git" nil buf nil "remote" "add"
|
|
|
|
doom-repo-remote doom-repo-url))
|
|
|
|
(error "Failed to add %s to remotes" doom-repo-remote))
|
|
|
|
(unless (zerop (process-file "git" nil buf nil "fetch" "--tags"
|
|
|
|
doom-repo-remote branch))
|
|
|
|
(error "Failed to fetch from upstream"))
|
2018-06-17 21:35:58 +02:00
|
|
|
(let ((current-rev (vc-git-working-revision doom-emacs-dir))
|
|
|
|
(rev (string-trim (shell-command-to-string (format "git rev-parse %s/%s" doom-repo-remote branch)))))
|
|
|
|
(unless rev
|
|
|
|
(error "Couldn't detect Doom's version. Is %s a repo?"
|
|
|
|
(abbreviate-file-name doom-emacs-dir)))
|
|
|
|
(when (equal current-rev rev)
|
|
|
|
(user-error "Doom is up to date!"))
|
|
|
|
(message "Updates for Doom are available!\n\n Old revision: %s\n New revision: %s\n"
|
|
|
|
current-rev rev)
|
|
|
|
;; TODO Display newsletter diff
|
|
|
|
(unless (or doom-auto-accept (y-or-n-p "Proceed?"))
|
|
|
|
(error "Aborted"))
|
|
|
|
(message "Removing byte-compiled files from your config (if any)")
|
|
|
|
(doom-clean-byte-compiled-files)
|
|
|
|
(unless (zerop (process-file "git" nil buf nil "reset" "--hard"
|
|
|
|
(format "%s/%s" doom-repo-remote branch)))
|
|
|
|
(error "An error occurred while checking out the latest commit\n\n%s"
|
|
|
|
(buffer-string)))
|
|
|
|
(unless (equal (vc-git-working-revision doom-emacs-dir) rev)
|
|
|
|
(error "Failed to checkout latest commit.\n\n%s" (buffer-string)))
|
|
|
|
(doom-refresh 'force)
|
|
|
|
(message "Done! Please restart Emacs for changes to take effect")))
|
2018-06-03 15:58:49 +02:00
|
|
|
(user-error
|
|
|
|
(message "%s Aborting." (error-message-string e)))
|
2018-06-02 13:56:39 +02:00
|
|
|
(error
|
|
|
|
(message "There was an unexpected error.\n\n%s -> %s\n\nOutput:\n%s"
|
2018-06-03 15:58:49 +02:00
|
|
|
(car e)
|
2018-06-02 13:56:39 +02:00
|
|
|
(buffer-string))))))))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-quickstart ()
|
2018-05-24 19:03:36 +02:00
|
|
|
"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."
|
2018-05-20 12:21:13 +02:00
|
|
|
(let ((short-private-dir (abbreviate-file-name doom-private-dir)))
|
2018-05-25 12:49:23 +02:00
|
|
|
(if (file-directory-p doom-private-dir)
|
|
|
|
(print! (yellow "%s directory already exists. Skipping." short-private-dir))
|
2018-05-24 19:03:36 +02:00
|
|
|
(print! "Creating %s" short-private-dir)
|
2018-05-25 12:49:23 +02:00
|
|
|
(make-directory doom-private-dir t)
|
|
|
|
(print! (green "Done!")))
|
2018-05-20 12:21:13 +02:00
|
|
|
(let ((init-file (expand-file-name "init.el" doom-private-dir)))
|
2018-05-24 19:03:36 +02:00
|
|
|
(if (file-exists-p init-file)
|
2018-05-25 12:49:23 +02:00
|
|
|
(print! (yellow "%sinit.el already exists. Skipping." short-private-dir))
|
2018-05-24 19:03:36 +02:00
|
|
|
(print! "Copying init.example.el to %s" short-private-dir)
|
2018-05-20 12:21:13 +02:00
|
|
|
(copy-file (expand-file-name "init.example.el" doom-emacs-dir)
|
2018-05-25 12:49:23 +02:00
|
|
|
init-file)
|
|
|
|
(print! (green "Done!"))))
|
2018-05-20 12:21:13 +02:00
|
|
|
(let ((config-file (expand-file-name "config.el" doom-private-dir)))
|
|
|
|
(if (file-exists-p config-file)
|
2018-05-24 19:03:36 +02:00
|
|
|
(print! "%sconfig.el already exists. Skipping." short-private-dir)
|
2018-05-25 12:49:23 +02:00
|
|
|
(print! "Deploying empty config.el file in %s" short-private-dir)
|
|
|
|
(with-temp-file config-file (insert ""))
|
|
|
|
(print! (green "Done!")))))
|
|
|
|
(print! "Installing plugins")
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom-packages-install)
|
2018-05-25 12:49:23 +02:00
|
|
|
(print! "Regenerating autoloads files")
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom-reload-autoloads nil 'force-p)
|
2018-05-25 12:49:23 +02:00
|
|
|
(print! (bold (green "\nFinished! Doom is ready to go!\n")))
|
|
|
|
(with-temp-buffer
|
|
|
|
(doom-template-insert "QUICKSTART_INTRO")
|
|
|
|
(print! (buffer-string))))
|
2018-05-20 12:21:13 +02:00
|
|
|
|
2018-06-11 23:20:45 +02:00
|
|
|
|
|
|
|
;;
|
|
|
|
;; 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-delete-autoloads-file (file)
|
|
|
|
"Delete FILE (an autoloads file), and delete the accompanying *.elc file, if
|
|
|
|
it exists."
|
|
|
|
(cl-check-type file string)
|
|
|
|
(when (file-exists-p file)
|
2018-06-14 19:46:31 +02:00
|
|
|
(when-let* ((buf (find-buffer-visiting doom-autoload-file)))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(set-buffer-modified-p nil))
|
|
|
|
(kill-buffer buf))
|
2018-06-11 23:20:45 +02:00
|
|
|
(delete-file file)
|
|
|
|
(ignore-errors (delete-file (byte-compile-dest-file file)))
|
|
|
|
(message "Deleted old %s" (file-name-nondirectory file))))
|
|
|
|
|
2018-06-17 21:38:30 +02:00
|
|
|
(defun doom--do (fn)
|
|
|
|
(doom-reload-doom-autoloads)
|
|
|
|
(when (funcall fn doom-auto-accept)
|
|
|
|
(doom-reload-package-autoloads)))
|
|
|
|
|
2018-07-12 19:51:21 +02:00
|
|
|
(defun doom--warn-refresh-session ()
|
|
|
|
(message "Detected a running Emacs session.\n")
|
|
|
|
(message "Use `M-x doom/reload' for changes to take effect."))
|
2018-07-03 00:53:06 +02:00
|
|
|
|
2018-07-12 19:51:21 +02:00
|
|
|
(defun doom--do-load (&rest files)
|
2018-07-03 00:53:06 +02:00
|
|
|
(if (and noninteractive (not (daemonp)))
|
|
|
|
(progn
|
|
|
|
(require 'server)
|
|
|
|
(when (server-running-p)
|
2018-07-12 19:51:21 +02:00
|
|
|
(add-hook 'kill-emacs-hook #'doom--warn-refresh-session)))
|
2018-07-03 00:53:06 +02:00
|
|
|
(dolist (file files)
|
|
|
|
(load-file (byte-compile-dest-file file)))))
|
2018-06-11 23:20:45 +02:00
|
|
|
|
|
|
|
(defun doom--byte-compile-file (file)
|
|
|
|
(let ((short-name (file-name-nondirectory file))
|
|
|
|
(byte-compile-dynamic-docstrings t))
|
2018-06-19 16:42:10 +02:00
|
|
|
(condition-case e
|
2018-06-11 23:20:45 +02:00
|
|
|
(when (byte-compile-file file)
|
2018-06-19 17:19:11 +02:00
|
|
|
;; Give autoloads file a chance to report error
|
|
|
|
(load (if doom-debug-mode
|
|
|
|
file
|
|
|
|
(byte-compile-dest-file file))
|
|
|
|
nil t)
|
2018-06-11 23:20:45 +02:00
|
|
|
(unless noninteractive
|
|
|
|
(message "Finished compiling %s" short-name)))
|
2018-06-19 16:42:10 +02:00
|
|
|
((debug error)
|
2018-06-19 17:19:11 +02:00
|
|
|
(let ((backup-file (concat file ".bk")))
|
|
|
|
(message "Copied backup to %s" backup-file)
|
|
|
|
(copy-file file backup-file 'overwrite))
|
2018-06-11 23:20:45 +02:00
|
|
|
(doom-delete-autoloads-file file)
|
2018-06-19 16:42:10 +02:00
|
|
|
(signal 'doom-autoload-error (list short-name e))))))
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-reload-autoloads (&optional file force-p)
|
2018-06-11 23:20:45 +02:00
|
|
|
"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!"
|
|
|
|
(or (null file)
|
|
|
|
(stringp file)
|
|
|
|
(signal 'wrong-type-argument (list 'stringp file)))
|
2018-06-19 17:16:08 +02:00
|
|
|
(if (stringp file)
|
|
|
|
(cond ((file-equal-p file doom-autoload-file)
|
|
|
|
(doom-reload-doom-autoloads force-p))
|
|
|
|
((file-equal-p file doom-package-autoload-file)
|
|
|
|
(doom-reload-package-autoloads force-p))
|
|
|
|
((error "Invalid autoloads file: %s" file)))
|
|
|
|
(doom-reload-doom-autoloads force-p)
|
|
|
|
(doom-reload-package-autoloads force-p)))
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2018-06-14 19:46:31 +02:00
|
|
|
|
|
|
|
;;
|
|
|
|
;; Doom autoloads
|
|
|
|
;;
|
|
|
|
|
2018-06-15 13:27:24 +02:00
|
|
|
(defun doom--file-cookie-p (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)
|
|
|
|
(<= (line-number-at-pos) 3))
|
|
|
|
(let ((load-file-name file))
|
|
|
|
(eval (sexp-at-point)))
|
|
|
|
t)))
|
|
|
|
|
2018-06-14 19:46:31 +02:00
|
|
|
(defun doom--generate-header (func)
|
|
|
|
(goto-char (point-min))
|
|
|
|
(insert ";; -*- lexical-binding:t -*-\n"
|
|
|
|
";; This file is autogenerated by `" (symbol-name func) "', DO NOT EDIT !!\n\n"))
|
|
|
|
|
|
|
|
(defun doom--generate-autoloads (targets)
|
|
|
|
(require 'autoload)
|
|
|
|
(dolist (file targets)
|
|
|
|
(let* ((file (file-truename file))
|
|
|
|
(generated-autoload-file doom-autoload-file)
|
|
|
|
(generated-autoload-load-name (file-name-sans-extension file))
|
|
|
|
(noninteractive (not doom-debug-mode))
|
|
|
|
autoload-timestamps)
|
|
|
|
(print!
|
2018-06-15 13:27:24 +02:00
|
|
|
(cond ((not (doom--file-cookie-p file))
|
2018-06-14 19:46:31 +02:00
|
|
|
"⚠ Ignoring %s")
|
|
|
|
((autoload-generate-file-autoloads file (current-buffer))
|
|
|
|
(yellow "✕ Nothing in %%s"))
|
|
|
|
((green "✓ Scanned %%s")))
|
|
|
|
(if (file-in-directory-p file default-directory)
|
|
|
|
(file-relative-name file)
|
|
|
|
(abbreviate-file-name file))))))
|
|
|
|
|
|
|
|
(defun doom--expand-autoloads ()
|
|
|
|
(let ((load-path (append doom-modules-dirs load-path))
|
|
|
|
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)
|
|
|
|
path)
|
|
|
|
t t nil 1)))))
|
|
|
|
|
|
|
|
(defun doom--generate-autodefs (targets enabled-targets)
|
|
|
|
(goto-char (point-max))
|
|
|
|
(search-backward ";;;***" nil t)
|
|
|
|
(save-excursion (insert "\n"))
|
|
|
|
(dolist (path targets)
|
|
|
|
(insert
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents path)
|
|
|
|
(let ((member-p (or (member path enabled-targets)
|
|
|
|
(file-in-directory-p path doom-core-dir)))
|
2018-06-15 14:56:45 +02:00
|
|
|
forms)
|
2018-06-14 19:46:31 +02:00
|
|
|
(while (re-search-forward "^;;;###autodef *\\([^\n]+\\)?\n" nil t)
|
2018-06-18 01:55:37 +02:00
|
|
|
(let* ((sexp (sexp-at-point))
|
|
|
|
(pred (match-string 1))
|
|
|
|
(type (car sexp))
|
|
|
|
(name (doom-unquote (cadr sexp)))
|
|
|
|
(origin (cond ((doom-module-from-path path))
|
|
|
|
((file-in-directory-p path doom-private-dir)
|
|
|
|
`(:private . ,(intern (file-name-base path))))
|
|
|
|
((file-in-directory-p path doom-emacs-dir)
|
|
|
|
`(:core . ,(intern (file-name-base path))))))
|
|
|
|
(doom-file-form
|
|
|
|
`(put ',name 'doom-file ,(abbreviate-file-name path))))
|
|
|
|
(cond ((memq type '(defun defmacro cl-defun cl-defmacro))
|
|
|
|
(cl-destructuring-bind (type name arglist &rest body) sexp
|
|
|
|
(let ((docstring (if (stringp (car body))
|
|
|
|
(pop body)
|
|
|
|
"No documentation.")))
|
|
|
|
(push (cond ((not (and member-p
|
|
|
|
(or (null pred)
|
|
|
|
(eval (read pred) t))))
|
|
|
|
(push doom-file-form forms)
|
|
|
|
(setq docstring (format "THIS FUNCTION DOES NOTHING BECAUSE %s IS DISABLED\n\n%s"
|
|
|
|
origin docstring))
|
|
|
|
(condition-case-unless-debug e
|
2018-06-18 17:30:33 +02:00
|
|
|
(append (list (pcase type
|
|
|
|
(`defun 'defmacro)
|
|
|
|
(`cl-defun `cl-defmacro))
|
|
|
|
name arglist docstring)
|
2018-06-18 01:55:37 +02:00
|
|
|
(cl-loop for arg in arglist
|
|
|
|
if (and (symbolp arg)
|
|
|
|
(not (keywordp arg))
|
|
|
|
(not (memq arg cl--lambda-list-keywords)))
|
2018-06-18 17:30:33 +02:00
|
|
|
collect arg into syms
|
2018-06-18 01:55:37 +02:00
|
|
|
else if (listp arg)
|
2018-06-18 17:30:33 +02:00
|
|
|
collect (car arg) into syms
|
|
|
|
finally return (if syms `((ignore ,@syms)))))
|
2018-06-18 01:55:37 +02:00
|
|
|
('error
|
|
|
|
(message "Ignoring autodef %s (%s)"
|
|
|
|
name e)
|
|
|
|
nil)))
|
2018-06-26 18:33:25 +02:00
|
|
|
((make-autoload sexp (abbreviate-file-name (file-name-sans-extension path)))))
|
2018-06-18 01:55:37 +02:00
|
|
|
forms)
|
|
|
|
(push `(put ',name 'doom-module ',origin) forms))))
|
|
|
|
|
|
|
|
((eq type 'defalias)
|
|
|
|
(cl-destructuring-bind (type name target &optional docstring) sexp
|
|
|
|
(let ((name (doom-unquote name))
|
|
|
|
(target (doom-unquote target)))
|
|
|
|
(unless (and member-p
|
|
|
|
(or (null pred)
|
|
|
|
(eval (read pred) t)))
|
|
|
|
(setq target #'ignore))
|
|
|
|
(push doom-file-form forms)
|
|
|
|
(push `(put ',name 'doom-module ',origin) forms)
|
|
|
|
(push `(defalias ',name #',target ,docstring)
|
|
|
|
forms))))
|
|
|
|
|
|
|
|
((and member-p
|
|
|
|
(or (null pred)
|
|
|
|
(eval (read pred) t)))
|
|
|
|
(push sexp forms)))))
|
2018-06-14 19:46:31 +02:00
|
|
|
(if forms
|
2018-06-15 14:56:45 +02:00
|
|
|
(concat (string-join (mapcar #'prin1-to-string (reverse forms)) "\n")
|
2018-06-14 19:46:31 +02:00
|
|
|
"\n")
|
|
|
|
""))))))
|
|
|
|
|
|
|
|
(defun doom--cleanup-autoloads ()
|
|
|
|
(goto-char (point-min))
|
|
|
|
(when (re-search-forward "^;;\\(;[^\n]*\\| no-byte-compile: t\\)\n" nil t)
|
|
|
|
(replace-match "" t t)))
|
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-reload-doom-autoloads (&optional force-p)
|
2018-06-11 23:20:45 +02:00
|
|
|
"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 `doom-autoload-file'. This file tells
|
|
|
|
Emacs where to find lazy-loaded functions.
|
|
|
|
|
|
|
|
This should be run whenever your `doom!' block, or a module autoload file, is
|
|
|
|
modified."
|
2018-06-14 19:46:31 +02:00
|
|
|
(let* ((default-directory doom-emacs-dir)
|
|
|
|
(doom-modules (doom-modules))
|
|
|
|
(targets
|
|
|
|
(file-expand-wildcards
|
|
|
|
(expand-file-name "autoload/*.el" doom-core-dir)))
|
|
|
|
(enabled-targets (copy-sequence targets))
|
|
|
|
case-fold-search)
|
|
|
|
(dolist (path (doom-module-load-path t))
|
|
|
|
(let* ((auto-dir (expand-file-name "autoload" path))
|
|
|
|
(auto-file (expand-file-name "autoload.el" path))
|
|
|
|
(module (doom-module-from-path auto-file))
|
|
|
|
(module-p (or (doom-module-p (car module) (cdr module))
|
|
|
|
(file-equal-p path doom-private-dir))))
|
2018-06-11 23:20:45 +02:00
|
|
|
(when (file-exists-p auto-file)
|
2018-06-14 19:46:31 +02:00
|
|
|
(push auto-file targets)
|
|
|
|
(if module-p (push auto-file enabled-targets)))
|
|
|
|
(dolist (file (doom-files-in auto-dir :match "\\.el$" :full t))
|
|
|
|
(push file targets)
|
|
|
|
(if module-p (push file enabled-targets)))))
|
2018-06-11 23:20:45 +02:00
|
|
|
(if (and (not force-p)
|
|
|
|
(not doom-emacs-changed-p)
|
|
|
|
(file-exists-p doom-autoload-file)
|
|
|
|
(not (file-newer-than-file-p (expand-file-name "init.el" doom-private-dir)
|
|
|
|
doom-autoload-file))
|
|
|
|
(not (cl-loop for file in targets
|
|
|
|
if (file-newer-than-file-p file doom-autoload-file)
|
|
|
|
return t)))
|
2018-06-14 19:46:31 +02:00
|
|
|
(progn (print! (green "Doom core autoloads is up-to-date"))
|
|
|
|
(doom-initialize-autoloads doom-autoload-file)
|
|
|
|
nil)
|
2018-06-11 23:20:45 +02:00
|
|
|
(doom-delete-autoloads-file doom-autoload-file)
|
|
|
|
(message "Generating new autoloads.el")
|
|
|
|
(make-directory (file-name-directory doom-autoload-file) t)
|
2018-06-14 19:46:31 +02:00
|
|
|
(with-temp-file doom-autoload-file
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom--generate-header 'doom-reload-doom-autoloads)
|
2018-06-14 19:46:31 +02:00
|
|
|
(save-excursion
|
|
|
|
(doom--generate-autoloads (reverse enabled-targets)))
|
|
|
|
;; Replace autoload paths (only for module autoloads) with absolute
|
|
|
|
;; paths for faster resolution during load and simpler `load-path'
|
|
|
|
(save-excursion
|
|
|
|
(doom--expand-autoloads)
|
|
|
|
(print! (green "✓ Expanded module autoload paths")))
|
|
|
|
;; Generates stub definitions for functions/macros defined in disabled
|
|
|
|
;; modules, so that you will never get a void-function when you use
|
|
|
|
;; them.
|
|
|
|
(save-excursion
|
2018-06-18 01:55:37 +02:00
|
|
|
(doom--generate-autodefs (reverse targets) enabled-targets)
|
|
|
|
(print! (green "✓ Generated autodefs")))
|
2018-06-14 19:46:31 +02:00
|
|
|
;; Remove byte-compile inhibiting file variables so we can byte-compile
|
|
|
|
;; the file, and autoload comments.
|
|
|
|
(doom--cleanup-autoloads)
|
|
|
|
(print! (green "✓ Clean up autoloads")))
|
|
|
|
;; Byte compile it to give the file a chance to reveal errors.
|
|
|
|
(doom--byte-compile-file doom-autoload-file)
|
2018-07-12 19:51:21 +02:00
|
|
|
(doom--do-load doom-autoload-file)
|
2018-06-14 19:46:31 +02:00
|
|
|
t)))
|
|
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
;; Package autoloads
|
|
|
|
;;
|
|
|
|
|
|
|
|
(defun doom--generate-package-autoloads ()
|
|
|
|
(dolist (spec (doom-get-package-alist))
|
|
|
|
(if-let* ((pkg (car spec))
|
|
|
|
(desc (cdr spec)))
|
|
|
|
(unless (memq pkg doom-autoload-excluded-packages)
|
|
|
|
(let ((file (concat (package--autoloads-file-name desc) ".el")))
|
|
|
|
(when (file-exists-p file)
|
|
|
|
(insert "(let ((load-file-name " (prin1-to-string (abbreviate-file-name file)) "))\n")
|
|
|
|
(insert-file-contents file)
|
|
|
|
(while (re-search-forward "^\\(?:;;\\(.*\n\\)\\|\n\\|(provide '[^\n]+\\)" nil t)
|
|
|
|
(unless (nth 8 (syntax-ppss))
|
|
|
|
(replace-match "" t t)))
|
|
|
|
(unless (bolp) (insert "\n"))
|
|
|
|
(insert ")\n"))))
|
|
|
|
(message "Couldn't find package desc for %s" (car spec)))))
|
|
|
|
|
|
|
|
(defun doom--generate-var-cache ()
|
|
|
|
(doom-initialize-packages)
|
|
|
|
(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--cleanup-package-autoloads ()
|
|
|
|
(while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|\\(?:when\\|if\\) (boundp\\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t)
|
|
|
|
(goto-char (match-beginning 1))
|
|
|
|
(kill-sexp)))
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-reload-package-autoloads (&optional force-p)
|
2018-06-11 23:20:45 +02:00
|
|
|
"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'.
|
|
|
|
|
|
|
|
Will do nothing if none of your installed packages have been modified. If
|
|
|
|
FORCE-P (universal argument) is non-nil, regenerate it anyway.
|
|
|
|
|
|
|
|
This should be run whenever your `doom!' block or update your packages."
|
|
|
|
(if (and (not force-p)
|
|
|
|
(not doom-emacs-changed-p)
|
|
|
|
(file-exists-p doom-package-autoload-file)
|
2018-06-17 21:38:53 +02:00
|
|
|
(not (file-newer-than-file-p doom-packages-dir doom-package-autoload-file))
|
2018-06-11 23:20:45 +02:00
|
|
|
(not (ignore-errors
|
|
|
|
(cl-loop for key being the hash-keys of (doom-modules)
|
|
|
|
for path = (doom-module-path (car key) (cdr key) "packages.el")
|
|
|
|
if (file-newer-than-file-p path doom-package-autoload-file)
|
|
|
|
return t))))
|
|
|
|
(ignore (print! (green "Doom package autoloads is up-to-date"))
|
|
|
|
(doom-initialize-autoloads doom-package-autoload-file))
|
2018-06-14 19:46:31 +02:00
|
|
|
(let (case-fold-search)
|
|
|
|
(doom-delete-autoloads-file doom-package-autoload-file)
|
|
|
|
(with-temp-file doom-package-autoload-file
|
2018-06-17 21:35:58 +02:00
|
|
|
(doom--generate-header 'doom-reload-package-autoloads)
|
2018-06-11 23:20:45 +02:00
|
|
|
(save-excursion
|
|
|
|
;; Cache the important and expensive-to-initialize state here.
|
2018-06-14 19:46:31 +02:00
|
|
|
(doom--generate-var-cache)
|
2018-06-11 23:20:45 +02:00
|
|
|
(print! (green "✓ Cached package state"))
|
2018-06-14 19:46:31 +02:00
|
|
|
;; Loop through packages and concatenate all their autoloads files.
|
|
|
|
(doom--generate-package-autoloads)
|
|
|
|
(print! (green "✓ Package autoloads included")))
|
2018-06-11 23:20:45 +02:00
|
|
|
;; 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.
|
2018-06-14 19:46:31 +02:00
|
|
|
(doom--cleanup-package-autoloads)
|
2018-06-11 23:20:45 +02:00
|
|
|
(print! (green "✓ Removed load-path/auto-mode-alist entries"))))
|
|
|
|
(doom--byte-compile-file doom-package-autoload-file)
|
2018-07-12 19:51:21 +02:00
|
|
|
(doom--do-load doom-package-autoload-file)
|
2018-06-11 23:20:45 +02:00
|
|
|
t))
|
|
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
;; Byte compilation
|
|
|
|
;;
|
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-byte-compile (&optional modules recompile-p)
|
2018-06-11 23:20:45 +02:00
|
|
|
"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.
|
|
|
|
|
2018-06-14 19:49:03 +02:00
|
|
|
WARNING: byte-compilation yields marginal gains and makes debugging new issues
|
|
|
|
difficult. It is recommended you don't use it unless you understand the
|
|
|
|
reprecussions.
|
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
Use `doom-clean-byte-compiled-files' or `make clean' to reverse
|
2018-06-14 19:49:03 +02:00
|
|
|
byte-compilation.
|
2018-06-11 23:20:45 +02:00
|
|
|
|
|
|
|
If RECOMPILE-P is non-nil, only recompile out-of-date files."
|
|
|
|
(let ((default-directory doom-emacs-dir)
|
|
|
|
(total-ok 0)
|
|
|
|
(total-fail 0)
|
|
|
|
(total-noop 0)
|
|
|
|
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"
|
2018-06-14 00:04:12 +02:00
|
|
|
(cl-loop for (name . desc) in (doom-get-package-alist)
|
|
|
|
do (package--compile desc))
|
2018-06-11 23:20:45 +02:00
|
|
|
(setq compile-plugins-p t
|
|
|
|
modules (delete ":plugins" modules)))
|
|
|
|
((pred file-directory-p)
|
|
|
|
(push module targets))
|
|
|
|
((pred (string-match "^\\([^/]+\\)/\\([^/]+\\)$"))
|
|
|
|
(push (doom-module-locate-path
|
|
|
|
(doom-keyword-intern (match-string 1 module))
|
|
|
|
(intern (match-string 2 module)))
|
|
|
|
targets))))
|
|
|
|
(cl-block 'byte-compile
|
|
|
|
;; If we're just here to byte-compile our plugins, we're done!
|
|
|
|
(and (not modules)
|
|
|
|
compile-plugins-p
|
|
|
|
(cl-return-from 'byte-compile t))
|
|
|
|
(unless (or (equal modules '(":core"))
|
|
|
|
recompile-p)
|
|
|
|
(unless (and (not doom-auto-accept)
|
|
|
|
(y-or-n-p
|
|
|
|
(concat "Warning: byte compiling is for advanced users. It will interfere with your\n"
|
|
|
|
"efforts to debug issues. It is not recommended you do it if you frequently\n"
|
|
|
|
"tinker with your Emacs config.\n\n"
|
|
|
|
"Alternatively, use `bin/doom compile :core` instead to byte-compile only the\n"
|
|
|
|
"Doom core files, as these don't change often.\n\n"
|
|
|
|
"If you have issues, please make sure byte-compilation isn't the cause by using\n"
|
|
|
|
"`bin/doom clean` to clear out your *.elc files.\n\n"
|
|
|
|
"Byte-compile anyway?")))
|
|
|
|
(message "Aborting.")
|
|
|
|
(cl-return-from 'byte-compile)))
|
2018-06-26 19:03:19 +02:00
|
|
|
(and (not recompile-p)
|
|
|
|
(or (null modules) (equal modules '(":core")))
|
|
|
|
(doom-clean-byte-compiled-files))
|
2018-06-11 23:20:45 +02:00
|
|
|
(let (doom-emacs-changed-p
|
|
|
|
noninteractive)
|
2018-06-26 19:03:19 +02:00
|
|
|
;; 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.
|
|
|
|
(unless (and (doom-initialize-autoloads doom-autoload-file)
|
|
|
|
(doom-initialize-autoloads doom-package-autoload-file))
|
|
|
|
(doom-reload-autoloads))
|
2018-06-11 23:20:45 +02:00
|
|
|
(doom-initialize)
|
|
|
|
(doom-initialize-modules 'force))
|
|
|
|
;; If no targets were supplied, then we use your module list.
|
|
|
|
(unless modules
|
|
|
|
(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.
|
2018-06-19 20:51:14 +02:00
|
|
|
(let ((target-files (doom-files-in targets :depth 1 :match "\\.el$"))
|
|
|
|
(load-path load-path)
|
|
|
|
kill-emacs-hook kill-buffer-query-functions)
|
2018-06-11 23:20:45 +02:00
|
|
|
(unless target-files
|
|
|
|
(if targets
|
|
|
|
(message "Couldn't find any valid targets")
|
|
|
|
(message "No targets to %scompile" (if recompile-p "re" "")))
|
|
|
|
(cl-return-from 'byte-compile))
|
2018-06-24 22:39:22 +02:00
|
|
|
(require 'use-package)
|
2018-06-18 14:52:24 +02:00
|
|
|
(condition-case e
|
|
|
|
(let ((use-package-defaults use-package-defaults)
|
|
|
|
(use-package-expand-minimally t))
|
|
|
|
;; Prevent packages from being loaded at compile time if they
|
|
|
|
;; don't meet their own predicates.
|
|
|
|
(push (list :no-require t
|
|
|
|
(lambda (_name args)
|
|
|
|
(or (when-let* ((pred (or (plist-get args :if)
|
|
|
|
(plist-get args :when))))
|
|
|
|
(not (eval pred t)))
|
|
|
|
(when-let* ((pred (plist-get args :unless)))
|
|
|
|
(eval pred t)))))
|
|
|
|
use-package-defaults)
|
2018-06-11 23:20:45 +02:00
|
|
|
;; Always compile private init file
|
|
|
|
(push (expand-file-name "init.el" doom-private-dir) target-files)
|
|
|
|
(push (expand-file-name "init.el" doom-emacs-dir) target-files)
|
|
|
|
(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)
|
2018-06-15 13:27:24 +02:00
|
|
|
(not (doom--file-cookie-p target)))
|
2018-06-11 23:20:45 +02:00
|
|
|
'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 target-files) total-noop)
|
|
|
|
total-noop))))
|
2018-06-24 14:48:27 +02:00
|
|
|
((debug error)
|
2018-06-18 14:47:36 +02:00
|
|
|
(print! (red "\n%s\n\n%%s" "There were breaking errors.")
|
2018-06-11 23:20:45 +02:00
|
|
|
"Reverting changes...")
|
2018-06-18 14:47:36 +02:00
|
|
|
(signal 'doom-error (list 'byte-compile e))))))))
|
2018-06-11 23:20:45 +02:00
|
|
|
|
2018-06-17 21:35:58 +02:00
|
|
|
(defun doom-clean-byte-compiled-files ()
|
2018-06-11 23:20:45 +02:00
|
|
|
"Delete all the compiled elc files in your Emacs configuration and private
|
|
|
|
module. This does not include your byte-compiled, third party packages.'"
|
|
|
|
(cl-loop with default-directory = doom-emacs-dir
|
2018-06-12 16:01:11 +02:00
|
|
|
for path in (append (doom-files-in doom-emacs-dir :match "\\.elc$" :depth 0)
|
|
|
|
(doom-files-in doom-private-dir :match "\\.elc$" :depth 1)
|
2018-06-11 23:20:45 +02:00
|
|
|
(doom-files-in doom-core-dir :match "\\.elc$")
|
2018-06-12 16:01:11 +02:00
|
|
|
(doom-files-in doom-modules-dirs :match "\\.elc$" :depth 3))
|
2018-06-11 23:20:45 +02:00
|
|
|
for truepath = (file-truename path)
|
|
|
|
if (file-exists-p path)
|
|
|
|
do (delete-file path)
|
|
|
|
and do
|
|
|
|
(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")))))
|
|
|
|
|
2018-06-20 12:03:23 +02:00
|
|
|
(provide 'core-cli)
|
|
|
|
;;; core-cli.el ends here
|