Skip to content
Merged
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
7 changes: 7 additions & 0 deletions lib/dry/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ def call(arguments: ARGV, out: $stdout, err: $stderr)
# @api private
def perform_command(arguments)
command, args = parse(kommand, arguments, [])

command.instance_variable_set(:@err, err) unless command.instance_variable_defined?(:@err)
command.instance_variable_set(:@out, out) unless command.instance_variable_defined?(:@out)

command.call(**args)
end

Expand All @@ -113,6 +117,9 @@ def perform_registry(arguments)

command, args = parse(result.command, result.arguments, result.names)

command.instance_variable_set(:@err, err) unless command.instance_variable_defined?(:@err)
command.instance_variable_set(:@out, out) unless command.instance_variable_defined?(:@out)

result.before_callbacks.run(command, args)
command.call(**args)
result.after_callbacks.run(command, args)
Expand Down
33 changes: 33 additions & 0 deletions lib/dry/cli/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,39 @@ def self.superclass_options
optional_arguments
subcommands
] => "self.class"

protected

# The error output used to print error messaging
#
# @example
# class MyCommand
# def call
# out.puts "Hello World!"
# exit(0)
# rescue StandardError => e
# err.puts "Uh oh: #{e.message}"
# exit(1)
# end
# end
#
# @since unreleased
# @return [IO]
attr_reader :err

# The standard output object used to print messaging
#
# @example
# class MyCommand
# def call
# out.puts "Hello World!"
# exit(0)
# end
# end
#
# @since unreleased
# @return [IO]
attr_reader :out
end
end
end
40 changes: 40 additions & 0 deletions spec/unit/dry/cli/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,45 @@
)
end
end

it "exposes @out and @err to command without overriding pre-existing ivars" do
# @out and @err are exposed by default
command_class = Class.new(Dry::CLI::Command) do
def call(**)
@out.puts "out"
@err.puts "err"
end
end
cli = Dry.CLI(command_class.new)

default_out = StringIO.new
default_err = StringIO.new
cli.call(arguments: [], out: default_out, err: default_err)

expect(default_out.string).to eq("out\n")
expect(default_err.string).to eq("err\n")

# @out and @err do not override pre-existing ivars
custom_command_class = Class.new(command_class) do
define_method(:initialize) do |out, err|
super()
@out = out
@err = err
end
end

custom_out = StringIO.new
custom_err = StringIO.new
cli = Dry.CLI(custom_command_class.new(custom_out, custom_err))

default_out = StringIO.new
default_err = StringIO.new
cli.call(arguments: [], out: default_out, err: default_err)

expect(custom_out.string).to eq("out\n")
expect(custom_err.string).to eq("err\n")
expect(default_out.string).to eq("")
expect(default_err.string).to eq("")
end
end
end