module Dry::CLI::Usage

def self.arguments(command)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.arguments(command)
  return unless CLI.command?(command)
  required_arguments = command.required_arguments
  optional_arguments = command.optional_arguments
  required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any?
  optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any?
  result = [required, optional].compact
  " #{result.join(" ")}" unless result.empty?
end

def self.call(result)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.call(result)
  header = "Commands:"
  max_length, commands = commands_and_arguments(result)
  commands.map do |banner, node|
    next if node.hidden
    usage = description(node.command) if node.leaf?
    "#{justify(banner, max_length, usage)}#{usage}"
  end.compact.unshift(header).join("\n")
end

def self.command_name(result, name)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.command_name(result, name)
  ProgramName.call([result.names, name])
end

def self.commands(result)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.commands(result)
  result.children.sort_by { |name, _| name }
end

def self.commands_and_arguments(result)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.commands_and_arguments(result)
  max_length = 0
  ret        = commands(result).each_with_object({}) do |(name, node), memo|
    args = if node.command && node.leaf? && node.children?
             ROOT_COMMAND_WITH_SUBCOMMANDS_BANNER
           elsif node.leaf?
             arguments(node.command)
           else
             SUBCOMMAND_BANNER
           end
    partial       = "  #{command_name(result, name)}#{args}"
    max_length    = partial.bytesize if max_length < partial.bytesize
    memo[partial] = node
  end
  [max_length, ret]
end

def self.description(command)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.description(command)
  return unless CLI.command?(command)
  " # #{command.description}" unless command.description.nil?
end

def self.justify(string, padding, usage)

Other tags:
    Api: - private

Other tags:
    Since: - 0.1.0
def self.justify(string, padding, usage)
  return string.chomp(" ") if usage.nil?
  string.ljust(padding + padding / 2)
end