davetron5000 / gli

Make awesome command-line applications the easy way
http://davetron5000.github.io/gli
Apache License 2.0
1.26k stars 102 forks source link

Use $stderr instead of STDERR #269

Closed kyledecot closed 6 years ago

kyledecot commented 6 years ago

I noticed that this method is using STDERR instead of $stderr. This becomes a problem when attempting to capture the output of a run command that has a exit_now! call in it.

In my case I was attempting to do something like:

cli.rb

require "gli"

module Vindetta
  class CLI
    extend GLI::App

    desc "Decodes a VIN"

    command %i[decode d] do |c|
      c.action do |_global, _options, args|
        vin = args.first

        exit_now!("vin is required", 1) if vin.nil? # TODO: Replace w/ I18n

        puts Vindetta::Decoder.decode_vin(vin).to_json
      end
    end
  end

cli_spec.rb

...
begin
  old_stdout, old_stderr, $stdout, $stderr = $stdout, $stderr, StringIO.new, StringIO.new

  @exit_code = described_class.run([command] + command_args)
  @stdout = $stdout.string
  @stderr = $stderr.string
ensure
  $stdout = old_stdout
  $stderror = old_stderr
end
...

As you can see I was attempting to redirect/capture $stderr (which I assigned to a StringIO instance) however this didn't work as expected as output_error_message was using the regular 'ol stderr.

davetron5000 commented 6 years ago

Not sure why you closed this, but GLI only uses STDERR directly in the scaffold script. There is a hidden but public method that lets you change the error device (which does default to STDERR):

https://github.com/davetron5000/gli/blob/84c21131320168178077e9bfe03f51f0e28d361e/lib/gli/app_support.rb#L1-L7

AppSupport is mixed into your GLI app, so you can call this if you like.

To test stuff like this, though, I would run the actual app and use Open3 to capture the stderr if possible.