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

Experimental: refactor Airbrussh::Colors to be class, rather than module #64

Closed
wants to merge 5 commits into from
Closed
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: 2 additions & 2 deletions lib/airbrussh/capistrano/tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ class Tasks
extend Forwardable
def_delegators :dsl, :set
def_delegators :config, :log_file

include Airbrussh::Colors
def_delegators :@colors, *Airbrussh::Colors.names

def initialize(dsl, stderr=$stderr, config=Airbrussh.configuration)
@dsl = dsl
@stderr = stderr
@config = config
@colors = config.colors(stderr)

configure
warn_if_missing_dsl
Expand Down
38 changes: 31 additions & 7 deletions lib/airbrussh/colors.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
module Airbrussh
# Very basic support for ANSI color, so that we don't have to rely on
# any external dependencies.
module Colors
class Colors
ANSI_CODES = {
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:gray => 90
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37,
:gray => 90,
:light_black => 90,
:light_red => 91,
:light_green => 92,
:light_yellow => 93,
:light_blue => 94,
:light_magenta => 95,
:light_cyan => 96,
:light_white => 97
}.freeze

def self.names
ANSI_CODES.keys
end

def initialize(enabled=true)
@enabled = enabled
end

def enabled?
@enabled
end

# Define red, green, blue, etc. methods that return a copy of the
# String that is wrapped in the corresponding ANSI color escape
# sequence.
ANSI_CODES.each do |name, code|
define_method(name) do |string|
return string.to_s unless enabled?
"\e[0;#{code};49m#{string}\e[0m"
end
module_function(name)
end
end
end
8 changes: 5 additions & 3 deletions lib/airbrussh/command_formatter.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# encoding: UTF-8
require "airbrussh/colors"
require "delegate"
require "forwardable"
# rubocop:disable Style/AsciiComments

module Airbrussh
Expand All @@ -11,11 +11,13 @@ module Airbrussh
# all commands that have been run in the current rake task
# class CommandFormatter < SimpleDelegator
class CommandFormatter < SimpleDelegator
include Airbrussh::Colors
extend Forwardable
def_delegators :@colors, *Airbrussh::Colors.names

def initialize(command, position)
def initialize(command, position, colors=Airbrussh::Colors.new)
super(command)
@position = position
@colors = colors
end

# Prefixes the line with the command number and removes the newline.
Expand Down
30 changes: 25 additions & 5 deletions lib/airbrussh/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@ def initialize
self.command_output = false
end

def banner_message
# Returns a configured Colors object appropriate for the given io.
# This is based on the color setting (true, false, or :auto), and whether
# the io is a tty.
def colors(io)
Airbrussh::Colors.new(color?(io))
end

def banner_message(io)
return nil unless banner
return banner unless banner == :auto
msg = "Using airbrussh format."
m = "Using airbrussh format."
if log_file
msg << "\n"
msg << "Verbose output is being written to #{Colors.blue(log_file)}."
m << "\n"
m << "Verbose output is being written to #{colors(io).blue(log_file)}."
end
msg
m
end

# This returns an array of formatters appropriate for the configuration.
Expand All @@ -39,5 +46,18 @@ def formatters(io)
def show_command_output?(sym)
command_output == true || Array(command_output).include?(sym)
end

private

def color?(io)
case color
when true
true
when :auto
ENV["SSHKIT_COLOR"] || (io.respond_to?("tty?") && io.tty?)
else
false
end
end
end
end
20 changes: 6 additions & 14 deletions lib/airbrussh/console.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ module Airbrussh
# Helper class that wraps an IO object and provides methods for truncating
# output, assuming the IO object represents a console window.
#
# This is useful for writing log messages that will typically show up on
# an ANSI color-capable console. When a console is not present (e.g. when
# running on a CI server) the output will gracefully degrade.
# If color is disabled for the IO object (based on Airbrussh::Configuration),
# any ANSI color codes will also be stripped from the output.
#
class Console
attr_reader :output, :config

Expand All @@ -17,9 +17,8 @@ def initialize(output, config=Airbrussh.configuration)
end

# Writes to the IO after first truncating the output to fit the console
# width. If the underlying IO is not a TTY, ANSI colors are removed from
# the output. A newline is always added. Color output can be forced by
# setting the SSHKIT_COLOR environment variable.
# width. If color is disabled for the underlying IO, ANSI colors are also
# removed from the output. A newline is always added.
def print_line(obj="")
string = obj.to_s

Expand Down Expand Up @@ -67,14 +66,7 @@ def console_width
private

def color_enabled?
case config.color
when true
true
when :auto
ENV["SSHKIT_COLOR"] || @output.tty?
else
false
end
@color_enabled ||= config.colors(output).enabled?
end

def utf8_supported?(string)
Expand Down
13 changes: 10 additions & 3 deletions lib/airbrussh/console_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
require "airbrussh/command_formatter"
require "airbrussh/console"
require "airbrussh/rake/context"
require "forwardable"
require "sshkit"

module Airbrussh
class ConsoleFormatter < SSHKit::Formatter::Abstract
include Airbrussh::Colors
extend Forwardable
def_delegators :@colors, *Airbrussh::Colors.names

attr_reader :config, :context
def_delegators :context, :current_task_name, :register_new_command
Expand All @@ -16,14 +17,16 @@ def initialize(io, config=Airbrussh.configuration)
super(io)

@config = config
@colors = config.colors(io)
@context = Airbrussh::Rake::Context.new(config)
@console = Airbrussh::Console.new(original_output, config)

write_banner
end

def write_banner
print_line(config.banner_message) if config.banner_message
message = config.banner_message(original_output)
print_line(message) if message
end

def log_command_start(command)
Expand Down Expand Up @@ -105,7 +108,11 @@ def debug?(obj)
end

def decorate(command)
Airbrussh::CommandFormatter.new(command, @context.position(command))
Airbrussh::CommandFormatter.new(
command,
@context.position(command),
@colors
)
end

def print_line(string)
Expand Down
40 changes: 39 additions & 1 deletion test/airbrussh/colors_test.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,64 @@
require "minitest_helper"
require "airbrussh/colors"
require "forwardable"

class Airbrussh::ColorsTest < Minitest::Test
include Airbrussh::Colors
extend Forwardable
def_delegators :@colors, *Airbrussh::Colors.names

def test_red
enable_color
assert_equal("\e[0;31;49mhello\e[0m", red("hello"))
end

def test_green
enable_color
assert_equal("\e[0;32;49mhello\e[0m", green("hello"))
end

def test_yellow
enable_color
assert_equal("\e[0;33;49mhello\e[0m", yellow("hello"))
end

def test_blue
enable_color
assert_equal("\e[0;34;49mhello\e[0m", blue("hello"))
end

def test_gray
enable_color
assert_equal("\e[0;90;49mhello\e[0m", gray("hello"))
end

def test_red_disabled
enable_color(false)
assert_equal("hello", red("hello"))
end

def test_green_disabled
enable_color(false)
assert_equal("hello", green("hello"))
end

def test_yellow_disabled
enable_color(false)
assert_equal("hello", yellow("hello"))
end

def test_blue_disabled
enable_color(false)
assert_equal("hello", blue("hello"))
end

def test_gray_disabled
enable_color(false)
assert_equal("hello", gray("hello"))
end

private

def enable_color(enabled=true)
@colors = Airbrussh::Colors.new(enabled)
end
end
37 changes: 32 additions & 5 deletions test/airbrussh/configuration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,30 @@ def test_defaults
def test_auto_banner_message_without_log
@config.log_file = nil
@config.banner = :auto
assert_equal("Using airbrussh format.", @config.banner_message)
assert_equal("Using airbrussh format.", @config.banner_message(stub))
end

def test_auto_banner_message_with_log
@config.log_file = "log/test.log"
@config.banner = :auto
@config.color = true
assert_equal(
"Using airbrussh format.\n"\
"Verbose output is being written to \e[0;34;49mlog/test.log\e[0m.",
@config.banner_message
@config.banner_message(stub)
)
end

def test_nil_or_false_banner_message
@config.banner = nil
assert_nil(@config.banner_message)
assert_nil(@config.banner_message(stub))
@config.banner = false
assert_nil(@config.banner_message)
assert_nil(@config.banner_message(stub))
end

def test_custom_banner_message
@config.banner = "Hello!"
assert_equal("Hello!", @config.banner_message)
assert_equal("Hello!", @config.banner_message(stub))
end

def test_formatters_without_log_file
Expand Down Expand Up @@ -95,4 +96,30 @@ def test_effects_of_command_output_stdout_stderr
assert(@config.show_command_output?(:stdout))
assert(@config.show_command_output?(:stderr))
end

def test_color_is_allowed_for_tty
@config.color = :auto
assert(@config.colors(stub("tty?" => true)).enabled?)
end

def test_color_can_be_forced
@config.color = true
assert(@config.colors(stub("tty?" => false)).enabled?)
end

def test_color_can_be_forced_via_env
@config.color = :auto
ENV.stubs(:[]).with("SSHKIT_COLOR").returns("1")
assert(@config.colors(stub("tty?" => false)).enabled?)
end

def test_color_disabled_non_tty
@config.color = :auto
refute(@config.colors(stub("tty?" => false)).enabled?)
end

def test_color_can_be_disabled_for_tty
@config.color = false
refute(@config.colors(stub("tty?" => true)).enabled?)
end
end