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

No colors for non tty outputs #246

Merged
merged 9 commits into from
May 9, 2015

Conversation

robd
Copy link
Contributor

@robd robd commented May 8, 2015

As discussed in #245, this PR reworks color support so that we don't ouput ANSI color escape sequences for output IOs which aren't associated with a tty.

The main rework is to convert the Color module into a class which can be instantiated with the output IO, rather than just being hard coded to the $stdout.tty?

As part of this change, I was trying to add a test for the colors in this message in the pretty formatter:

c.black(c.on_yellow("Output formatter doesn't know how to handle #{obj.class}\n"))

Calling write with an unexpected object type didn't call the above line, but instead raised an exception - (undefined method 'verbosity' for #<Object:0x007f8b73695450>) here, which meant that the line above was basically unreachable.

I made this line reachable by checking for the presence of the verbosity method and I saw this error instead undefined method 'on_yellow' for Color:Module.

I looked through the historical issues on SSHKit and Capistrano about the verbosity and on_yellow errors. There are several verbosity messgage issues which were was associated with the --dry-run option and I found this @leehambley comment:

I can confirm the log formatters expect objects on Command and LogMessage (?) classes. Any thing contrary is incorrect

Therefore, it seems to me that, in practice, we are never calling a formatter with a non Command / LogMessage object. Therefore, I've added tests to raise this as a more helpful error, and removed the coloring from the message.

Hopefully everything else is obvious.

robd added 6 commits May 7, 2015 11:18
Minitest runs every test method in a new instance, so no need to tear down instance methods
Tests enabling and disabling colours with different tty? and SSHKIT_COLOR combinations
The Pretty and Dot formatters now won’t output colors if writing to a File or non tty IO, unless the SSHKIT_COLOR environment variable is set
@mattbrictson
Copy link
Member

I like this but it has an unfortunate side effect of breaking airbrussh. 😭

Airbrussh constructs a pretty formatter with a Logger object, which responds to << (and thus works for output purposes). But Logger is not an IO object and does not respond to tty?. And so this happens:

NoMethodError: undefined method `tty?' for #<Logger:0x007ff88d10aaa8>
/Users/mbrictson/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/bundler/gems/sshkit-cc6fe03497d4/lib/sshkit/color.rb:15:in `colorize?'

Now this is totally my fault, because I am not passing in a proper IO object. The reason I am using Logger is because of its handy log rotation feature, which prevents the log file from growing unbounded.

Any ideas how best to solve this?

  1. Change airbrussh to use open instead of Logger.new (i.e. drop the log rotation feature, or roll my own).
  2. Change colorize? to use a more defensive check: @io.respond_to?(:tty?) && @io.tty?.
  3. Have airbrussh extend the logger object to respond to tty?.

@robd
Copy link
Contributor Author

robd commented May 8, 2015

Ah that is a shame - I was hoping the opposite - that this change would stop my capistrano.log file being full of color characters!

I think option 2 would be preferable. It narrows the contract for providing an output to SSHKit (ie only << or write need to be supported), and people can implement their own tty? method if they want more control (ie suggestion 3).

I think it's reasonable that if there is no tty? method we default to no color.

People providing a non IO output can wrap with a SimpleDelegator and add a tty? method.

If you're happy with this, I will add tests and update the docs to cover this case.

@mattbrictson
Copy link
Member

@robd That works for me. Thanks! 👍

@mattbrictson
Copy link
Member

I think this PR might also fix some lingering issues being reported in #214, since @robd's new Color implementation calls to_s before invoking colorize.

robd added 2 commits May 9, 2015 01:44
Any object which supports << can now be used for example Logger. Fixes compatibility with Airbrussh - see capistrano#246.
@robd robd force-pushed the no-colors-for-non-tty-outputs branch from cc6fe03 to b471f86 Compare May 9, 2015 00:55
@robd
Copy link
Contributor Author

robd commented May 9, 2015

@mattbrictson OK f37ef77 should fix the undefined method 'tty?' issue

@mattbrictson
Copy link
Member

f37ef77 should fix the undefined method 'tty?' issue

Verified!

@leehambley
Copy link
Member

Good work @robd and thanks again for the compat. sanity checking @mattbrictson - happy to merge if you are @robd

@robd
Copy link
Contributor Author

robd commented May 9, 2015

@leehambley great - yes please!

leehambley added a commit that referenced this pull request May 9, 2015
@leehambley leehambley merged commit e91d8c3 into capistrano:master May 9, 2015
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants