Module: CLI::Kit::CommandHelp::ClassMethods

Extended by:
T::Sig
Includes:
Kernel
Included in:
BaseCommand
Defined in:
lib/cli/kit/command_help.rb

Constant Summary collapse

DEFAULT_HELP_SECTIONS =
[
  :desc,
  :long_desc,
  :usage,
  :examples,
  :options,
]

Instance Method Summary collapse

Methods included from T::Sig

sig

Instance Method Details

#_command_nameObject



107
108
109
110
111
112
# File 'lib/cli/kit/command_help.rb', line 107

def _command_name
  return @command_name if @command_name

  last_camel = send(:name).split('::').last
  last_camel.gsub(/([a-z])([A-Z])/, '\1-\2').downcase
end

#_descObject



115
116
117
# File 'lib/cli/kit/command_help.rb', line 115

def _desc
  @desc
end

#build_descObject



120
121
122
123
124
125
126
# File 'lib/cli/kit/command_help.rb', line 120

def build_desc
  out = +"{{command:#{CommandHelp._tool_name} #{_command_name}}}"
  if @desc
    out << ": #{@desc}"
  end
  "{{bold:#{out}}}"
end

#build_examplesObject



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/cli/kit/command_help.rb', line 240

def build_examples
  return nil unless @examples

  cmd_prefix = "  {{command:#{CommandHelp._tool_name} #{_command_name}}}"
  "{{bold:Examples:}}\n" + @examples.map do |command, explanation|
    cmd = "#{cmd_prefix} #{command}"
    exp = "{{italic:{{gray:# #{explanation}}}}}"

    width = CLI::UI::ANSI.printing_width(CLI::UI.fmt("#{cmd} #{exp}"))
    if width > CLI::UI::Terminal.width
      "  #{exp}\n#{cmd}"
    else
      "#{cmd}  #{exp}"
    end
  end.join("\n\n")
end

#build_helpObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/cli/kit/command_help.rb', line 86

def build_help
  h = (@help_sections || DEFAULT_HELP_SECTIONS).map do |section|
    case section
    when :desc
      build_desc
    when :long_desc
      @long_desc
    when :usage
      @usage_section ||= build_usage
    when :examples
      @examples_section ||= build_examples
    when :options
      @options_section ||= build_options
    else
      raise "Unknown help section: #{section}"
    end
  end.compact.map(&:chomp).join("\n\n") + "\n"
  CLI::UI.fmt(h)
end

#build_optionsObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/cli/kit/command_help.rb', line 136

def build_options
  opts = opts_class
  return(nil) unless opts

  methods = []
  loop do
    methods.concat(opts.public_instance_methods(false))
    break if opts.superclass == CLI::Kit::Opts

    opts = opts.superclass
  end

  @defn = Args::Definition.new
  o = opts.new
  o.define!(@defn)

  return nil if @defn.options.empty? && @defn.flags.empty?

  merged = T.let(@defn.options, T::Array[T.any(Args::Definition::Option, Args::Definition::Flag)])
  merged += @defn.flags
  merged.sort_by!(&:name)
  "{{bold:Options:}}\n" + merged.map do |o|
    if o.is_a?(Args::Definition::Option)
      z = '  ' + [o.short&.prepend('-'), o.long&.prepend('--')].compact.join(', ') + ' VALUE'
      default = if o.dynamic_default?
        '(generated default)'
      elsif o.default.nil?
        '(no default)'
      else
        "(default: #{o.default.inspect})"
      end
      z << if o.desc
        "  {{italic:{{gray:# #{o.desc} #{default}}}}}"
      else
        "  {{italic:{{gray:# #{default}}}}}"
      end
    else
      z = '  ' + [o.short&.prepend('-'), o.long&.prepend('--')].compact.join(', ')
      if o.desc
        z << "  {{italic:{{gray:# #{o.desc}}}}}"
      end
    end
    z
  end.join("\n")
end

#build_usageObject



226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/cli/kit/command_help.rb', line 226

def build_usage
  '{{bold:Usage:}}' + case (@usage || []).size
  when 0
    " {{command:#{CommandHelp._tool_name} #{_command_name}}} [options]\n"
  when 1
    " {{command:#{CommandHelp._tool_name} #{_command_name}}} #{@usage.first}\n"
  else
    "\n" + @usage.map do |usage|
      "  {{command:#{CommandHelp._tool_name} #{_command_name}}} #{usage}\n"
    end.join
  end
end

#command_name(command_name) ⇒ Object



188
189
190
191
192
193
194
# File 'lib/cli/kit/command_help.rb', line 188

def command_name(command_name)
  if @command_name
    raise(ArgumentError, "Command name already set to #{@command_name}")
  end

  @command_name = command_name
end

#desc(desc) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/cli/kit/command_help.rb', line 197

def desc(desc)
  # A limit of 80 characters has been chosen to fit on standard terminal configurations. `long_desc` is
  # available when descriptions don't fit nicely in that space. If you're using CLI::Kit for an application
  # where you control the runtime environments and know that terminals will have more than 80 columns
  # available, you can use
  #
  #   CLI::Kit::CommandHelp.max_desc_length =
  #
  # to increase this limit.
  if desc.size > CommandHelp._max_desc_length
    raise(ArgumentError, "description must be #{CommandHelp._max_desc_length} characters or less")
  end
  if @desc
    raise(ArgumentError, 'description already set')
  end

  @desc = desc
end

#example(command, explanation) ⇒ Object



264
265
266
267
# File 'lib/cli/kit/command_help.rb', line 264

def example(command, explanation)
  @examples ||= []
  @examples << [command, explanation]
end

#help_sections(sections) ⇒ Object



183
184
185
# File 'lib/cli/kit/command_help.rb', line 183

def help_sections(sections)
  @help_sections = sections
end

#long_desc(long_desc) ⇒ Object



217
218
219
220
221
222
223
# File 'lib/cli/kit/command_help.rb', line 217

def long_desc(long_desc)
  if @long_desc
    raise(ArgumentError, 'long description already set')
  end

  @long_desc = long_desc
end

#opts_classObject



129
130
131
132
133
# File 'lib/cli/kit/command_help.rb', line 129

def opts_class
  T.unsafe(self).const_get(:Opts) # rubocop:disable Sorbet/ConstantsFromStrings
rescue NameError
  Class.new(CLI::Kit::Opts)
end

#usage(usage) ⇒ Object



258
259
260
261
# File 'lib/cli/kit/command_help.rb', line 258

def usage(usage)
  @usage ||= []
  @usage << usage
end