func (doc PluginDocument) GetRST() string {
	result := ""
	result += ".. Autogenerated by Gollum RST generator (docs/generator/*.go)\n\n"
	result += doc.PluginName + "\n"
	result += strings.Repeat("=", len(doc.PluginName)) + "\n"
	result += "\n"
	result += docBulletsToRstBullets(doc.Description) + "\n"
	result += "\n"
	if len(doc.Metadata.slice) > 0 {
		result += formatRstHeading("Metadata")
		result += doc.Metadata.getRST(false, 0)
	}
	for _, parentName := range sortInheritedKeys(doc.InheritedMetadata) {
		if len(doc.InheritedMetadata[parentName].slice) == 0 {
			continue
		}
		result += formatRstHeading(
			"Metadata (from " +   parentName   + ")")
		result += doc.InheritedMetadata[parentName].getRST(false, 0)
	}
	if len(doc.Parameters.slice) > 0 {
		result += formatRstHeading("Parameters")
		result += doc.Parameters.getRST(true, 0)
	}
	for _, parentName := range sortInheritedKeys(doc.InheritedParameters) {
		if len(doc.InheritedParameters[parentName].slice) == 0 {
			continue
		}
		result += formatRstHeading(
			"Parameters (from " +   parentName   + ")")
		result += doc.InheritedParameters[parentName].getRST(true, 0)
	}
	if len(doc.Example) > 0 {
		result += formatRstHeading("Examples")
		codeBlock := false
		for _, line := range strings.Split(doc.Example, "\n") {
			if strings.Index(line, " ") == 0 {
				if !codeBlock {
					result += ".. code-block:: yaml\n\n"
					codeBlock = true
				}
			} else {
				if codeBlock {
					result += "\n"
					codeBlock = false
				}
			}
			if codeBlock {
				result += "\t" + line + "\n"
			} else {
				result += line + "\n"
			}
		}
	}
	return result
}
GetRST returns an RST representation of this PluginDocument.
package main
import (
	"fmt"
	"sort"
	"strings"
)
type PluginDocument struct {
	PackageName         string                     
	PluginName          string                     
	BlockHeading        string                     
	Description         string                     
	Parameters          DefinitionList             
	InheritedParameters map[string]DefinitionList  
	Metadata            DefinitionList             
	InheritedMetadata   map[string]DefinitionList  
	Example             string                     
}
type sliceIterator struct {
	slice    []string
	position int
}
type section uint8
const (
	sectionStart section = iota
	sectionMetadata
	sectionParameters
	sectionConfigurationExample
)
const (
	headingMetadata             string = "Metadata"
	headingParameters           string = "Parameters"
	headingConfigurationExample string = "Examples"
)
func (iter *sliceIterator) next() (string, string, int) {
	if iter.position > len(iter.slice)-1 {
		return "", "", -1
	}
	position := iter.position
	iter.position++
	return iter.slice[position], strings.Trim(iter.slice[position], " \t"), position
}
func (iter *sliceIterator) peek() (string, string, int) {
	if iter.position > len(iter.slice)-1 {
		return "", "", -1
	}
	return iter.slice[iter.position],
		strings.Trim(iter.slice[iter.position], " \t"),
		iter.position
}
func NewPluginDocument(plugin GollumPlugin) PluginDocument {
	pluginDocument := PluginDocument{
		PackageName: plugin.Pkg,
		PluginName:  plugin.Name,
	}
	switch plugin.Pkg {
	case "consumer", "producer", "router":
		pluginDocument.Parameters.add(&Definition{
			name: "Enable",
			desc: "Switches this plugin on or off.",
			dfl:  "true",
		})
	}
	pluginDocument.ParseString(plugin.Comment)
	for _, stParamDef := range plugin.StructTagParams.slice {
		if docParamDef, found := pluginDocument.Parameters.findByName(stParamDef.name); found {
			docParamDef.unit = stParamDef.unit
			docParamDef.dfl = stParamDef.dfl
		} else {
			pluginDocument.Parameters.add(stParamDef)
		}
	}
	for _, embed := range plugin.Embeds {
		importDir := getImportDir(embed.pkg)
		astPackage := parseSourcePath(importDir)
		for _, embedPugin := range findGollumPlugins(astPackage) {
			if embedPugin.Pkg == embed.pkg && embedPugin.Name == embed.name {
				doc := NewPluginDocument(embedPugin)
				pluginDocument.InheritParameters(doc)
				pluginDocument.InheritMetadata(doc)
			}
		}
	}
	return pluginDocument
}
func (doc *PluginDocument) DumpString() string {
	str := ""
	str += "==================== START DUMP ============================\n"
	str += "PackageName: [" + doc.PackageName + "]\n"
	str += "PluginName:  [" + doc.PluginName + "]\n"
	str += "BlockHeading: [" + doc.BlockHeading + "]\n"
	str += "Description: [" + doc.Description + "]\n\n"
	str += "Parameters: [" + "\n"
	str += doc.Parameters.dumpString() + "\n"
	str += "]\n\n"
	for parentName, defMap := range doc.InheritedParameters {
		str += "Parameters (from " + parentName + ")[\n"
		str += defMap.dumpString() + "\n"
		str += "]\n\n"
	}
	str += "Metadata: [" + "\n"
	str += doc.Metadata.dumpString() + "\n"
	for parentName, defMap := range doc.InheritedMetadata {
		str += "Metadata (from " + parentName + ")[\n"
		str += defMap.dumpString() + "\n"
		str += "]\n\n"
	}
	str += "Example: [" + "\n------------\n" + doc.Example + "\n----------]\n"
	str += "==================== END DUMP ============================\n"
	return str
}
func (doc *PluginDocument) ParseString(comment string) {
	lines := sliceIterator{
		slice:    strings.Split(comment, "\n"),
		position: 0,
	}
	_, doc.BlockHeading, _ = lines.next()
	if _, tmp, _ := lines.next(); tmp != "" {
		panic(fmt.Sprintf("Expected empty line after block heading, got \"%s\"", tmp))
	}
	section := sectionStart
	var (
		metadataText   string
		parametersText string
		line           string
		trimmedLine    string
		lineNr         int
	)
	for {
		prevTrimmedLine := trimmedLine
		line, trimmedLine, lineNr = lines.next()
		if lineNr < 0 {
			break
		}
		_, nextTrimmedLine, _ := lines.peek()
		if prevTrimmedLine == "" && nextTrimmedLine == "" {
			switch trimmedLine {
			case headingMetadata:
				section = sectionMetadata
				lines.next()
				continue
			case headingParameters:
				section = sectionParameters
				lines.next()
				continue
			case headingConfigurationExample:
				section = sectionConfigurationExample
				lines.next()
				continue
			}
		}
		switch section {
		case sectionStart:
			doc.Description += line + "\n"
			continue
		case sectionMetadata:
			metadataText += line + "\n"
			continue
		case sectionParameters:
			parametersText += line + "\n"
			continue
		case sectionConfigurationExample:
			doc.Example += line + "\n"
			continue
		}
	}
	doc.Metadata.parseAndAppendString(metadataText)
	doc.Parameters.parseAndAppendString(parametersText)
}
func (doc *PluginDocument) InheritMetadata(parentDoc PluginDocument) {
	if doc.InheritedMetadata == nil {
		doc.InheritedMetadata = make(map[string]DefinitionList)
	}
	doc.InheritedMetadata[parentDoc.PackageName+"."+parentDoc.PluginName] =
		parentDoc.Metadata.subtractList(doc.Metadata)
	for parentName, metadataSet := range parentDoc.InheritedMetadata {
		doc.InheritedMetadata[parentName] = metadataSet.subtractList(doc.Metadata)
	}
}
func (doc *PluginDocument) InheritParameters(parentDoc PluginDocument) {
	if doc.InheritedParameters == nil {
		doc.InheritedParameters = make(map[string]DefinitionList)
	}
	doc.InheritedParameters[parentDoc.PackageName+"."+parentDoc.PluginName] =
		parentDoc.Parameters.subtractList(doc.Parameters)
	for parentName, paramSet := range parentDoc.InheritedParameters {
		doc.InheritedParameters[parentName] = paramSet.subtractList(doc.Parameters)
	}
}
func docBulletsToRstBullets(text string) string {
	result := ""
	inBullet := false
	for _, line := range strings.Split(text, "\n") {
		if len(line) == 0 {
			result += "\n"
			continue
		}
		chr := line[0]
		if inBullet {
			if chr == " "[0] {
				result += line + "\n"
				continue
			}
			result += "\n" + line + "\n"
			inBullet = false
		} else {
			if chr == "*"[0] {
				result += "\n" + line + "\n"
				inBullet = true
				continue
			}
			result += line + "\n"
		}
	}
	return result
}