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
Add named_args DSL for commands #10288
Conversation
Review period will end on 2021-01-12 at 06:28:12 UTC. |
f4c30a9
to
d61980a
Compare
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 PR refactors the NamedArgs class and replaces the named, min_named, and max_named methods with a single named_args method.
The existing methods are still used in (our) taps and therefore probably other taps too so need to be kept around in some form for compatibility reasons.
Otherwise: looking great so far, thanks for this!
Library/Homebrew/cli/named_args.rb
Outdated
when :installed_tap | ||
taps += taps installed: true, ignore_unavailable: ignore_unavailable | ||
else | ||
others += @args |
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.
Should this raise
if this value is invalid?
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.
Under my current thinking: no.
We do want to allow named arguments that don't fall into any of the categories. I also current used named_args :command
and named_args :diagnostic_check
for some commands. These symbols will cause the args to be treated simply as text, but will (in the future) allow completions to autofill commands or diagnostic checks.
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.
Although, on second thought, args.named
should be sufficient in these cases and we probably shouldn't be calling args.named.convert
, so maybe that's a good idea.
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.
These symbols will cause the args to be treated simply as text, but will (in the future) allow completions to autofill commands or diagnostic checks.
I feel like we can add this in future when we want but "treating symbols as text" seems overly permissive for now.
Library/Homebrew/cli/named_args.rb
Outdated
allow_formula_cask_conflicts: T::Boolean, | ||
).returns(T.any(Array, Hash)) | ||
end | ||
def convert(only: nil, separate_types: false, ignore_unavailable: false, allow_formula_cask_conflicts: false) |
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.
to_objects
or something feels like a nicer method name. I wonder if to_formulae_and_casks
or something could be used and just change the API?
Also, this method feels really big; maybe it's worth breaking down a bit?
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 reason I wanted to move away from to_*
was that I wanted this method to be a catch-all. One could always call args.named.convert
and get the converted objects. Maybe that's not the way to go about this.
I'd be in favor of breaking it down a little, but I think the main reason it's so long is it has a huge case
statement. It already calls out to helper methods for the actual arg conversion.
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 feel like having the return type of this depend on what is passed to CLI::Parser
is too implicit (also no way to have a meaningful type signature).
Maybe we could store arguments as Arg
objects which have e.g. a to_cask
method, etc., so the API would look like:
args.named.map(&:to_cask)
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 feel like having the return type of this depend on what is passed to
CLI::Parser
is too implicit (also no way to have a meaningful type signature).
Agreed 👍🏻
Maybe we could store arguments as
Arg
objects which have e.g. ato_cask
method, etc., so the API would look like:args.named.map(&:to_cask)
Yeh, something like this looks nice. I'm basically wanting to have "if I want to get casks the call method/parameters contain the word cask
"
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.
Agreed, something like this is a better solution. Let me give some more thought to this and whether this is actually any better than the existing args.named.to_*
methods. We were using those successfully before so I don't think we need to reinvent them just to allow this named_args
method.
That's why this is a draft PR. I'm still working through everything and figuring out what the best way to do it is
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 why this is a draft PR. I'm still working through everything and figuring out what the best way to do it is
Yup, all good ❤️
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.
We were using those successfully before so I don't think we need to reinvent them just to allow this
named_args
method.
Potentially they could be extended to raise
if called in the wrong way (i.e. if named_args :tap
and you request named.to_formulae
or something?).
Yes, that's why I added the commented-out deprecation lines on them. They haven't actually been removed yet (and will still work fine). I just layed the ground work for removing them. |
Thanks for the feedback. More generally, is this the right way to proceed? I was picturing |
Review period ended. |
d61980a
to
63ac3d2
Compare
I decided that what I really want from this PR is the I reverted the A few questions: should there be a difference between I've been operating under the assumption that all kegs are installed formulae. Is that fair or are there instances where kegs aren't formulae? Separately, what's the difference between |
👍🏻
Yes, I think now that we've removed
The latter uses |
Okay. For this PR, I think I'd rather continue to use
Yeah, I kind of figured
When would you want to use |
Actually, there is one small difference. Currently, we calculate installed formulae differently in completions. In bash we use I believe what you're saying is that Should completions complete installed formulae from
|
Fine with me 👍🏻
I'm not sure, depends on the implementation (and perhaps even the other flags passed 😭).
Sounds good 👍🏻 |
Maybe what I meant to ask is: "is there ever a situation where you would need to use I just quickly grepped and it seems the only two uses of I'm not worrying too much about it for now, but I wonder if
Edit 2: done! |
7a4f2d0
to
da81137
Compare
Yeh, it may be it can be used globally. Certainly the naming is not exactly transparent as to what it's doing. Would be a good thing to test (maybe with an environment variable to feature flag it?). |
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.
Fantastic work as usual @Rylan12. A few more thoughts/comments but nothing blocking here; merge when you're happy with it.
Thinking ahead a little bit: the I'm thinking about writing a blog post when all of that is completed with instructions explaining both how to migrate to using |
👍🏻 sounds good.
Sounds helpful but I'm not sure there's many external taps that'd use this, indeed. Could just be something on docs.brew.sh perhaps? |
Makes sense. I noticed that in the existing external command docs, the recommendation is to use |
I'm going to go ahead and merge this for now. I've got some time tonight and want to work on the completions which requires this PR. I've made some documentation changes locally and will open a separate PR for those so this isn't held up. |
brew style
with your changes locally?brew typecheck
with your changes locally?brew tests
with your changes locally?brew man
locally and committed any changes?See #10229 and #10229 for some more context/discussion.
This PR refactors the
NamedArgs
class and replaces thenamed
,min_named
, andmax_named
methods with a singlenamed_args
method.The
named_args
method takes a symbol describing the type of named arguments that should be accepted. These can be anything. The method can also define the number of named arguments allowed using thenamed
,min
, andmax
parameters. The main benefit of this new method is that it will allow shell completions to be generated automatically for all Homebrew commands.However, another benefit is that converting named arguments to the desired type is easier. I've replaced the
args.named.to_*
methods withargs.named.convert
andargs.named.convert_to_paths
.For example, calling
named_args :formula
and thenargs.named.convert
will convert all named arguments to formula objects.This PR is still a work in progress. I've yet to implement a few features of the
named_args
command and there are a few more internal commands that will need to be updated. I'm keeping track of which commands I've updated and what each of their constraints are in this spreadsheet.Additionally,
brew typecheck
is failing and I could use some help resolving those issues.Lastly, I know that
brew tests
fails at the moment. They're mostly timeout exceptions which makes me think that something isn't working right with the new methods. Regardless, I just wanted to get this up for initial feedback first.