module Puppet::Util::Docs

Some simple methods for helping manage automatic documentation generation.

Constants

HEADER_LEVELS

Attributes

doc[W]
nodoc[R]

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

Public Class Methods

scrub(text) click to toggle source

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.

    # File lib/puppet/util/docs.rb
114 def scrub(text)
115   # One-liners are easy! (One-liners may be buffered with extra newlines.)
116   return text.strip if text.strip !~ /\n/
117   excluding_first_line = text.partition("\n").last
118   indent = excluding_first_line.scan(/^[ \t]*(?=\S)/).min || '' # prevent nil
119   # Clean hanging indent, if any
120   if indent.length > 0
121     text = text.gsub(/^#{indent}/, '')
122   end
123   # Clean trailing space
124   text.lines.map{|line|line.rstrip}.join("\n").rstrip
125 end

Public Instance Methods

desc(str) click to toggle source

Specify the actual doc string.

  # File lib/puppet/util/docs.rb
4 def desc(str)
5   @doc = str
6 end
doc() click to toggle source

Generate the full doc string.

   # File lib/puppet/util/docs.rb
20 def doc
21   extra = methods.find_all { |m| m.to_s =~ /^dochook_.+/ }.sort.collect { |m|
22     self.send(m)
23   }.delete_if {|r| r.nil? }.collect {|r| "* #{r}"}.join("\n")
24 
25   if @doc
26     scrub(@doc) + (extra.empty? ? '' : "\n\n#{extra}")
27   else
28     extra
29   end
30 end
dochook(name, &block) click to toggle source

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.

   # File lib/puppet/util/docs.rb
11 def dochook(name, &block)
12   method = "dochook_#{name}"
13 
14   meta_def method, &block
15 end
doctable(headers, data) click to toggle source

Build a table

   # File lib/puppet/util/docs.rb
33 def doctable(headers, data)
34   str = "\n\n"
35 
36   lengths = []
37   # Figure out the longest field for all columns
38   data.each do |name, values|
39     [name, values].flatten.each_with_index do |value, i|
40       lengths[i] ||= 0
41       lengths[i] = value.to_s.length if value.to_s.length > lengths[i]
42     end
43   end
44 
45   # The headers could also be longest
46   headers.each_with_index do |value, i|
47     lengths[i] = value.to_s.length if value.to_s.length > lengths[i]
48   end
49 
50   # Add the header names
51   str += headers.zip(lengths).collect { |value, num| pad(value, num) }.join(" | ") + " |" + "\n"
52 
53   # And the header row
54   str += lengths.collect { |num| "-" * num }.join(" | ") + " |" + "\n"
55 
56   # Now each data row
57   data.sort { |a, b| a[0].to_s <=> b[0].to_s }.each do |name, rows|
58     str += [name, rows].flatten.zip(lengths).collect do |value, length|
59       pad(value, length)
60     end.join(" | ") + " |" + "\n"
61   end
62 
63   str + "\n"
64 end
markdown_definitionlist(term, definition) click to toggle source
   # File lib/puppet/util/docs.rb
83 def markdown_definitionlist(term, definition)
84   lines = scrub(definition).split("\n")
85   str = "#{term}\n: #{lines.shift}\n"
86   lines.each do |line|
87     str << "  " if line =~ /\S/
88     str << "#{line}\n"
89   end
90   str << "\n"
91 end
markdown_header(name, level) click to toggle source
   # File lib/puppet/util/docs.rb
79 def markdown_header(name, level)
80   "#{HEADER_LEVELS[level]} #{name}\n\n"
81 end
nodoc?() click to toggle source
   # File lib/puppet/util/docs.rb
68 def nodoc?
69   nodoc
70 end
pad(value, length) click to toggle source

Pad a field with spaces

   # File lib/puppet/util/docs.rb
73 def pad(value, length)
74   value.to_s + (" " * (length - value.to_s.length))
75 end

Private Instance Methods

scrub(text) click to toggle source

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.

    # File lib/puppet/util/docs.rb
114 def scrub(text)
115   # One-liners are easy! (One-liners may be buffered with extra newlines.)
116   return text.strip if text.strip !~ /\n/
117   excluding_first_line = text.partition("\n").last
118   indent = excluding_first_line.scan(/^[ \t]*(?=\S)/).min || '' # prevent nil
119   # Clean hanging indent, if any
120   if indent.length > 0
121     text = text.gsub(/^#{indent}/, '')
122   end
123   # Clean trailing space
124   text.lines.map{|line|line.rstrip}.join("\n").rstrip
125 end