Closed CyberShadow closed 6 months ago
use-package is a macro, so it's arguments aren't evaluated.
You could use eval
to do something like:
(eval `(use-package example :straight ,(your condition here)) t)
That means I would have to wrap all my use-package
invocations in eval
. Is there a better way?
You could write a macro which expands to the appropriate use-package declaration. That's not really straight.el specific, though.
Would it make sense for straight to recognize a special form, such as (eval ...)
, which would allow something like that without something as radical as wrapping the entire use-package
invocation in a custom macro?
You could write a macro which expands to the appropriate use-package declaration. That's not really straight.el specific, though.
Here it is:
;; https://github.com/radian-software/straight.el/issues/1142
(defmacro cs/use-package (&rest forms)
"A wrapper around `use-package' which allows using , to
evaluate Lisp expressions anywhere."
(declare (indent defun))
(let* (visit ; silence byte-compiler
(visit (lambda (form)
(cond
((and (consp form)
(consp (cdr form))
(null (cddr form)) ; two-element list
(eq (car form) '\`))
form)
((and (consp form)
(consp (cdr form))
(null (cddr form)) ; two-element list
(eq (car form) '\,))
(eval (cadr form)))
((consp form)
(cons (funcall visit (car form))
(funcall visit (cdr form))))
(t
form)))))
`(use-package ,@(funcall visit forms))))
Using ,
(while not in a `
) will now make it evaluate the expression, as if the entire call was wrapped in a `( ... )
.
It still doesn't seem right to me that this should be necessary. If I can't put a boolean expression somewhere where t
is accepted, I think something has gone very wrong - though, I don't know if the problem lies with straight.el or use-package.
Here it is:
Here's a modified version which should (untested) work the same.
(defun cs/visit (form)
(cond
((memq (car-safe form) '(quote \,)) (eval (cadr form)))
((consp form) (cons (cs/visit (car form)) (cs/visit (cdr form))))
(t form)))
(defmacro cs/use-package (&rest forms)
"A wrapper around `use-package' which allows using , to
evaluate Lisp expressions anywhere."
(declare (indent defun))
`(use-package ,@(cs/visit forms)))
If I can't put a boolean expression somewhere where t is accepted, I think something has gone very wrong - though, I don't know if the problem lies with straight.el or use-package.
Use-package offers a domain specific language with its own syntax rules.
Consider :defer
, :demand
, :ensure
, :no-require
, which also accept boolean values, but not expressions. This was likely a design decision to keep things simple.
It still doesn't seem right to me that this should be necessary.
Use-package's manual mentions a similar use-case to what you're after. See the "Making conditional loading affect :preface and :ensure" section:
https://www.gnu.org/software/emacs/manual/html_node/use-package/Conditional-loading.html
The advice given is to wrap the entire declaration form.
Would it make sense for straight to recognize a special form, such as (eval ...),
I don't think so. This would complicate straight's use-package integration for an uncommon case which can be dealt with outside of straight. Consider that the suggestion would make it impossible to distinguish between a recipe for a package called "eval" and the special form. It would also be an outlier in terms of other use-package keywords mentioned above. Any thoughts on this, @raxod502?
Here's a modified version which should (untested) work the same.
Nice. After posting I realized that the implementation can also be reduced to simply (eval (list '\` (cons 'use-package forms)))
.
Consider
:defer
,:demand
,:ensure
,:no-require
, which also accept boolean values, but not expressions.
Good point; perhaps this is better addressed by a change in use-package
then, not straight
.
Use-package's manual mentions a similar use-case to what you're after.
Thank you. The goal here is not to prevent the package from loading, though; it is to affect where it is loaded from.
Consider that the suggestion would make it impossible to distinguish between a recipe for a package called "eval" and the special form.
Good point.
Not that it is directly related, but I noticed that the use-package manual mentions an :eval
syntax for another integration (delight
).
One universal fix would be to make use-package
interpolate commas appearing at the top level, like the macro we discussed. This would be a purely additive change because commas currently are not valid syntax at the top level. It would not be very discoverable, though.
Vladimir Panteleev @.***> writes:
One universal fix would be to make use-package interpolate commas appearing at the top level, like the macro we discussed. This would be a purely additive change because commas currently are not valid syntax at the top level. It would not be very discoverable, though.
I'm sure the emacs-devel mailing list would be willing to discuss such a change. Give it a shot if you think it's a worthwhile addition to use-package.
Yes, I understand the use case, and I don't have any issue with it - but it should be done in a way that doesn't create complications for normal users. Given the sophistication of Emacs' macro system, I think the suggestion to create a custom macro is a reasonable one given the relative uncommonness of the situation. I do the same in my own configuration, to implement exactly the same conditional mechanism.
Hi, sorry, I couldn't figure out how to do this or if it is even possible.
I would like to do something like the following:
The motivation being that I'm trying to gradually migrate to a setup where some packages are provided via another mechanism (Nix).
Thanks!