From af3b34b02294d5c1e23010ad249ce3922a4a474b Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 1 Dec 2017 11:42:40 -0800 Subject: [PATCH] Remove the :defer-install keyword This may reappear as its own add-on to use-package in the future. See https://github.com/jwiegley/use-package/issues/442. --- etc/USE-PACKAGE-NEWS | 3 + lisp/use-package/use-package.el | 264 +++------------------ test/lisp/use-package/use-package-tests.el | 20 +- 3 files changed, 52 insertions(+), 235 deletions(-) diff --git a/etc/USE-PACKAGE-NEWS b/etc/USE-PACKAGE-NEWS index b0265fa5515..06adac97188 100644 --- a/etc/USE-PACKAGE-NEWS +++ b/etc/USE-PACKAGE-NEWS @@ -15,6 +15,9 @@ - Emacs 24.3 or higher is now a requirement. +- The `:defer-install` keyword has been remove. It may reappear as an add-on + module for use-package in a future release. See issue #442 for more details. + ### Other changes - Upgrade license to GPL 3. diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el index 5119e394ebe..ae361de6f6b 100644 --- a/lisp/use-package/use-package.el +++ b/lisp/use-package/use-package.el @@ -88,11 +88,6 @@ The check is performed by looking for the module using `locate-library'." :type 'boolean :group 'use-package) -(defcustom use-package-always-defer-install nil - "If non-nil, assume `:defer-install t` unless `:defer-install nil` 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 @@ -140,7 +135,6 @@ the user specified." (defcustom use-package-keywords '(:disabled :pin - :defer-install :ensure :if :when @@ -200,9 +194,8 @@ Must be set before loading use-package." "Function that ensures a package is installed. This function is called with four arguments: the name of the package declared in the `use-package' form; the argument passed -to `:ensure'; the current `state' plist created by previous -handlers; and a keyword indicating the context in which the -installation is occurring. +to `:ensure'; and the current `state' plist created by previous +handlers. 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 @@ -210,50 +203,14 @@ semantics of the various values for `:ensure'. This function should return non-nil if the package is installed. -The default value uses package.el to install the package. - -Possible values for the context keyword are: - -:byte-compile - package installed during byte-compilation -:ensure - package installed normally by :ensure -:autoload - deferred installation triggered by an autoloaded - function -:after - deferred installation triggered by the loading of a - feature listed in the :after declaration -:config - deferred installation was specified at the same time - as :demand, so the installation was triggered - immediately -:unknown - context not provided - -Note that third-party code can provide other values for the -context keyword by calling `use-package-install-deferred-package' -with the appropriate value." +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-pre-ensure-function 'ignore - "Function that is called upon installation deferral. -It is called immediately with the first three arguments that -would be passed to `use-package-ensure-function' (the context -keyword is omitted), but only if installation has been deferred. -It is intended for package managers other than package.el which -might want to activate the autoloads of a package immediately, if -it's installed, but otherwise defer installation until later (if -`:defer-install' is specified). The reason it is set to `ignore' -by default is that package.el activates the autoloads for all -known packages at initialization time, rather than one by one -when the packages are actually requested." - :type '(choice (const :tag "None" ignore) - (function :tag "Custom")) - :group 'use-package) - (defcustom use-package-defaults '((:config '(t) t) (:ensure use-package-always-ensure use-package-always-ensure) - (:defer-install - use-package-always-defer-install - use-package-always-defer-install) (: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 @@ -639,80 +596,6 @@ manually updated package." (push pin-form body)) ; or else wait until runtime. body)) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; :defer-install -;; - -(defvar use-package--deferred-packages (make-hash-table) - "Hash mapping packages to data about their installation. - -The keys are not actually symbols naming packages, but rather -symbols naming the features which are the names of \"packages\" -required by `use-package' forms. Since -`use-package-ensure-function' could be set to anything, it is -actually impossible for `use-package' to determine what package -is supposed to provide the feature being ensured just based on -the value of `:ensure'. - -Each value is a cons, with the car being the the value passed to -`:ensure' and the cdr being the `state' plist. See -`use-package-install-deferred-package' for information about how -these values are used to call `use-package-ensure-function'.") - -(defun use-package-install-deferred-package (name &optional context) - "Install a package whose installation has been deferred. -NAME should be a symbol naming a package (actually, a feature). -This is done by calling `use-package-ensure-function' is called -with four arguments: the key (NAME) and the two elements of the -cons in `use-package--deferred-packages' (the value passed to -`:ensure', and the `state' plist), and a keyword providing -information about the context in which the installation is -happening. (This defaults to `:unknown' but can be overridden by -providing CONTEXT.) - -Return t if the package is installed, nil otherwise. (This is -determined by the return value of `use-package-ensure-function'.) -If the package is installed, its entry is removed from -`use-package--deferred-packages'. If the package has no entry in -`use-package--deferred-packages', do nothing and return t." - (interactive - (let ((packages nil)) - (maphash (lambda (package info) - (push package packages)) - use-package--deferred-packages) - (if packages - (list - (intern - (completing-read "Select package: " - packages nil 'require-match)) - :interactive) - (user-error "No packages with deferred installation")))) - (let ((spec (gethash name use-package--deferred-packages))) - (if spec - (when (funcall use-package-ensure-function - name (car spec) (cdr spec) - (or context :unknown)) - (remhash name use-package--deferred-packages) - t) - t))) - -(defalias 'use-package-normalize/:defer-install 'use-package-normalize-test) - -(defun use-package-handler/:defer-install (name keyword defer rest state) - (use-package-process-keywords name rest - ;; Just specifying `:defer-install' does not do anything; this - ;; sets up a marker so that if `:ensure' is specified as well then - ;; it knows to set up deferred installation. But then later, when - ;; `:config' is processed, it might turn out that `:demand' was - ;; specified as well, and the deferred installation needs to be - ;; run immediately. For this we need to know if the deferred - ;; installation was actually set up or not, so we need to set one - ;; marker value in `:defer-install', and then change it to a - ;; different value in `:ensure', if the first one is present. (The - ;; first marker is `:defer-install', and the second is `:ensure'.) - (plist-put state :defer-install (when defer :defer-install)))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; :ensure @@ -729,66 +612,45 @@ If the package is installed, its entry is removed from (concat ":ensure wants an optional package name " "(an unquoted symbol name)"))))))) -(defun use-package-ensure-elpa (name ensure state context &optional no-refresh) - (let ((package (or (and (eq ensure t) (use-package-as-symbol name)) - ensure))) +(defun use-package-ensure-elpa (name ensure state &optional no-refresh) + (let ((package + (or (and (eq ensure t) (use-package-as-symbol name)) + ensure))) (when package (require 'package) - (or (package-installed-p package) - ;; Contexts in which the confirmation prompt is bypassed. - (not (or (member context '(:byte-compile :ensure :config)) - (y-or-n-p (format "Install package %S?" package)))) - (condition-case-unless-debug err - (progn + (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) (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) - (when (assoc package (bound-and-true-p - package-pinned-packages)) - (package-read-all-archive-contents)) - (package-install package)) - t) - (error - (ignore - (display-warning 'use-package - (format "Failed to install %s: %s" - name (error-message-string err)) - :error)))))))) + (package-install package)) + t) + (error + (ignore + (display-warning 'use-package + (format "Failed to install %s: %s" + name (error-message-string err)) + :error)))))))) (defun use-package-handler/:ensure (name keyword ensure rest state) - (let* ((body (use-package-process-keywords name rest - ;; Here we are conditionally updating the marker - ;; value for deferred installation; this will be - ;; checked later by `:config'. For more information - ;; see `use-package-handler/:defer-install'. - (if (eq (plist-get state :defer-install) - :defer-install) - (plist-put state :defer-install :ensure) - 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 do install packages when - ;; byte-compiling to avoid requiring `package' at runtime. - (cond - ((plist-get state :defer-install) - (push - `(puthash ',name '(,ensure . ,state) - use-package--deferred-packages) - body) - (push `(,use-package-pre-ensure-function - ',name ',ensure ',state) + (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) body)) - ((bound-and-true-p byte-compile-current-file) - ;; Eval when byte-compiling, - (funcall use-package-ensure-function - name ensure state :byte-compile)) - ;; or else wait until runtime. - (t (push `(,use-package-ensure-function - ',name ',ensure ',state :ensure) - body))) body)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1272,35 +1134,6 @@ representing symbols (that may need to be autloaded)." (defalias 'use-package-normalize/:defer 'use-package-normalize-predicate) -(defun use-package--autoload-with-deferred-install - (command package-name) - "Return a form defining an autoload supporting deferred install." - `(let* ((load-list-item '(defun . ,command)) - (already-loaded (member load-list-item current-load-list))) - (defun ,command (&rest args) - "[Arg list not available until function definition is loaded.] - - \(fn ...)" - (interactive) - (if (bound-and-true-p use-package--recursive-autoload) - (use-package-error - (format "Autoloading failed to define function %S" - ',command)) - (when (use-package-install-deferred-package - ',package-name :autoload) - (require ',package-name) - (let ((use-package--recursive-autoload t)) - (if (called-interactively-p 'any) - (call-interactively ',command) - (apply ',command args)))))) - ;; This prevents the user's init-file from being recorded as the - ;; definition location for the function before it is actually - ;; loaded. (Our goal is to leave the `current-load-list' - ;; unchanged, so we only remove the entry for this function if it - ;; was not already present.) - (unless already-loaded - (setq current-load-list (remove load-list-item current-load-list))))) - (defun use-package-handler/:defer (name keyword arg rest state) (let ((body (use-package-process-keywords name rest (plist-put state :deferred t))) @@ -1318,13 +1151,7 @@ representing symbols (that may need to be autloaded)." (when (symbolp command) (append `((unless (fboundp ',command) - ;; Here we are checking the marker value set in - ;; `use-package-handler/:ensure' to see if deferred - ;; installation is actually happening. See - ;; `use-package-handler/:defer-install' for more information. - ,(if (eq (plist-get state :defer-install) :ensure) - (use-package--autoload-with-deferred-install command name) - `(autoload #',command ,name-string nil t)))) + (autoload #',command ,name-string nil t))) (when (bound-and-true-p byte-compile-current-file) `((eval-when-compile (declare-function ,command ,name-string))))))) @@ -1374,15 +1201,10 @@ representing symbols (that may need to be autloaded)." (setq arg (cons :all arg))) (use-package-concat (when arg - (list (funcall (use-package-require-after-load arg) - (macroexp-progn - ;; Here we are checking the marker value for deferred - ;; installation set in `use-package-handler/:ensure'. - ;; See also `use-package-handler/:defer-install'. - `(,@(when (eq (plist-get state :defer-install) :ensure) - `((use-package-install-deferred-package - 'name :after))) - (require (quote ,name) nil t)))))) + (list (funcall + (use-package-require-after-load arg) + (macroexp-progn + `((require (quote ,name) nil t)))))) body))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1441,12 +1263,6 @@ representing symbols (that may need to be autloaded)." `((eval-after-load ,(if (symbolp name) `',name name) ',(macroexp-progn config-body)))) - ;; Here we are checking the marker value for deferred installation set - ;; in `use-package-handler/:ensure'. See also - ;; `use-package-handler/:defer-install'. - (when (eq (plist-get state :defer-install) :ensure) - (use-package-install-deferred-package name :config)) - (use-package--with-elapsed-timer (format "Loading package %s" name) (if use-package-expand-minimally @@ -1709,10 +1525,8 @@ this file. Usage: `: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. diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el index 64f5ab534d3..60cf2ff7b15 100644 --- a/test/lisp/use-package/use-package-tests.el +++ b/test/lisp/use-package/use-package-tests.el @@ -194,28 +194,28 @@ (match-expansion (use-package foo :ensure t) `(progn - (use-package-ensure-elpa 'foo 't 'nil :ensure) + (use-package-ensure-elpa 'foo 't 'nil) (require 'foo nil 'nil)))) (let ((use-package-always-ensure t)) (match-expansion (use-package foo :ensure t) `(progn - (use-package-ensure-elpa 'foo 't 'nil :ensure) + (use-package-ensure-elpa 'foo 't 'nil) (require 'foo nil 'nil)))) (let ((use-package-always-ensure nil)) (match-expansion (use-package foo :ensure nil) `(progn - (use-package-ensure-elpa 'foo 'nil 'nil :ensure) + (use-package-ensure-elpa 'foo 'nil 'nil) (require 'foo nil 'nil)))) (let ((use-package-always-ensure t)) (match-expansion (use-package foo :ensure nil) `(progn - (use-package-ensure-elpa 'foo 'nil 'nil :ensure) + (use-package-ensure-elpa 'foo 'nil 'nil) (require 'foo nil 'nil)))) (let ((use-package-always-ensure nil)) @@ -230,7 +230,7 @@ (match-expansion (use-package foo :load-path "foo") `(progn - (use-package-ensure-elpa 'foo 'nil 'nil :ensure) + (use-package-ensure-elpa 'foo 'nil 'nil) (eval-and-compile (add-to-list 'load-path ,(pred stringp))) (require 'foo nil 'nil)))) @@ -239,7 +239,7 @@ (match-expansion (use-package foo :ensure nil :load-path "foo") `(progn - (use-package-ensure-elpa 'foo 'nil 'nil :ensure) + (use-package-ensure-elpa 'foo 'nil 'nil) (eval-and-compile (add-to-list 'load-path ,(pred stringp))) (require 'foo nil 'nil)))) @@ -248,7 +248,7 @@ (match-expansion (use-package foo :ensure nil :load-path "foo") `(progn - (use-package-ensure-elpa 'foo 'nil 'nil :ensure) + (use-package-ensure-elpa 'foo 'nil 'nil) (eval-and-compile (add-to-list 'load-path ,(pred stringp))) (require 'foo nil 'nil)))) @@ -257,7 +257,7 @@ (match-expansion (use-package foo :ensure t :load-path "foo") `(progn - (use-package-ensure-elpa 'foo 't 'nil :ensure) + (use-package-ensure-elpa 'foo 't 'nil) (eval-and-compile (add-to-list 'load-path ,(pred stringp))) (require 'foo nil 'nil)))) @@ -266,14 +266,14 @@ (match-expansion (use-package foo :ensure t :load-path "foo") `(progn - (use-package-ensure-elpa 'foo 't 'nil :ensure) + (use-package-ensure-elpa 'foo 't 'nil) (eval-and-compile (add-to-list 'load-path ,(pred stringp))) (require 'foo nil 'nil)))) (let (tried-to-install) (flet ((use-package-ensure-elpa - (name ensure state context &optional no-refresh) + (name ensure state &optional no-refresh) (when ensure (setq tried-to-install name))) (require (&rest ignore))) -- 2.39.2