2013-05-15 09:01:37 -05:00
|
|
|
;;; use-package.el --- A use-package declaration for simplifying your .emacs
|
2012-06-17 04:40:25 -05:00
|
|
|
|
2017-11-29 16:37:55 -08:00
|
|
|
;; Copyright (C) 2012-2017 John Wiegley
|
2012-06-17 04:40:25 -05:00
|
|
|
|
2017-11-29 16:37:55 -08:00
|
|
|
;; Author: John Wiegley <johnw@newartisans.com>
|
|
|
|
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
2012-06-17 04:40:25 -05:00
|
|
|
;; Created: 17 Jun 2012
|
2017-11-29 16:37:55 -08:00
|
|
|
;; Modified: 29 Nov 2017
|
|
|
|
;; Version: 2.4
|
|
|
|
;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
|
2012-06-17 04:40:25 -05:00
|
|
|
;; Keywords: dotemacs startup speed config package
|
2015-03-21 03:57:09 -05:00
|
|
|
;; URL: https://github.com/jwiegley/use-package
|
2012-06-17 04:40:25 -05:00
|
|
|
|
|
|
|
;; This program is free software; you can redistribute it and/or
|
|
|
|
;; modify it under the terms of the GNU General Public License as
|
2017-11-28 11:22:53 -08:00
|
|
|
;; published by the Free Software Foundation; either version 3, or (at
|
2012-06-17 04:40:25 -05:00
|
|
|
;; 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.
|
2015-03-13 03:13:31 -05:00
|
|
|
|
2012-06-17 04:40:25 -05:00
|
|
|
;;; 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!
|
|
|
|
;;
|
2014-01-06 12:38:00 +00:00
|
|
|
;; Please see README.md from the same repository for documentation.
|
2015-03-13 03:13:31 -05:00
|
|
|
|
2012-06-17 20:25:58 -05:00
|
|
|
;;; Code:
|
2012-06-17 04:40:25 -05:00
|
|
|
|
|
|
|
(require 'bind-key)
|
2012-06-22 01:32:59 -05:00
|
|
|
(require 'bytecomp)
|
2017-11-29 15:47:00 +00:00
|
|
|
(require 'cl-lib)
|
2017-11-30 20:35:29 -08:00
|
|
|
(eval-when-compile
|
|
|
|
(require 'cl)
|
|
|
|
(require 'regexp-opt))
|
2012-06-17 04:40:25 -05:00
|
|
|
|
2016-07-17 22:28:25 -04:00
|
|
|
(declare-function package-installed-p "package")
|
2016-10-31 18:22:03 +01:00
|
|
|
(declare-function package-read-all-archive-contents "package" ())
|
2013-04-27 17:09:52 +02:00
|
|
|
|
2017-11-30 11:05:46 -08:00
|
|
|
(defconst use-package-version "2.4"
|
|
|
|
"This version of use-package.")
|
|
|
|
|
2012-06-22 01:32:59 -05:00
|
|
|
(defgroup use-package nil
|
2013-04-27 17:11:16 +02:00
|
|
|
"A use-package declaration for simplifying your `.emacs'."
|
2012-06-22 01:32:59 -05:00
|
|
|
:group 'startup)
|
2012-06-17 04:40:25 -05:00
|
|
|
|
2013-12-02 03:06:27 -07:00
|
|
|
(defcustom use-package-verbose nil
|
2015-01-18 11:41:13 +01:00
|
|
|
"Whether to report about loading and configuration details.
|
|
|
|
|
|
|
|
If you customize this, then you should require the `use-package'
|
2015-03-19 18:45:30 -05:00
|
|
|
feature in files that use `use-package', even if these files only
|
2015-01-18 11:41:13 +01:00
|
|
|
contain compiled expansions of the macros. If you don't do so,
|
|
|
|
then the expanded macros do their job silently."
|
2016-02-26 16:14:51 -08:00
|
|
|
:type '(choice (const :tag "Quiet" nil) (const :tag "Verbose" t)
|
|
|
|
(const :tag "Debug" debug))
|
2012-06-17 05:52:59 -05:00
|
|
|
:group 'use-package)
|
2012-06-17 04:40:25 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(defcustom use-package-debug nil
|
|
|
|
"Whether to display use-package expansions in a *use-package* buffer."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2016-02-25 17:24:59 -08:00
|
|
|
(defcustom use-package-check-before-init nil
|
|
|
|
"If non-nil, check that package exists before executing its `:init' block.
|
|
|
|
The check is performed by looking for the module using `locate-library'."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2016-02-25 17:04:17 -08:00
|
|
|
(defcustom use-package-always-defer nil
|
|
|
|
"If non-nil, assume `:defer t` unless `:demand t` is given."
|
2016-02-25 17:24:59 -08:00
|
|
|
:type 'boolean
|
2016-02-25 17:04:17 -08:00
|
|
|
:group 'use-package)
|
|
|
|
|
2016-12-22 09:02:52 -08:00
|
|
|
(defcustom use-package-always-demand nil
|
|
|
|
"If non-nil, assume `:demand t` unless `:defer t` is given."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2015-03-21 04:19:33 -05:00
|
|
|
(defcustom use-package-always-ensure nil
|
|
|
|
"Treat every package as though it had specified `:ensure SEXP`."
|
|
|
|
:type 'sexp
|
|
|
|
:group 'use-package)
|
|
|
|
|
2016-01-20 22:02:26 +00:00
|
|
|
(defcustom use-package-always-pin nil
|
2017-03-26 14:40:17 -07:00
|
|
|
"Treat every package as though it had specified `:pin SYM`."
|
2016-01-20 22:02:26 +00:00
|
|
|
:type 'symbol
|
|
|
|
:group 'use-package)
|
|
|
|
|
2015-03-14 05:22:43 -05:00
|
|
|
(defcustom use-package-minimum-reported-time 0.1
|
2015-01-18 11:41:13 +01:00
|
|
|
"Minimal load time that will be reported.
|
|
|
|
|
|
|
|
Note that `use-package-verbose' has to be set to t, for anything
|
|
|
|
to be reported at all.
|
|
|
|
|
|
|
|
If you customize this, then you should require the `use-package'
|
2015-03-19 18:45:30 -05:00
|
|
|
feature in files that use `use-package', even if these files only
|
2015-01-18 11:41:13 +01:00
|
|
|
contain compiled expansions of the macros. If you don't do so,
|
|
|
|
then the expanded macros do their job silently."
|
2013-02-05 21:46:02 +00:00
|
|
|
:type 'number
|
2013-04-27 17:11:16 +02:00
|
|
|
:group 'use-package)
|
2013-02-05 21:46:02 +00:00
|
|
|
|
2015-03-15 03:49:16 -05:00
|
|
|
(defcustom use-package-inject-hooks nil
|
2015-03-18 20:53:55 -05:00
|
|
|
"If non-nil, add hooks to the `:init' and `:config' sections.
|
2015-03-15 03:49:16 -05:00
|
|
|
In particular, for a given package `foo', the following hooks
|
2015-03-18 20:53:55 -05:00
|
|
|
become available:
|
2015-03-15 03:49:16 -05:00
|
|
|
|
2015-03-15 18:49:08 -05:00
|
|
|
`use-package--foo--pre-init-hook'
|
|
|
|
`use-package--foo--post-init-hook'
|
|
|
|
`use-package--foo--pre-config-hook'
|
|
|
|
`use-package--foo--post-config-hook'
|
2015-03-15 03:49:16 -05:00
|
|
|
|
2017-10-30 16:03:35 -04:00
|
|
|
This way, you can add to these hooks before evaluation of a
|
2015-03-15 03:49:16 -05:00
|
|
|
`use-package` declaration, and exercise some control over what
|
|
|
|
happens.
|
|
|
|
|
|
|
|
Note that if either `pre-init' hooks returns 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
|
2015-03-16 10:39:37 -05:00
|
|
|
the user specified."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(defcustom use-package-keywords
|
|
|
|
'(:disabled
|
|
|
|
:pin
|
|
|
|
:ensure
|
|
|
|
:if
|
|
|
|
:when
|
|
|
|
:unless
|
|
|
|
:requires
|
|
|
|
:load-path
|
2017-12-01 01:04:35 -08:00
|
|
|
:defines
|
|
|
|
:functions
|
|
|
|
:preface
|
2015-03-21 02:57:18 -05:00
|
|
|
:no-require
|
2015-03-19 22:26:53 -05:00
|
|
|
:bind
|
|
|
|
:bind*
|
2016-02-25 16:41:09 -08:00
|
|
|
:bind-keymap
|
|
|
|
:bind-keymap*
|
2015-03-19 22:26:53 -05:00
|
|
|
:interpreter
|
|
|
|
:mode
|
2017-06-15 20:44:11 +02:00
|
|
|
:magic
|
|
|
|
:magic-fallback
|
2015-03-19 22:26:53 -05:00
|
|
|
:commands
|
2017-11-28 13:58:38 -08:00
|
|
|
:hook
|
2017-12-01 00:46:45 -08:00
|
|
|
:defer
|
2017-10-17 19:35:19 +02:00
|
|
|
:custom
|
2017-10-17 19:40:38 +02:00
|
|
|
:custom-face
|
2016-06-23 10:01:33 -04:00
|
|
|
:init
|
2015-11-04 22:45:37 +00:00
|
|
|
:after
|
2015-03-19 22:26:53 -05:00
|
|
|
:demand
|
|
|
|
:config
|
2015-03-21 23:35:58 -05:00
|
|
|
:diminish
|
|
|
|
:delight)
|
2015-03-21 02:57:18 -05:00
|
|
|
"Establish which keywords are valid, and the order they are processed in.
|
|
|
|
|
|
|
|
Note that `:disabled' is special, in that it causes nothing at all to happen,
|
|
|
|
even if the rest of the use-package declaration is incorrect."
|
2015-03-19 22:26:53 -05:00
|
|
|
:type '(repeat symbol)
|
|
|
|
:group 'use-package)
|
|
|
|
|
2015-03-16 10:39:37 -05:00
|
|
|
(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
|
|
|
|
- Capture of load errors (normally redisplayed as warnings)
|
|
|
|
- Conditional loading of packages (load failures become errors)
|
2015-03-18 20:53:55 -05:00
|
|
|
The only advantage is that, if you know your configuration works,
|
|
|
|
then your byte-compiled init file is as minimal as possible."
|
2015-03-16 10:39:37 -05:00
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2016-06-13 09:45:27 -04:00
|
|
|
(defcustom use-package-enable-imenu-support nil
|
|
|
|
"If non-nil, adjust `lisp-imenu-generic-expression' to include
|
|
|
|
support for finding `use-package' and `require' forms.
|
|
|
|
|
|
|
|
Must be set before loading use-package."
|
|
|
|
:type 'boolean
|
|
|
|
:group 'use-package)
|
|
|
|
|
2017-01-15 09:03:05 -07:00
|
|
|
(defcustom use-package-ensure-function 'use-package-ensure-elpa
|
|
|
|
"Function that ensures a package is installed.
|
2017-03-18 19:34:28 -07:00
|
|
|
This function is called with four arguments: the name of the
|
2017-03-08 18:16:31 -08:00
|
|
|
package declared in the `use-package' form; the argument passed
|
2017-12-01 11:42:40 -08:00
|
|
|
to `:ensure'; and the current `state' plist created by previous
|
|
|
|
handlers.
|
2017-03-18 19:34:28 -07:00
|
|
|
|
|
|
|
Note that this function is called whenever `:ensure' is provided,
|
|
|
|
even if it is nil. It is up to the function to decide on the
|
|
|
|
semantics of the various values for `:ensure'.
|
|
|
|
|
|
|
|
This function should return non-nil if the package is installed.
|
|
|
|
|
2017-12-01 11:42:40 -08:00
|
|
|
The default value uses package.el to install the package."
|
2017-01-15 09:03:05 -07:00
|
|
|
:type '(choice (const :tag "package.el" use-package-ensure-elpa)
|
|
|
|
(function :tag "Custom"))
|
|
|
|
:group 'use-package)
|
|
|
|
|
2017-02-13 12:48:24 -08:00
|
|
|
(defcustom use-package-defaults
|
|
|
|
'((:config '(t) t)
|
|
|
|
(:ensure use-package-always-ensure use-package-always-ensure)
|
|
|
|
(:pin use-package-always-pin use-package-always-pin))
|
|
|
|
"Alist of default values for `use-package' keywords.
|
|
|
|
Each entry in the alist is a list of three elements. The first
|
|
|
|
element is the `use-package' keyword and the second is a form
|
|
|
|
that can be evaluated to get the default value. 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."
|
|
|
|
:type '(repeat (list symbol sexp sexp)))
|
|
|
|
|
2016-06-13 09:45:27 -04:00
|
|
|
(when use-package-enable-imenu-support
|
2016-06-14 22:37:56 -04:00
|
|
|
(eval-after-load 'lisp-mode
|
|
|
|
`(let ((sym-regexp (or (bound-and-true-p lisp-mode-symbol-regexp)
|
|
|
|
"\\(?:\\sw\\|\\s_\\|\\\\.\\)+")))
|
|
|
|
(add-to-list
|
|
|
|
'lisp-imenu-generic-expression
|
|
|
|
(list "Packages"
|
|
|
|
(concat "^\\s-*("
|
|
|
|
,(eval-when-compile
|
|
|
|
(regexp-opt '("use-package" "require") t))
|
|
|
|
"\\s-+\\(" sym-regexp "\\)")
|
|
|
|
2)))))
|
2016-06-13 09:45:27 -04:00
|
|
|
|
2016-06-22 22:46:32 -04:00
|
|
|
(defvar use-package-form-regexp "^\\s-*(\\s-*use-package\\s-+\\_<%s\\_>"
|
|
|
|
"Regexp used in `use-package-jump-to-package-form' to find use
|
|
|
|
package forms in user files.")
|
|
|
|
|
|
|
|
(defun use-package--find-require (package)
|
|
|
|
"Find file that required PACKAGE by searching
|
|
|
|
`load-history'. Returns an absolute file path or nil if none is
|
|
|
|
found."
|
|
|
|
(catch 'suspect
|
|
|
|
(dolist (filespec load-history)
|
|
|
|
(dolist (entry (cdr filespec))
|
|
|
|
(when (equal entry (cons 'require package))
|
|
|
|
(throw 'suspect (car filespec)))))))
|
|
|
|
|
|
|
|
(defun use-package-jump-to-package-form (package)
|
|
|
|
"Attempt to find and jump to the `use-package' form that loaded
|
|
|
|
PACKAGE. This will only find the form if that form actually
|
|
|
|
required PACKAGE. If PACKAGE was previously required then this
|
2017-10-30 16:03:35 -04:00
|
|
|
function will jump to the file that originally required PACKAGE
|
2016-06-22 22:46:32 -04:00
|
|
|
instead."
|
|
|
|
(interactive (list (completing-read "Package: " features)))
|
|
|
|
(let* ((package (if (stringp package) (intern package) package))
|
|
|
|
(requiring-file (use-package--find-require package))
|
|
|
|
file location)
|
|
|
|
(if (null requiring-file)
|
|
|
|
(user-error "Can't find file that requires this feature.")
|
|
|
|
(setq file (if (string= (file-name-extension requiring-file) "elc")
|
|
|
|
(concat (file-name-sans-extension requiring-file) ".el")
|
|
|
|
requiring-file))
|
|
|
|
(when (file-exists-p file)
|
|
|
|
(find-file-other-window file)
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-min))
|
|
|
|
(setq location
|
|
|
|
(re-search-forward
|
|
|
|
(format use-package-form-regexp package) nil t)))
|
|
|
|
(if (null location)
|
|
|
|
(message "No use-package form found.")
|
|
|
|
(goto-char location)
|
|
|
|
(beginning-of-line))))))
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; Utility functions
|
2015-03-19 22:26:53 -05:00
|
|
|
;;
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun 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)))
|
|
|
|
|
|
|
|
(defun 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)))
|
|
|
|
|
2017-07-02 16:20:01 +02:00
|
|
|
(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")))))
|
|
|
|
|
2015-09-06 20:51:31 -07:00
|
|
|
(defun use-package-load-name (name &optional noerror)
|
2015-06-17 13:33:09 -04:00
|
|
|
"Return a form which will load or require NAME depending on
|
|
|
|
whether it's a string or symbol."
|
2016-02-25 16:37:34 -08:00
|
|
|
(if (stringp name)
|
2015-09-06 22:28:50 -04:00
|
|
|
`(load ,name ',noerror)
|
|
|
|
`(require ',name nil ',noerror)))
|
2015-06-17 13:33:09 -04:00
|
|
|
|
2015-03-17 11:42:04 -05:00
|
|
|
(defun use-package-expand (name label form)
|
|
|
|
"FORM is a list of forms, so `((foo))' if only `foo' is being called."
|
2015-03-16 10:39:37 -05:00
|
|
|
(declare (indent 1))
|
|
|
|
(when form
|
|
|
|
(if use-package-expand-minimally
|
|
|
|
form
|
|
|
|
(let ((err (make-symbol "err")))
|
2015-03-17 11:42:04 -05:00
|
|
|
(list
|
|
|
|
`(condition-case-unless-debug ,err
|
2015-03-19 17:40:41 -04:00
|
|
|
,(macroexp-progn form)
|
2015-03-17 11:42:04 -05:00
|
|
|
(error
|
|
|
|
(ignore
|
2015-03-18 03:25:21 -05:00
|
|
|
(display-warning 'use-package
|
2015-03-21 02:57:18 -05:00
|
|
|
(format "%s %s: %s"
|
|
|
|
,name ,label (error-message-string ,err))
|
2015-03-17 11:42:04 -05:00
|
|
|
:error)))))))))
|
2015-03-16 10:39:37 -05:00
|
|
|
|
|
|
|
(put 'use-package-expand 'lisp-indent-function 'defun)
|
2015-03-15 03:49:16 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(defun use-package-hook-injector (name-string keyword body)
|
2015-03-17 11:42:04 -05:00
|
|
|
"Wrap pre/post hook injections around a given keyword form.
|
|
|
|
ARGS is a list of forms, so `((foo))' if only `foo' is being called."
|
2015-03-15 18:49:08 -05:00
|
|
|
(if (not use-package-inject-hooks)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-expand name-string (format "%s" keyword) body)
|
|
|
|
(let ((keyword-name (substring (format "%s" keyword) 1)))
|
2017-11-28 21:12:25 -08:00
|
|
|
`((when ,(macroexp-progn
|
|
|
|
(use-package-expand name-string (format "pre-%s hook" keyword)
|
|
|
|
`((run-hook-with-args-until-failure
|
|
|
|
',(intern (concat "use-package--" name-string
|
|
|
|
"--pre-" keyword-name "-hook"))))))
|
|
|
|
,(macroexp-progn
|
|
|
|
(use-package-expand name-string (format "%s" keyword) body))
|
|
|
|
,(macroexp-progn
|
|
|
|
(use-package-expand name-string (format "post-%s hook" keyword)
|
|
|
|
`((run-hooks
|
|
|
|
',(intern (concat "use-package--" name-string
|
|
|
|
"--post-" keyword-name "-hook")))))))))))
|
2015-03-17 11:42:04 -05:00
|
|
|
|
2015-03-19 18:48:14 -05:00
|
|
|
(defun use-package--with-elapsed-timer (text body)
|
2015-03-17 11:42:04 -05:00
|
|
|
"BODY is a list of forms, so `((foo))' if only `foo' is being called."
|
2014-03-09 18:55:54 +01:00
|
|
|
(declare (indent 1))
|
2015-03-16 10:39:37 -05:00
|
|
|
(if use-package-expand-minimally
|
2015-03-17 11:42:04 -05:00
|
|
|
body
|
2015-03-16 10:39:37 -05:00
|
|
|
(let ((nowvar (make-symbol "now")))
|
|
|
|
(if (bound-and-true-p use-package-verbose)
|
2015-03-17 11:42:04 -05:00
|
|
|
`((let ((,nowvar (current-time)))
|
|
|
|
(message "%s..." ,text)
|
|
|
|
(prog1
|
2015-03-19 17:40:41 -04:00
|
|
|
,(macroexp-progn body)
|
2015-03-17 11:42:04 -05:00
|
|
|
(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))))
|
|
|
|
|
2015-03-19 18:48:14 -05:00
|
|
|
(put 'use-package--with-elapsed-timer 'lisp-indent-function 1)
|
2015-03-14 05:22:43 -05:00
|
|
|
|
|
|
|
(defsubst use-package-error (msg)
|
|
|
|
"Report MSG as an error, so the user knows it came from this package."
|
|
|
|
(error "use-package: %s" msg))
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(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))))
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(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)))
|
2016-07-22 11:23:10 -07:00
|
|
|
(setq p (plist-put p (car plist) (nth 1 plist))))
|
2015-03-19 22:26:53 -05:00
|
|
|
(setq plist (cddr plist)))
|
|
|
|
p))
|
|
|
|
|
|
|
|
(defun use-package-split-list (pred xs)
|
|
|
|
(let ((ys (list nil)) (zs (list nil)) flip)
|
|
|
|
(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-keyword-index (keyword)
|
|
|
|
(loop named outer
|
|
|
|
with index = 0
|
|
|
|
for k in use-package-keywords do
|
|
|
|
(if (eq k keyword)
|
|
|
|
(return-from outer index))
|
|
|
|
(incf index)))
|
|
|
|
|
|
|
|
(defun use-package-sort-keywords (plist)
|
|
|
|
(let (plist-grouped)
|
|
|
|
(while plist
|
|
|
|
(push (cons (car plist) (cadr plist))
|
|
|
|
plist-grouped)
|
|
|
|
(setq plist (cddr plist)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(let (result)
|
|
|
|
(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)))
|
|
|
|
|
|
|
|
(defsubst use-package-concat (&rest elems)
|
2015-03-19 22:26:53 -05:00
|
|
|
"Delete all empty lists from ELEMS (nil or (list nil)), and append them."
|
|
|
|
(apply #'nconc (delete nil (delete (list nil) elems))))
|
|
|
|
|
2017-11-29 14:41:12 -08:00
|
|
|
(defsubst use-package--non-nil-symbolp (sym)
|
|
|
|
(and sym (symbolp sym)))
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(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)
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; Keyword processing
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; Normalization functions
|
2015-03-19 22:26:53 -05:00
|
|
|
;;
|
2015-03-14 05:22:43 -05:00
|
|
|
|
2017-11-29 14:41:12 -08:00
|
|
|
(defsubst use-package-regex-p (re)
|
2017-02-16 12:03:59 -08:00
|
|
|
"Return t if RE is some regexp-like thing."
|
2017-11-29 14:41:12 -08:00
|
|
|
(or (and (listp re)
|
|
|
|
(eq (car re) 'rx))
|
|
|
|
(stringp re)))
|
2017-02-16 12:03:59 -08:00
|
|
|
|
|
|
|
(defun use-package-normalize-regex (re)
|
|
|
|
"Given some regexp-like thing, resolve it down 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))))
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-plist (name input)
|
2015-03-21 02:57:18 -05:00
|
|
|
"Given a pseudo-plist, normalize it to a regular plist."
|
|
|
|
(unless (null input)
|
|
|
|
(let* ((keyword (car input))
|
|
|
|
(xs (use-package-split-list #'keywordp (cdr input)))
|
|
|
|
(args (car xs))
|
|
|
|
(tail (cdr xs))
|
|
|
|
(normalizer (intern (concat "use-package-normalize/"
|
|
|
|
(symbol-name keyword))))
|
|
|
|
(arg
|
|
|
|
(cond
|
|
|
|
((eq keyword :disabled)
|
2015-06-17 13:33:09 -04:00
|
|
|
(use-package-normalize-plist name tail))
|
2015-03-21 02:57:18 -05:00
|
|
|
((functionp normalizer)
|
2015-06-17 13:33:09 -04:00
|
|
|
(funcall normalizer name keyword args))
|
2015-03-21 02:57:18 -05:00
|
|
|
((= (length args) 1)
|
|
|
|
(car args))
|
|
|
|
(t
|
|
|
|
args))))
|
|
|
|
(if (memq keyword use-package-keywords)
|
|
|
|
(cons keyword
|
2015-06-17 13:33:09 -04:00
|
|
|
(cons arg (use-package-normalize-plist name tail)))
|
2017-11-28 11:31:35 -08:00
|
|
|
(ignore
|
|
|
|
(display-warning 'use-package
|
|
|
|
(format "Unrecognized keyword: %s" keyword)
|
|
|
|
:warning))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-process-keywords (name plist &optional state)
|
2015-03-21 02:57:18 -05:00
|
|
|
"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."
|
2016-02-25 15:16:04 -08:00
|
|
|
(declare (indent 1))
|
2015-03-21 02:57:18 -05:00
|
|
|
(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)
|
2015-06-17 13:33:09 -04:00
|
|
|
(funcall handler-sym name keyword arg rest state)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-error
|
|
|
|
(format "Keyword handler not defined: %s" handler)))))))
|
|
|
|
|
|
|
|
(put 'use-package-process-keywords 'lisp-indent-function 'defun)
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :pin
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
|
|
|
(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)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize/:pin (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-only-one (symbol-name keyword) args
|
|
|
|
(lambda (label arg)
|
|
|
|
(cond
|
|
|
|
((stringp arg) arg)
|
2017-11-29 14:41:12 -08:00
|
|
|
((use-package--non-nil-symbolp arg) (symbol-name arg))
|
2015-03-21 02:57:18 -05:00
|
|
|
(t
|
|
|
|
(use-package-error
|
|
|
|
":pin wants an archive name (a string)"))))))
|
|
|
|
|
|
|
|
(eval-when-compile
|
|
|
|
(defvar package-pinned-packages)
|
|
|
|
(defvar package-archives))
|
|
|
|
|
|
|
|
(defun use-package--archive-exists-p (archive)
|
|
|
|
"Check if a given ARCHIVE is enabled.
|
|
|
|
|
|
|
|
ARCHIVE can be a string or a symbol or 'manual to indicate a
|
|
|
|
manually updated package."
|
|
|
|
(if (member archive '(manual "manual"))
|
|
|
|
't
|
|
|
|
(let ((valid nil))
|
|
|
|
(dolist (pa package-archives)
|
|
|
|
(when (member archive (list (car pa) (intern (car pa))))
|
|
|
|
(setq valid 't)))
|
|
|
|
valid)))
|
|
|
|
|
|
|
|
(defun use-package-pin-package (package archive)
|
|
|
|
"Pin PACKAGE to ARCHIVE."
|
|
|
|
(unless (boundp 'package-pinned-packages)
|
|
|
|
(setq package-pinned-packages ()))
|
|
|
|
(let ((archive-symbol (if (symbolp archive) archive (intern archive)))
|
|
|
|
(archive-name (if (stringp archive) archive (symbol-name archive))))
|
|
|
|
(if (use-package--archive-exists-p archive-symbol)
|
2016-01-06 12:56:54 +13:00
|
|
|
(add-to-list 'package-pinned-packages (cons package archive-name))
|
2015-03-21 02:57:18 -05:00
|
|
|
(error "Archive '%s' requested for package '%s' is not available."
|
|
|
|
archive-name package))
|
2016-01-20 10:49:27 +13:00
|
|
|
(unless (bound-and-true-p package--initialized)
|
2016-01-18 14:41:27 +13:00
|
|
|
(package-initialize t))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:pin (name keyword archive-name rest state)
|
2016-01-06 11:15:22 +13:00
|
|
|
(let ((body (use-package-process-keywords name rest state))
|
|
|
|
(pin-form (if archive-name
|
2016-01-06 12:56:54 +13:00
|
|
|
`(use-package-pin-package ',(use-package-as-symbol name)
|
|
|
|
,archive-name))))
|
|
|
|
;; Pinning should occur just before ensuring
|
|
|
|
;; See `use-package-handler/:ensure'.
|
2016-01-06 11:15:22 +13:00
|
|
|
(if (bound-and-true-p byte-compile-current-file)
|
|
|
|
(eval pin-form) ; Eval when byte-compiling,
|
|
|
|
(push pin-form body)) ; or else wait until runtime.
|
|
|
|
body))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :ensure
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2016-02-04 10:20:55 +01:00
|
|
|
(defvar package-archive-contents)
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize/:ensure (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(if (null args)
|
|
|
|
t
|
|
|
|
(use-package-only-one (symbol-name keyword) args
|
|
|
|
(lambda (label arg)
|
2017-11-30 09:14:28 -08:00
|
|
|
(if (symbolp arg)
|
2015-03-21 02:57:18 -05:00
|
|
|
arg
|
|
|
|
(use-package-error
|
|
|
|
(concat ":ensure wants an optional package name "
|
|
|
|
"(an unquoted symbol name)")))))))
|
|
|
|
|
2017-12-01 11:42:40 -08:00
|
|
|
(defun use-package-ensure-elpa (name ensure state &optional no-refresh)
|
|
|
|
(let ((package
|
|
|
|
(or (and (eq ensure t) (use-package-as-symbol name))
|
|
|
|
ensure)))
|
2017-03-08 11:17:33 -08:00
|
|
|
(when package
|
|
|
|
(require 'package)
|
2017-12-01 11:42:40 -08:00
|
|
|
(unless (package-installed-p package)
|
|
|
|
(condition-case-unless-debug err
|
|
|
|
(progn
|
|
|
|
(when (assoc package (bound-and-true-p
|
|
|
|
package-pinned-packages))
|
|
|
|
(package-read-all-archive-contents))
|
|
|
|
(if (assoc package package-archive-contents)
|
|
|
|
(package-install package)
|
|
|
|
(package-refresh-contents)
|
2017-12-01 01:36:36 -08:00
|
|
|
(when (assoc package (bound-and-true-p
|
|
|
|
package-pinned-packages))
|
2017-03-18 19:34:28 -07:00
|
|
|
(package-read-all-archive-contents))
|
2017-12-01 11:42:40 -08:00
|
|
|
(package-install package))
|
|
|
|
t)
|
|
|
|
(error
|
|
|
|
(ignore
|
|
|
|
(display-warning 'use-package
|
|
|
|
(format "Failed to install %s: %s"
|
|
|
|
name (error-message-string err))
|
|
|
|
:error))))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:ensure (name keyword ensure rest state)
|
2017-12-01 11:42:40 -08:00
|
|
|
(let* ((body (use-package-process-keywords name rest state)))
|
|
|
|
;; We want to avoid installing packages when the `use-package' macro is
|
|
|
|
;; being macro-expanded by elisp completion (see `lisp--local-variables'),
|
|
|
|
;; but still install packages when byte-compiling, to avoid requiring
|
|
|
|
;; `package' at runtime.
|
|
|
|
(if (bound-and-true-p byte-compile-current-file)
|
|
|
|
;; Eval when byte-compiling,
|
|
|
|
(funcall use-package-ensure-function name ensure state)
|
|
|
|
;; or else wait until runtime.
|
|
|
|
(push `(,use-package-ensure-function ',name ',ensure ',state)
|
2017-03-18 19:34:28 -07:00
|
|
|
body))
|
2015-11-13 11:08:02 +13:00
|
|
|
body))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :if, :when and :unless
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-03-14 05:22:43 -05:00
|
|
|
(defsubst use-package-normalize-value (label arg)
|
|
|
|
"Normalize a value."
|
2017-04-04 21:16:06 -07:00
|
|
|
(cond ((null arg) nil)
|
2017-11-29 14:41:12 -08:00
|
|
|
((use-package--non-nil-symbolp arg)
|
2015-03-14 05:22:43 -05:00
|
|
|
`(symbol-value ',arg))
|
|
|
|
((functionp arg)
|
|
|
|
`(funcall #',arg))
|
|
|
|
(t arg)))
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-test (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-only-one (symbol-name keyword) args
|
|
|
|
#'use-package-normalize-value))
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:if 'use-package-normalize-test)
|
|
|
|
(defalias 'use-package-normalize/:when 'use-package-normalize-test)
|
2016-02-25 15:08:32 -08:00
|
|
|
(defalias 'use-package-normalize/:unless 'use-package-normalize-test)
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:if (name keyword pred rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
`((when ,pred ,@body))))
|
|
|
|
|
|
|
|
(defalias 'use-package-handler/:when 'use-package-handler/:if)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:unless (name keyword pred rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
`((unless ,pred ,@body))))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :requires
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2017-11-28 16:27:09 -08:00
|
|
|
(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."
|
2015-03-21 02:57:18 -05:00
|
|
|
(declare (indent 1))
|
2017-11-29 14:41:12 -08:00
|
|
|
(if (if args
|
2017-11-29 16:53:41 -08:00
|
|
|
(and (listp args) (listp (cdr args)))
|
|
|
|
allow-empty)
|
2015-03-21 02:57:18 -05:00
|
|
|
(if (= (length args) 1)
|
|
|
|
(funcall f label (car args))
|
|
|
|
(funcall f label args))
|
|
|
|
(use-package-error
|
2017-11-28 11:16:12 -08:00
|
|
|
(concat label " wants a non-empty list"))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
(put 'use-package-as-one 'lisp-indent-function 'defun)
|
|
|
|
|
|
|
|
(defun use-package-normalize-symbols (label arg &optional recursed)
|
|
|
|
"Normalize a list of symbols."
|
|
|
|
(cond
|
2017-11-29 14:41:12 -08:00
|
|
|
((use-package--non-nil-symbolp arg)
|
2015-03-21 02:57:18 -05:00
|
|
|
(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")))))
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-symlist (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-as-one (symbol-name keyword) args
|
|
|
|
#'use-package-normalize-symbols))
|
|
|
|
|
2017-02-16 13:48:05 -08:00
|
|
|
(defun use-package-normalize-recursive-symbols (label arg)
|
|
|
|
"Normalize a list of symbols."
|
|
|
|
(cond
|
2017-11-29 14:41:12 -08:00
|
|
|
((use-package--non-nil-symbolp arg)
|
2017-02-16 13:48:05 -08:00
|
|
|
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))
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(defalias 'use-package-normalize/:requires 'use-package-normalize-symlist)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:requires (name keyword requires rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(if (null requires)
|
|
|
|
body
|
|
|
|
`((when ,(if (listp requires)
|
|
|
|
`(not (member nil (mapcar #'featurep ',requires)))
|
|
|
|
`(featurep ',requires))
|
|
|
|
,@body)))))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :load-path
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(defun use-package-normalize-paths (label arg &optional recursed)
|
|
|
|
"Normalize a list of filesystem paths."
|
2015-03-14 05:22:43 -05:00
|
|
|
(cond
|
2017-11-29 14:41:12 -08:00
|
|
|
((and arg (or (use-package--non-nil-symbolp arg) (functionp arg)))
|
2015-03-19 22:26:53 -05:00
|
|
|
(let ((value (use-package-normalize-value label arg)))
|
|
|
|
(use-package-normalize-paths label (eval value))))
|
2015-03-14 05:22:43 -05:00
|
|
|
((stringp arg)
|
2015-03-19 22:26:53 -05:00
|
|
|
(let ((path (if (file-name-absolute-p arg)
|
|
|
|
arg
|
|
|
|
(expand-file-name arg user-emacs-directory))))
|
|
|
|
(list path)))
|
2015-03-14 05:22:43 -05:00
|
|
|
((and (not recursed) (listp arg) (listp (cdr arg)))
|
2015-03-19 22:26:53 -05:00
|
|
|
(mapcar #'(lambda (x)
|
|
|
|
(car (use-package-normalize-paths label x t))) arg))
|
2015-03-14 05:22:43 -05:00
|
|
|
(t
|
|
|
|
(use-package-error
|
2015-03-19 22:26:53 -05:00
|
|
|
(concat label " wants a directory path, or list of paths")))))
|
2015-03-16 10:39:37 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize/:load-path (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-as-one (symbol-name keyword) args
|
|
|
|
#'use-package-normalize-paths))
|
2015-03-14 05:22:43 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:load-path (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
|
|
|
(mapcar #'(lambda (path)
|
2016-02-25 17:13:02 -08:00
|
|
|
`(eval-and-compile (add-to-list 'load-path ,path))) arg)
|
2015-03-21 02:57:18 -05:00
|
|
|
body)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :no-require
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-predicate (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(if (null args)
|
|
|
|
t
|
|
|
|
(use-package-only-one (symbol-name keyword) args
|
|
|
|
#'use-package-normalize-value)))
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:no-require 'use-package-normalize-predicate)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:no-require (name keyword arg rest state)
|
2015-03-21 02:57:18 -05:00
|
|
|
;; This keyword has no functional meaning.
|
2017-11-30 21:45:17 -08:00
|
|
|
(use-package-process-keywords name rest
|
|
|
|
(plist-put state :no-require t)))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :preface
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
|
|
|
(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)
|
|
|
|
(eq (car form) 'use-package))
|
|
|
|
(macroexpand form)
|
|
|
|
form)) args))
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-forms (name keyword args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-normalize-form (symbol-name keyword) args))
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:preface 'use-package-normalize-forms)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:preface (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
2017-11-30 20:35:29 -08:00
|
|
|
(when arg
|
2015-03-21 02:57:18 -05:00
|
|
|
`((eval-and-compile ,@arg)))
|
|
|
|
body)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :bind, :bind*
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2015-03-16 10:39:37 -05:00
|
|
|
|
2016-05-26 15:08:32 -04:00
|
|
|
(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."
|
2015-03-14 05:22:43 -05:00
|
|
|
(and (consp x)
|
2016-05-26 15:08:32 -04:00
|
|
|
(funcall car-pred (car x))
|
|
|
|
(funcall cdr-pred (cdr x))))
|
2016-01-08 14:35:17 -05:00
|
|
|
|
2015-03-16 03:19:28 -05:00
|
|
|
(defun use-package-normalize-pairs
|
2016-05-26 15:08:32 -04:00
|
|
|
(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."
|
2015-03-14 05:22:43 -05:00
|
|
|
(cond
|
2016-05-26 15:08:32 -04:00
|
|
|
((funcall key-pred arg)
|
2015-06-17 13:33:09 -04:00
|
|
|
(list (cons arg (use-package-as-symbol name))))
|
2016-05-26 15:08:32 -04:00
|
|
|
((use-package-is-pair arg key-pred val-pred)
|
2015-03-14 05:22:43 -05:00
|
|
|
(list arg))
|
|
|
|
((and (not recursed) (listp arg) (listp (cdr arg)))
|
2017-11-29 14:41:12 -08:00
|
|
|
(let (last-item)
|
|
|
|
(mapcar
|
|
|
|
#'(lambda (x)
|
|
|
|
(prog1
|
|
|
|
(let ((ret (use-package-normalize-pairs
|
|
|
|
key-pred val-pred name label x t)))
|
|
|
|
;; Currently, the handling of keyword arguments by
|
|
|
|
;; `use-package' and `bind-key' is non-uniform and
|
|
|
|
;; undocumented. As a result, `use-package-normalize-pairs'
|
|
|
|
;; (as it is currently implemented) does not correctly handle
|
|
|
|
;; the keyword-argument syntax of `bind-keys'. A permanent
|
|
|
|
;; solution to this problem will require a careful
|
|
|
|
;; consideration of the desired keyword-argument interface
|
|
|
|
;; for `use-package' and `bind-key'. However, in the
|
|
|
|
;; meantime, we have a quick patch to fix a serious bug in
|
|
|
|
;; the handling of keyword arguments. Namely, the code below
|
|
|
|
;; would normally unwrap lists that were passed as keyword
|
|
|
|
;; arguments (for example, the `:filter' argument in `:bind')
|
|
|
|
;; without the (not (keywordp last-item)) clause. See #447
|
|
|
|
;; for further discussion.
|
|
|
|
(if (and (listp ret)
|
|
|
|
(not (keywordp last-item)))
|
|
|
|
(car ret)
|
|
|
|
ret))
|
|
|
|
(setq last-item x))) arg)))
|
2015-07-30 23:42:59 +01:00
|
|
|
(t arg)))
|
2015-03-14 05:22:43 -05:00
|
|
|
|
2017-11-29 22:03:03 -08:00
|
|
|
(defun use-package--recognize-function (v &optional binding additional-pred)
|
2017-11-29 14:41:12 -08:00
|
|
|
"A predicate that recognizes functional constructions:
|
2017-11-29 21:43:52 -08:00
|
|
|
nil
|
2017-11-29 14:41:12 -08:00
|
|
|
sym
|
|
|
|
'sym
|
|
|
|
(quote sym)
|
|
|
|
#'sym
|
|
|
|
(function sym)
|
|
|
|
(lambda () ...)
|
|
|
|
'(lambda () ...)
|
|
|
|
(quote (lambda () ...))
|
|
|
|
#'(lambda () ...)
|
|
|
|
(function (lambda () ...))"
|
|
|
|
(pcase v
|
2017-11-29 22:03:03 -08:00
|
|
|
((and x (guard (if binding
|
|
|
|
(symbolp x)
|
|
|
|
(use-package--non-nil-symbolp x)))) t)
|
2017-11-29 16:48:58 -08:00
|
|
|
(`(,(or `quote `function)
|
2017-11-29 22:03:03 -08:00
|
|
|
,(pred use-package--non-nil-symbolp)) t)
|
|
|
|
((and x (guard (if binding (commandp x) (functionp x)))) t)
|
2017-11-29 14:41:12 -08:00
|
|
|
(_ (and additional-pred
|
|
|
|
(funcall additional-pred v)))))
|
|
|
|
|
|
|
|
(defun use-package--normalize-function (v)
|
|
|
|
"Reduce functional constructions to one of two normal forms:
|
|
|
|
sym
|
|
|
|
#'(lambda () ...)"
|
|
|
|
(pcase v
|
2017-11-29 21:43:52 -08:00
|
|
|
((pred symbolp) v)
|
2017-11-29 16:48:58 -08:00
|
|
|
(`(,(or `quote `function)
|
2017-11-29 21:43:52 -08:00
|
|
|
,(and sym (pred symbolp))) sym)
|
2017-11-29 14:41:12 -08:00
|
|
|
(`(lambda . ,_) v)
|
|
|
|
(`(quote ,(and lam `(lambda . ,_))) lam)
|
|
|
|
(`(function ,(and lam `(lambda . ,_))) lam)
|
|
|
|
(_ v)))
|
|
|
|
|
|
|
|
(defun use-package--normalize-commands (args)
|
|
|
|
"Map over ARGS of the form ((_ . F) ...).
|
|
|
|
Normalizing functional F's and returning a list of F's
|
|
|
|
representing symbols (that may need to be autloaded)."
|
|
|
|
(let ((nargs (mapcar
|
|
|
|
#'(lambda (x)
|
|
|
|
(if (consp x)
|
|
|
|
(cons (car x)
|
|
|
|
(use-package--normalize-function (cdr x)))
|
|
|
|
x)) args)))
|
|
|
|
(cons nargs
|
2017-11-29 21:43:52 -08:00
|
|
|
(delete
|
|
|
|
nil (mapcar
|
|
|
|
#'(lambda (x)
|
|
|
|
(and (consp x)
|
|
|
|
(use-package--non-nil-symbolp (cdr x))
|
|
|
|
(cdr x))) nargs)))))
|
2017-11-29 14:41:12 -08:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-binder (name keyword args)
|
2015-03-19 22:26:53 -05:00
|
|
|
(use-package-as-one (symbol-name keyword) args
|
|
|
|
(lambda (label arg)
|
2016-08-05 18:43:34 -04:00
|
|
|
(unless (consp arg)
|
|
|
|
(use-package-error
|
2017-11-29 14:41:12 -08:00
|
|
|
(concat label " a (<string or vector> . <symbol, string or function>)"
|
2016-08-05 18:43:34 -04:00
|
|
|
" or list of these")))
|
2017-11-29 14:41:12 -08:00
|
|
|
(use-package-normalize-pairs
|
|
|
|
#'(lambda (k)
|
|
|
|
(pcase k
|
|
|
|
((pred stringp) t)
|
|
|
|
((pred vectorp) t)))
|
2017-11-29 22:03:03 -08:00
|
|
|
#'(lambda (v) (use-package--recognize-function v t #'stringp))
|
2017-11-29 14:41:12 -08:00
|
|
|
name label arg))))
|
2015-03-19 22:26:53 -05:00
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
|
|
|
|
(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
(defun use-package-handler/:bind
|
2017-11-29 14:41:12 -08:00
|
|
|
(name keyword args rest state &optional bind-macro)
|
|
|
|
(cl-destructuring-bind (nargs . commands)
|
|
|
|
(use-package--normalize-commands args)
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
2015-06-17 13:33:09 -04:00
|
|
|
(use-package-process-keywords name
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-sort-keywords
|
|
|
|
(use-package-plist-maybe-put rest :defer t))
|
|
|
|
(use-package-plist-append state :commands commands))
|
2016-02-25 15:57:50 -08:00
|
|
|
`((ignore
|
2017-12-01 00:45:43 -08:00
|
|
|
(,(if bind-macro bind-macro 'bind-keys)
|
|
|
|
:package ,name ,@nargs))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:bind* (name keyword arg rest state)
|
2015-09-23 11:06:58 -04:00
|
|
|
(use-package-handler/:bind name keyword arg rest state 'bind-keys*))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2016-02-25 16:41:09 -08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :bind-keymap, :bind-keymap*
|
2016-02-25 16:41:09 -08:00
|
|
|
;;
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
|
|
|
|
(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
|
|
|
|
|
2017-02-16 11:33:29 -08:00
|
|
|
;;;###autoload
|
2016-02-25 16:41:09 -08:00
|
|
|
(defun use-package-autoload-keymap (keymap-symbol package override)
|
|
|
|
"Loads PACKAGE and then binds the key sequence used to invoke
|
2017-11-29 14:41:12 -08:00
|
|
|
this function to KEYMAP-SYMBOL. It then simulates pressing the
|
|
|
|
same key sequence a again, so that the next key pressed is routed
|
|
|
|
to the newly loaded keymap.
|
|
|
|
|
|
|
|
This function supports use-package's :bind-keymap keyword. It
|
|
|
|
works by binding the given key sequence to an invocation of this
|
|
|
|
function for a particular keymap. The keymap is expected to be
|
|
|
|
defined by the package. In this way, loading the package is
|
|
|
|
deferred until the prefix key sequence is pressed."
|
2016-02-25 16:41:09 -08:00
|
|
|
(if (not (require package nil t))
|
2016-02-26 16:18:21 -08:00
|
|
|
(use-package-error (format "Cannot load package.el: %s" package))
|
2016-02-25 16:41:09 -08:00
|
|
|
(if (and (boundp keymap-symbol)
|
|
|
|
(keymapp (symbol-value keymap-symbol)))
|
|
|
|
(let* ((kv (this-command-keys-vector))
|
|
|
|
(key (key-description kv))
|
|
|
|
(keymap (symbol-value keymap-symbol)))
|
|
|
|
(if override
|
|
|
|
(bind-key* key keymap)
|
|
|
|
(bind-key key keymap))
|
|
|
|
(setq unread-command-events
|
|
|
|
(listify-key-sequence kv)))
|
|
|
|
(use-package-error
|
|
|
|
(format "use-package: package.el %s failed to define keymap %s"
|
|
|
|
package keymap-symbol)))))
|
|
|
|
|
|
|
|
(defun use-package-handler/:bind-keymap
|
|
|
|
(name keyword arg rest state &optional override)
|
2017-12-01 00:46:57 -08:00
|
|
|
(let ((form
|
|
|
|
(mapcar
|
|
|
|
#'(lambda (binding)
|
|
|
|
`(,(if override
|
|
|
|
'bind-key*
|
|
|
|
'bind-key)
|
|
|
|
,(car binding)
|
|
|
|
#'(lambda ()
|
|
|
|
(interactive)
|
|
|
|
(use-package-autoload-keymap
|
|
|
|
',(cdr binding) ',(use-package-as-symbol name)
|
|
|
|
,override)))) arg)))
|
2016-02-25 16:41:09 -08:00
|
|
|
(use-package-concat
|
|
|
|
(use-package-process-keywords name
|
|
|
|
(use-package-sort-keywords
|
|
|
|
(use-package-plist-maybe-put rest :defer t))
|
|
|
|
state)
|
|
|
|
`((ignore ,@form)))))
|
|
|
|
|
|
|
|
(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
|
|
|
|
(use-package-handler/:bind-keymap name keyword arg rest state t))
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :interpreter
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-mode (name keyword args)
|
2017-06-15 20:44:11 +02:00
|
|
|
"Normalize arguments for keywords which add regexp/mode pairs to an alist."
|
2015-03-19 22:26:53 -05:00
|
|
|
(use-package-as-one (symbol-name keyword) args
|
2016-05-26 15:08:32 -04:00
|
|
|
(apply-partially #'use-package-normalize-pairs
|
2017-02-16 12:03:59 -08:00
|
|
|
#'use-package-regex-p
|
2017-11-29 16:44:20 -08:00
|
|
|
#'use-package--recognize-function
|
2016-05-26 15:08:32 -04:00
|
|
|
name)))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2017-11-29 14:41:12 -08:00
|
|
|
(defun use-package-handle-mode (name alist args rest state)
|
2017-06-15 20:44:11 +02:00
|
|
|
"Handle keywords which add regexp/mode pairs to an alist."
|
2017-11-29 14:41:12 -08:00
|
|
|
(cl-destructuring-bind (nargs . commands)
|
|
|
|
(use-package--normalize-commands args)
|
|
|
|
(let ((form
|
|
|
|
(mapcar
|
|
|
|
#'(lambda (thing)
|
|
|
|
`(add-to-list
|
|
|
|
',alist
|
|
|
|
',(cons (use-package-normalize-regex (car thing))
|
|
|
|
(cdr thing))))
|
|
|
|
nargs)))
|
|
|
|
(use-package-concat
|
|
|
|
(use-package-process-keywords name
|
|
|
|
(use-package-sort-keywords
|
|
|
|
(use-package-plist-maybe-put rest :defer t))
|
|
|
|
(use-package-plist-append state :commands commands))
|
|
|
|
`((ignore ,@form))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2017-06-15 20:44:11 +02:00
|
|
|
(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
|
|
|
|
|
|
|
|
(defun use-package-handler/:interpreter (name keyword arg rest state)
|
|
|
|
(use-package-handle-mode name 'interpreter-mode-alist arg rest state))
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :mode
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:mode (name keyword arg rest state)
|
2017-06-15 20:44:11 +02:00
|
|
|
(use-package-handle-mode name 'auto-mode-alist arg rest state))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; :magic
|
|
|
|
;;
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:magic 'use-package-normalize-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)
|
|
|
|
|
|
|
|
(defun use-package-handler/:magic-fallback (name keyword arg rest state)
|
|
|
|
(use-package-handle-mode name 'magic-fallback-mode-alist arg rest state))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :commands
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2015-03-19 22:26:53 -05:00
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:commands (name keyword arg rest state)
|
2015-03-21 02:57:18 -05:00
|
|
|
;; The actual processing for commands is done in :defer
|
2015-06-17 13:33:09 -04:00
|
|
|
(use-package-process-keywords name
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-sort-keywords
|
|
|
|
(use-package-plist-maybe-put rest :defer t))
|
|
|
|
(use-package-plist-append state :commands arg)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :defines
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:defines (name keyword arg rest state)
|
2017-12-01 01:04:52 -08:00
|
|
|
(use-package-process-keywords name rest state))
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :functions
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:functions (name keyword arg rest state)
|
2017-12-01 01:04:52 -08:00
|
|
|
(use-package-process-keywords name rest state))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :defer
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2015-03-19 22:26:53 -05:00
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:defer 'use-package-normalize-predicate)
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:defer (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest
|
2015-03-21 02:57:18 -05:00
|
|
|
(plist-put state :deferred t)))
|
2015-06-17 13:33:09 -04:00
|
|
|
(name-string (use-package-as-string name)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
|
|
|
;; Load the package after a set amount of idle time, if the argument to
|
|
|
|
;; `:defer' was a number.
|
|
|
|
(when (numberp arg)
|
2017-11-29 14:41:12 -08:00
|
|
|
`((run-with-idle-timer ,arg nil #'require
|
|
|
|
',(use-package-as-symbol name) nil t)))
|
2015-03-21 02:57:18 -05:00
|
|
|
;; Since we deferring load, establish any necessary autoloads, and also
|
|
|
|
;; keep the byte-compiler happy.
|
2017-11-29 14:41:12 -08:00
|
|
|
(cl-mapcan
|
|
|
|
#'(lambda (command)
|
|
|
|
(when (symbolp command)
|
|
|
|
(append
|
|
|
|
`((unless (fboundp ',command)
|
2017-12-01 11:42:40 -08:00
|
|
|
(autoload #',command ,name-string nil t)))
|
2017-11-29 14:41:12 -08:00
|
|
|
(when (bound-and-true-p byte-compile-current-file)
|
|
|
|
`((eval-when-compile
|
|
|
|
(declare-function ,command ,name-string)))))))
|
|
|
|
(delete-dups (plist-get state :commands)))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
body)))
|
|
|
|
|
2015-11-04 22:45:37 +00:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :after
|
2015-11-04 22:45:37 +00:00
|
|
|
;;
|
|
|
|
|
2017-02-16 13:48:05 -08:00
|
|
|
(defalias 'use-package-normalize/:after 'use-package-normalize-recursive-symlist)
|
2015-11-04 22:45:37 +00:00
|
|
|
|
2017-11-29 14:41:12 -08:00
|
|
|
(defun use-package-require-after-load (features)
|
2015-11-04 22:45:37 +00:00
|
|
|
"Return form for after any of FEATURES require NAME."
|
2017-02-16 13:48:05 -08:00
|
|
|
(pcase features
|
2017-11-29 14:41:12 -08:00
|
|
|
((and (pred use-package--non-nil-symbolp) feat)
|
2017-02-16 13:48:05 -08:00
|
|
|
`(lambda (body)
|
|
|
|
(list 'eval-after-load (list 'quote ',feat)
|
|
|
|
(list 'quote body))))
|
|
|
|
(`(,(or :or :any) . ,rest)
|
|
|
|
`(lambda (body)
|
|
|
|
(append (list 'progn)
|
|
|
|
(mapcar (lambda (form)
|
|
|
|
(funcall form body))
|
|
|
|
(list ,@(use-package-require-after-load rest))))))
|
|
|
|
(`(,(or :and :all) . ,rest)
|
|
|
|
`(lambda (body)
|
|
|
|
(let ((result body))
|
|
|
|
(dolist (form (list ,@(use-package-require-after-load rest)))
|
|
|
|
(setq result (funcall form result)))
|
|
|
|
result)))
|
|
|
|
(`(,feat . ,rest)
|
|
|
|
(if rest
|
|
|
|
(cons (use-package-require-after-load feat)
|
|
|
|
(use-package-require-after-load rest))
|
|
|
|
(list (use-package-require-after-load feat))))))
|
2015-11-04 22:45:37 +00:00
|
|
|
|
|
|
|
(defun use-package-handler/:after (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest
|
|
|
|
(plist-put state :deferred t)))
|
|
|
|
(name-string (use-package-as-string name)))
|
2017-02-16 13:48:05 -08:00
|
|
|
(if (and (consp arg)
|
|
|
|
(not (memq (car arg) '(:or :any :and :all))))
|
|
|
|
(setq arg (cons :all arg)))
|
2015-11-04 22:45:37 +00:00
|
|
|
(use-package-concat
|
|
|
|
(when arg
|
2017-12-01 11:42:40 -08:00
|
|
|
(list (funcall
|
|
|
|
(use-package-require-after-load arg)
|
|
|
|
(macroexp-progn
|
|
|
|
`((require (quote ,name) nil t))))))
|
2015-11-04 22:45:37 +00:00
|
|
|
body)))
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :demand
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
(defalias 'use-package-normalize/:demand 'use-package-normalize-predicate)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:demand (name keyword arg rest state)
|
|
|
|
(use-package-process-keywords name rest
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-plist-delete state :deferred)))
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :init
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(defalias 'use-package-normalize/:init 'use-package-normalize-forms)
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:init (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
|
|
|
;; The user's initializations
|
2016-02-25 17:24:59 -08:00
|
|
|
(let ((init-body
|
|
|
|
(use-package-hook-injector (use-package-as-string name)
|
|
|
|
:init arg)))
|
|
|
|
(if use-package-check-before-init
|
|
|
|
`((if (locate-library ,(use-package-as-string name))
|
|
|
|
,(macroexp-progn init-body)))
|
|
|
|
init-body))
|
2015-03-21 02:57:18 -05:00
|
|
|
body)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :config
|
2015-03-21 02:57:18 -05:00
|
|
|
;;
|
|
|
|
|
|
|
|
(defalias 'use-package-normalize/:config 'use-package-normalize-forms)
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(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))
|
2015-03-21 02:57:18 -05:00
|
|
|
(config-body
|
|
|
|
(if (equal arg '(t))
|
|
|
|
body
|
|
|
|
(use-package--with-elapsed-timer
|
|
|
|
(format "Configuring package %s" name-symbol)
|
|
|
|
(use-package-concat
|
|
|
|
(use-package-hook-injector (symbol-name name-symbol)
|
|
|
|
:config arg)
|
|
|
|
body
|
|
|
|
(list t))))))
|
|
|
|
(if (plist-get state :deferred)
|
2015-03-21 03:49:08 -05:00
|
|
|
(unless (or (null config-body) (equal config-body '(t)))
|
2015-06-17 13:33:09 -04:00
|
|
|
`((eval-after-load ,(if (symbolp name) `',name name)
|
2015-03-21 02:57:18 -05:00
|
|
|
',(macroexp-progn config-body))))
|
2017-11-30 20:35:29 -08:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package--with-elapsed-timer
|
2015-06-17 13:33:09 -04:00
|
|
|
(format "Loading package %s" name)
|
2015-03-21 02:57:18 -05:00
|
|
|
(if use-package-expand-minimally
|
|
|
|
(use-package-concat
|
2017-11-30 21:45:17 -08:00
|
|
|
(unless (plist-get state ':no-require)
|
|
|
|
(list (use-package-load-name name)))
|
2015-03-21 02:57:18 -05:00
|
|
|
config-body)
|
2017-11-30 21:45:17 -08:00
|
|
|
(if (plist-get state ':no-require)
|
|
|
|
config-body
|
|
|
|
`((if (not ,(use-package-load-name name t))
|
|
|
|
(ignore
|
|
|
|
(message (format "Cannot load %s" ',name)))
|
|
|
|
,@config-body))))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
2017-11-28 13:58:38 -08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; :hook
|
|
|
|
;;
|
|
|
|
|
|
|
|
(defun use-package-normalize/:hook (name keyword args)
|
|
|
|
(use-package-as-one (symbol-name keyword) args
|
|
|
|
(lambda (label arg)
|
2017-11-29 14:41:12 -08:00
|
|
|
(unless (or (use-package--non-nil-symbolp arg) (consp arg))
|
2017-11-28 13:58:38 -08:00
|
|
|
(use-package-error
|
2017-11-28 14:16:13 -08:00
|
|
|
(concat label " a <symbol> or (<symbol or list of symbols> . <symbol or function>)"
|
2017-11-28 13:58:38 -08:00
|
|
|
" or list of these")))
|
|
|
|
(use-package-normalize-pairs
|
|
|
|
#'(lambda (k)
|
2017-11-29 14:41:12 -08:00
|
|
|
(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
|
2017-11-28 13:58:38 -08:00
|
|
|
name label arg))))
|
|
|
|
|
|
|
|
(defun use-package-handler/:hook (name keyword args rest state)
|
|
|
|
"Generate use-package custom keyword code."
|
2017-11-29 14:41:12 -08:00
|
|
|
(cl-destructuring-bind (nargs . commands)
|
|
|
|
(use-package--normalize-commands args)
|
2017-11-28 13:58:38 -08:00
|
|
|
(use-package-concat
|
|
|
|
(use-package-process-keywords name
|
|
|
|
(if commands
|
|
|
|
(use-package-sort-keywords
|
|
|
|
(use-package-plist-maybe-put rest :defer t))
|
|
|
|
rest)
|
|
|
|
(if commands
|
|
|
|
(use-package-plist-append state :commands commands)
|
|
|
|
state))
|
|
|
|
(cl-mapcan
|
|
|
|
(lambda (def)
|
|
|
|
(let ((syms (car def))
|
|
|
|
(fun (cdr def)))
|
2017-11-29 21:43:52 -08:00
|
|
|
(when fun
|
|
|
|
(mapcar
|
|
|
|
#'(lambda (sym)
|
|
|
|
`(add-hook (quote ,(intern (format "%s-hook" sym)))
|
|
|
|
(function ,fun)))
|
|
|
|
(if (use-package--non-nil-symbolp syms) (list syms) syms)))))
|
2017-11-29 14:41:12 -08:00
|
|
|
nargs))))
|
2017-11-28 13:58:38 -08:00
|
|
|
|
2017-10-17 19:35:19 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; :custom
|
|
|
|
;;
|
|
|
|
|
2017-11-28 14:16:13 -08:00
|
|
|
(defun use-package-normalize/:custom (name keyword args)
|
2017-10-17 19:35:19 +02:00
|
|
|
"Normalize use-package custom keyword."
|
2017-11-28 14:16:13 -08:00
|
|
|
(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")))
|
2017-11-29 14:41:12 -08:00
|
|
|
(if (use-package--non-nil-symbolp (car arg))
|
2017-11-28 14:39:59 -08:00
|
|
|
(list arg)
|
|
|
|
arg))))
|
2017-10-17 19:35:19 +02:00
|
|
|
|
|
|
|
(defun use-package-handler/:custom (name keyword args rest state)
|
|
|
|
"Generate use-package custom keyword code."
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
|
|
|
(use-package-concat
|
|
|
|
(mapcar (lambda (def)
|
|
|
|
(let ((variable (nth 0 def))
|
|
|
|
(value (nth 1 def))
|
|
|
|
(comment (nth 2 def)))
|
2017-11-28 11:03:47 -08:00
|
|
|
(unless (and comment (stringp comment))
|
2017-10-17 19:35:19 +02:00
|
|
|
(setq comment (format "Customized with use-package %s" name)))
|
|
|
|
`(customize-set-variable (quote ,variable) ,value ,comment)))
|
|
|
|
args)
|
|
|
|
body)))
|
|
|
|
|
2017-10-17 19:40:38 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; :custom-face
|
|
|
|
;;
|
2017-10-17 19:35:19 +02:00
|
|
|
|
2017-10-17 19:40:38 +02:00
|
|
|
(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))
|
|
|
|
(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 arg) 2))
|
|
|
|
(use-package-error error-msg))))))
|
|
|
|
|
|
|
|
(defun use-package-handler/:custom-face (name keyword args rest state)
|
|
|
|
"Generate use-package custom-face keyword code."
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
|
|
|
(use-package-concat
|
|
|
|
(mapcar (lambda (def)
|
|
|
|
`(custom-set-faces (quote ,def)))
|
|
|
|
args)
|
|
|
|
body)))
|
2017-10-17 19:35:19 +02:00
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :diminish
|
|
|
|
;;
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize-diminish (name label arg &optional recursed)
|
2015-03-19 22:26:53 -05:00
|
|
|
"Normalize the arguments to diminish down to a list of one of two forms:
|
|
|
|
SYMBOL
|
|
|
|
(SYMBOL . STRING)"
|
|
|
|
(cond
|
2017-06-14 20:24:01 +02:00
|
|
|
((not arg)
|
|
|
|
(list (use-package-as-mode name)))
|
2017-11-29 14:41:12 -08:00
|
|
|
((use-package--non-nil-symbolp arg)
|
2015-03-19 22:26:53 -05:00
|
|
|
(list arg))
|
2015-03-14 05:22:43 -05:00
|
|
|
((stringp arg)
|
2017-06-14 20:24:01 +02:00
|
|
|
(list (cons (use-package-as-mode name) arg)))
|
2015-03-19 22:26:53 -05:00
|
|
|
((and (consp arg) (stringp (cdr arg)))
|
|
|
|
(list arg))
|
2015-03-14 05:22:43 -05:00
|
|
|
((and (not recursed) (listp arg) (listp (cdr arg)))
|
2015-03-19 22:26:53 -05:00
|
|
|
(mapcar #'(lambda (x) (car (use-package-normalize-diminish
|
2017-11-29 14:41:12 -08:00
|
|
|
name label x t))) arg))
|
2015-03-14 05:22:43 -05:00
|
|
|
(t
|
|
|
|
(use-package-error
|
2015-03-19 22:26:53 -05:00
|
|
|
(concat label " wants a string, symbol, "
|
|
|
|
"(symbol . string) or list of these")))))
|
2015-03-14 05:22:43 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize/:diminish (name keyword args)
|
2015-03-19 22:26:53 -05:00
|
|
|
(use-package-as-one (symbol-name keyword) args
|
2017-11-28 16:27:09 -08:00
|
|
|
(apply-partially #'use-package-normalize-diminish name) t))
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:diminish (name keyword arg rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 02:57:18 -05:00
|
|
|
(use-package-concat
|
|
|
|
(mapcar #'(lambda (var)
|
2015-03-24 21:59:10 -05:00
|
|
|
`(if (fboundp 'diminish)
|
|
|
|
,(if (consp var)
|
|
|
|
`(diminish ',(car var) ,(cdr var))
|
|
|
|
`(diminish ',var))))
|
2015-03-21 02:57:18 -05:00
|
|
|
arg)
|
|
|
|
body)))
|
2015-03-19 22:26:53 -05:00
|
|
|
|
2015-03-21 23:35:58 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; :delight
|
2015-03-21 23:35:58 -05:00
|
|
|
;;
|
|
|
|
|
2017-07-02 16:20:01 +02:00
|
|
|
(defun use-package--normalize-delight-1 (name args)
|
|
|
|
"Normalize ARGS for a single call to `delight'."
|
|
|
|
(when (eq :eval (car args))
|
|
|
|
;; Handle likely common mistake.
|
|
|
|
(use-package-error ":delight mode line constructs must be quoted"))
|
2017-11-29 14:41:12 -08:00
|
|
|
(cond ((and (= (length args) 1)
|
|
|
|
(use-package--non-nil-symbolp (car args)))
|
2017-07-02 16:20:01 +02:00
|
|
|
`(,(nth 0 args) nil ,name))
|
|
|
|
((= (length args) 2)
|
|
|
|
`(,(nth 0 args) ,(nth 1 args) ,name))
|
|
|
|
((= (length args) 3)
|
|
|
|
args)
|
|
|
|
(t
|
|
|
|
(use-package-error
|
|
|
|
":delight expects `delight' arguments or a list of them"))))
|
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-normalize/:delight (name keyword args)
|
2015-03-21 23:35:58 -05:00
|
|
|
"Normalize arguments to delight."
|
2017-07-02 16:20:01 +02:00
|
|
|
(cond ((null args)
|
|
|
|
`((,(use-package-as-mode name) nil ,name)))
|
|
|
|
((and (= (length args) 1)
|
2017-11-29 14:41:12 -08:00
|
|
|
(use-package--non-nil-symbolp (car args)))
|
2017-07-02 16:20:01 +02:00
|
|
|
`((,(car args) nil ,name)))
|
|
|
|
((and (= (length args) 1)
|
2017-07-02 17:45:26 +02:00
|
|
|
(stringp (car args)))
|
2017-07-02 16:20:01 +02:00
|
|
|
`((,(use-package-as-mode name) ,(car args) ,name)))
|
2017-07-02 17:45:26 +02:00
|
|
|
((and (= (length args) 1)
|
|
|
|
(listp (car args))
|
|
|
|
(eq 'quote (caar args)))
|
|
|
|
`((,(use-package-as-mode name) ,@(cdar args) ,name)))
|
|
|
|
((and (= (length args) 2)
|
|
|
|
(listp (nth 1 args))
|
|
|
|
(eq 'quote (car (nth 1 args))))
|
|
|
|
`((,(car args) ,@(cdr (nth 1 args)) ,name)))
|
2017-07-02 16:20:01 +02:00
|
|
|
(t (mapcar
|
|
|
|
(apply-partially #'use-package--normalize-delight-1 name)
|
2017-11-29 14:41:12 -08:00
|
|
|
(if (use-package--non-nil-symbolp (car args))
|
|
|
|
(list args)
|
|
|
|
args)))))
|
2015-03-21 23:35:58 -05:00
|
|
|
|
2015-06-17 13:33:09 -04:00
|
|
|
(defun use-package-handler/:delight (name keyword args rest state)
|
|
|
|
(let ((body (use-package-process-keywords name rest state)))
|
2015-03-21 23:35:58 -05:00
|
|
|
(use-package-concat
|
|
|
|
body
|
2017-11-28 20:26:34 -08:00
|
|
|
`((if (fboundp 'delight)
|
|
|
|
(delight '(,@args)))))))
|
2015-03-21 23:35:58 -05:00
|
|
|
|
2015-03-19 22:26:53 -05:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
2016-12-17 15:26:15 +01:00
|
|
|
;;; The main macro
|
2015-03-19 22:26:53 -05:00
|
|
|
;;
|
2015-03-14 05:22:43 -05:00
|
|
|
|
2016-02-06 14:55:35 -05:00
|
|
|
;;;###autoload
|
2015-03-14 05:22:43 -05:00
|
|
|
(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]]...)
|
|
|
|
|
2017-06-15 20:44:11 +02:00
|
|
|
: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.
|
|
|
|
|
|
|
|
: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',
|
|
|
|
`: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 Defer loading of a package until after any of the named
|
|
|
|
features are loaded.
|
|
|
|
:demand Prevent deferred loading in all cases.
|
|
|
|
|
|
|
|
: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).
|
2017-07-09 22:23:38 +02:00
|
|
|
:delight Support for delight.el (if installed).
|
2017-10-17 19:35:19 +02:00
|
|
|
:custom Call `customize-set-variable' with each variable definition.
|
2017-10-17 19:40:38 +02:00
|
|
|
:custom-face Call `customize-set-faces' with each face definition.
|
2017-06-15 20:44:11 +02:00
|
|
|
:ensure Loads the package using package.el if necessary.
|
|
|
|
:pin Pin the package to an archive."
|
2015-03-14 05:22:43 -05:00
|
|
|
(declare (indent 1))
|
|
|
|
(unless (member :disabled args)
|
2017-02-13 12:48:24 -08:00
|
|
|
(let ((name-symbol (if (stringp name) (intern name) name))
|
2017-11-30 12:38:13 -08:00
|
|
|
(orig-args args)
|
2017-02-13 12:48:24 -08:00
|
|
|
(args (use-package-normalize-plist name args)))
|
2017-02-13 12:48:48 -08:00
|
|
|
(dolist (spec use-package-defaults)
|
2017-12-01 00:44:49 -08:00
|
|
|
(setq args (if (eval (nth 2 spec))
|
|
|
|
(use-package-plist-maybe-put
|
|
|
|
args (nth 0 spec) (eval (nth 1 spec)))
|
|
|
|
args)))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
;; When byte-compiling, pre-load the package so all its symbols are in
|
|
|
|
;; scope.
|
|
|
|
(if (bound-and-true-p byte-compile-current-file)
|
2017-02-13 12:48:24 -08:00
|
|
|
(setq args
|
2017-12-01 01:04:52 -08:00
|
|
|
(use-package-plist-append
|
2017-02-13 12:48:24 -08:00
|
|
|
args :preface
|
2017-12-01 01:04:52 -08:00
|
|
|
(use-package-concat
|
|
|
|
(mapcar #'(lambda (var) `(defvar ,var))
|
|
|
|
(plist-get args :defines))
|
|
|
|
(mapcar #'(lambda (fn) `(declare-function
|
|
|
|
,fn ,(use-package-as-string name)))
|
|
|
|
(plist-get args :functions))
|
|
|
|
`((eval-when-compile
|
|
|
|
(with-demoted-errors
|
|
|
|
,(format "Cannot load %s: %%S" name)
|
|
|
|
,(if (eq use-package-verbose 'debug)
|
|
|
|
`(message "Compiling package %s" ',name-symbol))
|
|
|
|
,(unless (plist-get args :no-require)
|
|
|
|
`(load ,(if (stringp name)
|
|
|
|
name
|
|
|
|
(symbol-name name)) nil t)))))))))
|
2015-03-21 02:57:18 -05:00
|
|
|
|
|
|
|
(let ((body
|
2017-12-01 10:23:06 -08:00
|
|
|
`(progn
|
|
|
|
,@(use-package-process-keywords name
|
|
|
|
(let ((args*
|
|
|
|
(use-package-sort-keywords
|
|
|
|
(if (and use-package-always-demand
|
|
|
|
(not (memq :defer args)))
|
|
|
|
(plist-put args :demand t)
|
|
|
|
args))))
|
2017-12-01 11:30:11 -08:00
|
|
|
;; The :demand keyword should not override :after
|
|
|
|
(if (and (plist-member args* :after)
|
|
|
|
(plist-member args* :demand))
|
|
|
|
(setq args* (use-package-plist-delete args* :demand)))
|
2017-12-01 10:23:06 -08:00
|
|
|
(when (and use-package-always-ensure
|
|
|
|
(plist-member args* :load-path)
|
|
|
|
(not (plist-member orig-args :ensure)))
|
|
|
|
(plist-put args* :ensure nil))
|
|
|
|
(unless (plist-member args* :init)
|
|
|
|
(plist-put args* :init nil))
|
|
|
|
(unless (plist-member args* :config)
|
|
|
|
(plist-put args* :config '(t)))
|
|
|
|
args*)
|
|
|
|
(and use-package-always-defer
|
|
|
|
(list :deferred t))))))
|
2017-11-28 11:41:41 -08:00
|
|
|
(when use-package-debug
|
|
|
|
(display-buffer
|
|
|
|
(save-current-buffer
|
|
|
|
(with-current-buffer (get-buffer-create "*use-package*")
|
|
|
|
(goto-char (point-max))
|
|
|
|
(emacs-lisp-mode)
|
|
|
|
(insert (pp-to-string body))
|
|
|
|
(current-buffer)))))
|
2015-03-21 02:57:18 -05:00
|
|
|
body))))
|
2014-12-18 04:34:49 +08:00
|
|
|
|
|
|
|
|
2015-03-21 02:57:18 -05:00
|
|
|
(put 'use-package 'lisp-indent-function 'defun)
|
2012-12-31 17:58:45 +01:00
|
|
|
|
2012-06-17 04:40:25 -05:00
|
|
|
(provide 'use-package)
|
2015-03-13 03:13:31 -05:00
|
|
|
|
2013-04-27 17:04:47 +02:00
|
|
|
;; Local Variables:
|
2016-12-17 15:26:15 +01:00
|
|
|
;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
|
2013-04-27 17:04:47 +02:00
|
|
|
;; indent-tabs-mode: nil
|
|
|
|
;; End:
|
2015-03-13 03:13:31 -05:00
|
|
|
|
2012-06-17 04:40:25 -05:00
|
|
|
;;; use-package.el ends here
|