1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
# frozen_string_literal: true
require "stringio"
require "clamp/messages"
module Clamp
# Command help generation.
#
module Help
def usage(usage)
@declared_usage_descriptions ||= []
@declared_usage_descriptions << usage
end
attr_reader :declared_usage_descriptions, :description
def description=(description)
@description = description.dup
if @description =~ /^\A\n*( +)/
indent = Regexp.last_match(1)
@description.gsub!(/^#{indent}/, "")
end
@description.strip!
end
def banner(description)
self.description = description
end
def derived_usage_description
parts = ["[OPTIONS]"]
parts += parameters.map(&:name)
parts.join(" ")
end
def usage_descriptions
declared_usage_descriptions || [derived_usage_description]
end
def help(invocation_path, builder = Builder.new)
help = builder
help.add_usage(invocation_path, usage_descriptions)
help.add_description(description)
help.add_list(Clamp.message(:parameters_heading), parameters) if has_parameters?
help.add_list(Clamp.message(:subcommands_heading), recognised_subcommands) if has_subcommands?
help.add_list(Clamp.message(:options_heading), recognised_options)
help.string
end
# A builder for auto-generated help.
#
class Builder
def initialize
@lines = []
end
def string
left_column_width = lines.grep(Array).map(&:first).map(&:size).max
StringIO.new.tap do |out|
lines.each do |line|
case line
when Array
line[0] = line[0].ljust(left_column_width)
line.unshift("")
out.puts(line.join(" "))
else
out.puts(line)
end
end
end.string
end
def line(text = "")
@lines << text
end
def row(lhs, rhs)
@lines << [lhs, rhs]
end
def add_usage(invocation_path, usage_descriptions)
line "#{Clamp.message(:usage_heading)}:"
usage_descriptions.each do |usage|
line " #{invocation_path} #{usage}".rstrip
end
end
def add_description(description)
return unless description
line
line description.gsub(/^/, " ")
end
DETAIL_FORMAT = " %-29s %s"
def add_list(heading, items)
line
line "#{heading}:"
items.reject { |i| i.respond_to?(:hidden?) && i.hidden? }.each do |item|
label, description = item.help
description.each_line do |line|
row(label, line)
label = ""
end
end
end
private
attr_accessor :lines
end
end
end
|