Skip to content

Commit

Permalink
Update CLI filtered option to allow Array or Proc in addition to a …
Browse files Browse the repository at this point in the history
…single value. This allows, for example, a command to be associated with multiple formats.
  • Loading branch information
gkellogg committed Aug 7, 2022
1 parent 90aad9f commit c19c0a1
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 12 deletions.
34 changes: 29 additions & 5 deletions lib/rdf/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
rdf/xsd
shacl
shex
yaml_ld
).each do |ser|
begin
require ser
Expand Down Expand Up @@ -177,7 +178,10 @@ def to_hash
# * `parse` Boolean value to determine if input files should automatically be parsed into `repository`.
# * `help` used for the CLI help output.
# * `lambda` code run to execute command.
# * `filter` Option values that must match for command to be used
# * `filter` value is a Hash whose keys are matched against selected command options. All specified `key/value` pairs are compared against the equivalent key in the current invocation.
# If an Array, option value (as a string) must match any value of the array (as a string)
# If a Proc, it is passed the option value and must return `true`.
# Otherwise, the option value (as a string) must equal the `value` (as a string).
# * `control` Used to indicate how (if) command is displayed
# * `repository` Use this repository, if set
# * `options` an optional array of `RDF::CLI::Option` describing command-specific options.
Expand Down Expand Up @@ -505,9 +509,22 @@ def self.exec(args, output: $stdout, option_parser: nil, messages: {}, **options
# Make sure any selected command isn't filtered out
cmds.each do |c|
COMMANDS[c.to_sym].fetch(:filter, {}).each do |opt, val|
if options[opt].to_s != val.to_s
usage(option_parser, banner: "Command #{c.inspect} requires #{opt}: #{val}, not #{options.fetch(opt, 'null')}")
raise ArgumentError, "Incompatible command #{c} used with option #{opt}=#{options[opt]}"
case val
when Array
unless val.map(&:to_s).include?(options[opt].to_s)
usage(option_parser, banner: "Command #{c.inspect} requires #{opt} in #{val.map(&:to_s).inspect}, not #{options.fetch(opt, 'null')}")
raise ArgumentError, "Incompatible command #{c} used with option #{opt}=#{options[opt]}"
end
when Proc
unless val.call(options[opt])
usage(option_parser, banner: "Command #{c.inspect} #{opt} inconsistent with #{options.fetch(opt, 'null')}")
raise ArgumentError, "Incompatible command #{c} used with option #{opt}=#{options[opt]}"
end
else
unless val.to_s == options[opt].to_s
usage(option_parser, banner: "Command #{c.inspect} requires compatible value for #{opt}, not #{options.fetch(opt, 'null')}")
raise ArgumentError, "Incompatible command #{c} used with option #{opt}=#{options[opt]}"
end
end
end

Expand Down Expand Up @@ -594,7 +611,14 @@ def self.commands(format: nil, **options)
# Subset commands based on filter options
cmds = COMMANDS.reject do |k, c|
c.fetch(:filter, {}).any? do |opt, val|
options.merge(format: format)[opt].to_s != val.to_s
case val
when Array
!val.map(&:to_s).include?(options[opt].to_s)
when Proc
!val.call(options[opt])
else
val.to_s != options[opt].to_s
end
end
end

Expand Down
38 changes: 31 additions & 7 deletions spec/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,37 @@
end
end

it "complains if filtered command is attempted" do
RDF::CLI.add_command(:filtered, filter: {output_format: :nquads})
expect do
expect do
RDF::CLI.exec(["filtered"], output_format: :ntriples)
end.to raise_error(ArgumentError)
end.to write(%(Command "filtered" requires output_format: nquads, not ntriples)).to(:output)
describe "filter" do
context "complains if filtered command is attempted" do
before(:each) {RDF::CLI::COMMANDS.delete(:filtered)}

it "single value" do
RDF::CLI.add_command(:filtered, filter: {output_format: :nquads})
expect do
expect do
RDF::CLI.exec(["filtered"], output_format: :ntriples)
end.to raise_error(ArgumentError)
end.to write(%(Command "filtered" requires compatible value for output_format, not ntriples)).to(:output)
end

it "Array of values" do
RDF::CLI.add_command(:filtered, filter: {output_format: %i{nquads turtle}})
expect do
expect do
RDF::CLI.exec(["filtered"], output_format: :ntriples)
end.to raise_error(ArgumentError)
end.to write(%(Command "filtered" requires output_format in ["nquads", "turtle"], not ntriples)).to(:output)
end

it "Proc" do
RDF::CLI.add_command(:filtered, filter: {output_format: ->(v) {v == :nquads}})
expect do
expect do
RDF::CLI.exec(["filtered"], output_format: :ntriples)
end.to raise_error(ArgumentError)
end.to write(%(Command "filtered" output_format inconsistent with ntriples)).to(:output)
end
end
end

it "uses repository specified in command" do
Expand Down

0 comments on commit c19c0a1

Please sign in to comment.