class TTY::Option::Formatter

Constants

DEFAULT_NAME_SELECTOR
DEFAULT_ORDER
DEFAULT_PARAM_DISPLAY
DEFAULT_WIDTH
ELLIPSIS
NEWLINE
NOOP_PROC
SHORT_OPT_LENGTH
SPACE

Attributes

width[R]

Public Class Methods

help(parameters, usage, **config, &block) click to toggle source

@api public

# File lib/tty/option/formatter.rb, line 23
def self.help(parameters, usage, **config, &block)
  new(parameters, usage, **config).help(&block)
end
new(parameters, usage, param_display: DEFAULT_PARAM_DISPLAY, width: DEFAULT_WIDTH, order: DEFAULT_ORDER, indent: 0) click to toggle source

Create a help formatter

@param [Parameters]

@api public

# File lib/tty/option/formatter.rb, line 34
def initialize(parameters, usage, param_display: DEFAULT_PARAM_DISPLAY,
               width: DEFAULT_WIDTH, order: DEFAULT_ORDER, indent: 0)
  @parameters = parameters
  @usage = usage
  @param_display = param_display
  @order = order
  @width = width
  @indent = indent
  @space_indent = SPACE * indent
  @param_indent = indent + 2
  @section_names = {
    usage: "Usage:",
    arguments: "Arguments:",
    keywords: "Keywords:",
    options: "Options:",
    env: "Environment:",
    examples: "Examples:"
  }
end

Public Instance Methods

help() { |sections| ... } click to toggle source

A formatted help usage information

@yieldparam [TTY::Option::Sections] sections

@return [String]

@api public

# File lib/tty/option/formatter.rb, line 61
def help
  sections = Sections.new

  sections.add(:header, help_header) if @usage.header?
  sections.add(:banner, help_banner)
  sections.add(:description, help_description) if @usage.desc?

  if @parameters.arguments.any?(&:display?)
    sections.add(:arguments, help_arguments)
  end

  if @parameters.keywords.any?(&:display?)
    sections.add(:keywords, help_keywords)
  end

  if @parameters.options?
    sections.add(:options, help_options)
  end

  if @parameters.environments.any?(&:display?)
    sections.add(:environments, help_environments)
  end

  sections.add(:examples, help_examples) if @usage.example?
  sections.add(:footer, help_footer) if @usage.footer?

  yield(sections) if block_given?

  formatted = sections.reject(&:empty?).join(NEWLINE)
  formatted.end_with?(NEWLINE) ? formatted : formatted + NEWLINE
end
help_arguments() click to toggle source
# File lib/tty/option/formatter.rb, line 105
def help_arguments
  "#{NEWLINE}#{@space_indent}#{@section_names[:arguments]}#{NEWLINE}" +
    format_section(@parameters.arguments, ->(param) do
      @param_display.(param.name)
    end)
end
help_banner() click to toggle source
# File lib/tty/option/formatter.rb, line 97
def help_banner
  (@usage.banner? ? @usage.banner : format_usage)
end
help_description() click to toggle source
# File lib/tty/option/formatter.rb, line 101
def help_description
  "#{NEWLINE}#{format_description}"
end
help_environments() click to toggle source
# File lib/tty/option/formatter.rb, line 124
def help_environments
  "#{NEWLINE}#{@space_indent}#{@section_names[:env]}#{NEWLINE}" +
    format_section(@order.(@parameters.environments))
end
help_examples() click to toggle source
# File lib/tty/option/formatter.rb, line 129
def help_examples
  "#{NEWLINE}#{@space_indent}#{@section_names[:examples]}#{NEWLINE}" +
    format_examples
end
help_header() click to toggle source
# File lib/tty/option/formatter.rb, line 93
def help_header
  "#{format_multiline(@usage.header, @indent)}#{NEWLINE}"
end
help_keywords() click to toggle source
# File lib/tty/option/formatter.rb, line 112
def help_keywords
  "#{NEWLINE}#{@space_indent}#{@section_names[:keywords]}#{NEWLINE}" +
    format_section(@parameters.keywords, ->(param) do
      kwarg_param_display(param).split("=").map(&@param_display).join("=")
    end)
end
help_options() click to toggle source
# File lib/tty/option/formatter.rb, line 119
def help_options
  "#{NEWLINE}#{@space_indent}#{@section_names[:options]}#{NEWLINE}" +
    format_options
end

Private Instance Methods

format_argument_usage(arg) click to toggle source

Provide an argument summary

@api private

# File lib/tty/option/formatter.rb, line 171
def format_argument_usage(arg)
  arg_name = @param_display.(arg.name)
  format_parameter_usage(arg, arg_name)
end
format_arguments_usage() click to toggle source

Format arguments

@api private

# File lib/tty/option/formatter.rb, line 158
def format_arguments_usage
  return "" unless @parameters.arguments?

  @parameters.arguments.reduce([]) do |acc, arg|
    next acc if arg.hidden?

    acc << format_argument_usage(arg)
  end.join(SPACE)
end
format_default(param) click to toggle source

Format default value

@api private

# File lib/tty/option/formatter.rb, line 357
def format_default(param)
  return if !param.default? || [true, false].include?(param.default)

  if param.default.is_a?(String)
    format(" (default %p)", param.default)
  else
    format(" (default %s)", param.default)
  end
end
format_description() click to toggle source

Format multiline description

@api private

# File lib/tty/option/formatter.rb, line 284
def format_description
  format_multiline(@usage.desc, @indent)
end
format_examples() click to toggle source

Format examples section

@api private

# File lib/tty/option/formatter.rb, line 370
def format_examples
  format_multiline(@usage.example, @param_indent)
end
format_keyword_usage(kwarg) click to toggle source

Provide a keyword summary

@api private

# File lib/tty/option/formatter.rb, line 210
def format_keyword_usage(kwarg)
  param_name = kwarg_param_display(kwarg, @param_display)
  format_parameter_usage(kwarg, param_name)
end
format_keywords_usage() click to toggle source

Format keywords usage

@api private

# File lib/tty/option/formatter.rb, line 197
def format_keywords_usage
  return "" unless @parameters.keywords?

  @parameters.keywords.reduce([]) do |acc, kwarg|
    next acc if kwarg.hidden?

    acc << format_keyword_usage(kwarg)
  end.join(SPACE)
end
format_multiline(lines, indent) click to toggle source

Format multiline content

@api private

# File lib/tty/option/formatter.rb, line 377
def format_multiline(lines, indent)
  last_index = lines.size - 1
  lines.map.with_index do |line, i|
    line.map do |part|
      part.split(NEWLINE).map do |p|
        wrap(p, indent: indent, width: width, indent_first: true)
      end.join(NEWLINE)
    end.join(NEWLINE) + (last_index != i ? NEWLINE : "")
  end.join(NEWLINE)
end
format_option(option, longest_length, any_short) click to toggle source

Format an option

@api private

# File lib/tty/option/formatter.rb, line 310
def format_option(option, longest_length, any_short)
  line = [@space_indent]
  desc = []
  indent = @indent

  if any_short
    short_option = option.short? ? option.short_name : SPACE
    line << format("%#{SHORT_OPT_LENGTH}s", short_option)
    indent += SHORT_OPT_LENGTH
  end

  # short & long option separator
  line << ((option.short? && option.long?) ? ", " : "  ")
  indent += 2

  if option.long?
    if option.desc?
      line << format("%-#{longest_length}s", option.long)
    else
      line << option.long
    end
  else
    line << format("%-#{longest_length}s", SPACE)
  end
  indent += longest_length

  if option.desc?
    desc << "  #{option.desc}"
  end
  indent += 2

  if option.permit?
    desc << format(" (permitted: %s)", option.permit.join(","))
  end

  if (default = format_default(option))
    desc << default
  end

  line << wrap(desc.join, indent: indent, width: width)

  line.join
end
format_options() click to toggle source

Returns all the options formatted to fit 80 columns

@return [String]

@api private

# File lib/tty/option/formatter.rb, line 293
def format_options
  return "" if @parameters.options.empty?

  longest_option = @parameters.options.map(&:long)
                              .compact.max_by(&:length).length
  any_short = @parameters.options.map(&:short).compact.any?
  ordered_options = @order.(@parameters.options)

  ordered_options.reduce([]) do |acc, option|
    next acc if option.hidden?
    acc << format_option(option, longest_option, any_short)
  end.join(NEWLINE)
end
format_parameter_usage(param, param_name) click to toggle source

Format parameter usage

@api private

# File lib/tty/option/formatter.rb, line 179
def format_parameter_usage(param, param_name)
  args = []
  if 0 < param.arity
    args << "[" if param.optional?
    args << param_name
    (param.arity - 1).times { args << " #{param_name}" }
    args << "]" if param.optional?
    args.join
  else
    (param.arity.abs - 1).times { args << param_name }
    args << "[#{param_name}#{ELLIPSIS}]"
    args.join(SPACE)
  end
end
format_section(params, name_selector = DEFAULT_NAME_SELECTOR) click to toggle source

Format a parameter section in the help display

@param [String] parameters_name

the name of parameter type

@param [Proc] name_selector

selects a name from the parameter, by defeault the name

@return [String]

@api private

# File lib/tty/option/formatter.rb, line 241
def format_section(params, name_selector = DEFAULT_NAME_SELECTOR)
  longest_param = params.map(&name_selector).compact.max_by(&:length).length

  params.reduce([]) do |acc, param|
    next acc if param.hidden?

    acc << format_section_parameter(param, longest_param, name_selector)
  end.join(NEWLINE)
end
format_section_parameter(param, longest_param, name_selector) click to toggle source

Format a section parameter line

@return [String]

@api private

# File lib/tty/option/formatter.rb, line 256
def format_section_parameter(param, longest_param, name_selector)
  line = []
  desc = []
  indent = @param_indent + longest_param + 2
  param_name = name_selector.(param)

  if param.desc?
    line << format("%s%-#{longest_param}s", SPACE * @param_indent, param_name)
    desc << "  #{param.desc}"
  else
    line << format("%s%s", SPACE * @param_indent, param_name)
  end

  if param.permit?
    desc << format(" (permitted: %s)", param.permit.join(", "))
  end

  if (default = format_default(param))
    desc << default
  end

  line << wrap(desc.join, indent: indent, width: width)
  line.join
end
format_usage() click to toggle source

Provide a default usage banner

@api private

# File lib/tty/option/formatter.rb, line 143
def format_usage
  usage = @space_indent + @section_names[:usage] + SPACE
  output = []
  output << @usage.program
  output << " #{@usage.commands.join(" ")}" if @usage.command?
  output << " [#{@param_display.("options")}]" if @parameters.options?
  output << " [#{@param_display.("environment")}]" if @parameters.environments?
  output << " #{format_arguments_usage}" if @parameters.arguments?
  output << " #{format_keywords_usage}" if @parameters.keywords?
  usage + wrap(output.join, indent: usage.length, width: width)
end
kwarg_param_display(kwarg, param_display = NOOP_PROC) click to toggle source

Provide a keyword argument display format

@api private

# File lib/tty/option/formatter.rb, line 218
def kwarg_param_display(kwarg, param_display = NOOP_PROC)
  kwarg_name = param_display.(kwarg.name)
  conv_name = case kwarg.convert
              when Proc, NilClass
                kwarg_name
              else
                param_display.(kwarg.convert)
              end

  "#{kwarg_name}=#{conv_name}"
end