-
Notifications
You must be signed in to change notification settings - Fork 259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for deferred installation #433
Conversation
Modify the expected API of `use-package-ensure-function' so that it is passed three arguments: the name of the package declared in the `use-package' form; the argument passed to `:ensure'; and the current `state' plist created by previous handlers. (Previously, it was only given a single argument, which was the argument passed to `:ensure', or the name of the package declared in the `use-package' form, if the former was `t'. This allows for more flexibility in the capabilities of the `use-package-ensure-function' implementation. For example, its behavior can change depending on the values of other keywords, if those keywords modify the `state' plist appropriately.
This new keyword, if provided along with a non-nil value, causes the action of :ensure to be deferred until "necessary". Package installation can be triggered by the user calling the new interactive function `use-package-install-deferred-package', or by the feature declared by the `use-package' form being required. This latter behavior seems to be the simplest way to make sure that package installation actually takes place when it needs to, but it requires that an advice be added to `require', which may be considered overly intrusive. (Also, it's generally considered bad practice for functions in Emacs to put advice on other functions in Emacs.) Thus it may make sense to add an option or function to explicitly enable this behavior, if there does not turn out to be a better way to accomplish deferred installation. Documentation has not been updated to reflect :defer-install yet.
Now it properly reflects the API changes recently made.
This time around, I've gotten rid of the advice on `require' (that was never going to work) and instead made `use-package' try to handle loading the package at the appropriate time. In particular, when deferred installation is active, all the autoloads generated by `use-package' are not regular autoloads, but regular functions that will install the relevant package, require the relevant feature, and only then call the newly defined (autoloaded) function. Some smarter logic has been added to make sure things like `:demand' play nicely with the autoloading system; see the extensive comment in `use-package-handler/:defer-install' for more information on how that works. There was a section in `use-package-install-deferred-package' which referred to a nonexistent variable `use-package--deferred-features'; that has been removed. There is now, in addition to `use-package-ensure-function', a new variable called `use-package-pre-ensure-function'. This is intended for use by package managers which, unlike package.el, activate autoloads package-by-package instead of all at once. Even if a package is marked for deferred installation, the user would likely want its autoloads activated immediately *if* it was already installed. The logic for doing that can now be put in `use-package-pre-ensure-function'.
* A quoting error has been fixed in `use-package-handler/:defer'. * `use-package-install-deferred-package' has been updated to return t if the package was actually installed, and nil otherwise. * The fake autoloads generated during deferred installation are doctored so Emacs does not think they were defined in the user's init-file. * The docstrings of the fake autoloads have been improved. * Arguments and interactivity are now correctly passed to the autoloaded function. * The autoload now skips requiring the feature and calling the original function if the user declines to install the package. This prevents unprofessional errors.
It works! Here is a short demo: https://youtu.be/az5C1nd3fh0. (In case you are wondering about the text that is printed when I install the package, that is from my package manager—but this should work with Usage looks like this:
In theory, specifying I'll be testing this in my own config. Comments and suggestions would be appreciated! |
I've realized that the confirmation prompt needs to be moved out of the I'm currently working on this. |
It appears to be at least mostly working! I have integrated deferred installation with my config, and out of 52 packages only 25 are installed on initial Emacs launch. |
Resolve merge conflicts.
Wow, how did I base this branch on a four-week-old commit? I've fixed the merge conflicts. |
After this merge the
info+ doesn't get loaded anymore. |
That's not good— |
Commit [1] broke the functionality of :after (see [2]) due to an extraneous quote being added. [1]: bf9a73f [2]: jwiegley#433 (comment)
@drot Should be fixed now, it was a silly quoting error. |
Can you please add use-package-always-defer-install as
use-package-always-defer for this feature?
This would be trivial to add via `use-package-defaults`. One thing to note
though, is that autoloads are no longer automatically accessible when the
package is yet to be installed (because obviously if the source code isn't
on your hard drive, there's no way to tell what autoloaded commands the
package provides). Same for `auto-mode-alist`, etc. So you have to set
these by hand (using `:commands`, `:mode`, etc.) if you want to use
deferred installation.
|
Just found out about this through the commit log and I think it's pretty cool! Thanks for taking the initiative to implement it! I was wondering if there's a way to have something like So I guess said another way, assume I was reading through the diff's elisp doc strings but couldn't figure out if this was already possible. If not, is it even possible? Or aside from that, is there a reason why that would be inadvisable? |
@raxod502 It seems that change removed from master now. Is deferred install now possible in another way? |
No, there's no way to achieve this behavior. If the feature were to be reimplemented, it should be done at the package-manager level, in my opinion. The ideal place would be |
[RFC] Support for deferred installation GitHub-reference: jwiegley/use-package#433
Commit [1] broke the functionality of :after (see [2]) due to an extraneous quote being added. [1]: 2b8b608 [2]: jwiegley/use-package#433 (comment)
[RFC] Support for deferred installation GitHub-reference: jwiegley/use-package#433
Commit [1] broke the functionality of :after (see [2]) due to an extraneous quote being added. [1]: bd2afa5 [2]: jwiegley/use-package#433 (comment)
Considering how to address #409. I think that this is not the right
approach to take (esp. because autoloads are handled in the C code and
therefore do not respect the advice on
require
), but I thought Iwould post my progress so far. I think I have an idea about how to
proceed.
NB: The text of this message is severely obsolete. I completely changed the implementation; in particular, there are no advices placed on
require
!