diff options
Diffstat (limited to 'lisp/use-package/use-package.el')
-rw-r--r-- | lisp/use-package/use-package.el | 190 |
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: |