#!/usr/bin/env ruby

#
# = Synopsis
#
# Generate a reference for all Puppet types.  Largely meant for internal Reductive
# Labs use.
#
# = Usage
#
#   puppetdoc [-a|--all] [-h|--help] [-m|--mode <text|pdf|trac> [-r|--reference <[type]|configuration|..>]
#
# = Description
#
# This command generates a restructured-text document describing all installed
# Puppet types or all allowable arguments to puppet executables.  It is largely
# meant for internal use and is used to generate the reference document
# available on the Reductive Labs web site.
#
# = Options
#
# all::
#   Output the docs for all of the reference types.
#
# help::
#   Print this help message
#
# mode::
#   Determine the output mode.  Valid modes are 'text', 'trac', and 'pdf'.  Note that 'trac' mode only works on Reductive Labs servers.  The default mode is 'text'.
#
# reference::
#   Build a particular reference.  Get a list of references by running +puppetdoc --list+.
#
# = Example
#
#   $ puppetdoc -r type > /tmp/type_reference.rst
#
# = Author
#
# Luke Kanies
#
# = Copyright
#
# Copyright (c) 2005-2007 Reductive Labs, LLC
# Licensed under the GNU Public License

require 'puppet'
require 'puppet/util/reference'
require 'puppet/network/handler'
require 'getoptlong'

result = GetoptLong.new(
	[ "--all",	"-a",			GetoptLong::NO_ARGUMENT ],
	[ "--list",	"-l",			GetoptLong::NO_ARGUMENT ],
	[ "--format",	"-f",			GetoptLong::REQUIRED_ARGUMENT ],
	[ "--mode",	"-m",			GetoptLong::REQUIRED_ARGUMENT ],
	[ "--reference",	"-r",			GetoptLong::REQUIRED_ARGUMENT ],
	[ "--help",		"-h",			GetoptLong::NO_ARGUMENT ]
)

debug = false

$tab = "    "
options = {:references => [], :mode => :text, :format => :to_rest}

Reference = Puppet::Util::Reference

begin
    result.each { |opt,arg|
        case opt
            when "--all"
                options[:all] = true
            when "--format"
                method = "to_%s" % arg
                if Reference.method_defined?(method)
                    options[:format] = method
                else
                    raise "Invalid output format %s" % arg
                end
            when "--mode"
                if Reference.modes.include?(arg)
                    options[:mode] = arg.intern
                else
                    raise "Invalid output mode %s" % arg
                end
            when "--list"
                puts Reference.references.collect { |r| Reference.reference(r).doc }.join("\n")
                exit(0)
            when "--reference"
                options[:references] << arg.intern
            when "--help"
                if Puppet.features.usage?
                    RDoc::usage && exit
                else
                    puts "No help available unless you have RDoc::usage installed"
                    exit
                end
        end
    }
rescue GetoptLong::InvalidOption => detail
    $stderr.puts "Try '#{$0} --help'"
    exit(1)
end

if options[:all]
    # Don't add dynamic references to the "all" list.
    options[:references] = Reference.references.reject do |ref|
        Reference.reference(ref).dynamic?
    end
end

if options[:references].empty?
    options[:references] << :type
end

case options[:mode]
when :trac
    options[:references].each do |name|
        section = Puppet::Util::Reference.reference(name) or raise "Could not find section %s" % name
        unless options[:mode] == :pdf
            section.trac
        end
    end
else
    text = ""
    if options[:references].length > 1
        with_contents = false
    else
        with_contents = true
    end
    options[:references].sort { |a,b| a.to_s <=> b.to_s }.each do |name|
        section = Puppet::Util::Reference.reference(name)

        # Add the per-section text, but with no ToC
        text += section.send(options[:format], with_contents)
    end

    unless with_contents # We've only got one reference
        text += Puppet::Util::Reference.footer
    end

    # Replace the trac links, since they're invalid everywhere else
    text.gsub!(/`\w+\s+([^`]+)`:trac:/) { |m| $1 }

    if options[:mode] == :pdf
        Puppet::Util::Reference.pdf(text)
    else
        puts text
    end
end


# $Id: puppetdoc 2485 2007-05-08 19:29:38Z luke $
