Module: Puppet::Util::Docs

Overview

Some simple methods for helping manage automatic documentation generation.

Constant Summary collapse

HEADER_LEVELS =
[nil, "#", "##", "###", "####", "#####"]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#docObject

Generate the full doc string.


20
21
22
23
24
25
26
27
28
29
30
# File 'lib/puppet/util/docs.rb', line 20

def doc
  extra = methods.find_all { |m| m.to_s =~ /^dochook_.+/ }.sort.collect { |m|
    self.send(m)
  }.delete_if {|r| r.nil? }.collect {|r| "* #{r}"}.join("\n")

  if @doc
    scrub(@doc) + (extra.empty? ? '' : "\n\n#{extra}")
  else
    extra
  end
end

#nodocObject (readonly)

There is nothing that would ever set this. It gets read in reference/type.rb, but will never have any value but nil.


67
68
69
# File 'lib/puppet/util/docs.rb', line 67

def nodoc
  @nodoc
end

Class Method Details

.scrub(text) ⇒ Object

Strip indentation and trailing whitespace from embedded doc fragments.

Multi-line doc fragments are sometimes indented in order to preserve the formatting of the code they're embedded in. Since indents are syntactic elements in Markdown, we need to make sure we remove any indent that was added solely to preserve surrounding code formatting, but LEAVE any indent that delineates a Markdown element (code blocks, multi-line bulleted list items). We can do this by removing the *least common indent* from each line.

Least common indent is defined as follows:

  • Find the smallest amount of leading space on any line…

  • …excluding the first line (which may have zero indent without affecting the common indent)…

  • …and excluding lines that consist solely of whitespace.

  • The least common indent may be a zero-length string, if the fragment is not indented to match code.

  • If there are hard tabs for some dumb reason, we assume they're at least consistent within this doc fragment.

See tests in spec/unit/util/docs_spec.rb for examples.


114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/puppet/util/docs.rb', line 114

def scrub(text)
  # One-liners are easy! (One-liners may be buffered with extra newlines.)
  return text.strip if text.strip !~ /\n/
  excluding_first_line = text.partition("\n").last
  indent = excluding_first_line.scan(/^[ \t]*(?=\S)/).min || '' # prevent nil
  # Clean hanging indent, if any
  if indent.length > 0
    text = text.gsub(/^#{indent}/, '')
  end
  # Clean trailing space
  text.lines.map{|line|line.rstrip}.join("\n").rstrip
end

Instance Method Details

#desc(str) ⇒ Object

Specify the actual doc string.


4
5
6
# File 'lib/puppet/util/docs.rb', line 4

def desc(str)
  @doc = str
end

#dochook(name, &block) ⇒ Object

Add a new autodoc block. We have to define these as class methods, rather than just sticking them in a hash, because otherwise they're too difficult to do inheritance with.


11
12
13
14
15
# File 'lib/puppet/util/docs.rb', line 11

def dochook(name, &block)
  method = "dochook_#{name}"

  meta_def method, &block
end

#doctable(headers, data) ⇒ Object

Build a table


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
# File 'lib/puppet/util/docs.rb', line 33

def doctable(headers, data)
  str = "\n\n"

  lengths = []
  # Figure out the longest field for all columns
  data.each do |name, values|
    [name, values].flatten.each_with_index do |value, i|
      lengths[i] ||= 0
      lengths[i] = value.to_s.length if value.to_s.length > lengths[i]
    end
  end

  # The headers could also be longest
  headers.each_with_index do |value, i|
    lengths[i] = value.to_s.length if value.to_s.length > lengths[i]
  end

  # Add the header names
  str += headers.zip(lengths).collect { |value, num| pad(value, num) }.join(" | ") + " |" + "\n"

  # And the header row
  str += lengths.collect { |num| "-" * num }.join(" | ") + " |" + "\n"

  # Now each data row
  data.sort { |a, b| a[0].to_s <=> b[0].to_s }.each do |name, rows|
    str += [name, rows].flatten.zip(lengths).collect do |value, length|
      pad(value, length)
    end.join(" | ") + " |" + "\n"
  end

  str + "\n"
end

#markdown_definitionlist(term, definition) ⇒ Object


83
84
85
86
87
88
89
90
91
# File 'lib/puppet/util/docs.rb', line 83

def markdown_definitionlist(term, definition)
  lines = scrub(definition).split("\n")
  str = "#{term}\n: #{lines.shift}\n"
  lines.each do |line|
    str << "  " if line =~ /\S/
    str << "#{line}\n"
  end
  str << "\n"
end

#markdown_header(name, level) ⇒ Object


79
80
81
# File 'lib/puppet/util/docs.rb', line 79

def markdown_header(name, level)
  "#{HEADER_LEVELS[level]} #{name}\n\n"
end

#nodoc?Boolean


68
69
70
# File 'lib/puppet/util/docs.rb', line 68

def nodoc?
  nodoc
end

#pad(value, length) ⇒ Object

Pad a field with spaces


73
74
75
# File 'lib/puppet/util/docs.rb', line 73

def pad(value, length)
  value.to_s + (" " * (length - value.to_s.length))
end