class Cri::HelpRenderer
The {HelpRenderer} class is responsible for generating a string containing the help for a given command, intended to be printed on the command line.
Constants
- DESC_INDENT
The indentation of descriptions
- LINE_WIDTH
The line width of the help output
- OPT_DESC_SPACING
The spacing between an option name and option description
Public Class Methods
new(cmd, **params)
click to toggle source
Creates a new help renderer for the given command.
@param [Cri::Command] cmd The command to generate the help for
@option params [Boolean] :verbose true if the help output should be
verbose, false otherwise.
# File lib/cri/help_renderer.rb, line 22 def initialize(cmd, **params) @cmd = cmd @is_verbose = params.fetch(:verbose, false) @io = params.fetch(:io, $stdout) end
Public Instance Methods
render()
click to toggle source
@return [String] The help text for this command
# File lib/cri/help_renderer.rb, line 29 def render text = +'' append_summary(text) append_usage(text) append_description(text) append_subcommands(text) append_options(text) text end
Private Instance Methods
append_description(text)
click to toggle source
# File lib/cri/help_renderer.rb, line 76 def append_description(text) return if @cmd.description.nil? text << "\n" text << fmt.format_as_title('description', @io) << "\n" text << (fmt.wrap_and_indent(@cmd.description, LINE_WIDTH, DESC_INDENT) + "\n") end
append_option_group(text, name, defs, length)
click to toggle source
# File lib/cri/help_renderer.rb, line 149 def append_option_group(text, name, defs, length) return if defs.empty? text << "\n" text << fmt.format_as_title(name.to_s, @io) text << "\n" ordered_defs = defs.sort_by { |x| x.short || x.long } ordered_defs.reject(&:hidden).each do |opt_defn| text << format_opt_defn(opt_defn, length) desc = opt_defn.desc + (opt_defn.default ? " (default: #{opt_defn.default})" : '') text << fmt.wrap_and_indent(desc, LINE_WIDTH, length + OPT_DESC_SPACING + DESC_INDENT, true) << "\n" end end
append_options(text)
click to toggle source
# File lib/cri/help_renderer.rb, line 137 def append_options(text) groups = { 'options' => @cmd.option_definitions } if @cmd.supercommand groups["options for #{@cmd.supercommand.name}"] = @cmd.supercommand.global_option_definitions end length = length_for_opt_defns(groups.values.inject(&:+)) groups.keys.sort.each do |name| defs = groups[name] append_option_group(text, name, defs, length) end end
append_subcommands(text)
click to toggle source
# File lib/cri/help_renderer.rb, line 84 def append_subcommands(text) return if @cmd.subcommands.empty? text << "\n" text << fmt.format_as_title(@cmd.supercommand ? 'subcommands' : 'commands', @io) text << "\n" shown_subcommands = @cmd.subcommands.select { |c| !c.hidden? || @is_verbose } length = shown_subcommands.map { |c| fmt.format_as_command(c.name, @io).size }.max # Command shown_subcommands.sort_by(&:name).each do |cmd| text << format( " %<name>-#{length + DESC_INDENT}s %<summary>s\n", name: fmt.format_as_command(cmd.name, @io), summary: cmd.summary, ) end # Hidden notice unless @is_verbose diff = @cmd.subcommands.size - shown_subcommands.size if diff == 1 text << " (1 hidden command omitted; show it with --verbose)\n" elsif diff > 1 text << " (#{diff} hidden commands omitted; show them with --verbose)\n" end end end
append_summary(text)
click to toggle source
# File lib/cri/help_renderer.rb, line 47 def append_summary(text) return if @cmd.name.nil? text << fmt.format_as_title('name', @io) << "\n" text << ' ' << fmt.format_as_command(@cmd.name, @io) if @cmd.summary text << ' - ' << @cmd.summary end text << "\n" unless @cmd.aliases.empty? text << ' aliases: ' << @cmd.aliases.map { |a| fmt.format_as_command(a, @io) }.join(' ') << "\n" end end
append_usage(text)
click to toggle source
# File lib/cri/help_renderer.rb, line 63 def append_usage(text) return if @cmd.usage.nil? path = [@cmd.supercommand] path.unshift(path[0].supercommand) until path[0].nil? formatted_usage = @cmd.usage.gsub(/^([^\s]+)/) { |m| fmt.format_as_command(m, @io) } full_usage = path[1..-1].map { |c| fmt.format_as_command(c.name, @io) + ' ' }.join + formatted_usage text << "\n" text << fmt.format_as_title('usage', @io) << "\n" text << fmt.wrap_and_indent(full_usage, LINE_WIDTH, DESC_INDENT) << "\n" end
fmt()
click to toggle source
# File lib/cri/help_renderer.rb, line 43 def fmt @fmt ||= Cri::StringFormatter.new end
format_opt_defn(opt_defn, length)
click to toggle source
# File lib/cri/help_renderer.rb, line 196 def format_opt_defn(opt_defn, length) short_value_postfix = short_value_postfix_for(opt_defn) long_value_postfix = long_value_postfix_for(opt_defn) opt_text = +'' opt_text_len = 0 if opt_defn.short opt_text << fmt.format_as_option('-' + opt_defn.short, @io) opt_text << short_value_postfix opt_text << ' ' opt_text_len += 1 + opt_defn.short.size + short_value_postfix.size + 1 else opt_text << ' ' opt_text_len += 3 end opt_text << fmt.format_as_option('--' + opt_defn.long, @io) if opt_defn.long opt_text << long_value_postfix opt_text_len += 2 + opt_defn.long.size if opt_defn.long opt_text_len += long_value_postfix.size ' ' + opt_text + (' ' * (length + OPT_DESC_SPACING - opt_text_len)) end
length_for_opt_defns(opt_defns)
click to toggle source
# File lib/cri/help_renderer.rb, line 115 def length_for_opt_defns(opt_defns) opt_defns.map do |opt_defn| string = +'' # Always pretend there is a short option string << '-X' if opt_defn.long string << (' --' + opt_defn.long) end case opt_defn.argument when :required string << '=<value>' when :optional string << '=[<value>]' end string.size end.max end
long_value_postfix_for(opt_defn)
click to toggle source
# File lib/cri/help_renderer.rb, line 180 def long_value_postfix_for(opt_defn) value_postfix = case opt_defn.argument when :required '=<value>' when :optional '[=<value>]' end if value_postfix opt_defn.long ? value_postfix : '' else '' end end
short_value_postfix_for(opt_defn)
click to toggle source
# File lib/cri/help_renderer.rb, line 164 def short_value_postfix_for(opt_defn) value_postfix = case opt_defn.argument when :required '<value>' when :optional '[<value>]' end if value_postfix opt_defn.long ? '' : ' ' + value_postfix else '' end end