-
Notifications
You must be signed in to change notification settings - Fork 158
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
Provide Distinct Builder for Reedline
#740
base: main
Are you sure you want to change the base?
Conversation
I forgot to add documentation, which I think is important, so I won't mark this PR ready without it. I might add a (declarative) macro for the Builder as well, will see. |
Hey! Thanks for this! @stormasm and I can try to look through it, maybe others. We're generally against macros unless they're undeniably intuitive and necessary, with the nushell team being the judge, of course. I'm excited to dig through and see what you've come up with as an easier and more intuitive API. |
After skimming through the code quickly, this question comes to mind, if you wouldn't mind explaining a bit more. What makes these changes better or more intuitive for API consumers? They just look different to me but maybe I'm missing something. |
I took a look at your PR --- and have a general sense of what you are trying to accomplish. Thanks for putting in the effort ! Just an FYI for future PRs of this magnitude in Reedline... It probably makes sense to discuss stuff like this ahead of time on our Discord Reedline Channel... Also --- the Reedline issues are also a good place to present the ideas... With all of that said I will review the PR over the next number of days. We have a release coming up next week so it will probably be after that.. |
I think the largest improvement is naming consistency for related methods. Names should help choose which method to use for a purpose and In the current code, I implemented the MVP. There are probably more methods that could be beneficial on a builder. They are not strictly necessary to use it correctly though. Things like The generic In their functionality, most of the builder methods are setters. They allow changing internal state after initialization. I am uncertain whether that's what you want but given that there is at least one explicit setter ( And, as I pointed out before, construction and workable are fundamentally different states and a shared representation just feels wrong. There's an excellent video on a vaguely related topic. I don't think using an object before it's finalized can lead to UB like with C++ constructors, but it can cause behavioral bugs so the explicit state change (also represented in the type system) helps with clarity. It also helps with confidence: If the Builder is passed to a library function it can't call |
I made some notes on what I want to improve. When I look at them now there are things that probably would have been less structural changes (like the consistent naming that I quickly hinted at in my previous message). Maybe not the best idea to start with this. |
A lot of the builder code is repetitive and a macro might simplify the structure. So it's definitely not necessary, but greatly reduces the amount of (similiar) code that has to be maintained. |
Thanks for the explanation. I appreciate the thoughtfulness. |
The new commits introduce a macro for generalizing similarly structured methods. I put it together quickly and roughly, so this probably isn't the nicest it could be. Looking forward to feedback on it. The macro generates a I haven't finished the documentation yet. I think writing good documentation is difficult, and even more so with the macro generalizing the code. |
Thanks for trying to tackle the inconsistencies in the API and going through all the config options. You are correct that our current configuration interface doesn't really meet the builder definition and also doesn't really provide assurances that things are properly configured. With how we are handling the This would in effect kind of favor a I think there could still be a place for a |
That's why I deprecated rather than removing the methods outright ;) I still think that having a distinct builder and setters is an improvement because it allows for more granularity. I haven't looked much at nushell, but I'll do that. Oh, and could you give me some feedback on the macro? |
I removed the macros, saving a dependency (
I haven't looked at Besides that, I tried to make this a little nicer with the points suggested. |
(I think I did some general "tidying up" in some files alongside the actual code changes. I hope that's fine) |
The motivation for this is to
|
This PR is most likely not the place to discuss this, but there's a fundamental discussion to be had about what a prompt is. I think the current implementation is semantically a bit weird, as it mashes two answers together. |
In
engine.rs
there are a few methods whose docstrings start with the words "a builder to". The Builder pattern isalmost certainly a great fit for initializing a
Reedline
, but it is improperly implemented here.I've checked online and all sources (including this one) noted or implied that a Builder is a separate type specially for complex initializations.
I see three problems with the current structure:
of thumb for whether something is well designed. I can think of at least two ways to branch the
hinting strategy on some condition. The first is two write a hinter that looks at some state and
then decides what to do from there. The second is to change the current hinter every time some
state changes. Just considering my ability to reason about to code, I don't think the latter is
ever a good idea.
Reedline::create
is called, it initializes with default values. This is great for quicklystarting, but it somewhat conflicts with the idea of customizing an instance through a Builder.
If nothing else, this might make some very unnecessary allocations for the defaults.
different from a finished instance, so it probably shouldn't be the same type. This theoretically
might even lead to issues when the instance is used before it is finalized.
Having a distinct Builder type makes sure instances of
Reedline
are finished for use and disallowsmutation during use.
This only marks the builder methods on
Reedline
as deprecated, so it doesn't break the API