summaryrefslogtreecommitdiff
path: root/lisp/use-package/use-package.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/use-package/use-package.el')
-rw-r--r--lisp/use-package/use-package.el190
1 files changed, 129 insertions, 61 deletions
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
index f99a3767777..b20d149cb86 100644
--- a/lisp/use-package/use-package.el
+++ b/lisp/use-package/use-package.el
@@ -47,6 +47,7 @@
(eval-when-compile (require 'regexp-opt))
(declare-function package-installed-p "package")
+(declare-function package-read-all-archive-contents "package" ())
(defgroup use-package nil
"A use-package declaration for simplifying your `.emacs'."
@@ -79,6 +80,11 @@ The check is performed by looking for the module using `locate-library'."
:type 'boolean
:group 'use-package)
+(defcustom use-package-always-demand nil
+ "If non-nil, assume `:demand t` unless `:defer t` is given."
+ :type 'boolean
+ :group 'use-package)
+
(defcustom use-package-always-ensure nil
"Treat every package as though it had specified `:ensure SEXP`."
:type 'sexp
@@ -125,6 +131,7 @@ the user specified."
(defcustom use-package-keywords
'(:disabled
+ :preface
:pin
:ensure
:if
@@ -132,7 +139,6 @@ the user specified."
:unless
:requires
:load-path
- :preface
:no-require
:bind
:bind*
@@ -176,24 +182,87 @@ Must be set before loading use-package."
:type 'boolean
:group 'use-package)
+(defcustom use-package-ensure-function 'use-package-ensure-elpa
+ "Function that ensures a package is installed.
+This function is called with one argument, the package name as a
+symbol, by the `:ensure' keyword.
+
+The default value uses package.el to install the package."
+ :type '(choice (const :tag "package.el" use-package-ensure-elpa)
+ (function :tag "Custom"))
+ :group 'use-package)
+
+(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)))
+
(when use-package-enable-imenu-support
- ;; Not defined in Emacs 24
- (defvar lisp-mode-symbol-regexp
- "\\(?:\\sw\\|\\s_\\|\\\\.\\)+")
- (add-to-list
- 'lisp-imenu-generic-expression
- (list "Package"
- (purecopy (concat "^\\s-*("
- (eval-when-compile
- (regexp-opt
- '("use-package" "require")
- t))
- "\\s-+\\(" lisp-mode-symbol-regexp "\\)"))
- 2)))
+ (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)))))
+
+(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
+function will jump to the file that orginally required PACKAGE
+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))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; Utility functions
+;;; Utility functions
;;
(defun use-package-as-symbol (string-or-symbol)
@@ -350,12 +419,12 @@ This is in contrast to merely setting it to 0."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; Keyword processing
+;;; Keyword processing
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; Normalization functions
+;;; Normalization functions
;;
(defun use-package-normalize-plist (name input)
@@ -413,7 +482,7 @@ next value for the STATE."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :pin
+;;; :pin
;;
(defun use-package-only-one (label args f)
@@ -483,7 +552,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :ensure
+;;; :ensure
;;
(defvar package-archive-contents)
(defun use-package-normalize/:ensure (name keyword args)
@@ -498,6 +567,7 @@ manually updated package."
"(an unquoted symbol name)")))))))
(defun use-package-ensure-elpa (package &optional no-refresh)
+ (require 'package)
(if (package-installed-p package)
t
(if (and (not no-refresh)
@@ -512,9 +582,8 @@ manually updated package."
(defun use-package-handler/:ensure (name keyword ensure rest state)
(let* ((body (use-package-process-keywords name rest state))
(package-name (or (and (eq ensure t) (use-package-as-symbol name)) ensure))
- (ensure-form (if package-name
- `(progn (require 'package)
- (use-package-ensure-elpa ',package-name)))))
+ (ensure-form (when package-name
+ `(,use-package-ensure-function ',package-name))))
;; We want to avoid installing packages when the `use-package'
;; macro is being macro-expanded by elisp completion (see
;; `lisp--local-variables'), but still do install packages when
@@ -526,7 +595,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :if, :when and :unless
+;;; :if, :when and :unless
;;
(defsubst use-package-normalize-value (label arg)
@@ -557,7 +626,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :requires
+;;; :requires
;;
(defun use-package-as-one (label args f)
@@ -600,7 +669,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :load-path
+;;; :load-path
;;
(defun use-package-normalize-paths (label arg &optional recursed)
@@ -634,7 +703,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :no-require
+;;; :no-require
;;
(defun use-package-normalize-predicate (name keyword args)
@@ -651,7 +720,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :preface
+;;; :preface
;;
(defun use-package-normalize-form (label args)
@@ -678,7 +747,7 @@ manually updated package."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :bind, :bind*
+;;; :bind, :bind*
;;
(defsubst use-package-is-pair (x car-pred cdr-pred)
@@ -744,7 +813,7 @@ If RECURSED is non-nil, recurse into sublists."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :bind-keymap, :bind-keymap*
+;;; :bind-keymap, :bind-keymap*
;;
(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
@@ -801,7 +870,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :interpreter
+;;; :interpreter
;;
(defun use-package-normalize-mode (name keyword args)
@@ -826,7 +895,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :mode
+;;; :mode
;;
(defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
@@ -845,7 +914,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :commands
+;;; :commands
;;
(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
@@ -859,7 +928,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :defines
+;;; :defines
;;
(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
@@ -870,7 +939,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :functions
+;;; :functions
;;
(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
@@ -889,7 +958,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :defer
+;;; :defer
;;
(defalias 'use-package-normalize/:defer 'use-package-normalize-predicate)
@@ -923,7 +992,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :after
+;;; :after
;;
(defalias 'use-package-normalize/:after 'use-package-normalize-symlist)
@@ -949,7 +1018,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :demand
+;;; :demand
;;
(defalias 'use-package-normalize/:demand 'use-package-normalize-predicate)
@@ -960,7 +1029,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :init
+;;; :init
;;
(defalias 'use-package-normalize/:init 'use-package-normalize-forms)
@@ -980,7 +1049,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :config
+;;; :config
;;
(defalias 'use-package-normalize/:config 'use-package-normalize-forms)
@@ -1015,7 +1084,8 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :diminish
+;;; :diminish
+;;
(defun use-package-normalize-diminish (name label arg &optional recursed)
"Normalize the arguments to diminish down to a list of one of two forms:
@@ -1053,7 +1123,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; :delight
+;;; :delight
;;
(defun use-package-normalize/:delight (name keyword args)
@@ -1079,7 +1149,7 @@ deferred until the prefix key sequence is pressed."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; The main macro
+;;; The main macro
;;
;;;###autoload
@@ -1135,40 +1205,37 @@ this file. Usage:
:pin Pin the package to an archive."
(declare (indent 1))
(unless (member :disabled args)
- (let* ((name-symbol (if (stringp name) (intern name) name))
- (args0 (use-package-plist-maybe-put
- (use-package-normalize-plist name args)
- :config '(t)))
- (args* (use-package-sort-keywords
- (if use-package-always-ensure
- (use-package-plist-maybe-put
- args0 :ensure use-package-always-ensure)
- args0)))
- (args* (use-package-sort-keywords
- (if use-package-always-pin
- (use-package-plist-maybe-put
- args* :pin use-package-always-pin)
- args*))))
+ (let ((name-symbol (if (stringp name) (intern name) name))
+ (args (use-package-normalize-plist name args)))
+ (dolist (spec use-package-defaults)
+ (setq args (use-package-sort-keywords
+ (if (eval (nth 2 spec))
+ (use-package-plist-maybe-put
+ args (nth 0 spec) (eval (nth 1 spec)))
+ args))))
;; When byte-compiling, pre-load the package so all its symbols are in
;; scope.
(if (bound-and-true-p byte-compile-current-file)
- (setq args*
+ (setq args
(use-package-plist-cons
- args* :preface
+ args :preface
`(eval-when-compile
,@(mapcar #'(lambda (var) `(defvar ,var))
- (plist-get args* :defines))
+ (plist-get args :defines))
(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)
+ ,(unless (plist-get args :no-require)
(use-package-load-name name)))))))
(let ((body
(macroexp-progn
- (use-package-process-keywords name args*
+ (use-package-process-keywords name
+ (if use-package-always-demand
+ (append args '(:demand t))
+ args)
(and use-package-always-defer (list :deferred t))))))
(if use-package-debug
(display-buffer
@@ -1187,6 +1254,7 @@ this file. Usage:
(provide 'use-package)
;; Local Variables:
+;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
;; indent-tabs-mode: nil
;; End: