-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce consult-config for very flexible configuration
Remove many consult-preview-* customizable variables.
- Loading branch information
Showing
3 changed files
with
104 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to spoil the fun something like
consult-config
is certainly nice but doesn't this suffer from the same problems you get with ivy that we talked about on Selectrum side? I often wrap commands or call them within another commands, last time I checked ivy introduced some inheritance mechanism to avoid this but this is much more complicated and also make configuration more complicated than needed, I think.36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which problem? I am using this-command to obtain the configuration. If you wrap a command you can let-bind this-command to avoid issues.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean making it hard to reuse configuration or adjust existing configuration, for example when calling consult commands within other commands.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you wrap a command you can let-bind
this-command
to avoid issues. I think we win a lot of flexibility by doing that and allow configuration of options which are not exposed in other ways. Furthermore it allows me to get rid of many customization variables. I don't see a real downside of having this.Another option we could think of is to add a
consult-local-config
variable which can be let-bound with a plist. This could be used in wrappers. But you can also achieve this by setting the consult-config and this-command accordingly.However this feature is a bit of an expert feature since it relies on private (semi stable) API, but users who write wrappers can handle this, I guess.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can let-bind this-command but then you have the problem that the inner most call tells how the configuration should be. I don't think there is something wrong with this approach ivy does something similar I just don't like the problems I remember I had when fighting with ivy.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. I agree that it is not without problems, but from what I am seeing right now it has many upsides, in particular the additional flexibility and the code reduction of trivial boilerplate. Could you be a bit more concrete regarding the problems you had? Did you write wrappers of wrappers of wrappers? There are also problems if you overwrite options like :predicate, :narrow, :lookup or :preview. This is not a fail safe API and it is not intended to be one.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, I should add - Manipulating this-command is quite common. Many commands depend on checking this-command or last-command to adjust their behavior. This is also very brittle, even more than this I guess.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See here for example, it was always hard to reuse and adapt the configuration of existing commands.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes many commands depend on this-command checks but usually they don't allow extensive configuration through this mechanism. I think if you have many options which vary the behaviour it becomes more important to be able to adjust them according to the need of the current caller.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand. I don't have a :caller argument. I am using
this-command
. So we retain full reusability of the code here. You have to duplicate the config however - but I think this is actually a feature, since by just wrapping a command you make it a separate command which requires a separate config.This would be the idea of adding a
consult-local-config
let bound variable.We can add such a local config variable too if you need that. But I would still keep the global configuration based on this-command.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was just the issue I found, sorry if it did not match the exact use case here but with this-command you have the problem we just talked about which also comes apparent after the first wrapper you wrote around a consult command.
But this still has the problem that you can't wrap
my-wrapper
and reuse/adapt the configuration ofmy-wrapper
and you also can't reuse the existing config ofconsult...
command.36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, there are two reusability problems here: You can reuse the config if you hard code the caller name, but this may impede reuse of the function itself.
But what do you suggest? Do you have an alternative? Since this is a new addition, the alternative would be to remove this feature again and just do nothing. Adding back the boilerplate and losing the flexibility.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only alternative I know of is the approach we sketched for Selectrum. I don't really know what conflict potentials there are because I haven't done much with consult yet if there aren't users which run into problems with this it might also be just fine to use this approach.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which alternative exactly - I got a bit lost? Basically I implemented the configuration version similar to the one I proposed for selectrum, radian-software/selectrum#244.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the local variables minibuffer-with-setup-hook dance :) I'm no suggesting you use it, this is just the only way to cleanly do this I'm currently aware of.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, yes this is basically the variant with
consult-local-config
, I proposed above. We can add this if the need comes up. But I guess I will keep the current version based on this-command too, since it helps me to avoid all those preview customizable variables, which have gotten out of hand. If you don't use it, it won't hurt and if someone uses this way of configuration we can see if some problems come up. Since it is based on unstable API, the stability guarantees regarding this API are less strong, so I could even kick this out again if it turns out to not work well in most cases.36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When all settings would be contained in one variable you can't combine them easily for example when you want to enable
:sort
but reuse the rest. You would need to copy the settings from the old command with:sort
changed. As long as there aren't that many options this is probably not an issue, the demand to adjust some settings probably won't come up as often as with ivy which defines many more UI related settings.36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, just use elisp to manipulate the config. Why do we have elisp after all? I certainly wouldn't copy it by hand. Or do you mean that you want some kind of inheritance mechanism? We could add an :inherit option which performs recursive lookup in the config. But this would add some complexity. Or do you mean that you want the solution you favor in selectrum with the global configuration variables?
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inheritance in the sense that you can reuse a config but override any options one by one.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is reasonably easy to do using the existing seq/list/plist functions. But if the use case comes up we can add helpers to make this easier, or add :inherit.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I understand, you would then query the alist you save configs in and copy the plist to adjust it for the current session?
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I like about using variables is you don't need additional context, you just set the settings you care about and the rest is reused, it is less work for the user.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But for consult it might be overkill, I'm more in the context of ivy/selectrum.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like this.
Yes, I know global variables are comfortable and easy to customize. But I think they have quite a high cost otherwise - Namespace pollution, problematic side effects, they introduce the potentially undesired possibility to bypass some checks. Basically every dynamically bound global variable acts as an additional argument to every function in the call chain. From the static analysis perspective this is horror. I know it is the Emacs way, but I generally avoid it if possible. And I think Emacs also came to reason a bit when they introduced lexical scoping by default...
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I usually don't even add buffer-local internal variables if I can avoid it and instead use closures.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good points and I agree, though for user options there is no other way, you can use a single configuration variable for each package but this would have other problems. I'm probably not as reluctant to add global state as I should be. I'm also very happy we got Lexical-scope in Emacs, that improved the situation a lot! I also think without all the macros which set/restor state the general Emacs "everything is global" approach wouldn't be feasible at all.
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it wouldn't make sense to have a single configuration variable per package. This case here is a bit different since it allows you to hook into the argument plists. Here it is a very special case and it is justified to do it like this. But this is obviously not a generally applicable solution.
I don't think it is feasible even with that. I am happy with lexical scopes. Luckily I just started writing serious elisp after that has been added. For many years I only "used" Emacs but didn't tweak it as deeply as I am doing now ;) Maybe it is the Corona situation :-P
36c9f20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, hopefully it gets better soon...