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.



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

def doc
  extra = methods.find_all { |m| m.to_s =~ /^dochook_.+/ }.sort.filter_map { |m|
    send(m)
  }.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.



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

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.



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/puppet/util/docs.rb', line 117

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(&:rstrip).join("\n").rstrip
end

Instance Method Details

#desc(str) ⇒ Object

Specify the actual doc string.



6
7
8
# File 'lib/puppet/util/docs.rb', line 6

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.



13
14
15
16
17
# File 'lib/puppet/util/docs.rb', line 13

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

  meta_def method, &block
end

#doctable(headers, data) ⇒ Object

Build a table



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

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



86
87
88
89
90
91
92
93
94
# File 'lib/puppet/util/docs.rb', line 86

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



82
83
84
# File 'lib/puppet/util/docs.rb', line 82

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

#nodoc?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/puppet/util/docs.rb', line 71

def nodoc?
  nodoc
end

#pad(value, length) ⇒ Object

Pad a field with spaces



76
77
78
# File 'lib/puppet/util/docs.rb', line 76

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