Module: Rubycom::Documentation

Defined in:
lib/rubycom/documentation.rb

Class Method Summary collapse

Class Method Details

.get_command_summary(base, command_name, separator = ' - ') ⇒ String

Retrieves the summary for the given command_name

Raises:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rubycom/documentation.rb', line 30

def self.get_command_summary(base, command_name, separator = '  -  ')
  raise CLIError, "Can not get usage for #{command_name} with base: #{base||"nil"}" if base.nil? || !base.respond_to?(:included_modules)
  return 'No command specified.' if command_name.nil? || command_name.length == 0
  if base.included_modules.map { |mod| mod.name.to_sym }.include?(command_name.to_sym)
    begin
      mod_const = Kernel.const_get(command_name.to_sym)
      desc = File.read(mod_const.public_method(mod_const.singleton_methods().first).source_location.first).split(//).reduce("") { |str, c|
        unless str.gsub("\n", '').gsub(/\s+/, '').include?("module#{mod_const}")
          str << c
        end
        str
      }.split("\n").select { |line| line.strip.match(/^#/) && !line.strip.match(/^#!/) }.map { |line| line.strip.gsub(/^#+/, '') }.join("\n")
    rescue
      desc = ""
    end
  else
    raise CLIError, "Invalid command for #{base}, #{command_name}" unless base.public_methods.include?(command_name.to_sym)
    desc = self.get_doc(base.public_method(command_name.to_sym))[:desc].join("\n") rescue ""
  end
  (desc.nil?||desc=='nil'||desc.length==0) ? "#{command_name}\n" : self.get_formatted_summary(command_name, desc, separator)
end

.get_command_usage(base, command_name, args = []) ⇒ String

Retrieves the usage description for the given command_name

Raises:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rubycom/documentation.rb', line 81

def self.get_command_usage(base, command_name, args=[])
  raise CLIError, "Can not get usage for #{command_name} with base: #{base||"nil"}" if base.nil? || !base.respond_to?(:included_modules)
  return 'No command specified.' if command_name.nil? || command_name.length == 0
  if base.included_modules.map { |mod| mod.name.to_sym }.include?(command_name.to_sym)
    if args.empty?
      self.get_usage(eval(command_name.to_s))
    else
      self.get_command_usage(eval(command_name.to_s), args[0], args[1..-1])
    end
  else
    raise CLIError, "Invalid command for #{base}, #{command_name}" unless base.public_methods.include?(command_name.to_sym)
    m = base.public_method(command_name.to_sym)
    method_doc = self.get_doc(m) || {}

    msg = "Usage: #{m.name}#{self.get_param_usage(m)}\n"
    msg << "Parameters:\n    " unless m.parameters.empty?
    msg << "#{method_doc[:param].join("\n    ")}\n" unless method_doc[:param].nil?
    msg << "Returns:\n    " unless method_doc[:return].nil?
    msg << "#{method_doc[:return].join("\n    ")}\n" unless method_doc[:return].nil?
    msg
  end
end

.get_default_commands_usageString



151
152
153
154
155
156
157
158
159
160
# File 'lib/rubycom/documentation.rb', line 151

def self.get_default_commands_usage()
  "\n  Default Commands:\n  help                 - prints this help page\n  job                  - run a job file\n  register_completions - setup bash tab completion\n  tab_complete         - print a list of possible matches for a given word\n  END\nend\n".gsub(/^ {6}/,'')

.get_doc(method) ⇒ Hash

Retrieves the given method’s documentation from it’s source code



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/rubycom/documentation.rb', line 137

def self.get_doc(method)
  method.comment.split("\n").map { |line|
    line.gsub(/#\s*/, '') }.group_by { |doc|
    if doc.match(/^@\w+/).nil?
      :desc
    else
      doc.match(/^@\w+/).to_s.gsub('@', '').to_sym
    end
  }.map { |key, val|
    Hash[key, val.map { |val_line| val_line.gsub(/^@\w+/, '').lstrip }.select { |line| line != '' }]
  }.reduce(&:merge)
end

.get_formatted_summary(command_name, command_description, separator = ' - ') ⇒ Object

Arranges the given command_name and command_description with the separator in a standard format



57
58
59
60
61
62
63
# File 'lib/rubycom/documentation.rb', line 57

def self.get_formatted_summary(command_name, command_description, separator = '  -  ')
  width = 95
  prefix = command_name.to_s.split(//).map { " " }.join + separator.split(//).map { " " }.join
  line_width = width - prefix.length
  description_msg = command_description.gsub(/(.{1,#{line_width}})(?: +|$)\n?|(.{#{line_width}})/, "#{prefix}"+'\1\2'+"\n")
  "#{command_name}#{separator}#{description_msg.lstrip}"
end

.get_job_usage(base) ⇒ String



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/rubycom/documentation.rb', line 163

def self.get_job_usage(base)
  "  Usage: \#{base} job <job_path>\n  Parameters:\n    [String] job_path the path to the job yaml to be run\n  Details:\n  A job yaml is any yaml file which follows the format below.\n    * The env: key shown below is optional\n    * The steps: key must contain a set of numbered steps as shown\n    * The desc: key shown below is an optional context for the job's log output\n      * Other than cmd: there may be as many keys in a numbered command as you choose\n  ---\n  env:\n    test_msg: Hello World\n    test_arg: 123\n    working_dir: ./test\n  steps:\n    1:\n      desc: Run test command with environment variable\n      test_context: Some more log context\n      cmd: ruby env[working_dir]/test.rb test_command env[test_msg]\n    2:\n      cmd: ls env[working_dir]\n  END\nend\n".gsub(/^ {6}/,'')

.get_param_usage(method) ⇒ Object

Discovers the given Method’s parameters and uses them to build a formatted usage string



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rubycom/documentation.rb', line 107

def self.get_param_usage(method)
  return "" if method.parameters.nil? || method.parameters.empty?
  Arguments.get_param_definitions(method).group_by { |_, hsh|
    hsh[:type]
  }.map { |key, val_arr|
    vals = Hash[*val_arr.flatten]
    {
        key => if key == :opt
                 vals.map { |param, val_hsh| "-#{param.to_s}=#{val_hsh[:default]}" }
               elsif key == :req
                 vals.keys.map { |param| " <#{param.to_s}>" }
               else
                 vals.keys.map { |param| " [&#{param.to_s}]" }
               end
    }
  }.reduce(&:merge).map { |type, param_arr|
    if type == :opt
      " [#{param_arr.join("|")}]"
    else
      param_arr.join
    end
  }.join
end

.get_register_completions_usage(base) ⇒ Object



189
190
191
192
193
# File 'lib/rubycom/documentation.rb', line 189

def self.get_register_completions_usage(base)
  "  Usage: \#{base} register_completions\n  END\nend\n".gsub(/^ {6}/,'')

.get_separator(sym, spacer_length = 0) ⇒ String

Creates a separator with the appropriate spacing to line up a command/description pair in a command list



21
22
23
# File 'lib/rubycom/documentation.rb', line 21

def self.get_separator(sym, spacer_length=0)
  [].unshift(" " * (spacer_length - sym.to_s.length)).join << "  -  "
end

.get_summary(base) ⇒ String

Retrieves the summary for each command method in the given Module



10
11
12
13
14
# File 'lib/rubycom/documentation.rb', line 10

def self.get_summary(base)
  Commands.get_top_level_commands(base).each_with_index.map { |sym, index|
    "#{"Commands:\n" if index == 0}" << self.get_command_summary(base, sym, self.get_separator(sym, Commands.get_longest_command_name(base).length))
  }.reduce(:+) or "No Commands found for #{base}."
end

.get_tab_complete_usage(base) ⇒ Object



195
196
197
198
199
200
201
# File 'lib/rubycom/documentation.rb', line 195

def self.get_tab_complete_usage(base)
  "  Usage: \#{base} tab_complete <word>\n  Parameters:\n    [String] word the word or partial word to find matches for\n  END\nend\n".gsub(/^ {6}/,'')

.get_usage(base) ⇒ String

Retrieves the usage description for the given Module with a list of command methods



69
70
71
72
73
# File 'lib/rubycom/documentation.rb', line 69

def self.get_usage(base)
  return '' if base.nil? || !base.respond_to?(:included_modules)
  return '' if Commands.get_top_level_commands(base).size == 0
  "Usage:\n    #{base} <command> [args]\n\n" << self.get_summary(base)
end