-
Notifications
You must be signed in to change notification settings - Fork 551
Add support for repeatable options #468
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
Conversation
|
Hey guys, any feedback on this? |
If an option is marked as :repeatable => true, then its value is
an array of values.
i.e., option :item, :type => :hash, :repeatable => true
$ mycmd --item name:one age:1 --item name:two age:2
options['item'] = [{ name:one, ...}, { name:two, ...}]
i.e., option :item, :type => :array, :repeatable => true
$ mycmd --item 1 2 3 --item 4 5 6
options['item'] = [ [1, 2, 3], [4, 5, 6]]
7f88632 to
d779a4f
Compare
|
Just to give more context, I've pushed some documentation on my wiki's fork: https://github.com/astratto/thor/wiki/Method-Options |
|
I’m curious what @wycats thinks of this feature. |
|
Bump. This will be really useful... Any update on this? |
|
I'd really like to see this merged as well - any possibility of pushing it soon? |
|
From your example, this code: option :item, :type => :array, :repeatable => trueWith this command: Produces this option: options[:item] = [[1, 2, 3], [4, 5, 6]]First, it’s not obvious to me how this would create an array of integers. Where is the integer type declared? Normally, any input arriving via options[:item] = [["1", "2", "3"], ["4", "5", "6"]]It’s also not clear to me why specifying an array option multiple times would create an array of arrays, instead of appending to the array. I think some users would expect this result: options[:item] = ["1", "2", "3", "4", "5", "6"]Again, from your example, this code: option :item, :type => :hash, :repeatable => trueWith this command: Produces this option: options[:item] = [{"name" => "one", "age" => "1"}, {"name" => "two", "age" => "2"}]This is confusing to me because the result is an array, not a hash. It seems odd that making an option repeatable would change the type of the option itself. Also, users might expect repeating an option would merge the hashes. It would be helpful to understand your specific use-case for this feature so I can get a better understand your requirements. From that, we can work on a solution with a clear and simple interface. |
|
Hi @sferik, thank you for your reply. I'll try to reply to your comments and then I'll give you some use cases.
From my point of view, if I specify an option twice I expect to get a set (array) of something and then I can manage it as I wish; if we introduced a magic merging strategy that would be tricky. As far as use cases are concerned, I usually need two cases but I can probably imagine others:
Let me know if something's not clear. |
Right. But it’s inconsistent for a
I’m not arguing that append or merge is necessarily the right behavior. I just don’t think it’s obvious what the behavior would or should be.
I can think of a few different ways of supporting this feature without adding desc :test, "test"
option :verbose, aliases: :v
def test
puts options[:verbose]
endToday, if this command was run as: It would output: Instead of always setting the value of the option to its name, it could return the way the option was passed, in this case: The downside of this approach is that it could be a breaking change, but hopefully no one relies on those values, since they are not so meaningful. I still don’t fully understand your other use case but I would argue that providing complex structured data as command line arguments is probably not the best way to get that data into your program. Instead, consider allowing the user to specify that input from a file or stdin. |
I understand your point of view on that, but I think 'repeatable' reasonably implies that it's going to be a collection.
That's an interesting idea, but that wouldn't help with
That use case is probably a bit borderline and I tend to agree that it's not an ideal user experience; but when the target of that binary is a script things are slightly different. Think of a simpler use case Honestly, I don't care too much about the implementation details, but I think such a feature is really useful. What do you think? |
|
I'd still really like to see this feature, whatever the internal implementation is. I write command-line tools and regularly have need for things like @astratto is suggesting. Whatever the internal representation ends up looking like after implementation, it would be really useful to be able to specify commands that can be used by scripts like:
Without that, I have to write really ugly workarounds that my users need to know about and understand like: |
|
@sferik I'm sorry I keep pushing, but I'd like to understand what's your (as in Thor maintainers) take on the concept of allowing repeatable options. Right now I'm not talking about the specific implementation, but I think we can close this issue if you're completely against the whole idea. |
|
I like the idea and I think the implementation make sense. generates and not because if I provided the option twice I wanted two different values and not only one. If I want the later I can do Same with the hash case. The only problem is, when the option is repeatable, should |
|
Let's close this before it turns 3... |
|
Years later here, I have a need for a repeatable Hash option. And I find the current implementation does not provide what I am looking for, while the proposal in this closed PR does, for the Hash case. To illustrate, looking at the current test at https://github.com/rails/thor/blob/master/spec/parser/options_spec.rb#L420, why would this all be munged together into 1 hash? The other repeatable collection type, Array, yields an Array of Arrays, so why does hash type not yield an Array of Hashes? Perhaps, I am looking at the use case differently than the authors of the current implementation? For example, Yet, it currently yields 1 person Hash: So, I applied @astratto's code for repeatable hash locally and it works for my use case, yielding an Array of Hashes, as passed in. So, not sure if you want to Re-Raise another PR or not? I would like to see the above get merged, but perhaps there was a good reason for the current implementation and people are using it as is? Thanks @astratto |
|
@jamlevi it looks like there's a specific case in that implementation that merges hashes. Unfortunately we can't change that behavior without breaking it and everyone who relies on it. We'd need to either create a new type of option or a brand new type (hash_array?) to enable this behavior. |
|
@dorner Thanks very much, yes, after going over the comments again, specifically, #468 (comment), it's a bit more clear to me: "providing sets of structured data" was NOT implemented in master. I'll just go with my patched version for my use case, but maybe there are other people who would like to a "hash_array", as you suggest? Bow to all you maintainers. |
If an option is marked as
:repeatable => true, then its value is an array of values.Hash
Array
Note: This patch is backward-compatible, because options must be marked explicitly with
:repeatable.