diff options
Diffstat (limited to 'elpa/use-package-20210207.1926/use-package-core.el')
-rw-r--r-- | elpa/use-package-20210207.1926/use-package-core.el | 1633 |
1 files changed, 0 insertions, 1633 deletions
diff --git a/elpa/use-package-20210207.1926/use-package-core.el b/elpa/use-package-20210207.1926/use-package-core.el deleted file mode 100644 index 28bc5a5..0000000 --- a/elpa/use-package-20210207.1926/use-package-core.el +++ /dev/null @@ -1,1633 +0,0 @@ -;;; use-package-core.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*- - -;; Copyright (C) 2012-2017 John Wiegley - -;; Author: John Wiegley <johnw@newartisans.com> -;; Maintainer: John Wiegley <johnw@newartisans.com> -;; Created: 17 Jun 2012 -;; Modified: 29 Nov 2017 -;; Version: 2.4.1 -;; Package-Requires: ((emacs "24.3")) -;; Keywords: dotemacs startup speed config package -;; URL: https://github.com/jwiegley/use-package - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; The `use-package' declaration macro allows you to isolate package -;; configuration in your ".emacs" in a way that is performance-oriented and, -;; well, just tidy. I created it because I have over 80 packages that I use -;; in Emacs, and things were getting difficult to manage. Yet with this -;; utility my total load time is just under 1 second, with no loss of -;; functionality! -;; -;; Please see README.md from the same repository for documentation. - -;;; Code: - -(require 'bytecomp) -(require 'cl-lib) -(require 'tabulated-list) - -(eval-and-compile - ;; Declare a synthetic theme for :custom variables. - ;; Necessary in order to avoid having those variables saved by custom.el. - (deftheme use-package)) - -(enable-theme 'use-package) -;; Remove the synthetic use-package theme from the enabled themes, so -;; iterating over them to "disable all themes" won't disable it. -(setq custom-enabled-themes (remq 'use-package custom-enabled-themes)) - -(if (and (eq emacs-major-version 24) (eq emacs-minor-version 3)) - (defsubst hash-table-keys (hash-table) - "Return a list of keys in HASH-TABLE." - (cl-loop for k being the hash-keys of hash-table collect k)) - (eval-when-compile (require 'subr-x))) - -(eval-when-compile - (require 'regexp-opt)) - -(defgroup use-package nil - "A use-package declaration for simplifying your `.emacs'." - :group 'startup) - -(defconst use-package-version "2.4.1" - "This version of use-package.") - -(defcustom use-package-keywords - '(:disabled - :load-path - :requires - :defines - :functions - :preface - :if :when :unless - :no-require - :catch - :after - :custom - :custom-face - :bind - :bind* - :bind-keymap - :bind-keymap* - :interpreter - :mode - :magic - :magic-fallback - :hook - ;; Any other keyword that also declares commands to be autoloaded (such as - ;; :bind) must appear before this keyword. - :commands - :init - :defer - :demand - :load - ;; This must occur almost last; the only forms which should appear after - ;; are those that must happen directly after the config forms. - :config) - "The set of valid keywords, in the order they are processed in. -The order of this list is *very important*, so it is only -advisable to insert new keywords, never to delete or reorder -them. Further, attention should be paid to the NEWS.md if the -default order ever changes, as they may have subtle effects on -the semantics of use-package declarations and may necessitate -changing where you had inserted a new keyword earlier. - -Note that `:disabled' is special in this list, as it causes -nothing at all to happen, even if the rest of the use-package -declaration is incorrect." - :type '(repeat symbol) - :group 'use-package) - -(defcustom use-package-deferring-keywords - '(:bind-keymap - :bind-keymap* - :commands) - "Unless `:demand' is used, keywords in this list imply deferred loading. -The reason keywords like `:hook' are not in this list is that -they only imply deferred loading if they reference actual -function symbols that can be autoloaded from the module; whereas -the default keywords provided here always defer loading unless -otherwise requested." - :type '(repeat symbol) - :group 'use-package) - -(defcustom use-package-ignore-unknown-keywords nil - "If non-nil, issue warning instead of error when unknown -keyword is encountered. The unknown keyword and its associated -arguments will be ignored in the `use-package' expansion." - :type 'boolean - :group 'use-package) - -(defcustom use-package-use-theme t - "If non-nil, use a custom theme to avoid saving :custom -variables twice (once in the Custom file, once in the use-package -call)." - :type 'boolean - :group 'use-package) - -(defcustom use-package-verbose nil - "Whether to report about loading and configuration details. -If you customize this, then you should require the `use-package' -feature in files that use `use-package', even if these files only -contain compiled expansions of the macros. If you don't do so, -then the expanded macros do their job silently." - :type '(choice (const :tag "Quiet, without catching errors" errors) - (const :tag "Quiet" nil) - (const :tag "Verbose" t) - (const :tag "Debug" debug)) - :group 'use-package) - -(defcustom use-package-check-before-init nil - "If non-nil, check that package exists before executing its `:init' block. -This check is performed by calling `locate-library'." - :type 'boolean - :group 'use-package) - -(defcustom use-package-always-defer nil - "If non-nil, assume `:defer t' unless `:demand' is used. -See also `use-package-defaults', which uses this value." - :type 'boolean - :group 'use-package) - -(defcustom use-package-always-demand nil - "If non-nil, assume `:demand t' unless `:defer' is used. -See also `use-package-defaults', which uses this value." - :type 'boolean - :group 'use-package) - -(defcustom use-package-defaults - '(;; this '(t) has special meaning; see `use-package-handler/:config' - (:config '(t) t) - (:init nil t) - (:catch t (lambda (name args) - (not use-package-expand-minimally))) - (:defer use-package-always-defer - (lambda (name args) - (and use-package-always-defer - (not (plist-member args :defer)) - (not (plist-member args :demand))))) - (:demand use-package-always-demand - (lambda (name args) - (and use-package-always-demand - (not (plist-member args :defer)) - (not (plist-member args :demand)))))) - "Default values for specified `use-package' keywords. -Each entry in the alist is a list of three elements: -The first element is the `use-package' keyword. - -The second is a form that can be evaluated to get the default -value. It can also be a function that will receive the name of -the use-package declaration and the keyword plist given to -`use-package', in normalized form. The value it returns should -also be in normalized form (which is sometimes *not* what one -would normally write in a `use-package' declaration, so use -caution). - -The third element is a form that can be evaluated to determine -whether or not to assign a default value; if it evaluates to nil, -then the default value is not assigned even if the keyword is not -present in the `use-package' form. This third element may also be -a function, in which case it receives the name of the package (as -a symbol) and a list of keywords (in normalized form). It should -return nil or non-nil depending on whether defaulting should be -attempted." - :type `(repeat - (list (choice :tag "Keyword" - ,@(mapcar #'(lambda (k) (list 'const k)) - use-package-keywords)) - (choice :tag "Default value" sexp function) - (choice :tag "Enable if non-nil" sexp function))) - :group 'use-package) - -(defcustom use-package-merge-key-alist - '((:if . (lambda (new old) `(and ,new ,old))) - (:after . (lambda (new old) `(:all ,new ,old))) - (:defer . (lambda (new old) old)) - (:bind . (lambda (new old) (append new (list :break) old)))) - "Alist of keys and the functions used to merge multiple values. -For example, if the following form is provided: - - (use-package foo :if pred1 :if pred2) - -Then based on the above defaults, the merged result will be: - - (use-package foo :if (and pred1 pred2)) - -This is done so that, at the stage of invoking handlers, each -handler is called only once." - :type `(repeat - (cons (choice :tag "Keyword" - ,@(mapcar #'(lambda (k) (list 'const k)) - use-package-keywords) - (const :tag "Any" t)) - function)) - :group 'use-package) - -(defcustom use-package-hook-name-suffix "-hook" - "Text append to the name of hooks mentioned by :hook. -Set to nil if you don't want this to happen; it's only a -convenience." - :type '(choice string (const :tag "No suffix" nil)) - :group 'use-package) - -(defcustom use-package-minimum-reported-time 0.1 - "Minimal load time that will be reported. -Note that `use-package-verbose' has to be set to a non-nil value -for anything to be reported at all." - :type 'number - :group 'use-package) - -(defcustom use-package-inject-hooks nil - "If non-nil, add hooks to the `:init' and `:config' sections. -In particular, for a given package `foo', the following hooks -become available: - - `use-package--foo--pre-init-hook' - `use-package--foo--post-init-hook' - `use-package--foo--pre-config-hook' - `use-package--foo--post-config-hook' - -This way, you can add to these hooks before evaluation of a -`use-package` declaration, and exercise some control over what -happens. - -NOTE: These hooks are run even if the user does not specify an -`:init' or `:config' block, and they will happen at the regular -time when initialization and configuration would have been -performed. - -NOTE: If the `pre-init' hook return a nil value, that block's -user-supplied configuration is not evaluated, so be certain to -return t if you only wish to add behavior to what the user had -specified." - :type 'boolean - :group 'use-package) - -(defcustom use-package-expand-minimally nil - "If non-nil, make the expanded code as minimal as possible. -This disables: - - - Printing to the *Messages* buffer of slowly-evaluating forms - - Capturing of load errors (normally redisplayed as warnings) - - Conditional loading of packages (load failures become errors) - -The main advantage to this variable is that, if you know your -configuration works, it will make the byte-compiled file as -minimal as possible. It can also help with reading macro-expanded -definitions, to understand the main intent of what's happening." - :type 'boolean - :group 'use-package) - -(defcustom use-package-form-regexp-eval - `(concat ,(eval-when-compile - (concat "^\\s-*(" - (regexp-opt '("use-package" "require") t) - "\\s-+\\(")) - (or (bound-and-true-p lisp-mode-symbol-regexp) - "\\(?:\\sw\\|\\s_\\|\\\\.\\)+") "\\)") - "Sexp providing regexp for finding use-package forms in user files. -This is used by `use-package-jump-to-package-form' and -`use-package-enable-imenu-support'." - :type 'sexp - :group 'use-package) - -(defcustom use-package-enable-imenu-support nil - "If non-nil, cause imenu to see `use-package' declarations. -This is done by adjusting `lisp-imenu-generic-expression' to -include support for finding `use-package' and `require' forms. - -Must be set before loading use-package." - :type 'boolean - :set - #'(lambda (_sym value) - (eval-after-load 'lisp-mode - (if value - `(add-to-list 'lisp-imenu-generic-expression - (list "Packages" ,use-package-form-regexp-eval 2)) - `(setq lisp-imenu-generic-expression - (remove (list "Packages" ,use-package-form-regexp-eval 2) - lisp-imenu-generic-expression))))) - :group 'use-package) - -(defconst use-package-font-lock-keywords - '(("(\\(use-package\\)\\_>[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?" - (1 font-lock-keyword-face) - (2 font-lock-constant-face nil t)))) - -(font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords) - -(defcustom use-package-compute-statistics nil - "If non-nil, compute statistics concerned use-package declarations. -View the statistical report using `use-package-report'. Note that -if this option is enabled, you must require `use-package' in your -user init file at loadup time, or you will see errors concerning -undefined variables." - :type 'boolean - :group 'use-package) - -(defvar use-package-statistics (make-hash-table)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Utility functions -;; - -(defsubst use-package-error (msg) - "Report MSG as an error, so the user knows it came from this package." - (error "use-package: %s" msg)) - -(defsubst use-package-concat (&rest elems) - "Delete all empty lists from ELEMS (nil or (list nil)), and append them." - (apply #'append (delete nil (delete (list nil) elems)))) - -(defsubst use-package-non-nil-symbolp (sym) - (and sym (symbolp sym))) - -(defsubst use-package-as-symbol (string-or-symbol) - "If STRING-OR-SYMBOL is already a symbol, return it. Otherwise -convert it to a symbol and return that." - (if (symbolp string-or-symbol) string-or-symbol - (intern string-or-symbol))) - -(defsubst use-package-as-string (string-or-symbol) - "If STRING-OR-SYMBOL is already a string, return it. Otherwise -convert it to a string and return that." - (if (stringp string-or-symbol) string-or-symbol - (symbol-name string-or-symbol))) - -(defsubst use-package-regex-p (re) - "Return t if RE is some regexp-like thing." - (or (and (listp re) (eq (car re) 'rx)) - (stringp re))) - -(defun use-package-normalize-regex (re) - "Given some regexp-like thing in RE, resolve to a regular expression." - (cond - ((and (listp re) (eq (car re) 'rx)) (eval re)) - ((stringp re) re) - (t (error "Not recognized as regular expression: %s" re)))) - -(defsubst use-package-is-pair (x car-pred cdr-pred) - "Return non-nil if X is a cons satisfying the given predicates. -CAR-PRED and CDR-PRED are applied to X's `car' and `cdr', -respectively." - (and (consp x) - (funcall car-pred (car x)) - (funcall cdr-pred (cdr x)))) - -(defun use-package-as-mode (string-or-symbol) - "If STRING-OR-SYMBOL ends in `-mode' (or its name does), return -it as a symbol. Otherwise, return it as a symbol with `-mode' -appended." - (let ((string (use-package-as-string string-or-symbol))) - (intern (if (string-match "-mode\\'" string) - string - (concat string "-mode"))))) - -(defsubst use-package-load-name (name &optional noerror) - "Return a form which will load or require NAME. -It does the right thing no matter if NAME is a string or symbol. -Argument NOERROR means to indicate load failures as a warning." - (if (stringp name) - `(load ,name ,noerror) - `(require ',name nil ,noerror))) - -(defun use-package-hook-injector (name-string keyword body) - "Wrap pre/post hook injections around the given BODY for KEYWORD. -The BODY is a list of forms, so `((foo))' if only `foo' is being called." - (if (not use-package-inject-hooks) - body - (let ((keyword-name (substring (format "%s" keyword) 1))) - `((when (run-hook-with-args-until-failure - ',(intern (concat "use-package--" name-string - "--pre-" keyword-name "-hook"))) - ,@body - (run-hooks - ',(intern (concat "use-package--" name-string - "--post-" keyword-name "-hook")))))))) - -(defun use-package-with-elapsed-timer (text body) - "BODY is a list of forms, so `((foo))' if only `foo' is being called." - (declare (indent 1)) - (if use-package-expand-minimally - body - (let ((nowvar (make-symbol "now"))) - (if (bound-and-true-p use-package-verbose) - `((let ((,nowvar (current-time))) - (message "%s..." ,text) - (prog1 - ,(macroexp-progn body) - (let ((elapsed - (float-time (time-subtract (current-time) ,nowvar)))) - (if (> elapsed ,use-package-minimum-reported-time) - (message "%s...done (%.3fs)" ,text elapsed) - (message "%s...done" ,text)))))) - body)))) - -(put 'use-package-with-elapsed-timer 'lisp-indent-function 1) - -(defun use-package-require (name &optional no-require body) - (if use-package-expand-minimally - (use-package-concat - (unless no-require - (list (use-package-load-name name))) - body) - (if no-require - body - (use-package-with-elapsed-timer - (format "Loading package %s" name) - `((if (not ,(use-package-load-name name t)) - (display-warning 'use-package - (format "Cannot load %s" ',name) - :error) - ,@body)))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Property lists -;; - -(defun use-package-plist-delete (plist property) - "Delete PROPERTY from PLIST. -This is in contrast to merely setting it to 0." - (let (p) - (while plist - (if (not (eq property (car plist))) - (setq p (plist-put p (car plist) (nth 1 plist)))) - (setq plist (cddr plist))) - p)) - -(defun use-package-plist-delete-first (plist property) - "Delete PROPERTY from PLIST. -This is in contrast to merely setting it to 0." - (let (p) - (while plist - (if (eq property (car plist)) - (setq p (nconc p (cddr plist)) - plist nil) - (setq p (nconc p (list (car plist) (cadr plist))) - plist (cddr plist)))) - p)) - -(defsubst use-package-plist-maybe-put (plist property value) - "Add a VALUE for PROPERTY to PLIST, if it does not already exist." - (if (plist-member plist property) - plist - (plist-put plist property value))) - -(defsubst use-package-plist-cons (plist property value) - "Cons VALUE onto the head of the list at PROPERTY in PLIST." - (plist-put plist property (cons value (plist-get plist property)))) - -(defsubst use-package-plist-append (plist property value) - "Append VALUE onto the front of the list at PROPERTY in PLIST." - (plist-put plist property (append value (plist-get plist property)))) - -(defun use-package-split-list (pred xs) - (let ((ys (list nil)) (zs (list nil)) flip) - (cl-dolist (x xs) - (if flip - (nconc zs (list x)) - (if (funcall pred x) - (progn - (setq flip t) - (nconc zs (list x))) - (nconc ys (list x))))) - (cons (cdr ys) (cdr zs)))) - -(defun use-package-split-list-at-keys (key lst) - (and lst - (let ((xs (use-package-split-list (apply-partially #'eq key) lst))) - (cons (car xs) (use-package-split-list-at-keys key (cddr xs)))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Keywords -;; - -(defun use-package-keyword-index (keyword) - (cl-loop named outer - with index = 0 - for k in use-package-keywords do - (if (eq k keyword) - (cl-return-from outer index)) - (cl-incf index))) - -(defun use-package-normalize-plist (name input &optional plist merge-function) - "Given a pseudo-plist, normalize it to a regular plist. -The normalized key/value pairs from input are added to PLIST, -extending any keys already present." - (if (null input) - plist - (let* ((keyword (car input)) - (xs (use-package-split-list #'keywordp (cdr input))) - (args (car xs)) - (tail (cdr xs)) - (normalizer - (intern-soft (concat "use-package-normalize/" - (symbol-name keyword)))) - (arg (and (functionp normalizer) - (funcall normalizer name keyword args))) - (error-string (format "Unrecognized keyword: %s" keyword))) - (if (memq keyword use-package-keywords) - (progn - (setq plist (use-package-normalize-plist - name tail plist merge-function)) - (plist-put plist keyword - (if (plist-member plist keyword) - (funcall merge-function keyword arg - (plist-get plist keyword)) - arg))) - (if use-package-ignore-unknown-keywords - (progn - (display-warning 'use-package error-string) - (use-package-normalize-plist - name tail plist merge-function)) - (use-package-error error-string)))))) - -(defun use-package-unalias-keywords (_name args) - (setq args (cl-nsubstitute :if :when args)) - (let (temp) - (while (setq temp (plist-get args :unless)) - (setq args (use-package-plist-delete-first args :unless) - args (append args `(:if (not ,temp)))))) - args) - -(defun use-package-merge-keys (key new old) - (let ((merger (assq key use-package-merge-key-alist))) - (if merger - (funcall (cdr merger) new old) - (append new old)))) - -(defun use-package-sort-keywords (plist) - (let (plist-grouped) - (while plist - (push (cons (car plist) (cadr plist)) - plist-grouped) - (setq plist (cddr plist))) - (let (result) - (cl-dolist - (x - (nreverse - (sort plist-grouped - #'(lambda (l r) (< (use-package-keyword-index (car l)) - (use-package-keyword-index (car r))))))) - (setq result (cons (car x) (cons (cdr x) result)))) - result))) - -(defun use-package-normalize-keywords (name args) - (let* ((name-symbol (if (stringp name) (intern name) name)) - (name-string (symbol-name name-symbol))) - - ;; The function `elisp--local-variables' inserts this unbound variable into - ;; macro forms to determine the locally bound variables for - ;; `elisp-completion-at-point'. It ends up throwing a lot of errors since it - ;; can occupy the position of a keyword (or look like a second argument to a - ;; keyword that takes one). Deleting it when it's at the top level should be - ;; harmless since there should be no locally bound variables to discover - ;; here anyway. - (setq args (delq 'elisp--witness--lisp args)) - - ;; Reduce the set of keywords down to its most fundamental expression. - (setq args (use-package-unalias-keywords name-symbol args)) - - ;; Normalize keyword values, coalescing multiple occurrences. - (setq args (use-package-normalize-plist name-symbol args nil - #'use-package-merge-keys)) - - ;; Add default values for keywords not specified, when applicable. - (cl-dolist (spec use-package-defaults) - (when (let ((func (nth 2 spec))) - (if (and func (functionp func)) - (funcall func name args) - (eval func))) - (setq args (use-package-plist-maybe-put - args (nth 0 spec) - (let ((func (nth 1 spec))) - (if (and func (functionp func)) - (funcall func name args) - (eval func))))))) - - ;; Determine any autoloads implied by the keywords used. - (let ((iargs args) - commands) - (while iargs - (when (keywordp (car iargs)) - (let ((autoloads - (intern-soft (concat "use-package-autoloads/" - (symbol-name (car iargs)))))) - (when (functionp autoloads) - (setq commands - ;; jww (2017-12-07): Right now we just ignored the type of - ;; the autoload being requested, and assume they are all - ;; `command'. - (append (mapcar - #'car - (funcall autoloads name-symbol (car iargs) - (cadr iargs))) - commands))))) - (setq iargs (cddr iargs))) - (when commands - (setq args - ;; Like `use-package-plist-append', but removing duplicates. - (plist-put args :commands - (delete-dups - (append commands (plist-get args :commands))))))) - - ;; If byte-compiling, pre-load the package so all its symbols are in - ;; scope. This is done by prepending statements to the :preface. - (when (bound-and-true-p byte-compile-current-file) - (setq args - (use-package-plist-append - args :preface - (use-package-concat - (mapcar #'(lambda (var) `(defvar ,var)) - (plist-get args :defines)) - (mapcar #'(lambda (fn) `(declare-function ,fn ,name-string)) - (plist-get args :functions)) - `((eval-when-compile - (with-demoted-errors - ,(format "Cannot load %s: %%S" name-string) - ,(when (eq use-package-verbose 'debug) - `(message ,(format "Compiling package %s" name-string))) - ,(unless (plist-get args :no-require) - `(unless (featurep ',name-symbol) - (load ,name-string nil t)))))))))) - - ;; Certain keywords imply :defer, if :demand was not specified. - (when (and (not (plist-member args :demand)) - (not (plist-member args :defer)) - (not (or (equal '(t) (plist-get args :load)) - (equal (list (use-package-as-string name)) - (mapcar #'use-package-as-string - (plist-get args :load))))) - (cl-some #'identity - (mapcar (apply-partially #'plist-member args) - use-package-deferring-keywords))) - (setq args (append args '(:defer t)))) - - ;; The :load keyword overrides :no-require - (when (and (plist-member args :load) - (plist-member args :no-require)) - (setq args (use-package-plist-delete args :no-require))) - - ;; If at this point no :load, :defer or :no-require has been seen, then - ;; :load the package itself. - (when (and (not (plist-member args :load)) - (not (plist-member args :defer)) - (not (plist-member args :no-require))) - (setq args (append args `(:load (,name))))) - - ;; Sort the list of keywords based on the order of `use-package-keywords'. - (use-package-sort-keywords args))) - -(defun use-package-process-keywords (name plist &optional state) - "Process the next keyword in the free-form property list PLIST. -The values in the PLIST have each been normalized by the function -use-package-normalize/KEYWORD (minus the colon). - -STATE is a property list that the function may modify and/or -query. This is useful if a package defines multiple keywords and -wishes them to have some kind of stateful interaction. - -Unless the KEYWORD being processed intends to ignore remaining -keywords, it must call this function recursively, passing in the -plist with its keyword and argument removed, and passing in the -next value for the STATE." - (declare (indent 1)) - (unless (null plist) - (let* ((keyword (car plist)) - (arg (cadr plist)) - (rest (cddr plist))) - (unless (keywordp keyword) - (use-package-error (format "%s is not a keyword" keyword))) - (let* ((handler (concat "use-package-handler/" (symbol-name keyword))) - (handler-sym (intern handler))) - (if (functionp handler-sym) - (funcall handler-sym name keyword arg rest state) - (use-package-error - (format "Keyword handler not defined: %s" handler))))))) - -(put 'use-package-process-keywords 'lisp-indent-function 'defun) - -(defun use-package-list-insert (elem xs &optional anchor after test) - "Insert ELEM into the list XS. -If ANCHOR is also a keyword, place the new KEYWORD before that -one. -If AFTER is non-nil, insert KEYWORD either at the end of the -keywords list, or after the ANCHOR if one has been provided. -If TEST is non-nil, it is the test used to compare ELEM to list -elements. The default is `eq'. -The modified list is returned. The original list is not modified." - (let (result) - (dolist (k xs) - (if (funcall (or test #'eq) k anchor) - (if after - (setq result (cons k result) - result (cons elem result)) - (setq result (cons elem result) - result (cons k result))) - (setq result (cons k result)))) - (if anchor - (nreverse result) - (if after - (nreverse (cons elem result)) - (cons elem (nreverse result)))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Argument Processing -;; - -(defun use-package-only-one (label args f) - "Call F on the first member of ARGS if it has exactly one element." - (declare (indent 1)) - (cond - ((and (listp args) (listp (cdr args)) - (= (length args) 1)) - (funcall f label (car args))) - (t - (use-package-error - (concat label " wants exactly one argument"))))) - -(put 'use-package-only-one 'lisp-indent-function 'defun) - -(defun use-package-as-one (label args f &optional allow-empty) - "Call F on the first element of ARGS if it has one element, or all of ARGS. -If ALLOW-EMPTY is non-nil, it's OK for ARGS to be an empty list." - (declare (indent 1)) - (if (if args - (and (listp args) (listp (cdr args))) - allow-empty) - (if (= (length args) 1) - (funcall f label (car args)) - (funcall f label args)) - (use-package-error - (concat label " wants a non-empty list")))) - -(put 'use-package-as-one 'lisp-indent-function 'defun) - -(defun use-package-memoize (f arg) - "Ensure the macro-expansion of F applied to ARG evaluates ARG -no more than once." - (let ((loaded (cl-gentemp "use-package--loaded")) - (result (cl-gentemp "use-package--result")) - (next (cl-gentemp "use-package--next"))) - `((defvar ,loaded nil) - (defvar ,result nil) - (defvar ,next #'(lambda () (if ,loaded ,result - (setq ,loaded t ,result ,arg)))) - ,@(funcall f `((funcall ,next)))))) - -(defsubst use-package-normalize-value (_label arg) - "Normalize the Lisp value given by ARG. -The argument LABEL is ignored." - (cond ((null arg) nil) - ((eq t arg) t) - ((use-package-non-nil-symbolp arg) - `(symbol-value ',arg)) - ((functionp arg) - `(funcall #',arg)) - (t arg))) - -(defun use-package-normalize-symbols (label arg &optional recursed) - "Normalize a list of symbols." - (cond - ((use-package-non-nil-symbolp arg) - (list arg)) - ((and (not recursed) (listp arg) (listp (cdr arg))) - (mapcar #'(lambda (x) (car (use-package-normalize-symbols label x t))) arg)) - (t - (use-package-error - (concat label " wants a symbol, or list of symbols"))))) - -(defun use-package-normalize-symlist (_name keyword args) - (use-package-as-one (symbol-name keyword) args - #'use-package-normalize-symbols)) - -(defun use-package-normalize-recursive-symbols (label arg) - "Normalize a list of symbols." - (cond - ((use-package-non-nil-symbolp arg) - arg) - ((and (listp arg) (listp (cdr arg))) - (mapcar #'(lambda (x) (use-package-normalize-recursive-symbols label x)) - arg)) - (t - (use-package-error - (concat label " wants a symbol, or nested list of symbols"))))) - -(defun use-package-normalize-recursive-symlist (_name keyword args) - (use-package-as-one (symbol-name keyword) args - #'use-package-normalize-recursive-symbols)) - -(defun use-package-normalize-paths (label arg &optional recursed) - "Normalize a list of filesystem paths." - (cond - ((and arg (or (use-package-non-nil-symbolp arg) (functionp arg))) - (let ((value (use-package-normalize-value label arg))) - (use-package-normalize-paths label (eval value)))) - ((stringp arg) - (let ((path (if (file-name-absolute-p arg) - arg - (expand-file-name arg user-emacs-directory)))) - (list path))) - ((and (not recursed) (listp arg) (listp (cdr arg))) - (mapcar #'(lambda (x) - (car (use-package-normalize-paths label x t))) arg)) - (t - (use-package-error - (concat label " wants a directory path, or list of paths"))))) - -(defun use-package-normalize-predicate (_name keyword args) - (if (null args) - t - (use-package-only-one (symbol-name keyword) args - #'use-package-normalize-value))) - -(defun use-package-normalize-form (label args) - "Given a list of forms, return it wrapped in `progn'." - (unless (listp (car args)) - (use-package-error (concat label " wants a sexp or list of sexps"))) - (mapcar #'(lambda (form) - (if (and (consp form) - (memq (car form) - '(use-package bind-key bind-key* - unbind-key bind-keys bind-keys*))) - (macroexpand form) - form)) args)) - -(defun use-package-normalize-forms (_name keyword args) - (use-package-normalize-form (symbol-name keyword) args)) - -(defun use-package-normalize-pairs - (key-pred val-pred name label arg &optional recursed) - "Normalize a list of pairs. -KEY-PRED and VAL-PRED are predicates recognizing valid keys and -values, respectively. -If RECURSED is non-nil, recurse into sublists." - (cond - ((funcall key-pred arg) - (list (cons arg (use-package-as-symbol name)))) - ((use-package-is-pair arg key-pred val-pred) - (list arg)) - ((and (not recursed) (listp arg) (listp (cdr arg))) - (let (last-item) - (mapcar - #'(lambda (x) - (prog1 - (let ((ret (use-package-normalize-pairs - key-pred val-pred name label x t))) - (if (and (listp ret) - (not (keywordp last-item))) - (car ret) - ret)) - (setq last-item x))) arg))) - (t arg))) - -(defun use-package-recognize-function (v &optional binding additional-pred) - "A predicate that recognizes functional constructions: - nil - sym - 'sym - (quote sym) - #'sym - (function sym) - (lambda () ...) - '(lambda () ...) - (quote (lambda () ...)) - #'(lambda () ...) - (function (lambda () ...))" - (or (if binding - (symbolp v) - (use-package-non-nil-symbolp v)) - (and (listp v) - (memq (car v) '(quote function)) - (use-package-non-nil-symbolp (cadr v))) - (if binding (commandp v) (functionp v)) - (and additional-pred - (funcall additional-pred v)))) - -(defun use-package-normalize-function (v) - "Reduce functional constructions to one of two normal forms: - sym - #'(lambda () ...)" - (cond ((symbolp v) v) - ((and (listp v) - (memq (car v) '(quote function)) - (use-package-non-nil-symbolp (cadr v))) - (cadr v)) - ((and (consp v) - (eq 'lambda (car v))) - v) - ((and (listp v) - (memq (car v) '(quote function)) - (eq 'lambda (car (cadr v)))) - (cadr v)) - (t v))) - -(defun use-package-normalize-commands (args) - "Map over ARGS of the form ((_ . F) ...), normalizing functional F's." - (mapcar #'(lambda (x) - (if (consp x) - (cons (car x) (use-package-normalize-function (cdr x))) - x)) - args)) - -(defun use-package-normalize-mode (name keyword args) - "Normalize arguments for keywords which add regexp/mode pairs to an alist." - (use-package-as-one (symbol-name keyword) args - (apply-partially #'use-package-normalize-pairs - #'use-package-regex-p - #'use-package-recognize-function - name))) - -(defun use-package-autoloads-mode (_name _keyword args) - (mapcar - #'(lambda (x) (cons (cdr x) 'command)) - (cl-remove-if-not #'(lambda (x) - (and (consp x) - (use-package-non-nil-symbolp (cdr x)))) - args))) - -(defun use-package-handle-mode (name alist args rest state) - "Handle keywords which add regexp/mode pairs to an alist." - (use-package-concat - (use-package-process-keywords name rest state) - (mapcar - #'(lambda (thing) - `(add-to-list - ',alist - ',(cons (use-package-normalize-regex (car thing)) - (cdr thing)))) - (use-package-normalize-commands args)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Statistics -;; - -(defun use-package-reset-statistics () - (interactive) - (setq use-package-statistics (make-hash-table))) - -(defun use-package-statistics-status (package) - "Return loading configuration status of PACKAGE statistics." - (cond ((gethash :config package) "Configured") - ((gethash :init package) "Initialized") - ((gethash :preface package) "Prefaced") - ((gethash :use-package package) "Declared"))) - -(defun use-package-statistics-last-event (package) - "Return the date when PACKAGE's status last changed. -The date is returned as a string." - (format-time-string "%Y-%m-%d %a %H:%M" - (or (gethash :config package) - (gethash :init package) - (gethash :preface package) - (gethash :use-package package)))) - -(defun use-package-statistics-time (package) - "Return the time is took for PACKAGE to load." - (+ (float-time (gethash :config-secs package '(0 0 0 0))) - (float-time (gethash :init-secs package '(0 0 0 0))) - (float-time (gethash :preface-secs package '(0 0 0 0))) - (float-time (gethash :use-package-secs package '(0 0 0 0))))) - -(defun use-package-statistics-convert (package) - "Return information about PACKAGE. - -The information is formatted in a way suitable for -`use-package-statistics-mode'." - (let ((statistics (gethash package use-package-statistics))) - (list - package - (vector - (symbol-name package) - (use-package-statistics-status statistics) - (use-package-statistics-last-event statistics) - (format "%.2f" (use-package-statistics-time statistics)))))) - -(defun use-package-report () - "Show current statistics gathered about use-package declarations. -In the table that's generated, the status field has the following -meaning: - Configured :config has been processed (the package is loaded!) - Initialized :init has been processed (load status unknown) - Prefaced :preface has been processed - Declared the use-package declaration was seen" - (interactive) - (with-current-buffer (get-buffer-create "*use-package statistics*") - (setq tabulated-list-entries - (mapcar #'use-package-statistics-convert - (hash-table-keys use-package-statistics))) - (use-package-statistics-mode) - (tabulated-list-print) - (display-buffer (current-buffer)))) - -(define-derived-mode use-package-statistics-mode tabulated-list-mode - "use-package statistics" - "Show current statistics gathered about use-package declarations." - (setq tabulated-list-format - ;; The sum of column width is 80 characters: - [("Package" 25 t) - ("Status" 13 t) - ("Last Event" 23 t) - ("Time" 10 t)]) - (tabulated-list-init-header)) - -(defun use-package-statistics-gather (keyword name after) - (let* ((hash (gethash name use-package-statistics - (make-hash-table))) - (before (and after (gethash keyword hash (current-time))))) - (puthash keyword (current-time) hash) - (when after - (puthash (intern (concat (symbol-name keyword) "-secs")) - (time-subtract (current-time) before) hash)) - (puthash name hash use-package-statistics))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Handlers -;; - -;;;; :disabled - -;; Don't alias this to `ignore', as that will cause the resulting -;; function to be interactive. -(defun use-package-normalize/:disabled (_name _keyword _arg) - "Do nothing, return nil.") - -(defun use-package-handler/:disabled (name _keyword _arg rest state) - (use-package-process-keywords name rest state)) - -;;;; :if, :when and :unless - -(defun use-package-normalize-test (_name keyword args) - (use-package-only-one (symbol-name keyword) args - #'use-package-normalize-value)) - -(defalias 'use-package-normalize/:if 'use-package-normalize-test) - -(defun use-package-handler/:if (name _keyword pred rest state) - (let ((body (use-package-process-keywords name rest state))) - `((when ,pred ,@body)))) - -(defalias 'use-package-normalize/:when 'use-package-normalize-test) - -(defalias 'use-package-handler/:when 'use-package-handler/:if) - -(defalias 'use-package-normalize/:unless 'use-package-normalize-test) - -(defun use-package-handler/:unless (name _keyword pred rest state) - (let ((body (use-package-process-keywords name rest state))) - `((unless ,pred ,@body)))) - -;;;; :requires - -(defalias 'use-package-normalize/:requires 'use-package-normalize-symlist) - -(defun use-package-handler/:requires (name _keyword requires rest state) - (let ((body (use-package-process-keywords name rest state))) - (if (null requires) - body - `((when ,(if (> (length requires) 1) - `(not (member nil (mapcar #'featurep ',requires))) - `(featurep ',(car requires))) - ,@body))))) - -;;;; :load-path - -(defun use-package-normalize/:load-path (_name keyword args) - (use-package-as-one (symbol-name keyword) args - #'use-package-normalize-paths)) - -(defun use-package-handler/:load-path (name _keyword arg rest state) - (let ((body (use-package-process-keywords name rest state))) - (use-package-concat - (mapcar #'(lambda (path) - `(eval-and-compile (add-to-list 'load-path ,path))) - arg) - body))) - -;;;; :no-require - -(defalias 'use-package-normalize/:no-require 'use-package-normalize-predicate) - -(defun use-package-handler/:no-require (name _keyword _arg rest state) - (use-package-process-keywords name rest state)) - -;;;; :defines - -(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist) - -(defun use-package-handler/:defines (name _keyword _arg rest state) - (use-package-process-keywords name rest state)) - -;;;; :functions - -(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist) - -(defun use-package-handler/:functions (name _keyword _arg rest state) - (use-package-process-keywords name rest state)) - -;;;; :preface - -(defalias 'use-package-normalize/:preface 'use-package-normalize-forms) - -(defun use-package-handler/:preface (name _keyword arg rest state) - (let ((body (use-package-process-keywords name rest state))) - (use-package-concat - (when use-package-compute-statistics - `((use-package-statistics-gather :preface ',name nil))) - (when arg - `((eval-and-compile ,@arg))) - body - (when use-package-compute-statistics - `((use-package-statistics-gather :preface ',name t)))))) - -;;;; :catch - -(defvar use-package--form) -(defvar use-package--hush-function #'(lambda (_keyword body) body)) - -(defsubst use-package-hush (context keyword body) - `((condition-case-unless-debug err - ,(macroexp-progn body) - (error (funcall ,context ,keyword err))))) - -(defun use-package-normalize/:catch (_name keyword args) - (if (null args) - t - (use-package-only-one (symbol-name keyword) args - use-package--hush-function))) - -(defun use-package-handler/:catch (name keyword arg rest state) - (let* ((context (cl-gentemp "use-package--warning"))) - (cond - ((not arg) - (use-package-process-keywords name rest state)) - ((eq arg t) - `((defvar ,context - #'(lambda (keyword err) - (let ((msg (format "%s/%s: %s" ',name keyword - (error-message-string err)))) - ,@(when (eq use-package-verbose 'debug) - `((with-current-buffer - (get-buffer-create "*use-package*") - (goto-char (point-max)) - (insert "-----\n" msg ,use-package--form) - (emacs-lisp-mode)) - (setq msg - (concat msg - " (see the *use-package* buffer)")))) - (display-warning 'use-package msg :error)))) - ,@(let ((use-package--hush-function - (apply-partially #'use-package-hush context))) - (funcall use-package--hush-function keyword - (use-package-process-keywords name rest state))))) - ((functionp arg) - `((defvar ,context ,arg) - ,@(let ((use-package--hush-function - (apply-partially #'use-package-hush context))) - (funcall use-package--hush-function keyword - (use-package-process-keywords name rest state))))) - (t - (use-package-error "The :catch keyword expects 't' or a function"))))) - -;;;; :interpreter - -(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode) -(defalias 'use-package-autoloads/:interpreter 'use-package-autoloads-mode) - -(defun use-package-handler/:interpreter (name _keyword arg rest state) - (use-package-handle-mode name 'interpreter-mode-alist arg rest state)) - -;;;; :mode - -(defalias 'use-package-normalize/:mode 'use-package-normalize-mode) -(defalias 'use-package-autoloads/:mode 'use-package-autoloads-mode) - -(defun use-package-handler/:mode (name _keyword arg rest state) - (use-package-handle-mode name 'auto-mode-alist arg rest state)) - -;;;; :magic - -(defalias 'use-package-normalize/:magic 'use-package-normalize-mode) -(defalias 'use-package-autoloads/:magic 'use-package-autoloads-mode) - -(defun use-package-handler/:magic (name _keyword arg rest state) - (use-package-handle-mode name 'magic-mode-alist arg rest state)) - -;;;; :magic-fallback - -(defalias 'use-package-normalize/:magic-fallback 'use-package-normalize-mode) -(defalias 'use-package-autoloads/:magic-fallback 'use-package-autoloads-mode) - -(defun use-package-handler/:magic-fallback (name _keyword arg rest state) - (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state)) - -;;;; :hook - -(defun use-package-normalize/:hook (name keyword args) - (use-package-as-one (symbol-name keyword) args - #'(lambda (label arg) - (unless (or (use-package-non-nil-symbolp arg) (consp arg)) - (use-package-error - (concat label " a <symbol> or (<symbol or list of symbols> . <symbol or function>)" - " or list of these"))) - (use-package-normalize-pairs - #'(lambda (k) - (or (use-package-non-nil-symbolp k) - (and k (let ((every t)) - (while (and every k) - (if (and (consp k) - (use-package-non-nil-symbolp (car k))) - (setq k (cdr k)) - (setq every nil))) - every)))) - #'use-package-recognize-function - name label arg)))) - -(defalias 'use-package-autoloads/:hook 'use-package-autoloads-mode) - -(defun use-package-handler/:hook (name _keyword args rest state) - "Generate use-package custom keyword code." - (use-package-concat - (use-package-process-keywords name rest state) - (cl-mapcan - #'(lambda (def) - (let ((syms (car def)) - (fun (cdr def))) - (when fun - (mapcar - #'(lambda (sym) - `(add-hook - (quote ,(intern - (concat (symbol-name sym) - use-package-hook-name-suffix))) - (function ,fun))) - (if (use-package-non-nil-symbolp syms) (list syms) syms))))) - (use-package-normalize-commands args)))) - -;;;; :commands - -(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist) - -(defun use-package-handler/:commands (name _keyword arg rest state) - (use-package-concat - ;; Since we deferring load, establish any necessary autoloads, and also - ;; keep the byte-compiler happy. - (let ((name-string (use-package-as-string name))) - (cl-mapcan - #'(lambda (command) - (when (symbolp command) - (append - (unless (plist-get state :demand) - `((unless (fboundp ',command) - (autoload #',command ,name-string nil t)))) - (when (bound-and-true-p byte-compile-current-file) - `((eval-when-compile - (declare-function ,command ,name-string))))))) - (delete-dups arg))) - (use-package-process-keywords name rest state))) - -;;;; :defer - -(defalias 'use-package-normalize/:defer 'use-package-normalize-predicate) - -(defun use-package-handler/:defer (name _keyword arg rest state) - (let ((body (use-package-process-keywords name rest state))) - (use-package-concat - ;; Load the package after a set amount of idle time, if the argument to - ;; `:defer' was a number. - (when (numberp arg) - `((run-with-idle-timer ,arg nil #'require - ',(use-package-as-symbol name) nil t))) - (if (or (not arg) (null body)) - body - `((eval-after-load ',name ',(macroexp-progn body))))))) - -;;;; :after - -(defun use-package-normalize/:after (name keyword args) - (setq args (use-package-normalize-recursive-symlist name keyword args)) - (if (consp args) - args - (list args))) - -(defun use-package-after-count-uses (features*) - "Count the number of time the body would appear in the result." - (cond ((use-package-non-nil-symbolp features*) - 1) - ((and (consp features*) - (memq (car features*) '(:or :any))) - (let ((num 0)) - (cl-dolist (next (cdr features*)) - (setq num (+ num (use-package-after-count-uses next)))) - num)) - ((and (consp features*) - (memq (car features*) '(:and :all))) - (apply #'max (mapcar #'use-package-after-count-uses - (cdr features*)))) - ((listp features*) - (use-package-after-count-uses (cons :all features*))))) - -(defun use-package-require-after-load (features* body) - "Generate `eval-after-load' statements to represents FEATURES*. -FEATURES* is a list containing keywords `:and' and `:all', where -no keyword implies `:all'." - (cond - ((use-package-non-nil-symbolp features*) - `((eval-after-load ',features* ',(macroexp-progn body)))) - ((and (consp features*) - (memq (car features*) '(:or :any))) - (cl-mapcan #'(lambda (x) (use-package-require-after-load x body)) - (cdr features*))) - ((and (consp features*) - (memq (car features*) '(:and :all))) - (cl-dolist (next (cdr features*)) - (setq body (use-package-require-after-load next body))) - body) - ((listp features*) - (use-package-require-after-load (cons :all features*) body)))) - -(defun use-package-handler/:after (name _keyword arg rest state) - (let ((body (use-package-process-keywords name rest state)) - (uses (use-package-after-count-uses arg))) - (if (or (null uses) (null body)) - body - (if (<= uses 1) - (use-package-require-after-load arg body) - (use-package-memoize - (apply-partially #'use-package-require-after-load arg) - (macroexp-progn body)))))) - -;;;; :demand - -(defalias 'use-package-normalize/:demand 'use-package-normalize-predicate) - -(defun use-package-handler/:demand (name _keyword _arg rest state) - (use-package-process-keywords name rest state)) - -;;;; :custom - -(defun use-package-normalize/:custom (_name keyword args) - "Normalize use-package custom keyword." - (use-package-as-one (symbol-name keyword) args - #'(lambda (label arg) - (unless (listp arg) - (use-package-error - (concat label " a (<symbol> <value> [comment])" - " or list of these"))) - (if (use-package-non-nil-symbolp (car arg)) - (list arg) - arg)))) - -(defun use-package-handler/:custom (name _keyword args rest state) - "Generate use-package custom keyword code." - (use-package-concat - (if (bound-and-true-p use-package-use-theme) - `((let ((custom--inhibit-theme-enable nil)) - ;; Declare the theme here so use-package can be required inside - ;; eval-and-compile without warnings about unknown theme. - (unless (memq 'use-package custom-known-themes) - (deftheme use-package) - (enable-theme 'use-package) - (setq custom-enabled-themes (remq 'use-package custom-enabled-themes))) - (custom-theme-set-variables - 'use-package - ,@(mapcar - #'(lambda (def) - (let ((variable (nth 0 def)) - (value (nth 1 def)) - (comment (nth 2 def))) - (unless (and comment (stringp comment)) - (setq comment (format "Customized with use-package %s" name))) - `'(,variable ,value nil () ,comment))) - args)))) - (mapcar - #'(lambda (def) - (let ((variable (nth 0 def)) - (value (nth 1 def)) - (comment (nth 2 def))) - (unless (and comment (stringp comment)) - (setq comment (format "Customized with use-package %s" name))) - `(customize-set-variable (quote ,variable) ,value ,comment))) - args)) - (use-package-process-keywords name rest state))) - -;;;; :custom-face - -(defun use-package-normalize/:custom-face (name-symbol _keyword arg) - "Normalize use-package custom-face keyword." - (let ((error-msg - (format "%s wants a (<symbol> <face-spec>) or list of these" - name-symbol))) - (unless (listp arg) - (use-package-error error-msg)) - (cl-dolist (def arg arg) - (unless (listp def) - (use-package-error error-msg)) - (let ((face (nth 0 def)) - (spec (nth 1 def))) - (when (or (not face) - (not spec) - (> (length def) 2)) - (use-package-error error-msg)))))) - -(defun use-package-handler/:custom-face (name _keyword args rest state) - "Generate use-package custom-face keyword code." - (use-package-concat - (mapcar #'(lambda (def) `(custom-set-faces (backquote ,def))) args) - (use-package-process-keywords name rest state))) - -;;;; :init - -(defalias 'use-package-normalize/:init 'use-package-normalize-forms) - -(defun use-package-handler/:init (name _keyword arg rest state) - (use-package-concat - (when use-package-compute-statistics - `((use-package-statistics-gather :init ',name nil))) - (let ((init-body - (use-package-hook-injector (use-package-as-string name) - :init arg))) - (when init-body - (funcall use-package--hush-function :init - (if use-package-check-before-init - `((when (locate-library ,(use-package-as-string name)) - ,@init-body)) - init-body)))) - (use-package-process-keywords name rest state) - (when use-package-compute-statistics - `((use-package-statistics-gather :init ',name t))))) - -;;;; :load - -(defun use-package-normalize/:load (name keyword args) - (setq args (use-package-normalize-recursive-symlist name keyword args)) - (if (consp args) - args - (list args))) - -(defun use-package-handler/:load (name _keyword arg rest state) - (let ((body (use-package-process-keywords name rest state))) - (cl-dolist (pkg arg) - (setq body (use-package-require (if (eq t pkg) name pkg) nil body))) - body)) - -;;;; :config - -(defalias 'use-package-normalize/:config 'use-package-normalize-forms) - -(defun use-package-handler/:config (name _keyword arg rest state) - (let* ((body (use-package-process-keywords name rest state)) - (name-symbol (use-package-as-symbol name))) - (use-package-concat - (when use-package-compute-statistics - `((use-package-statistics-gather :config ',name nil))) - (if (and (or (null arg) (equal arg '(t))) (not use-package-inject-hooks)) - body - (use-package-with-elapsed-timer - (format "Configuring package %s" name-symbol) - (funcall use-package--hush-function :config - (use-package-concat - (use-package-hook-injector - (symbol-name name-symbol) :config arg) - body - (list t))))) - (when use-package-compute-statistics - `((use-package-statistics-gather :config ',name t)))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; The main macro -;; - -(defmacro use-package-core (name args) - `(let* ((args* (use-package-normalize-keywords ,name ,args)) - (use-package--form - (if (eq use-package-verbose 'debug) - (concat "\n\n" - (pp-to-string `(use-package ,name ,@,args)) - "\n -->\n\n" - (pp-to-string `(use-package ,name ,@args*)) - "\n ==>\n\n" - (pp-to-string - (macroexp-progn - (let ((use-package-verbose 'errors) - (use-package-expand-minimally t)) - (use-package-process-keywords name args* - (and (plist-get args* :demand) - (list :demand t))))))) - ""))) - (use-package-process-keywords name args* - (and (plist-get args* :demand) - (list :demand t))))) - -;;;###autoload -(defmacro use-package (name &rest args) - "Declare an Emacs package by specifying a group of configuration options. - -For full documentation, please see the README file that came with -this file. Usage: - - (use-package package-name - [:keyword [option]]...) - -:init Code to run before PACKAGE-NAME has been loaded. -:config Code to run after PACKAGE-NAME has been loaded. Note that - if loading is deferred for any reason, this code does not - execute until the lazy load has occurred. -:preface Code to be run before everything except `:disabled'; this - can be used to define functions for use in `:if', or that - should be seen by the byte-compiler. - -:mode Form to be added to `auto-mode-alist'. -:magic Form to be added to `magic-mode-alist'. -:magic-fallback Form to be added to `magic-fallback-mode-alist'. -:interpreter Form to be added to `interpreter-mode-alist'. - -:commands Define autoloads for commands that will be defined by the - package. This is useful if the package is being lazily - loaded, and you wish to conditionally call functions in your - `:init' block that are defined in the package. -:hook Specify hook(s) to attach this package to. - -:bind Bind keys, and define autoloads for the bound commands. -:bind* Bind keys, and define autoloads for the bound commands, - *overriding all minor mode bindings*. -:bind-keymap Bind a key prefix to an auto-loaded keymap defined in the - package. This is like `:bind', but for keymaps. -:bind-keymap* Like `:bind-keymap', but overrides all minor mode bindings - -:defer Defer loading of a package -- this is implied when using - `:commands', `:bind', `:bind*', `:mode', `:magic', `:hook', - `:magic-fallback', or `:interpreter'. This can be an integer, - to force loading after N seconds of idle time, if the package - has not already been loaded. -:after Delay the use-package declaration until after the named modules - have loaded. Once load, it will be as though the use-package - declaration (without `:after') had been seen at that moment. -:demand Prevent the automatic deferred loading introduced by constructs - such as `:bind' (see `:defer' for the complete list). - -:if EXPR Initialize and load only if EXPR evaluates to a non-nil value. -:disabled The package is ignored completely if this keyword is present. -:defines Declare certain variables to silence the byte-compiler. -:functions Declare certain functions to silence the byte-compiler. -:load-path Add to the `load-path' before attempting to load the package. -:diminish Support for diminish.el (if installed). -:delight Support for delight.el (if installed). -:custom Call `custom-set' or `set-default' with each variable - definition without modifying the Emacs `custom-file'. - (compare with `custom-set-variables'). -:custom-face Call `customize-set-faces' with each face definition. -:ensure Loads the package using package.el if necessary. -:pin Pin the package to an archive." - (declare (indent 1)) - (unless (memq :disabled args) - (macroexp-progn - (use-package-concat - (when use-package-compute-statistics - `((use-package-statistics-gather :use-package ',name nil))) - (if (eq use-package-verbose 'errors) - (use-package-core name args) - (condition-case-unless-debug err - (use-package-core name args) - (error - (ignore - (display-warning - 'use-package - (format "Failed to parse package %s: %s" - name (error-message-string err)) :error))))) - (when use-package-compute-statistics - `((use-package-statistics-gather :use-package ',name t))))))) - -(put 'use-package 'lisp-indent-function 'defun) - -(provide 'use-package-core) - -;; Local Variables: -;; indent-tabs-mode: nil -;; End: - -;;; use-package-core.el ends here |