Skip to content
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

Fix arguments with values allowing any value #142

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/dry/cli/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ class CLI
class Error < StandardError
end

# @since 1.3.0
class UnknownValueError < Error
end

# @since 0.2.1
class UnknownCommandError < Error
# @since 0.2.1
Expand Down
13 changes: 13 additions & 0 deletions lib/dry/cli/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ def alias_names
.map { |name| name.size == 1 ? "-#{name}" : "--#{name}" }
.map { |name| boolean? || flag? ? name : "#{name} VALUE" }
end

# @since 1.3.0
# @api private
def valid_value?(value)
available_values = values
return true if available_values.nil?

if array?
(value - available_values).empty?
else
available_values.map(&:to_s).include?(value.to_s)
end
end
end

# Command line argument
Expand Down
17 changes: 11 additions & 6 deletions lib/dry/cli/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def self.call(command, arguments, prog_name)

parsed_options = command.default_params.merge(parsed_options)
parse_required_params(command, arguments, prog_name, parsed_options)
rescue ::OptionParser::ParseError
rescue ::OptionParser::ParseError, UnknownValueError
Result.failure("ERROR: \"#{prog_name}\" was called with arguments \"#{original_arguments.join(" ")}\"") # rubocop:disable Layout/LineLength
end

Expand All @@ -40,8 +40,8 @@ def self.call(command, arguments, prog_name)
#
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
def self.parse_required_params(command, arguments, prog_name, parsed_options)
parsed_params = match_arguments(command.arguments, arguments)
parsed_required_params = match_arguments(command.required_arguments, arguments)
parsed_params = match_arguments(command.arguments, arguments, parsed_options)
parsed_required_params = match_arguments(command.required_arguments, arguments, parsed_options)
all_required_params_satisfied = command.required_arguments.all? { |param| !parsed_required_params[param.name].nil? } # rubocop:disable Layout/LineLength

unused_arguments = arguments.drop(command.required_arguments.length)
Expand Down Expand Up @@ -69,15 +69,20 @@ def self.parse_required_params(command, arguments, prog_name, parsed_options)
end
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity

def self.match_arguments(command_arguments, arguments)
def self.match_arguments(command_arguments, arguments, default_values)
result = {}

arg = nil
command_arguments.each_with_index do |cmd_arg, index|
if cmd_arg.array?
result[cmd_arg.name] = arguments[index..]
arg = arguments[index..] || default_values[cmd_arg.name]
raise UnknownValueError unless cmd_arg.valid_value?(arg)
result[cmd_arg.name] = arg
break
else
result[cmd_arg.name] = arguments.at(index)
arg = arguments.at(index) || default_values[cmd_arg.name]
raise UnknownValueError unless cmd_arg.valid_value?(arg)
result[cmd_arg.name] = arg
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/support/fixtures/foo
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ module Foo
class Rollback < Dry::CLI::Command
desc "Rollback the database"

argument :steps, desc: "Number of versions to rollback", default: 1
argument :steps, desc: "Number of versions to rollback", default: 1, values: [1, 2, 3]

def call(steps:, **)
puts steps
Expand Down
2 changes: 1 addition & 1 deletion spec/support/fixtures/shared_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def call(*); end
class Rollback < Dry::CLI::Command
desc "Rollback the database"

argument :steps, desc: "Number of versions to rollback", default: 1
argument :steps, desc: "Number of versions to rollback", default: 1, values: [1, 2, 3]

def call(steps:, **)
puts steps
Expand Down
7 changes: 7 additions & 0 deletions spec/support/shared_examples/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@
expect(error).to eq("ERROR: \"rspec console\" was called with arguments \"--engine=unknown\"\n")
end
end

context "with an unknown argument" do
it "prints error" do
error = capture_error { cli.call(arguments: %w[db rollback 4]) }
expect(error).to eq("ERROR: \"rspec db rollback\" was called with arguments \"4\"\n")
end
end
end

it "with help param" do
Expand Down