summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn Keiser <jkeiser@opscode.com>2014-05-01 15:56:11 -0700
committerJohn Keiser <jkeiser@opscode.com>2014-05-01 15:56:11 -0700
commit71424d4556f07bb630b59fdb3ed5ee3100873657 (patch)
tree18ad42f638a3fabdf37130fdf1b2d7b606169489 /lib
parentb3815bfaebfa6a026fd64ce8e141cc751d076211 (diff)
downloadchef-71424d4556f07bb630b59fdb3ed5ee3100873657.tar.gz
Move output stream to its own class file
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/formatters/base.rb146
-rw-r--r--lib/chef/formatters/indentable_output_stream.rb154
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