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

Public Instance Methods

desc(str) click to toggle source

Specify the actual doc string.

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

Generate the full doc string.

   # File lib/puppet/util/docs.rb
21 def doc
22   extra = methods.find_all { |m| m.to_s =~ /^dochook_.+/ }.sort.collect { |m|
23     self.send(m)
24   }.delete_if {|r| r.nil? }.collect {|r| "* #{r}"}.join("\n")
25 
26   if @doc
27     scrub(@doc) + (extra.empty? ? '' : "\n\n#{extra}")
28   else
29     extra
30   end
31 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
12 def dochook(name, &block)
13   method = "dochook_#{name}"
14 
15   meta_def method, &block
16 end
doctable(headers, data) click to toggle source

Build a table

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

Pad a field with spaces

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