rails / thor

Thor is a toolkit for building powerful command-line interfaces.
http://whatisthor.com/
MIT License
5.11k stars 552 forks source link

How about supporting `Thor::CoreExt::HashWithIndifferentAccess#slice` method? #804

Closed shuuuuun closed 1 year ago

shuuuuun commented 1 year ago

When extracting a part of options hash in a Thor command, options.slice(:foo) does not work as expected. Wouldn't it be more intuitive to support the Thor::CoreExt::HashWithIndifferentAccess#slice method?

require 'thor'

hash = Thor::CoreExt::HashWithIndifferentAccess.new 'foo' => 'bar'

hash['foo'] #=> 'bar'
hash[:foo]  #=> 'bar'
hash.slice('foo') #=> {'foo'=>'bar'}
hash.slice(:foo)  #=> {}

As a side note, ActiveSupport::HashWithIndifferentAccess works as expected.

require 'active_support/core_ext/hash/indifferent_access'

hash = ActiveSupport::HashWithIndifferentAccess.new 'foo' => 'bar'

hash['foo'] #=> 'bar'
hash[:foo]  #=> 'bar'
hash.slice('foo') #=> {'foo'=>'bar'}
hash.slice(:foo)  #=> {'foo'=>'bar'}

I checked with thor v1.2.1 and current main branch. https://github.com/rails/thor/blob/v1.2.1/lib/thor/core_ext/hash_with_indifferent_access.rb https://github.com/rails/thor/blob/e4907fdd663d0a1ff51d18eb1827552ee61300a3/lib/thor/core_ext/hash_with_indifferent_access.rb

Thank you. 🌈

rafaelfranca commented 1 year ago

Thank you but this class is not supposed to be used by users of thor, so if there isn't a reason for thor to use that method, there isn't a reason to add to thor.

shuuuuun commented 1 year ago

When using options within the methods of the Thor command, we indirectly use its class. Sometimes I want to extract a part of the options hash. I think some users have similar needs. Is this not a reason to consider adding it?

For example:

# ./thor.rb
require "thor"

class MyCLI < Thor
  class_option :foo

  desc "hello NAME", "say hello to NAME"
  option :from
  def hello(name)
    puts "Hello #{name}"
    puts "options: #{options}"
    puts "options.class: #{options.class}"
    puts "options.slice('foo'): #{options.slice('foo')}"
    puts "options.slice(:foo): #{options.slice(:foo)}"
  end
end

MyCLI.start(ARGV)
$ ruby ./thor.rb hello world --from=Tokyo --foo=bar
Hello world
options: {"from"=>"Tokyo", "foo"=>"bar"}
options.class: Thor::CoreExt::HashWithIndifferentAccess
options.slice('foo'): {"foo"=>"bar"}
options.slice(:foo): {}

Thank you.

rafaelfranca commented 1 year ago

Makes sense. Please send a PR.