Class: Executable::Help
- Inherits:
-
Object
- Object
- Executable::Help
- Defined in:
- lib/executable/help.rb
Overview
Encpsulates command help for defining and displaying well formated help output in plain text, markdown or via manpages if found.
TODO: Currently doesn’t hande aliases/shortcuts well and simply lists them as separate entries.
Creating text help in the fly is fine for personal projects, but for production app, ideally you want to have man pages. You can use the #markdown method to generate ‘.ronn` files and use the ronn tool to build manpages for your project. There is also the binman and md2man projects which can be used similarly.
Defined Under Namespace
Classes: Option
Instance Attribute Summary collapse
-
#cli_class ⇒ Object
readonly
The Executable subclass to which this help applies.
Class Method Summary collapse
Instance Method Summary collapse
- #call_method ⇒ Object private
-
#copyright(text = nil) ⇒ Object
Get or set copyright text.
-
#description(text = nil) ⇒ Object
Get or set command description.
-
#initialize(cli_class) ⇒ Help
constructor
Setup new help object.
- #inspect ⇒ Object
- #lookup(glob, dir) ⇒ Object private
-
#manpage(dir = nil) ⇒ Object
Get man-page if there is one.
-
#markdown ⇒ Object
(also: #md)
Generate a RONN-style Markdown.
-
#method_list ⇒ Object
private
Produce a list relavent methods.
-
#name(text = nil) ⇒ Object
Get or set command name.
-
#option(name, description) ⇒ Object
Set description of an option.
- #option_list ⇒ Object
-
#see_also(text = nil) ⇒ Object
Get or set “see also” text.
-
#show_help(hint = nil) ⇒ Object
(also: #show)
Show help.
- #show_manpage(file) ⇒ Object
-
#subcommand(name, description) ⇒ Object
Set desciption of a subcommand.
-
#text ⇒ Object
(also: #txt)
Generate plain text output.
-
#text_description ⇒ String, NilClass
Description of command in printable form.
-
#text_options ⇒ Array<Fixnum, Options>
List of options coverted to a printable string.
-
#text_subcommands ⇒ String, NilClass
List of subcommands converted to a printable string.
-
#to_s(format = nil) ⇒ Object
Render help text to a given
format
. -
#usage(text = nil) ⇒ Object
Get or set command usage string.
Constructor Details
#initialize(cli_class) ⇒ Help
Setup new help object.
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/executable/help.rb', line 34 def initialize(cli_class) @cli_class = cli_class @name = nil @usage = nil @decription = nil @copying = nil @see_also = nil @options = {} @subcmds = {} end |
Instance Attribute Details
#cli_class ⇒ Object (readonly)
The Executable subclass to which this help applies.
53 54 55 |
# File 'lib/executable/help.rb', line 53 def cli_class @cli_class end |
Class Method Details
.section(name, &default) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/executable/help.rb', line 20 def self.section(name, &default) define_method("default_#{name}", &default) class_eval %{ def #{name}(text=nil) @#{name} = text.to_s unless text.nil? @#{name} ||= default_#{name} end def #{name}=(text) @#{name} = text.to_s end } end |
Instance Method Details
#call_method ⇒ Object (private)
338 339 340 |
# File 'lib/executable/help.rb', line 338 def call_method @call_method ||= method_list.find{ |m| m.name == :call } end |
#copyright(text = nil) ⇒ Object
Get or set copyright text.
92 93 94 |
# File 'lib/executable/help.rb', line 92 section(:copyright) do 'Copyright (c) ' + Time.now.strftime('%Y') end |
#description(text = nil) ⇒ Object
Get or set command description.
83 84 85 |
# File 'lib/executable/help.rb', line 83 section(:description) do nil end |
#inspect ⇒ Object
48 |
# File 'lib/executable/help.rb', line 48 alias_method :inspect, :to_s |
#lookup(glob, dir) ⇒ Object (private)
363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/executable/help.rb', line 363 def lookup(glob, dir) dir = File.(dir) root = '/' home = File.('~') list = [] while dir != home && dir != root list.concat(Dir.glob(File.join(dir, glob))) break unless list.empty? dir = File.dirname(dir) end list.first end |
#manpage(dir = nil) ⇒ Object
Get man-page if there is one.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/executable/help.rb', line 144 def manpage(dir=nil) @manpage ||= ( man = [] dir = nil if dir raise unless File.directory?(dir) end if !dir && call_method file, line = call_method.source_location dir = File.dirname(file) end man_name = name.gsub(/\s+/, '-') + '.1' if dir glob = "man/{man1/,}#{man_name}" lookup(glob, dir) else nil end ) end |
#markdown ⇒ Object Also known as: md
Generate a RONN-style Markdown.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/executable/help.rb', line 218 def markdown commands = text_subcommands = dashname = name.sub(/\s+/, '-') s = [] h = "#{dashname}(1) - #{text_description}" s << h + "\n" + ("=" * h.size) s << "## SYNOPSIS" s << "`" + name + "` [options...] [subcommand]" s << "## DESCRIPTION" s << text_description if !commands.empty? s << "## COMMANDS" s << commands.map{ |cmd, desc| " * `%s:`\n %s" % [cmd, desc] }.join("\n") end if !.empty? s << "## OPTIONS" s << .map{ |max, opt| " * `#{opt.mark}%s`:\n %s" % [opt.usage, opt.description] }.join("\n\n") end if copyright && !copyright.empty? s << "## COPYRIGHT" s << copyright end if see_also && !see_also.empty? s << "## SEE ALSO" s << see_also end s.compact.join("\n\n") end |
#method_list ⇒ Object (private)
Produce a list relavent methods.
345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/executable/help.rb', line 345 def method_list list = [] methods = [] stop_at = cli_class.ancestors.index(Executable::Command) || cli_class.ancestors.index(Executable) || -1 ancestors = cli_class.ancestors[0...stop_at] ancestors.reverse_each do |a| a.instance_methods(false).each do |m| list << cli_class.instance_method(m) end end list end |
#name(text = nil) ⇒ Object
Should this instead default to ‘File.basename($0)` ?
Get or set command name.
By default the name is assumed to be the class name, substituting dashes for double colons.
65 66 67 |
# File 'lib/executable/help.rb', line 65 section(:name) do cli_class.usage_name end |
#option(name, description) ⇒ Object
Set description of an option.
108 109 110 |
# File 'lib/executable/help.rb', line 108 def option(name, description) @options[name.to_s] = description end |
#option_list ⇒ Object
324 325 326 327 328 329 330 331 332 333 |
# File 'lib/executable/help.rb', line 324 def option_list @option_list ||= ( method_list.map do |meth| case meth.name when /^(.*?)[\!\=]$/ Option.new(meth) end end.compact.sort ) end |
#see_also(text = nil) ⇒ Object
Get or set “see also” text.
101 102 103 |
# File 'lib/executable/help.rb', line 101 section(:see_also) do nil end |
#show_help(hint = nil) ⇒ Object Also known as: show
man-pages will probably fail on Windows.
Show help.
124 125 126 127 128 129 130 |
# File 'lib/executable/help.rb', line 124 def show_help(hint=nil) if file = manpage(hint) show_manpage(file) else puts self end end |
#show_manpage(file) ⇒ Object
136 137 138 139 |
# File 'lib/executable/help.rb', line 136 def show_manpage(file) #exec "man #{file}" system "man #{file}" end |
#subcommand(name, description) ⇒ Object
Set desciption of a subcommand.
115 116 117 |
# File 'lib/executable/help.rb', line 115 def subcommand(name, description) @subcmds[name.to_s] = description end |
#text ⇒ Object Also known as: txt
Generate plain text output.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/executable/help.rb', line 185 def text commands = text_subcommands = s = [] s << usage s << text_description if !commands.empty? s << "COMMANDS\n" + commands.map{ |cmd, desc| " %-17s %s" % [cmd, desc] }.join("\n") end if !.empty? s << "OPTIONS\n" + .map{ |max, opt| " %2s%-#{max}s %s" % [opt.mark, opt.usage, opt.description] }.join("\n") end s << copyright s << see_also s.compact.join("\n\n") end |
#text_description ⇒ String, NilClass
Description of command in printable form. But will return nil
if there is no description.
270 271 272 273 274 275 |
# File 'lib/executable/help.rb', line 270 def text_description return description if description #return Source.get_above_comment(@file, @line) if @file call_method ? call_method.comment : nil end |
#text_options ⇒ Array<Fixnum, Options>
List of options coverted to a printable string. But will return nil
if there are no options.
297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/executable/help.rb', line 297 def option_list.each do |opt| if @options.key?(opt.name) opt.description = @options[opt.name] end end max = option_list.map{ |opt| opt.usage.size }.max.to_i + 2 option_list.map do |opt| [max, opt] end end |
#text_subcommands ⇒ String, NilClass
List of subcommands converted to a printable string. But will return nil
if there are no subcommands.
283 284 285 286 287 288 289 |
# File 'lib/executable/help.rb', line 283 def text_subcommands commands = @cli_class.subcommands commands.map do |cmd, klass| desc = klass.help.text_description.to_s.split("\n").first [cmd, desc] end end |
#to_s(format = nil) ⇒ Object
Render help text to a given format
. If no format it given then renders to plain text.
173 174 175 176 177 178 179 180 |
# File 'lib/executable/help.rb', line 173 def to_s(format=nil) case format when :markdown, :md markdown else text end end |
#usage(text = nil) ⇒ Object
Get or set command usage string.
74 75 76 |
# File 'lib/executable/help.rb', line 74 section(:usage) do "Usage: " + name + ' [options...] [subcommand]' end |