diff options
author | John Keiser <jkeiser@opscode.com> | 2014-05-01 15:56:11 -0700 |
---|---|---|
committer | John Keiser <jkeiser@opscode.com> | 2014-05-01 15:56:11 -0700 |
commit | 71424d4556f07bb630b59fdb3ed5ee3100873657 (patch) | |
tree | 18ad42f638a3fabdf37130fdf1b2d7b606169489 /lib | |
parent | b3815bfaebfa6a026fd64ce8e141cc751d076211 (diff) | |
download | chef-71424d4556f07bb630b59fdb3ed5ee3100873657.tar.gz |
Move output stream to its own class file
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/formatters/base.rb | 146 | ||||
-rw-r--r-- | lib/chef/formatters/indentable_output_stream.rb | 154 |
2 files changed, 156 insertions, 144 deletions
diff --git a/lib/chef/formatters/base.rb b/lib/chef/formatters/base.rb index c86a14e9eb..636ba9c83f 100644 --- a/lib/chef/formatters/base.rb +++ b/lib/chef/formatters/base.rb @@ -21,6 +21,7 @@ require 'chef/event_dispatch/base' require 'chef/formatters/error_inspectors' require 'chef/formatters/error_descriptor' require 'chef/formatters/error_mapper' +require 'chef/formatters/indentable_output_stream' class Chef @@ -56,145 +57,6 @@ class Chef formatter_class.new(out, err) end - # == Outputter - # Handles basic printing tasks like colorizing and indenting. - # -- - # TODO: Duplicates functionality from knife, upfactor. - class Outputter - - attr_reader :out - attr_reader :err - attr_accessor :indent - attr_reader :line_started - attr_accessor :stream - attr_reader :semaphore - - def initialize(out, err) - @out, @err = out, err - @indent = 0 - @line_started = false - @semaphore = Mutex.new - end - - def highline - @highline ||= begin - require 'highline' - HighLine.new - end - end - - # Print text. This will start a new line and indent if necessary - # but will not terminate the line (future print and puts statements - # will start off where this print left off). - def color(string, *colors) - print(string, from_args(colors)) - end - - # Print the start of a new line. This will terminate any existing lines and - # cause indentation but will not move to the next line yet (future 'print' - # and 'puts' statements will stay on this line). - def start_line(string, *colors) - print(string, from_args(colors, :start_line => true)) - end - - # Print a line. This will continue from the last start_line or print, - # or start a new line and indent if necessary. - def puts(string, *colors) - print(string, from_args(colors, :end_line => true)) - end - - # Print an entire line from start to end. This will terminate any existing - # lines and cause indentation. - def puts_line(string, *colors) - print(string, from_args(colors, :start_line => true, :end_line => true)) - end - - # Print a string. Without any further options, this will - def print(string, *colors) - options = from_args(colors) - - # Make sure each line stays a unit even with threads sending output - semaphore.synchronize do - # If we aren't printing to the same stream, move to the next line - # and print the stream header (if any) - if @stream != options[:stream] - @stream = options[:stream] - if @line_started - @out.puts '' - end - if options[:name] - @out.print "#{(' ' * indent)}[#{options[:name]}] " - else - @out.print ' ' * indent - end - @line_started = true - - # if start_line is true, move to the next line. - elsif options[:start_line] - if @line_started - @out.puts '' - @line_started = false - end - end - - # Split the output by line and indent each - printed_anything = false - string.lines.each do |line| - printed_anything = true - print_line(line, options) - end - - if options[:end_line] - # If we're supposed to end the line, and the string did not end with - # \n, then we end the line. - if @line_started - @out.puts '' - @line_started = false - elsif !printed_anything - if options[:name] - @out.puts ' ' * (indent + 3 + options[:name].size) - else - @out.puts ' ' * indent - end - end - end - end - end - - private - - def from_args(colors, merge_options = {}) - if colors.size == 1 && colors[0].kind_of?(Hash) - merge_options.merge(colors[0]) - else - merge_options.merge({ :colors => colors }) - end - end - - def print_line(line, options) - # Start the line with indent if it is not started - if !@line_started - if options[:name] - @out.print ' ' * (indent + 3 + options[:name].size) - else - @out.print ' ' * indent - end - @line_started = true - end - # Note that the next line will need to be started - if line[-1..-1] == "\n" - @line_started = false - end - - if Chef::Config[:color] && options[:colors] - @out.print highline.color(line, *options[:colors]) - else - @out.print line - end - end - end - - # == Formatters::Base # Base class that all formatters should inherit from. class Base < EventDispatch::Base @@ -210,7 +72,7 @@ class Chef attr_reader :output def initialize(out, err) - @output = Outputter.new(out, err) + @output = IndentableOutputStream.new(out, err) end def puts(*args) @@ -229,10 +91,6 @@ class Chef @output.start_line(*args) end - def print_sticky(*args) - @output.print_sticky(*args) - end - def indent_by(amount) @output.indent += amount end diff --git a/lib/chef/formatters/indentable_output_stream.rb b/lib/chef/formatters/indentable_output_stream.rb new file mode 100644 index 0000000000..6e7d2c3990 --- /dev/null +++ b/lib/chef/formatters/indentable_output_stream.rb @@ -0,0 +1,154 @@ +class Chef + module Formatters + # Handles basic indentation and colorization tasks + class IndentableOutputStream + + attr_reader :out + attr_reader :err + attr_accessor :indent + attr_reader :line_started + attr_accessor :current_stream + attr_reader :semaphore + + def initialize(out, err) + @out, @err = out, err + @indent = 0 + @line_started = false + @semaphore = Mutex.new + end + + def highline + @highline ||= begin + require 'highline' + HighLine.new + end + end + + # Print text. This will start a new line and indent if necessary + # but will not terminate the line (future print and puts statements + # will start off where this print left off). + def color(string, *args) + print(string, from_args(args)) + end + + # Print the start of a new line. This will terminate any existing lines and + # cause indentation but will not move to the next line yet (future 'print' + # and 'puts' statements will stay on this line). + def start_line(string, *args) + print(string, from_args(args, :start_line => true)) + end + + # Print a line. This will continue from the last start_line or print, + # or start a new line and indent if necessary. + def puts(string, *args) + print(string, from_args(args, :end_line => true)) + end + + # Print an entire line from start to end. This will terminate any existing + # lines and cause indentation. + def puts_line(string, *args) + print(string, from_args(args, :start_line => true, :end_line => true)) + end + + # Print a string. + # + # == Arguments + # string: string to print. + # options: a hash with these possible options: + # - :stream => OBJ: unique identifier for a stream. If two prints have + # different streams, they will print on separate lines. + # Otherwise, they will stay together. + # - :start_line => BOOLEAN: if true, print will begin on a blank (indented) line. + # - :end_line => BOOLEAN: if true, current line will be ended. + # - :name => STRING: a name to prefix in front of a stream. It will be printed + # once (with the first line of the stream) and subsequent lines + # will be indented to match. + # + # == Alternative + # + # You may also call print('string', :red) (a list of colors a la Highline.color) + def print(string, *args) + options = from_args(args) + + # Make sure each line stays a unit even with threads sending output + semaphore.synchronize do + # If we aren't printing to the same stream, move to the next line + # and print the stream header (if any) + if @current_stream != options[:stream] + @current_stream = options[:stream] + if @line_started + @out.puts '' + end + if options[:name] + @out.print "#{(' ' * indent)}[#{options[:name]}] " + else + @out.print ' ' * indent + end + @line_started = true + + # if start_line is true, move to the next line. + elsif options[:start_line] + if @line_started + @out.puts '' + @line_started = false + end + end + + # Split the output by line and indent each + printed_anything = false + string.lines.each do |line| + printed_anything = true + print_line(line, options) + end + + if options[:end_line] + # If we're supposed to end the line, and the string did not end with + # \n, then we end the line. + if @line_started + @out.puts '' + @line_started = false + elsif !printed_anything + if options[:name] + @out.puts ' ' * (indent + 3 + options[:name].size) + else + @out.puts ' ' * indent + end + end + end + end + end + + private + + def from_args(colors, merge_options = {}) + if colors.size == 1 && colors[0].kind_of?(Hash) + merge_options.merge(colors[0]) + else + merge_options.merge({ :colors => colors }) + end + end + + def print_line(line, options) + # Start the line with indent if it is not started + if !@line_started + if options[:name] + @out.print ' ' * (indent + 3 + options[:name].size) + else + @out.print ' ' * indent + end + @line_started = true + end + # Note that the next line will need to be started + if line[-1..-1] == "\n" + @line_started = false + end + + if Chef::Config[:color] && options[:colors] + @out.print highline.color(line, *options[:colors]) + else + @out.print line + end + end + end + end +end |