require 'erb' require 'fileutils' module GemStone VERSION = '0.2' class MissingOption < Exception; end class CLI def self.ask_options options = {} while options.empty? do puts "Hi, I'll need some data about your next ruby gem, please answer all questions" questions = [ [:name , 'gem name?'], [:author , 'gem author?'], [:email , 'author email?'], [:summary , 'gem summary? (be brief)'], [:description , 'gem description? (not so brief)'], [:homepage , 'gem homepage URL?'], [:executable , 'will the gem include an executable? (y/n)'] ] questions.each do |option, question| puts question options[option] = gets.chomp end options[:executable] = options[:executable].downcase.include?('y') begin OptionsValidator.validate!(options) rescue MissingOption => e puts "Please answer all questions." options = {} end end options end end class OptionsValidator REQUIRED_OPTIONS = [:name, :author, :email, :description, :summary, :homepage, :executable] def self.validate!(options) REQUIRED_OPTIONS.each do |option| raise MissingOption, "'#{option}' option required" unless present?(options[option]) end end def self.present?(value) !value.nil? && !value.to_s.strip.empty? end end class Generator def initialize(options = nil) cli_mode = options.nil? options ||= CLI.ask_options @options = options OptionsValidator.validate!(@options) @options[:gem_file_name] = underscore(@options[:name]) @options[:gem_class_name] = classify(@options[:name]) @options[:gem_path] ||= "./#{options[:gem_file_name]}" %w{ README.md Changelog.md Gemfile RakeFile LICENSE test/test_helper.rb }.each{ |path| render_file path } render_file 'sample.gemspec', "#{@options[:gem_file_name]}.gemspec" render_file 'test/sample_test.rb', "test/#{@options[:gem_file_name]}_test.rb" render_file 'lib/sample.rb', "lib/#{@options[:gem_file_name]}.rb" if @options[:executable] render_file('bin/sample', "bin/#{@options[:gem_file_name]}") exec_path = result_path "bin/#{@options[:gem_file_name]}" `chmod +x #{exec_path}` end puts "Your gem is ready at #{@options[:gem_path]}, start coding!" if cli_mode end # 'My gem' => 'my_gem' def underscore(gem_name) gem_name.strip.downcase.gsub(' ', '_') end # 'My gem' => 'MyGem' def classify(gem_name) gem_name.strip.split.map{ |word| word.capitalize}.join.gsub(' ', '') end def render_file(path, result_file_path = path) source_path = File.join 'template', path result_file_path = result_path(result_file_path) FileUtils.mkdir_p File.dirname(result_file_path) result = ERB.new(File.read(source_path)).result(binding) File.open(result_file_path, 'w') {|f| f.write(result) } end def result_path(source_path) File.join @options[:gem_path], source_path end end end