SamovarSourceSamovarOutputUsageFormatter

class UsageFormatter

Formats and prints usage information to a terminal.

Dispatches on the type of each output object to apply custom formatting rules.

Definitions

def self.print(rows, output)

Print usage information to the output.

Signature

parameter rows Rows

The rows to format and print.

parameter output IO

The output stream to print to.

yields {|formatter| ...}

Optional block to customize the formatter.

Implementation

def self.print(rows, output)
	formatter = self.new(output)
	
	yield formatter if block_given?
	
	formatter.print(rows)
end

def print(rows, first: true)

Print the formatted usage output.

Implementation

def print(rows, first: true)
	map(rows, first: first)
end

def initialize(output)

Initialize a new usage formatter.

Signature

parameter rows Rows

The rows to format.

parameter output IO

The output stream to print to.

Implementation

def initialize(output)
	@output = output
	@width = 80
	
	@terminal = Console::Terminal.for(@output)
	@terminal[:header] = @terminal.style(nil, nil, :bright)
	@terminal[:description] = @terminal.style(:blue)
	@terminal[:error] = @terminal.style(:red)
end

def map(object, *arguments, first: true)

Format and print the given object according to its type.

Signature

parameter object Object

The object to format (a class Samovar::Output::Rows, class Samovar::Output::Row, class Samovar::Output::Header, or error).

parameter arguments Array

Extra context passed through to nested rows (the containing class Samovar::Output::Rows).

Implementation

def map(object, *arguments, first: true)
	case object
	when InvalidInputError
		# This is a little hack which avoids printing out "--help" if it was part of an incomplete parse. In the future I'd prefer if this was handled explicitly.
		@terminal.puts("#{object.message} in:", style: :error) unless object.help?
	when MissingValueError
		@terminal.puts("#{object.message} in:", style: :error)
	when Header
		header, rows = object, arguments.first
		
		if first
			first = false
		else
			@terminal.puts
		end
		
		command_line = header.object.command_line(header.name)
		@terminal.puts "#{rows.indentation}#{command_line}", style: :header
		
		if description = header.object.description
			@terminal.puts "#{rows.indentation}\t#{description}", style: :description
			@terminal.puts
		end
	when Row
		row, rows = object, arguments.first
		@terminal.puts "#{rows.indentation}#{row.align(rows.columns)}"
	when Rows
		object.each do |row, rows|
			first = map(row, rows, first: first)
		end
	else
		raise ArgumentError, "Unable to format #{object.class}!"
	end
	
	return first
end