outil 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a3cfe1efb43ae4eb0bf954722310c091cfa0fbd3
4
+ data.tar.gz: 5f00fa7f90c1894982e0f3112c55fbea676e4e0c
5
+ SHA512:
6
+ metadata.gz: eb6a368e983db65fa663bc7036444a3e1c9faaeafa7e681c3ac229d1289aeabc1a858a1aa9d5aaa619937a2609094425d023276c54ddcbef1a9d90df508b65a9
7
+ data.tar.gz: 3fdd16515f75d37b7da50785d75ba397c7212bc3423fe0bb3e29d17660db7da2d3ee750b1a0f89b5372922e9d0b72e21d734900d655422a75107ab9ce27ea497
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
3
+ require 'outil'
4
+
5
+ puts ARGV
6
+ Outil::OCS.bootstrap(:index => ARGV[1], :config => ARGV[2])
7
+
@@ -0,0 +1,108 @@
1
+ require 'bundler/setup'
2
+ require 'ruby_decorators'
3
+ require 'parser/current'
4
+ require 'unparser'
5
+ require 'yaml'
6
+
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+
9
+ require 'outil/version'
10
+ require 'outil/decorators'
11
+ require 'outil/workspace'
12
+ require 'outil/ocs'
13
+ require 'outil/ocs/index'
14
+ require 'outil/ocs/config'
15
+ require 'outil/ocs/parser'
16
+
17
+ module Outil
18
+
19
+ def self.index
20
+ Workspace.ocs.index
21
+ end
22
+
23
+ def self.reset!
24
+ Workspace.reset!
25
+ end
26
+
27
+ def self.included(base)
28
+ # Add the decorator class-method logic to the includer
29
+ # E.G. The client has control over the "use" and "named"
30
+ # class-level directives.
31
+
32
+ base.extend(Inferace)
33
+
34
+ # By default, only the Registration decorator
35
+ # is added, and it's added under the generic :outil namespace
36
+
37
+ base.class_eval do
38
+ use Decorators::Register
39
+ named :outil
40
+ end
41
+
42
+ # Pull all the AST's in the user index
43
+ # and define them as methods of the Bucket
44
+ # module just before the inclusion is done.
45
+
46
+ Workspace.ocs.index.all.each do |ast|
47
+ Outil.module_eval <<-RUBY_EVAL
48
+ #{Unparser.unparse(ast)}
49
+ RUBY_EVAL
50
+ end
51
+ end
52
+
53
+ module Inferace
54
+ # BucketInterface is a basically
55
+ # a module mirror of the RubyDecorators::Interface
56
+ # class. To avoid adding dependencies, and increasing
57
+ # the sheer volume of hacks at work here, the Interface
58
+ # code is essentially copied and pasted here as module
59
+ # instance variables
60
+
61
+ include RubyDecorators
62
+
63
+ def self.decorate
64
+ RubyDecorators::Stack.all << self
65
+ Workspace.sync
66
+ end
67
+
68
+ def named(name)
69
+ @name = name.to_s
70
+ class_eval <<-RUBY_EVAL
71
+ def self.#{@name}(dcr)
72
+ if decorators[dcr]
73
+ self.decorate(decorators[dcr])
74
+ end
75
+ end
76
+ RUBY_EVAL
77
+ end
78
+
79
+ def name
80
+ @name ||= self.class.name.to_s
81
+ end
82
+
83
+ def decorators
84
+ @decorators ||= {}
85
+ end
86
+
87
+ def use *decs
88
+ append = Proc.new do |dec|
89
+ fmt = dec.name.split('::').last.
90
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
91
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
92
+ tr("-", "_").
93
+ downcase.
94
+ to_sym
95
+ self.decorators[fmt] = dec
96
+ end
97
+ decs.each &append
98
+ end
99
+
100
+ def registered_methods
101
+ @registered_methods ||= {}
102
+ end
103
+
104
+ def self.registered_decorators
105
+ @registered_decorators ||= {}
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,30 @@
1
+ module Outil
2
+ module Decorators
3
+
4
+ class Register < RubyDecorators::Decorator
5
+
6
+ def call(this, *args, &blk)
7
+ Outil::Workspace.scan *this.source_location << this.name
8
+ this.call(*args, &blk)
9
+ end
10
+
11
+ end
12
+
13
+ class NameSpace
14
+
15
+ def initialize(namespace)
16
+ @namespace = namespace
17
+ end
18
+
19
+ def call(this, *args, &blk)
20
+ # TODO
21
+ # Intended behavior is to register the decorated
22
+ # method under a given namespace, so you can
23
+ # have two methods named the same thing, etc.
24
+ this.call(*args, &blk)
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ module Outil
2
+
3
+ module OCS
4
+
5
+ # Object Control System
6
+
7
+ class << self
8
+
9
+ def config(params={})
10
+ @config ||= Config.new(params)
11
+ end
12
+
13
+ def bootstrap options={}
14
+ options.merge! Config.new().params
15
+ Dir.mkdir(options[:index]) unless Dir.exists?(options[:index])
16
+ File.open(options.delete(:path), 'w+') do |f|
17
+ f.write options.to_yaml
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,51 @@
1
+ module Outil
2
+ module OCS
3
+ class Config
4
+
5
+ INDEX_PATH = '.outil'
6
+ CONFIG_PATH = '.outil.rc'
7
+
8
+ def self.home_path
9
+ @home_path ||= File.expand_path(
10
+ File.expand_path(ENV['HOME'] || '~'))
11
+ end
12
+
13
+ attr :params
14
+
15
+ def initialize(params={})
16
+ @params = params
17
+ infer = Proc.new do |key, const|
18
+ @params[key] = "#{self.class.home_path}/#{const}"
19
+ end
20
+ infer.call(:index, INDEX_PATH)
21
+ infer.call(:path, CONFIG_PATH)
22
+ end
23
+
24
+ def options
25
+ @options ||= (
26
+ unless File.exists?(@params[:path])
27
+ raise StandardError "Could not locate your Outil Config File"
28
+ end
29
+ indifference = Proc.new do |hash, x|
30
+ hash[x.first] = x.last
31
+ hash[x.first.to_sym] = x.last
32
+ hash
33
+ end
34
+ YAML.load_file(@params[:path])
35
+ .inject(Hash.new, &indifference)
36
+ )
37
+ end
38
+
39
+ def index
40
+ @index ||= (
41
+ unless options[:index]
42
+ raise StandardError "Could not locate your Outil Index Path"
43
+ end
44
+ Index.new(:path => options[:index])
45
+ )
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,68 @@
1
+ module Outil
2
+ module OCS
3
+ class Index
4
+
5
+ attr :path
6
+
7
+ def initialize params={}
8
+ @path = params[:path]
9
+ end
10
+
11
+ def index_path
12
+ @index_path ||= "#{@path}/index"
13
+ end
14
+
15
+ def append name, ast
16
+ write_serialize name, ast
17
+ update_index name
18
+ end
19
+
20
+ def write_serialize name, ast
21
+ File.open("#{@path}/#{name}.ast", 'w+') do |file|
22
+ file.write ast.to_yaml
23
+ end
24
+ end
25
+
26
+ def indexed_names
27
+ File.open(index_path, 'r') do |f|
28
+ f.read.split(/\n/)
29
+ end.map(&:strip)
30
+ end
31
+
32
+ def update_index name
33
+ return if indexed_names.include?(name.to_s)
34
+ File.open(index_path, 'a') do |file|
35
+ file.write name.to_s << "\n"
36
+ end
37
+ end
38
+
39
+ def read(name)
40
+ File.open("#{@path}/#{name}.ast", 'r') do |file|
41
+ YAML.load(file.read)
42
+ end
43
+ end
44
+
45
+ def all
46
+ indexed_names.map do |name|
47
+ read name
48
+ end
49
+ end
50
+
51
+ def read_exec(name)
52
+ instance_eval <<-RUBY_EVAL
53
+ #{Unparser.unparse(read(name))}
54
+ RUBY_EVAL
55
+ end
56
+
57
+ def hard_reset!
58
+ Dir["#{@path}/*.ast"].each do |path|
59
+ File.delete path
60
+ end
61
+ File.open(index_path, 'w+') do |file|
62
+ file.write String.new
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,63 @@
1
+ module Outil
2
+ module OCS
3
+ class ObjectParser
4
+
5
+ attr :name, :path, :found
6
+
7
+ def initialize(path, name)
8
+ @path = path
9
+ @name = name
10
+ @found = false
11
+ end
12
+
13
+ def node
14
+ @node ||= Parser::CurrentRuby.parse(
15
+ File.open(@path, 'r') do |f|
16
+ f.read
17
+ end
18
+ )
19
+ end
20
+
21
+ def find
22
+ return @found if @found
23
+ set_and_stop = Proc.new do |node|
24
+ return @found = node
25
+ end
26
+ traverse = Proc.new do |node|
27
+ # if we're not at a node, we can move on
28
+ next unless node.is_a?(Parser::AST::Node)
29
+ # unless we're at a method definition
30
+ # we're probably in a begin block, a class, or module
31
+ # in which case traverse the children of the current node
32
+ node.children.each &traverse unless [:defs, :def].include?(node.type)
33
+ # bottom-level node interrogation...
34
+ case node.type
35
+ when :defs
36
+ # class methods
37
+ set_and_stop.call(node) if node.children[1] == name
38
+ next
39
+ when :def
40
+ # instance method
41
+ set_and_stop.call(node) if node.children.first == name
42
+ next
43
+ else
44
+ # other kind of object
45
+ if node.is_a?(Parser::AST::Node)
46
+ # another parent node
47
+ node.children.each &traverse
48
+ else
49
+ # the bottom of a node
50
+ next
51
+ end
52
+ end
53
+ end
54
+ begin
55
+ traverse.call(node)
56
+ rescue
57
+ false
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,13 @@
1
+ module Outil
2
+ module OCS
3
+ class Serialize
4
+ # TODO: Move the Index away from YAML and toward Binary
5
+ # I want to get away from using YAML
6
+ # dumps AST Node class as a serialization method
7
+ # and the nature of AST's themselves make
8
+ # them really friendly to binary serialization.
9
+ # In theory anyway.
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Outil
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,35 @@
1
+ module Outil
2
+
3
+ class Workspace
4
+
5
+ def self.ocs
6
+ @ocs ||= OCS::Config.new
7
+ end
8
+
9
+ def self.reset!
10
+ @references = []
11
+ @asts = {}
12
+ end
13
+
14
+ def self.references
15
+ @references ||= []
16
+ end
17
+
18
+ def self.asts
19
+ @asts ||= {}
20
+ end
21
+
22
+ def self.scan path, lineno, name
23
+ references << [path, lineno, name]
24
+ asts[name] = OCS::ObjectParser.new(path, name).find
25
+ end
26
+
27
+ def self.sync
28
+ asts.each_pair do |name, tree|
29
+ ocs.index.append name, tree
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Outil::Decorators do
4
+
5
+ describe Outil::Decorators::Register do
6
+
7
+ describe "call" do
8
+
9
+ it "should update workspace references" do
10
+ Outil.reset!
11
+ class DummyInterfaceTwo < RubyDecorators::Interface
12
+ use Outil::Decorators::Register
13
+ named :outil
14
+
15
+ outil :register
16
+ def baz
17
+ 'bar'
18
+ end
19
+ end
20
+ DummyInterfaceTwo.new.baz
21
+ target = [[__FILE__, 18, :baz]]
22
+ Outil::Workspace.references.should eq target
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,111 @@
1
+ require 'rubygems'
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ describe Outil::OCS::Index do
6
+
7
+ before do
8
+ @config = Outil::OCS::Config.new
9
+ @index = @config.index
10
+ end
11
+
12
+ describe "initialize" do
13
+ it "should set path instance variable" do
14
+ @index.path.should eq(@config.params[:index])
15
+ end
16
+ end
17
+
18
+ describe "index_path" do
19
+ it "should return the path with index at the end" do
20
+ @index.index_path.should eq(@config.params[:index] + "/index")
21
+ end
22
+ end
23
+
24
+ describe "write_serialize" do
25
+ it "should write a file named for the method to the index" do
26
+ @index.write_serialize(:hello, build_target_ast)
27
+ Dir["#{@index.path}/*.ast"].map do |path|
28
+ File.basename path
29
+ end.include?("hello.ast")
30
+ .should eq(true)
31
+ end
32
+ end
33
+
34
+ describe "indexed_names" do
35
+ it "return a list of registered methods names" do
36
+ @index.write_serialize(:hello, build_target_ast)
37
+ @index.indexed_names.include?("hello").should eq(true)
38
+ end
39
+ end
40
+
41
+ describe "update_index" do
42
+ it "adds a method name to the end of the index file" do
43
+ @index.write_serialize(:dummy, build_target_ast(:dummy))
44
+ @index.update_index :dummy
45
+ @index.indexed_names.include?('dummy').should eq(true)
46
+ end
47
+ end
48
+
49
+ describe "read" do
50
+ it "return an ast for the specified method" do
51
+ @index.write_serialize(:dummy, build_target_ast(:dummy))
52
+ @index.update_index :dummy
53
+ @index.read(:dummy).is_a?(Parser::AST::Node).should eq(true)
54
+ end
55
+ end
56
+
57
+ describe "append" do
58
+
59
+ before do
60
+ @index.append :baz, build_target_ast(:baz)
61
+ end
62
+
63
+ it "should write a file named for the method to the index" do
64
+ @index.indexed_names.include?('baz').should eq(true)
65
+ end
66
+
67
+ it "adds a method name to the end of the index file" do
68
+ Dir["#{@index.path}/*.ast"].map do |path|
69
+ File.basename path
70
+ end.include?("baz.ast")
71
+ .should eq(true)
72
+ end
73
+ end
74
+
75
+ describe "all" do
76
+ it "should return an array of asts" do
77
+ all_ast = Proc.new do |response|
78
+ response.map {|x| x.is_a?(Parser::AST::Node)}
79
+ .uniq == [true]
80
+ end
81
+ all_ast.call(@index.all)
82
+ end
83
+ end
84
+
85
+ describe "read_exec" do
86
+ it "should produce a method" do
87
+ @index.read_exec(:hello)
88
+ @index.send(:hello).should eq('hello')
89
+ end
90
+ end
91
+
92
+ describe "update_index" do
93
+ it "should append method names to the index file" do
94
+ # initialize the interface a bunch and call the
95
+ # registered methods, to make sure they don't keep
96
+ 10.times do
97
+ DummyInterface.new.hello
98
+ DummyInterface.new.goodbye
99
+ end
100
+ target = ['hello', 'dummy']
101
+ include_all = Proc.new do |a,b|
102
+ a.map {|x| b.include?(x) }.uniq == [true]
103
+ end
104
+ indexed = @index.indexed_names
105
+ include_all.call(target,
106
+ indexed)
107
+ .should eq(true)
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ describe Outil do
6
+
7
+ before do
8
+
9
+ class MyClient
10
+ include Outil
11
+
12
+ outil :register
13
+ def foo
14
+ 'bar'
15
+ end
16
+ end
17
+
18
+ Outil::Workspace.sync
19
+ end
20
+
21
+ describe "included" do
22
+ it "should include registered methods" do
23
+ client = MyClient.new
24
+ client.hello.should eq('hello')
25
+ client.goodbye.should eq('goodbye')
26
+ end
27
+
28
+ it "should allow registration for its own methods" do
29
+ Outil::Workspace.ocs.index.indexed_names.include?('foo').should eq(true)
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Outil::OCS::ObjectParser do
4
+
5
+ before do
6
+ Outil.reset!
7
+ DummyInterface.new.hello
8
+ @target = build_target_ast
9
+ end
10
+
11
+ after do
12
+ Outil.reset!
13
+ end
14
+
15
+ describe "append" do
16
+ it "append ast to workspace" do
17
+ Outil::Workspace.asts[:hello].should eq(@target)
18
+ end
19
+ end
20
+
21
+ describe "initialize" do
22
+ before do
23
+ @parser = Outil::OCS::ObjectParser.new(__FILE__, :hello)
24
+ end
25
+
26
+ it "should set path" do
27
+ @parser.path.should eq(__FILE__)
28
+ end
29
+
30
+ it "should set name" do
31
+ @parser.name.should eq(:hello)
32
+ end
33
+ end
34
+
35
+ describe "node" do
36
+ before do
37
+ @parser = build_generic_parser
38
+ end
39
+
40
+ it "should return an ast" do
41
+ @parser.node.is_a?(Parser::AST::Node).should eq(true)
42
+ end
43
+ end
44
+
45
+ describe "find" do
46
+ before do
47
+ @parser = build_generic_parser
48
+ end
49
+
50
+ it "should locate the named method in the parse tree" do
51
+ @parser.find.should eq(build_target_ast)
52
+ end
53
+
54
+ it "should set the found instance variable" do
55
+ @parser.find
56
+ @parser.found.should eq(build_target_ast)
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../../lib/outil', __FILE__)
2
+ require 'rspec'
3
+ require 'rspec/expectations'
4
+
5
+ def build_target_ast(name=false)
6
+ name = name ? name : :hello
7
+ Parser::AST::Node.new(:def,
8
+ children=[name,
9
+ Parser::AST::Node.new(:args),
10
+ Parser::AST::Node.new(:str,
11
+ children=["hello"])])
12
+ end
13
+
14
+ def build_generic_parser
15
+ Outil::OCS::ObjectParser
16
+ .new("#{File.dirname(__FILE__)}/spec_helper.rb",
17
+ :hello)
18
+ end
19
+
20
+
21
+ class DummyInterface < RubyDecorators::Interface
22
+ use Outil::Decorators::Register
23
+ named :outil
24
+
25
+ outil :register
26
+ def hello
27
+ 'hello'
28
+ end
29
+
30
+ outil :register
31
+ def goodbye
32
+ 'goodbye'
33
+ end
34
+
35
+ end
36
+
37
+ DummyInterface.new.hello
38
+
39
+ Outil::Workspace.sync
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: outil
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Matt Aliabadi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0.beta5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0.beta5
41
+ - !ruby/object:Gem::Dependency
42
+ name: unparser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Outil is a library for storing and importing reusable code
56
+ email:
57
+ - mattmaliabadi@gmail.com
58
+ executables:
59
+ - outil-boostrap
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - bin/outil-boostrap
64
+ - lib/outil/decorators.rb
65
+ - lib/outil/ocs/config.rb
66
+ - lib/outil/ocs/index.rb
67
+ - lib/outil/ocs/parser.rb
68
+ - lib/outil/ocs/serialize.rb
69
+ - lib/outil/ocs.rb
70
+ - lib/outil/version.rb
71
+ - lib/outil/workspace.rb
72
+ - lib/outil.rb
73
+ - spec/decorator_spec.rb
74
+ - spec/index_spec.rb
75
+ - spec/outil_spec.rb
76
+ - spec/parser_spec.rb
77
+ - spec/spec_helper.rb
78
+ homepage: http://www.github.com/maliabadi/outil
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.0.6
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Stores persistently available utility functions
102
+ test_files: []