# rubygems require 'rubygems' require 'optparse' require 'directory_watcher' require 'liquid' require 'maruku' require 'mash' require 'RedCloth' require 'less' require 'webrick' require 'core_ext/string' require 'core_ext/hash' require 'stack/configuration' require 'stack/generator' require 'stack/runner' require 'stack/template' require 'stack/parsable' require 'stack/server' require 'stack/watcher' require 'stack/filters/register' require 'stack/filters/standard' require 'stack/filters/convertors' require 'stack/filters/datetime' require 'stack/filters/string' require 'stack/templates/page' require 'stack/templates/layout' require 'stack/utils/standard' module Stack # Default options used by stack, overridden from the command line or YML configration file. DEFAULTS = { :source => '.', :target => File.join('.', '_stack'), :server => { :port => 4000, :watch => true } }.freeze # Array of valid commands stack can use COMMANDS = %w(create generate gen server watch) # Array of transformable extensions (these extensions go through the liquid transformer) EXTENSIONS = %w(.html .markdown .mdown .mkdn .md .textile .js .less .css) class << self attr_accessor :runner end # Parses the options configuration from the command line def self.parse!(argv) config = Stack::DEFAULTS.dup parser = OptionParser.new do |opts| opts.banner = "Usage: stack #{Stack::COMMANDS.join('|')} [options...]" opts.separator "" opts.separator "Generator options:" opts.on("-s", "--source [DIR]", "Directory to use as the source for generating a stack") do |l| if !l.nil? config[:source] = l config[:target] = File.join(config[:source], "_stack") end end opts.on("-t", "--target [DIR]", "Directory to use as the target directory") do |l| config[:target] = l unless l.nil? end opts.separator "" opts.separator "Server options:" opts.on("-p", "--port [PORT]", "Port number to use when serving content") do |l| config[:server][:port] = l unless l.nil? end opts.on("--disable-watch", "--disable-watch", "Disables automatic transformation when serving content") do |l| config[:server][:watch] = false end opts.separator "" opts.separator "Common options:" opts.on_tail("-h", "--help", "Show this message") { puts opts; exit } opts.on_tail("-v", "--version", "Show version") do puts "stack #{Stack::version}"; exit; end end parser.parse! argv options = Stack::configuration(config) options end # Merges the configuration from YAML file, command line and defaults def self.configuration(override) config = { } source = File.join(override[:source] || Stack::DEFAULTS[:source]) config_file = File.join(source, "_stack.yml") begin yml = YAML.load_file(config_file) raise "Invalid configuration - #{config_file}" if !config.is_a?(Hash) yml.each { |key, value| config[key.to_sym] = value } STDOUT.puts "Configuration loaded from #{config_file}" rescue => error STDERR.puts "WARNING: Could not read configuration. Using defaults (and options)." STDERR.puts "\t" + error.to_s end # Merge configuration with defaults Stack::DEFAULTS.deep_merge(override).deep_merge(config) end # Stacks current version def self.version version_file = File.join(File.dirname(__FILE__), *%w[.. VERSION.yml]) if File.exist?(version_file) yml = YAML.load(File.read(version_file)) "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}" else "0.0.0" end end end