auto 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2009 Winton Welsh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ Automaton
2
+ =========
3
+
4
+ Automate everything!
5
+
6
+ Notice
7
+ ------
8
+
9
+ This gem is in development. Functionality updates will show up in this file.
10
+
11
+ Goals
12
+ -----
13
+
14
+ * Writing automation scripts should be simple
15
+ * Global namespace
16
+ * A library of simple methods that do complex things
17
+ * Adding outside scripts and script functionality should be simple
18
+ * Obvious plugin structure
19
+ * Automated installation/updates
20
+ * Running tasks should be simple
21
+ * Everything available via "auto task" command
22
+ * Easy to ask questions
23
+ * Sessions
24
+ * Record input for any number of questions
25
+ * Replay using "auto session" command
26
+ * Or, use the web interface
27
+ * Make it easy for novices to use and extend
28
+
29
+ Install
30
+ -------
31
+
32
+ <pre>
33
+ gem sources -a http://gems.github.com
34
+ sudo gem install winton-automaton
35
+ </pre>
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/gempackagetask'
4
+ require 'spec/rake/spectask'
5
+
6
+ GEM_NAME = 'automaton'
7
+ PKG_FILES = FileList['**/*'] - FileList['coverage', 'coverage/**/*', 'pkg', 'pkg/**/*']
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.author = "Winton Welsh"
11
+ s.email = "mail@wintoni.us"
12
+ s.extra_rdoc_files = [ "README.markdown" ]
13
+ s.files = PKG_FILES.to_a
14
+ s.has_rdoc = false
15
+ s.homepage = "http://github.com/winton/#{GEM_NAME}"
16
+ s.name = 'auto'
17
+ s.platform = Gem::Platform::RUBY
18
+ s.require_path = "lib"
19
+ s.summary = "Automate everything!"
20
+ s.version = "0.1.0"
21
+ end
22
+
23
+
24
+ desc "Package gem"
25
+ Rake::GemPackageTask.new(spec) do |pkg|
26
+ pkg.gem_spec = spec
27
+ end
28
+
29
+ desc "Install gem"
30
+ task :install do
31
+ Rake::Task['gem'].invoke
32
+ `sudo gem uninstall #{GEM_NAME} -x`
33
+ `sudo gem install pkg/#{GEM_NAME}*.gem`
34
+ `rm -Rf pkg`
35
+ end
36
+
37
+ desc "Generate gemspec"
38
+ task :gemspec do
39
+ File.open("#{File.dirname(__FILE__)}/#{GEM_NAME}.gemspec", 'w') do |f|
40
+ f.write(spec.to_ruby)
41
+ end
42
+ end
43
+
44
+ desc "Run specs"
45
+ Spec::Rake::SpecTask.new do |t|
46
+ t.rcov = true
47
+ t.spec_opts = ["--format", "specdoc", "--colour"]
48
+ t.spec_files = FileList["spec/**/*_spec.rb"]
49
+ end
@@ -0,0 +1,6 @@
1
+ automaton-questions:
2
+ repo: git@github.com:winton/automaton-questions.git
3
+ path: vendor/plugins
4
+ automaton-terminal:
5
+ repo: git@github.com:winton/automaton-terminal.git
6
+ path: vendor/plugins
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + "/automaton/require"
2
+
3
+ module Automaton
4
+ Runner.new do
5
+ terminal($0)
6
+ end
7
+ exit
8
+ end
@@ -0,0 +1,44 @@
1
+ class Module
2
+
3
+ # Encapsulates the common pattern of:
4
+ #
5
+ # alias_method :foo_without_feature, :foo
6
+ # alias_method :foo, :foo_with_feature
7
+ #
8
+ # With this, you simply do:
9
+ #
10
+ # alias_method_chain :foo, :feature
11
+ #
12
+ # And both aliases are set up for you.
13
+ #
14
+ # Query and bang methods (foo?, foo!) keep the same punctuation:
15
+ #
16
+ # alias_method_chain :foo?, :feature
17
+ #
18
+ # is equivalent to
19
+ #
20
+ # alias_method :foo_without_feature?, :foo?
21
+ # alias_method :foo?, :foo_with_feature?
22
+ #
23
+ # so you can safely chain foo, foo?, and foo! with the same feature.
24
+ def alias_method_chain(target, feature)
25
+ # Strip out punctuation on predicates or bang methods since
26
+ # e.g. target?_without_feature is not a valid method name.
27
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
28
+ yield(aliased_target, punctuation) if block_given?
29
+
30
+ with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
31
+
32
+ alias_method without_method, target
33
+ alias_method target, with_method
34
+
35
+ case
36
+ when public_method_defined?(without_method)
37
+ public target
38
+ when protected_method_defined?(without_method)
39
+ protected target
40
+ when private_method_defined?(without_method)
41
+ private target
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,46 @@
1
+ class Class
2
+
3
+ def cattr_reader(*syms)
4
+ syms.flatten.each do |sym|
5
+ next if sym.is_a?(Hash)
6
+ class_eval(<<-EOS, __FILE__, __LINE__)
7
+ unless defined? @@#{sym} # unless defined? @@hair_colors
8
+ @@#{sym} = nil # @@hair_colors = nil
9
+ end # end
10
+ #
11
+ def self.#{sym} # def self.hair_colors
12
+ @@#{sym} # @@hair_colors
13
+ end # end
14
+ #
15
+ def #{sym} # def hair_colors
16
+ @@#{sym} # @@hair_colors
17
+ end # end
18
+ EOS
19
+ end
20
+ end
21
+
22
+ def cattr_writer(*syms)
23
+ syms.flatten.each do |sym|
24
+ class_eval(<<-EOS, __FILE__, __LINE__)
25
+ unless defined? @@#{sym} # unless defined? @@hair_colors
26
+ @@#{sym} = nil # @@hair_colors = nil
27
+ end # end
28
+ #
29
+ def self.#{sym}=(obj) # def self.hair_colors=(obj)
30
+ @@#{sym} = obj # @@hair_colors = obj
31
+ end # end
32
+ #
33
+ #{" #
34
+ def #{sym}=(obj) # def hair_colors=(obj)
35
+ @@#{sym} = obj # @@hair_colors = obj
36
+ end # end
37
+ "}
38
+ EOS
39
+ end
40
+ end
41
+
42
+ def cattr_accessor(*syms)
43
+ cattr_reader(*syms)
44
+ cattr_writer(*syms)
45
+ end
46
+ end
@@ -0,0 +1,108 @@
1
+ require 'rubygems'
2
+
3
+ module Automaton
4
+ class Plugins
5
+
6
+ @@directories = [
7
+ Gem.dir + "/gems",
8
+ "~/.auto",
9
+ "#{File.dirname(__FILE__)}/../../vendor/plugins"
10
+ ]
11
+ @@plugins = nil
12
+
13
+ cattr_accessor :directories
14
+
15
+ class <<self
16
+
17
+ # Add a directory to the plugin load paths.
18
+ def add(path)
19
+ @@directories = [] if $TESTING
20
+ @@directories << path
21
+ @@directories.uniq!
22
+ @@plugins = nil
23
+ end
24
+
25
+ # Returns an array of Plugin instances.
26
+ def plugins
27
+ return @@plugins if @@plugins
28
+ directories = @@directories.collect do |d|
29
+ File.expand_path("#{d}/*automaton-*/")
30
+ end
31
+ @@plugins = Dir[*directories].collect do |d|
32
+ Plugin.new(d)
33
+ end
34
+ @@plugins.compact!
35
+ @@plugins
36
+ end
37
+
38
+ # Returns an array of library file paths.
39
+ def libraries
40
+ collector { |plugin| plugin.library }
41
+ end
42
+
43
+ # Returns an array of modules.
44
+ def modules
45
+ collector { |plugin| plugin.module }
46
+ end
47
+
48
+ # Returns a sorted array of hashes that describe tasks.
49
+ # Returns a specific task with an optional task parameter (string, 'task:name').
50
+ def tasks(task=nil)
51
+ if task
52
+ tasks.select { |t| t[:name] == task.downcase }.first
53
+ else
54
+ t = collector { |plugin| plugin.tasks }
55
+ t = t.flatten
56
+ t.sort do |a, b|
57
+ a[:name].gsub(':', '0') <=> b[:name].gsub(':', '0')
58
+ end
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # A quick way to get an array of @@plugins attributes.
65
+ def collector(&block)
66
+ self.plugins.collect { |plugin| block.call(plugin) }.compact
67
+ end
68
+ end
69
+
70
+ # Stores a plugin's name, library, and tasks.
71
+ class Plugin
72
+
73
+ attr_reader :name
74
+ attr_reader :library
75
+ attr_reader :module
76
+ attr_reader :tasks
77
+
78
+ # Assigns attributes using a plugin directory path.
79
+ def initialize(directory)
80
+ name = File.basename(directory)
81
+ name = name.split('-')
82
+
83
+ return nil unless name.include?('automaton')
84
+ @name = name[name.index('automaton') + 1]
85
+
86
+ # ~/.auto/automaton-plugin/lib/plugin.rb
87
+ @library = "#{directory}/lib/#{@name}.rb"
88
+ @library = nil unless File.exists?(@library)
89
+
90
+ # Automaton::Plugin
91
+ if @library
92
+ @module = File.basename(@library, '.rb').camelize
93
+ else
94
+ @module = nil
95
+ end
96
+
97
+ # ~/.auto/automaton-plugin/auto/task.rb
98
+ @tasks = Dir["#{directory}/auto/**/*.rb"].sort.collect do |path|
99
+ relative = path.gsub("#{directory}/auto/", '')
100
+ {
101
+ :name => relative[0..-4].split('/').join(':').downcase,
102
+ :path => path
103
+ }
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,8 @@
1
+ # By default, <tt>require 'automaton'</tt> uses Runner to re-evaluate the script.
2
+ # If you don't want the environment (just the classes), require this file.
3
+
4
+ require File.dirname(__FILE__) + "/alias"
5
+ require File.dirname(__FILE__) + "/class"
6
+ require File.dirname(__FILE__) + "/plugins"
7
+ require File.dirname(__FILE__) + "/runner"
8
+ require File.dirname(__FILE__) + "/string"
@@ -0,0 +1,38 @@
1
+ module Automaton
2
+ class Runner
3
+
4
+ def initialize(path_or_task=nil, &block)
5
+ self.class.require!
6
+ run(path_or_task, &block)
7
+ end
8
+
9
+ def run(path_or_task=nil, &block)
10
+ self.instance_eval(&block) if block
11
+ if path_or_task
12
+ task = Plugins.tasks(path_or_task)
13
+ if task
14
+ @path = task[:path]
15
+ elsif File.exists?(path_or_task)
16
+ @path = path_or_task
17
+ end
18
+ self.instance_eval(File.read(@path), @path) if @path
19
+ end
20
+ self
21
+ end
22
+
23
+ class <<self
24
+
25
+ def require!
26
+ Plugins.plugins.each do |plugin|
27
+ if plugin.library
28
+ require plugin.library
29
+ end
30
+ begin
31
+ include eval(plugin.module)
32
+ rescue
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ class String
2
+
3
+ def camelize
4
+ lower_case_and_underscored_word = self
5
+ first_letter_in_uppercase = true
6
+ if first_letter_in_uppercase
7
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
8
+ else
9
+ lower_case_and_underscored_word.first.downcase + lower_case_and_underscored_word.camelize[1..-1]
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ module Automaton
4
+ describe Automaton::Plugins do
5
+
6
+ before(:all) do
7
+ Plugins.add @fixtures = "#{SPEC}/plugins"
8
+ @libraries = Plugins.libraries
9
+ @modules = Plugins.modules
10
+ @tasks = Plugins.tasks
11
+ # debug @libraries
12
+ # debug @modules
13
+ # debug @tasks
14
+ end
15
+
16
+ it "should provide an array of plugin library files" do
17
+ @libraries.should == [
18
+ "#{@fixtures}/automaton-plugin2/lib/plugin2.rb",
19
+ "#{@fixtures}/user-automaton-plugin-0.0.0/lib/plugin.rb"
20
+ ]
21
+ end
22
+
23
+ it "should provide an array of module strings" do
24
+ @modules.should == [ 'Plugin2', 'Plugin' ]
25
+ end
26
+
27
+ it "should provide a hash of plugin task information" do
28
+ @tasks.should == [
29
+ {
30
+ :path => "#{@fixtures}/user-automaton-plugin-0.0.0/auto/plugin/task.rb",
31
+ :name => "plugin:task"
32
+ },
33
+ {
34
+ :path => "#{@fixtures}/automaton-plugin2/auto/plugin2/task.rb",
35
+ :name => "plugin2:task"
36
+ },
37
+ {
38
+ :path => "#{@fixtures}/automaton-plugin2/auto/plugin2/task2.rb",
39
+ :name => "plugin2:task2"
40
+ }
41
+ ]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ module Automaton
4
+ describe Automaton::Runner do
5
+
6
+ before(:all) do
7
+ Plugins.add @fixtures = "#{SPEC}/plugins"
8
+ @runner = Runner.new
9
+ end
10
+
11
+ it 'should require plugin library files' do
12
+ $".include?("#{@fixtures}/user-automaton-plugin-0.0.0/lib/plugin.rb").should == true
13
+ $".include?("#{@fixtures}/automaton-plugin2/lib/plugin2.rb").should == true
14
+ end
15
+
16
+ it 'should include all plugin library modules' do
17
+ @runner.public_methods.include?('plugin').should == true
18
+ @runner.public_methods.include?('plugin2').should == true
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module Automaton
2
+ module Plugin2
3
+ def plugin2
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Automaton
2
+ module Plugin
3
+ def plugin
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,15 @@
1
+ $TESTING=true
2
+ SPEC = File.dirname(__FILE__)
3
+ $:.unshift File.expand_path("#{SPEC}/../lib")
4
+
5
+ require 'automaton/require'
6
+ require 'pp'
7
+
8
+ Spec::Runner.configure do |config|
9
+ end
10
+
11
+ def debug(object)
12
+ puts "<pre>"
13
+ puts object.pretty_inspect.gsub('<', '&lt;').gsub('>', '&gt;')
14
+ puts "</pre>"
15
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Winton Welsh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-06 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: mail@wintoni.us
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - config/externals.yml
26
+ - lib/automaton/alias.rb
27
+ - lib/automaton/class.rb
28
+ - lib/automaton/plugins.rb
29
+ - lib/automaton/require.rb
30
+ - lib/automaton/runner.rb
31
+ - lib/automaton/string.rb
32
+ - lib/automaton.rb
33
+ - MIT-LICENSE
34
+ - Rakefile
35
+ - README.markdown
36
+ - spec/automaton/plugins_spec.rb
37
+ - spec/automaton/runner_spec.rb
38
+ - spec/plugins/automaton-plugin2/auto/plugin2/task.rb
39
+ - spec/plugins/automaton-plugin2/auto/plugin2/task2.rb
40
+ - spec/plugins/automaton-plugin2/lib/plugin2.rb
41
+ - spec/plugins/user-automaton-plugin-0.0.0/auto/plugin/task.rb
42
+ - spec/plugins/user-automaton-plugin-0.0.0/lib/plugin.rb
43
+ - spec/spec.opts
44
+ - spec/spec_helper.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/winton/automaton
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Automate everything!
73
+ test_files: []
74
+