Comments (7)
I would consider your example an anti-pattern:
n in a :config section of the use-package declaration. That way, if some aspect of the foo package's declaration is changed (e.g. the user decides to defer loading it), such "free" forms needn't be tracked down and wrapped in eval-after-load
I see what you mean. I think my example was not specific enough. I'll use my own case as an example.
I use several external libraries (such as dash.el, anaphora, dbc, shut-up) to write my own macros and functions. The macros/functions I write are used pervasively throughout my init file. So pervasively that if I can't assume these libraries are installed I'd have to wrap what is honestly most of my init file in elpaca-use-package
forms. At that point it would probably be better to opt for plan B--using a config.el file as you mention.
So if you configure a package once and don't use its function in other places--which to be fair is probably the case for most packages, then we're good. But if you have custom functions and macros that rely on several packages which are used throughout, this use-package
nesting is not desirable/practical.
Then config.el can assume all packages are installed and activated.
Yes, as I was thinking about this I thought that creating another file with your actual config and loading that is the way to do it.
There is also the question of whether there is anything that needs to be done or a user is relying on being done before the after-init-hook
--I imagine for most users there would be nothing, but it is something to keep in mind.
I would reconsider the idea of separating out the installation from the configuration, though.
IMO it will complicate your setup for no tangible benefit
The tangible benefit is that you can freely assume packages are installed (just as you would with built-in packages) as opposed to not being sure and needing to wrap any external package dependent code in an elpaca-use-package
form.
such "free" forms needn't be tracked down and wrapped in eval-after-load
As you alluded to there are obvious benefits with use-package
forms in the sense that if you decide to defer a package--or even remove it entirely--you can do it without breaking anything else. Packages are like puzzle-pieces that can be plugged in/removed in a robust fashion.
But there are also costs to coding this way--namely more boilerplate and a defensive coding style because you can't assume anything is installed yet.
from elpaca.
I think this point should be emphasized more in the readme. It is kind of mentioned in the FAQs, but I don't think it is stated directly enough.
There is an example in the https://github.com/progfolio/elpaca#installing-packages section. I've re-iterated it in the FAQ section.
elpaca provides integration with use-package for this, but still this means--at least from my understanding--that the user would likely have to wrap many "free" forms in elpaca-use-package blocks.
I would consider your example an anti-pattern:
(use-package foo :demand t)
;; can assume that foo is installed and initialized
(foo-message "hi")
In this example, the foo-message
call should happen in a :config
section of the use-package declaration. That way, if some aspect of the foo
package's declaration is changed (e.g. the user decides to defer loading it), such "free" forms needn't be tracked down and wrapped in eval-after-load
(duplicating what use-package's :config
will expand to when the package loading is deferred).
Furthermore, I argue that the user should be able to "circumvent" this if they provide all their recipes via a lockfile. Something like elpaca-bootstrap-from-lockfile which would take a path to the lockfile.
It's not as simple as your example seems:
;; bootstrap-code
(...)
(elpaca-bootstrap-from-lockfile "~/.emacs.d/lockfile") ; processing done immediately since we already have all package recipes
;; can assume everything is setup and don't have to wait until after the `elpaca-after-init-hook`.
(require 'foo)
(foo-message "hi")
elpaca-bootstrap-from-lockfile
would either have to block until all queues are processed (a non-goal of Elpaca) or take a callback which executes the forms below it. That would not be very flexible, because you would have to unwrap those forms if you changed your mind about loading the lockfile.
My current thoughts on the design of the lockfile system is to keep it simple.
Writing a lockfile will essentially create a menu. Each declared package will be associated with a full recipe.
Loading that lockfile will push that menu to elpaca-menu-functions
, so its recipes will take precedence over other recipes. I've yet to implement lockfile reading, so this may change.
If I understand your desired use case correctly, a working setup would look something like this:
init.el:
;;bootstrap omitted
(add-hook 'elpaca-after-init-hook (lambda () (load-file "./config.el")))
(elpaca-load-lockfile "path/to/lockfile")
;; package declarations
(elpaca example-package)
;;etc
Then config.el can assume all packages are installed and activated.
I would reconsider the idea of separating out the installation from the configuration, though.
IMO it will complicate your setup for no tangible benefit (it will actually be slower, though it's impossible to say if that's a meaningful concern without measuring anything).
from elpaca.
There is also the question of whether there is anything that needs to be done or a user is relying on being done before the after-init-hook--I imagine for most users there would be nothing, but it is something to keep in mind.
Good point. I think cases which will not work by moving the execution to elpaca-after-init-hook
will be rare. Noted, though.
But there are also costs to coding this way--namely more boilerplate and a defensive coding style because you can't assume anything is installed yet.
Always a tradeoff. IMO the boilerplate is greatly reduced by macros like use-package, so the benefit far outweighs the cost. Seems like the separate file solution should work for your use-case, though.
Thanks again.
Closing this issue, but feel free to open more if you have any other thoughts on how things can be improved.
from elpaca.
I think this is the issue I have.
I use use-package and have much of my init.el depending on package loaded. As I noted elsewhere I don't see the benefit of async loading as it just breaks things.
My elpaca init.el includes
(elpaca use-package (require 'use-package)) # as per examples
# Then add a use-package keyword
# Keyword setup
# Then I need to alter the keyword list - which fails
(setq use-package-keywords
(cons :mwb-load-path use-package-keywords)
# use-package-keywords is undefined in elpaca but not in straight or package.el
from elpaca.
Try adding it just after your require in the elpaca body. If that doesn't work, please fill out the bug report form describing your issue.
from elpaca.
I'm dealing with similar problems, lot's of packages with functions that i use later on in my init file.
In my config file I define a lot of custom evil-operators and hydras, while it would be possible to wrap all of that inside the use-package block, but that wouldn't play nice with the way i order it in the org file i tangle from.
A possibility would be to start the file with the packages that are used later on, call elpaca-process-queues and add the stuff that depends on something.
Would there be a downside to this approach?
from elpaca.
@Dickby please open a separate support issue and include specific examples of what is giving you trouble. It's hard for me to give advice otherwise.
One piece of generic advice I can give regarding:
but that wouldn't play nice with the way i order it in the org file i tangle from.
If you are tangling, you have access to the noweb syntax, which should allow you to present your init file separately from the order in which it is tangled.
from elpaca.
Related Issues (20)
- [Feature]: Recipe for bootstrapping via `package.el` HOT 1
- [Support]: Use of `:wait` over `(elpaca-wait)`? HOT 6
- [Support]: magit-section and git-commit update fail with magit pinned HOT 3
- [Support]: Org loaded before Elpaca activation HOT 2
- [Support]: (elpaca nil) does not work as shown in the tutorial HOT 5
- [Support]: `flymake-json` elpaca--check-version: (error "Invalid version syntax: βDEVβ (must start with a number)") HOT 3
- [Bug/Support]: elpaca fails to do download dependency of parinfer-rust-mode HOT 16
- [Support] eros-eval-last-sexp, eros-eval-defun do not process elpaca queues HOT 6
- [Bug]: fails to install packages which depend on ignored dependencies HOT 4
- [Support]: How to enforce the use of the (m)elpa package over the builtin HOT 5
- [Bug/Support]: Cannot operate on orphans in elpaca-ui HOT 3
- [BUG] package skipped as pinned package when not pinned HOT 1
- [Support]: Advice on dealing with mono-repos HOT 3
- [Bug]: incorrect load-history library paths when autoloads cached HOT 3
- [Feature]: Build texi/info manuals from README.org HOT 2
- [Bug/Support]: flymake-ruby -> elpaca--check-version: (error "Invalid version syntax: βDEVβ (must start with a number)") HOT 2
- [Bug/Support]: M-x elpaca-version could be easier to use HOT 1
- [Bug/Support]: use-package :ensure keyword does not work as expected HOT 3
- [Bug/Support]: Error installing magit HOT 2
- [Bug/Support]: "Unable to determine repo dir" for lots of repos HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from elpaca.