Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
winton committed Nov 15, 2009
1 parent 761f9ef commit d62f112
Show file tree
Hide file tree
Showing 19 changed files with 352 additions and 14 deletions.
8 changes: 4 additions & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ Setup the template
You only have to do this once.

<pre>
git clone git@github.com:winton/gem_template.git
cd gem_template
git clone git@github.com:winton/auto.git
cd auto
stencil
</pre>

Expand All @@ -29,8 +29,8 @@ Do this for every new project.
<pre>
mkdir my_project
git init
stencil gem_template
stencil auto
rake rename
</pre>

The last command does a find-replace (gem\_template -> my\_project) on files and filenames.
The last command does a find-replace (gem\_template -> my\_project) on files and filenames.
4 changes: 0 additions & 4 deletions bin/gem_template

This file was deleted.

9 changes: 5 additions & 4 deletions gemspec.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
GEM_NAME = 'gem_template'
GEM_NAME = 'auto'
GEM_FILES = FileList['**/*'] - FileList['coverage', 'coverage/**/*', 'pkg', 'pkg/**/*']
GEM_SPEC = Gem::Specification.new do |s|
# == CONFIGURE ==
s.author = "Winton Welsh"
s.email = "mail@wintoni.us"
s.homepage = "http://github.com/winton/#{GEM_NAME}"
s.summary = ""
s.summary = "Automate everything!"
# == CONFIGURE ==
s.add_dependency('auto-terminal', '=0.0.1')
s.executables << GEM_NAME
s.extra_rdoc_files = [ "README.markdown" ]
s.files = GEM_FILES.to_a
s.has_rdoc = false
s.name = GEM_NAME
s.platform = Gem::Platform::RUBY
s.require_path = "lib"
s.version = "0.1.0"
end
s.version = "0.0.1"
end
8 changes: 8 additions & 0 deletions lib/auto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require File.dirname(__FILE__) + "/auto/require"

module Auto
Runner.new do
terminal($0)
end
exit
end
44 changes: 44 additions & 0 deletions lib/auto/alias.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class Module

# Encapsulates the common pattern of:
#
# alias_method :foo_without_feature, :foo
# alias_method :foo, :foo_with_feature
#
# With this, you simply do:
#
# alias_method_chain :foo, :feature
#
# And both aliases are set up for you.
#
# Query and bang methods (foo?, foo!) keep the same punctuation:
#
# alias_method_chain :foo?, :feature
#
# is equivalent to
#
# alias_method :foo_without_feature?, :foo?
# alias_method :foo?, :foo_with_feature?
#
# so you can safely chain foo, foo?, and foo! with the same feature.
def alias_method_chain(target, feature)
# Strip out punctuation on predicates or bang methods since
# e.g. target?_without_feature is not a valid method name.
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
yield(aliased_target, punctuation) if block_given?

with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"

alias_method without_method, target
alias_method target, with_method

case
when public_method_defined?(without_method)
public target
when protected_method_defined?(without_method)
protected target
when private_method_defined?(without_method)
private target
end
end
end
46 changes: 46 additions & 0 deletions lib/auto/class.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class Class

def cattr_reader(*syms)
syms.flatten.each do |sym|
next if sym.is_a?(Hash)
class_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym} # unless defined? @@hair_colors
@@#{sym} = nil # @@hair_colors = nil
end # end
#
def self.#{sym} # def self.hair_colors
@@#{sym} # @@hair_colors
end # end
#
def #{sym} # def hair_colors
@@#{sym} # @@hair_colors
end # end
EOS
end
end

def cattr_writer(*syms)
syms.flatten.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym} # unless defined? @@hair_colors
@@#{sym} = nil # @@hair_colors = nil
end # end
#
def self.#{sym}=(obj) # def self.hair_colors=(obj)
@@#{sym} = obj # @@hair_colors = obj
end # end
#
#{" #
def #{sym}=(obj) # def hair_colors=(obj)
@@#{sym} = obj # @@hair_colors = obj
end # end
"}
EOS
end
end

def cattr_accessor(*syms)
cattr_reader(*syms)
cattr_writer(*syms)
end
end
108 changes: 108 additions & 0 deletions lib/auto/plugins.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require 'rubygems'

module Auto
class Plugins

@@directories = [
Gem.dir + "/gems",
"~/.auto",
"#{File.dirname(__FILE__)}/../../vendor/plugins"
]
@@plugins = nil

cattr_accessor :directories

class <<self

# Add a directory to the plugin load paths.
def add(path)
@@directories = [] if $TESTING
@@directories << path
@@directories.uniq!
@@plugins = nil
end

# Returns an array of Plugin instances.
def plugins
return @@plugins if @@plugins
directories = @@directories.collect do |d|
File.expand_path("#{d}/*auto-*/")
end
@@plugins = Dir[*directories].collect do |d|
Plugin.new(d)
end
@@plugins.compact!
@@plugins
end

# Returns an array of library file paths.
def libraries
collector { |plugin| plugin.library }
end

# Returns an array of modules.
def modules
collector { |plugin| plugin.module }
end

# Returns a sorted array of hashes that describe tasks.
# Returns a specific task with an optional task parameter (string, 'task:name').
def tasks(task=nil)
if task
tasks.select { |t| t[:name] == task.downcase }.first
else
t = collector { |plugin| plugin.tasks }
t = t.flatten
t.sort do |a, b|
a[:name].gsub(':', '0') <=> b[:name].gsub(':', '0')
end
end
end

private

# A quick way to get an array of @@plugins attributes.
def collector(&block)
self.plugins.collect { |plugin| block.call(plugin) }.compact
end
end

# Stores a plugin's name, library, and tasks.
class Plugin

attr_reader :name
attr_reader :library
attr_reader :module
attr_reader :tasks

# Assigns attributes using a plugin directory path.
def initialize(directory)
name = File.basename(directory)
name = name.split('-')

return nil unless name.include?('auto')
@name = name[name.index('auto') + 1]

# ~/.auto/auto-plugin/lib/plugin.rb
@library = "#{directory}/lib/#{@name}.rb"
@library = nil unless File.exists?(@library)

# Auto::Plugin
if @library
@module = File.basename(@library, '.rb').camelize
else
@module = nil
end

# ~/.auto/auto-plugin/auto/task.rb
@tasks = Dir["#{directory}/auto/**/*.rb"].sort.collect do |path|
relative = path.gsub("#{directory}/auto/", '')
{
:name => relative[0..-4].split('/').join(':').downcase,
:path => path
}
end
end
end
end
end
8 changes: 8 additions & 0 deletions lib/auto/require.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# By default, <tt>require 'auto'</tt> uses Runner to re-evaluate the script.
# If you don't want the environment (just the classes), require this file.

require File.dirname(__FILE__) + "/alias"
require File.dirname(__FILE__) + "/class"
require File.dirname(__FILE__) + "/plugins"
require File.dirname(__FILE__) + "/runner"
require File.dirname(__FILE__) + "/string"
37 changes: 37 additions & 0 deletions lib/auto/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Auto
class Runner

def initialize(path_or_task=nil, &block)
self.class.require!
run(path_or_task, &block)
end

def run(path_or_task=nil, &block)
self.instance_eval(&block) if block
if path_or_task
if File.exists?(path_or_task)
@path = path_or_task
elsif task = Plugins.tasks(path_or_task)
@path = task[:path]
end
self.instance_eval(File.read(@path), @path) if @path
end
self
end

class <<self

def require!
Plugins.plugins.each do |plugin|
if plugin.library
require plugin.library
end
begin
include eval(plugin.module)
rescue
end
end
end
end
end
end
12 changes: 12 additions & 0 deletions lib/auto/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class String

def camelize
lower_case_and_underscored_word = self
first_letter_in_uppercase = true
if first_letter_in_uppercase
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
else
lower_case_and_underscored_word.first.downcase + lower_case_and_underscored_word.camelize[1..-1]
end
end
end
1 change: 0 additions & 1 deletion lib/gem_template.rb

This file was deleted.

44 changes: 44 additions & 0 deletions spec/auto/plugins_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")

module Auto
describe Auto::Plugins do

before(:all) do
Plugins.add @fixtures = "#{SPEC}/plugins"
@libraries = Plugins.libraries
@modules = Plugins.modules
@tasks = Plugins.tasks
# debug @libraries
# debug @modules
# debug @tasks
end

it "should provide an array of plugin library files" do
@libraries.should == [
"#{@fixtures}/auto-plugin-0.0.0/lib/plugin.rb",
"#{@fixtures}/auto-plugin2/lib/plugin2.rb"
]
end

it "should provide an array of module strings" do
@modules.should == [ 'Plugin', 'Plugin2' ]
end

it "should provide a hash of plugin task information" do
@tasks.should == [
{
:path => "#{@fixtures}/auto-plugin-0.0.0/auto/plugin/task.rb",
:name => "plugin:task"
},
{
:path => "#{@fixtures}/auto-plugin2/auto/plugin2/task.rb",
:name => "plugin2:task"
},
{
:path => "#{@fixtures}/auto-plugin2/auto/plugin2/task2.rb",
:name => "plugin2:task2"
}
]
end
end
end
21 changes: 21 additions & 0 deletions spec/auto/runner_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")

module Auto
describe Auto::Runner do

before(:all) do
Plugins.add @fixtures = "#{SPEC}/plugins"
@runner = Runner.new
end

it 'should require plugin library files' do
$".include?("#{@fixtures}/auto-plugin-0.0.0/lib/plugin.rb").should == true
$".include?("#{@fixtures}/auto-plugin2/lib/plugin2.rb").should == true
end

it 'should include all plugin library modules' do
@runner.public_methods.include?('plugin').should == true
@runner.public_methods.include?('plugin2').should == true
end
end
end
File renamed without changes.
Loading

0 comments on commit d62f112

Please sign in to comment.