#!/usr/bin/env ruby
#--
# Copyright (c) 1996-2004, Yauheni Akhotnikau
# Copyright (c) 2004-2006, JSC Intervale
# Copyright (c) 2006-2011, The Mxx_ru Project
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#++
# This code is based on the code from RuCodeGen
# (http://www.rubyforge.org/projects/rucodegen) project.
# RuCodeGen is distributed under the following license:
#--
#
# Copyright (c) 2005-2006, Yauheni Akhotnikau
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#++


# Since v.1.4.0
#
# Template generation scripts runner.

require 'optparse'
require 'ostruct'

module MxxRuGen

module Impl

# Standard name of generation script inside template.
STD_CODEGEN_SCRIPT_NAME = 'g.rb'

# Command-line argument parsing.
#
# Returns object with the following methods:
# template_name:: Name of template chosen.
# list:: Contains _true_ if list of templates must be shown.
# include_paths:: Contains list of addition path for templates.
#
# Finishes script work is --help specified.
#
def Impl.parse_args
	result = OpenStruct.new(
			:template_name => nil,
			:list => false,
			:include_paths => [] )

	parser = OptionParser.new

	parser.banner = <<BANNER
Mxx_ru Ad-Hoc generation runner

Usage:

mxxrugen [<options>] template-name [<template-options>]

BANNER

	parser.on_head( '-l', '--list', 'Show list of available templates' ) do
		result.list = true
	end

	parser.on_head( '-I', '--include-path PATH',
			'Additional path to looking for templates' ) do |p|
		result.include_paths << p
	end

	parser.on_head( '-h', '--help', 'Show this message' ) do
		puts parser
		exit( 1 )
	end

	parser.order!( ARGV ) do |nonarg|
		# First non-option is a template name.
		result.template_name = nonarg
		parser.terminate
	end

	if !result.template_name && !result.list
		$stderr.puts "template_name must be specified"
		exit( 2 )
	end

	result
end

# Prints list of available templates.
def Impl.show_templates_list( include_paths )
	include_paths.each do |path|
		templates_found = []
		Dir.glob( File.join( path, '*' ), File::FNM_PATHNAME ) do |dir|
			probe_name = File.join( dir, STD_CODEGEN_SCRIPT_NAME )
			if File.readable?( probe_name )
				templates_found << File.basename( dir )
			end
		end

		templates_found.sort.each do |template|
			puts template + " (#{path})"
		end
	end
end

# Searches full path to a template by the template name.
#
# Returns nil if searching fails.
#
def Impl.find_full_template_path( template_name, include_paths )
	include_paths.each do |path|
		probe_name = File.join( path, template_name, STD_CODEGEN_SCRIPT_NAME )
		if File.readable?( probe_name )
			return probe_name
		end
	end

	nil
end

# Searches and runs the template specified with option list is given.
def Impl.find_and_run_template( template_name, include_paths )
	full_path = find_full_template_path( template_name, include_paths )
	if full_path 
		require full_path
	else
		$stderr.puts "#{template_name}: template not found in:\n\t" +
				include_paths.join( "\n\t" )
		exit( 3 )
	end
end

end # Impl

# Performs main work.
def MxxRuGen.run_ad_hoc_generation
	options = Impl.parse_args

  # Standard path to templates must be added.
	options.include_paths << File.expand_path( File.join(
			File.dirname( __FILE__ ),
			'../lib/mxx_ru/generators' ) )

	if options.list
		Impl.show_templates_list( options.include_paths )
	else
		Impl.find_and_run_template(
				options.template_name,
				options.include_paths )
	end
end

end # MxxRuGen

MxxRuGen.run_ad_hoc_generation

# vim:ft=ruby:

