Antwrap 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +4 -1
- data/docs/index.html +147 -109
- data/docs/index_files/Brander.css +669 -0
- data/docs/index_files/blankdot.gif +0 -0
- data/docs/index_files/blankdot.html +163 -0
- data/docs/index_files/urchin.js +624 -0
- data/lib/ant_project.rb +133 -0
- data/lib/ant_task.rb +118 -0
- data/lib/antwrap.rb +14 -214
- data/lib/antwrap_utilities.rb +18 -15
- data/lib/jruby_modules.rb +7 -0
- data/lib/rjb_modules.rb +7 -0
- data/test/{tc_antwrap.rb → antwrap_test.rb} +47 -46
- metadata +11 -7
- data/lib/convert.rb +0 -104
- data/lib/dsl.rb +0 -163
- data/test/tc_convert.rb +0 -34
data/lib/antwrap_utilities.rb
CHANGED
@@ -1,31 +1,34 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require 'rubygems'
|
8
|
-
require 'rjb'
|
9
|
-
autoload :ApacheAnt, 'rjb_modules.rb'
|
10
|
-
autoload :JavaLang, 'rjb_modules.rb'
|
11
|
-
autoload :XmlOrg, 'rjb_modules.rb'
|
12
|
-
end
|
1
|
+
# antwrap_utilities.rb
|
2
|
+
#
|
3
|
+
# Copyright Caleb Powell 2007
|
4
|
+
#
|
5
|
+
# Licensed under the LGPL, see the file COPYING in the distribution
|
6
|
+
#
|
13
7
|
|
14
8
|
module AntwrapClassLoader
|
9
|
+
|
15
10
|
require 'find'
|
11
|
+
|
16
12
|
def match(*paths)
|
17
|
-
|
13
|
+
|
14
|
+
matched = Array.new
|
18
15
|
Find.find(*paths){ |path| matched << path if yield path }
|
19
16
|
return matched
|
17
|
+
|
20
18
|
end
|
21
19
|
|
22
20
|
def load_ant_libs(ant_home)
|
23
|
-
|
21
|
+
|
22
|
+
jars = match(ant_home + File::SEPARATOR + 'lib') {|p| ext = p[-4...p.size]; ext && ext.downcase == '.jar'}
|
23
|
+
|
24
24
|
if(RUBY_PLATFORM == 'java')
|
25
25
|
jars.each {|jar| require jar }
|
26
26
|
else
|
27
|
-
Rjb::load(jars.join(
|
27
|
+
Rjb::load(jars.join(File::PATH_SEPARATOR), [])
|
28
28
|
end
|
29
|
+
|
29
30
|
end
|
31
|
+
|
30
32
|
module_function :match, :load_ant_libs
|
33
|
+
|
31
34
|
end
|
data/lib/jruby_modules.rb
CHANGED
data/lib/rjb_modules.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# rjb_modules.rb
|
2
|
+
#
|
3
|
+
# Copyright Caleb Powell 2007
|
4
|
+
#
|
5
|
+
# Licensed under the LGPL, see the file COPYING in the distribution
|
6
|
+
#
|
7
|
+
|
1
8
|
module ApacheAnt
|
2
9
|
DefaultLogger = Rjb::import("org.apache.tools.ant.DefaultLogger")
|
3
10
|
Main = Rjb::import("org.apache.tools.ant.Main")
|
@@ -4,23 +4,23 @@
|
|
4
4
|
#
|
5
5
|
# Licensed under the LGPL, see the file COPYING in the distribution
|
6
6
|
#
|
7
|
+
|
7
8
|
require 'test/unit'
|
8
9
|
require 'fileutils'
|
9
|
-
$LOAD_PATH.push(
|
10
|
+
$LOAD_PATH.push(FileUtils::pwd + '/lib')
|
10
11
|
require 'antwrap'
|
11
12
|
require 'logger'
|
12
13
|
|
13
|
-
class
|
14
|
+
class AntwrapTest < Test::Unit::TestCase
|
14
15
|
|
15
16
|
def setup
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@resource_dir = @current_dir + '/test/test-resources'
|
17
|
+
@output_dir = FileUtils::pwd + File::SEPARATOR + 'test' + File::SEPARATOR + 'output'
|
18
|
+
@resource_dir = FileUtils::pwd + File::SEPARATOR + 'test' + File::SEPARATOR + 'test-resources'
|
19
19
|
|
20
|
-
@ant_home = @resource_dir + "
|
20
|
+
@ant_home = @resource_dir + File::SEPARATOR + "apache-ant-1.7.0"
|
21
21
|
# @ant_home = "/Users/caleb/tools/apache-ant-1.6.5"
|
22
22
|
# @ant_home = "/Users/caleb/tools/apache-ant-1.5.4"
|
23
|
-
@ant_proj_props = {:name=>"testProject", :basedir
|
23
|
+
@ant_proj_props = {:name=>"testProject", :basedir=>FileUtils::pwd, :declarative=>true,
|
24
24
|
:logger=>Logger.new(STDOUT), :loglevel=>Logger::DEBUG, :ant_home => @ant_home}
|
25
25
|
@ant = AntProject.new(@ant_proj_props)
|
26
26
|
|
@@ -35,7 +35,7 @@ class TestAntwrap < Test::Unit::TestCase
|
|
35
35
|
:logger=>Logger.new(STDOUT), :loglevel=>Logger::ERROR}
|
36
36
|
ant_proj = AntProject.new(@ant_proj_props)
|
37
37
|
assert(@ant_proj_props[:name] == ant_proj.name())
|
38
|
-
assert(
|
38
|
+
# assert(FileUtils::pwd == ant_proj.basedir())
|
39
39
|
assert(@ant_proj_props[:declarative] == ant_proj.declarative())
|
40
40
|
assert(@ant_proj_props[:logger] == ant_proj.logger())
|
41
41
|
end
|
@@ -83,14 +83,14 @@ class TestAntwrap < Test::Unit::TestCase
|
|
83
83
|
@ant.property(:name => 'pattern', :value => '**/*.jar')
|
84
84
|
@ant.property(:name => 'resource_dir', :value => @resource_dir)
|
85
85
|
@ant.path(:id => 'common.class.path'){
|
86
|
-
fileset(:dir => '${resource_dir}'){
|
87
|
-
include(:name => '${pattern}')
|
86
|
+
@ant.fileset(:dir => '${resource_dir}'){
|
87
|
+
@ant.include(:name => '${pattern}')
|
88
88
|
}
|
89
89
|
}
|
90
|
-
|
90
|
+
puts "Resource dir: #{@resource_dir}"
|
91
91
|
@ant.javac(:srcdir => @resource_dir + '/src',
|
92
92
|
:destdir => @output_dir + '/classes',
|
93
|
-
:debug =>
|
93
|
+
:debug => true,
|
94
94
|
:verbose => true,
|
95
95
|
:fork => 'no',
|
96
96
|
:failonerror => 'blahblahblah',
|
@@ -130,15 +130,15 @@ class TestAntwrap < Test::Unit::TestCase
|
|
130
130
|
|
131
131
|
@ant.property(:name => 'output_dir', :value => @output_dir)
|
132
132
|
@ant.property(:name => 'resource_dir', :value =>@resource_dir)
|
133
|
-
@ant.java(:classname => 'foo.bar.FooBar', :fork => 'false') {
|
134
|
-
arg(:value => 'argOne')
|
135
|
-
classpath(){
|
136
|
-
pathelement(:location => '${output_dir}/classes')
|
137
|
-
pathelement(:location => '${resource_dir}/parent.jar')
|
133
|
+
@ant.java(:classname => 'foo.bar.FooBar', :fork => 'false') {|ant|
|
134
|
+
ant.arg(:value => 'argOne')
|
135
|
+
ant.classpath(){
|
136
|
+
ant.pathelement(:location => '${output_dir}/classes')
|
137
|
+
ant.pathelement(:location => '${resource_dir}/parent.jar')
|
138
138
|
}
|
139
|
-
arg(:value => 'argTwo')
|
140
|
-
jvmarg(:value => 'client')
|
141
|
-
sysproperty(:key=> 'antwrap', :value => 'coolio')
|
139
|
+
ant.arg(:value => 'argTwo')
|
140
|
+
ant.jvmarg(:value => 'client')
|
141
|
+
ant.sysproperty(:key=> 'antwrap', :value => 'coolio')
|
142
142
|
}
|
143
143
|
end
|
144
144
|
|
@@ -178,11 +178,11 @@ class TestAntwrap < Test::Unit::TestCase
|
|
178
178
|
|
179
179
|
assert_absent dir
|
180
180
|
|
181
|
-
@ant.macrodef(:name => 'testmacrodef'){
|
182
|
-
attribute(:name => 'destination')
|
183
|
-
sequential(){
|
184
|
-
echo(:message => "Creating @{destination}")
|
185
|
-
_mkdir(:dir => "@{destination}")
|
181
|
+
@ant.macrodef(:name => 'testmacrodef'){|ant|
|
182
|
+
ant.attribute(:name => 'destination')
|
183
|
+
ant.sequential(){
|
184
|
+
ant.echo(:message => "Creating @{destination}")
|
185
|
+
ant._mkdir(:dir => "@{destination}")
|
186
186
|
}
|
187
187
|
}
|
188
188
|
@ant.testmacrodef(:destination => dir)
|
@@ -200,24 +200,24 @@ class TestAntwrap < Test::Unit::TestCase
|
|
200
200
|
@ant.taskdef(:resource => "net/sf/antcontrib/antlib.xml")
|
201
201
|
|
202
202
|
@ant.property(:name => "bar", :value => "bar")
|
203
|
-
@ant._if(){
|
204
|
-
_equals(:arg1 => "${bar}", :arg2 => "bar")
|
205
|
-
_then(){
|
206
|
-
echo(:message => "if 1 is equal")
|
203
|
+
@ant._if(){|ant|
|
204
|
+
ant._equals(:arg1 => "${bar}", :arg2 => "bar")
|
205
|
+
ant._then(){
|
206
|
+
ant.echo(:message => "if 1 is equal")
|
207
207
|
}
|
208
|
-
_else(){
|
209
|
-
echo(:message => "if 1 is not equal")
|
208
|
+
ant._else(){
|
209
|
+
ant.echo(:message => "if 1 is not equal")
|
210
210
|
}
|
211
211
|
}
|
212
212
|
|
213
213
|
@ant.property(:name => "baz", :value => "foo")
|
214
|
-
@ant._if(){
|
215
|
-
_equals(:arg1 => "${baz}", :arg2 => "bar")
|
216
|
-
_then(){
|
217
|
-
echo(:message => "if 2 is equal")
|
214
|
+
@ant._if(){|ant|
|
215
|
+
ant._equals(:arg1 => "${baz}", :arg2 => "bar")
|
216
|
+
ant._then(){
|
217
|
+
ant.echo(:message => "if 2 is equal")
|
218
218
|
}
|
219
|
-
_else(){
|
220
|
-
echo(:message => "if 2 is not equal")
|
219
|
+
ant._else(){
|
220
|
+
ant.echo(:message => "if 2 is not equal")
|
221
221
|
}
|
222
222
|
}
|
223
223
|
|
@@ -234,16 +234,17 @@ class TestAntwrap < Test::Unit::TestCase
|
|
234
234
|
rescue ArgumentError
|
235
235
|
end
|
236
236
|
end
|
237
|
-
# def test_open_pja
|
238
|
-
# @ant.taskdef(:name=>"mappingtool", :classname=>"org.apache.openjpa.jdbc.ant.MappingToolTask")
|
239
|
-
#
|
240
|
-
# @ant.mappingtool(:action => "buildSchema"){
|
241
|
-
# fileset(:dir => "."){
|
242
|
-
# include(:name => "**/*.jdo")
|
243
|
-
# }
|
244
|
-
# }
|
245
|
-
# end
|
246
237
|
|
238
|
+
def test_declarative
|
239
|
+
@ant = AntProject.new({:declarative=>false,:loglevel=>Logger::DEBUG, :ant_home => @ant_home})
|
240
|
+
echo = @ant.echo(:message => "Echo")
|
241
|
+
assert_not_nil(echo)
|
242
|
+
|
243
|
+
@ant = AntProject.new({:declarative=>true,:loglevel=>Logger::DEBUG, :ant_home => @ant_home})
|
244
|
+
echo = @ant.echo(:message => "Echo")
|
245
|
+
assert_nil(echo)
|
246
|
+
end
|
247
|
+
|
247
248
|
private
|
248
249
|
def assert_exists(file_path)
|
249
250
|
assert(File.exists?(file_path), "Does not exist[#{file_path}]")
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
|
|
3
3
|
specification_version: 1
|
4
4
|
name: Antwrap
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-06-
|
6
|
+
version: 0.6.0
|
7
|
+
date: 2007-06-18
|
8
8
|
summary: "A Ruby module that wraps the Apache Ant build tool, enabling Ant Tasks to be
|
9
9
|
invoked from a Ruby/JRuby scripts."
|
10
10
|
require_paths:
|
@@ -28,16 +28,15 @@ platform: ruby
|
|
28
28
|
authors:
|
29
29
|
- Caleb Powell
|
30
30
|
files:
|
31
|
+
- lib/ant_project.rb
|
32
|
+
- lib/ant_task.rb
|
31
33
|
- lib/antwrap.rb
|
32
34
|
- lib/antwrap_utilities.rb
|
33
|
-
- lib/convert.rb
|
34
|
-
- lib/dsl.rb
|
35
35
|
- lib/jruby_modules.rb
|
36
36
|
- lib/rjb_modules.rb
|
37
|
+
- test/antwrap_test.rb
|
37
38
|
- test/build.xml
|
38
39
|
- test/output
|
39
|
-
- test/tc_antwrap.rb
|
40
|
-
- test/tc_convert.rb
|
41
40
|
- test/test-resources
|
42
41
|
- test/output/META-INF
|
43
42
|
- test/output/parent
|
@@ -57,10 +56,15 @@ files:
|
|
57
56
|
- test/test-resources/src/foo/bar/FooBar.java
|
58
57
|
- test/test-resources/src/foo/bar/baz/FooBarBaz.java
|
59
58
|
- docs/index.html
|
59
|
+
- docs/index_files
|
60
|
+
- docs/index_files/blankdot.gif
|
61
|
+
- docs/index_files/blankdot.html
|
62
|
+
- docs/index_files/Brander.css
|
63
|
+
- docs/index_files/urchin.js
|
60
64
|
- README
|
61
65
|
- COPYING
|
62
66
|
test_files:
|
63
|
-
- test/
|
67
|
+
- test/antwrap_test.rb
|
64
68
|
rdoc_options: []
|
65
69
|
extra_rdoc_files:
|
66
70
|
- README
|
data/lib/convert.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# antwrap
|
2
|
-
#
|
3
|
-
# Copyright Caleb Powell 2007
|
4
|
-
#
|
5
|
-
# Licensed under the LGPL, see the file COPYING in the distribution
|
6
|
-
#
|
7
|
-
require 'rexml/document'
|
8
|
-
|
9
|
-
if ARGV.empty?
|
10
|
-
puts "Usage: #{$0} [antfile] [rakefile]"
|
11
|
-
exit! 1
|
12
|
-
end
|
13
|
-
|
14
|
-
@antfile = File.open(ARGV[0])
|
15
|
-
@rakefile = File.new(ARGV[1], 'w+')
|
16
|
-
@@reserved_words = ['alias', 'and', 'BEGIN', 'begin', 'break', 'case', 'class',
|
17
|
-
'def', 'defined', 'do', 'else', 'elsif', 'END', 'end', 'ensure',
|
18
|
-
'false', 'for', 'if', 'in', 'module', 'next', 'nil', 'not', 'or',
|
19
|
-
'redo', 'rescue', 'retry', 'return', 'self', 'super', 'then', 'true',
|
20
|
-
'undef', 'unless', 'until', 'when', 'while', 'yield', 'java']
|
21
|
-
|
22
|
-
xml = REXML::Document.new(@antfile)
|
23
|
-
|
24
|
-
puts "Converting from Ant build script[#{@antfile.path}] == to ==> \n Rakefile[#{@rakefile.path}]"
|
25
|
-
|
26
|
-
def create_symbol(str)
|
27
|
-
str = rubyize(str)
|
28
|
-
return str.gsub(/(\w*[^,\s])/, ':\1')
|
29
|
-
end
|
30
|
-
|
31
|
-
def rubyize(str)
|
32
|
-
if (str == nil)
|
33
|
-
str = ''
|
34
|
-
elsif (@@reserved_words.index(str) != nil)
|
35
|
-
str = '_' + str
|
36
|
-
else
|
37
|
-
str = str.gsub(/(\w*)[\-|\.](\w*)/, '\1_\2')
|
38
|
-
end
|
39
|
-
return str
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
@rakefile.print "require_gem 'Antwrap'\n"
|
44
|
-
@rakefile.print "@ant = AntProject.new()\n"
|
45
|
-
@one_tab= ' '
|
46
|
-
def print_task(task, tab=@one_tab, prefix='')
|
47
|
-
task_name = rubyize(task.name)
|
48
|
-
@rakefile.print "#{tab}#{prefix}#{task_name}("
|
49
|
-
|
50
|
-
if(task_name == 'macrodef')
|
51
|
-
task.attributes['name'] = rubyize(task.attributes['name'])
|
52
|
-
elsif(task_name == 'java')
|
53
|
-
task_name = 'jvm'
|
54
|
-
end
|
55
|
-
|
56
|
-
isFirst = true;
|
57
|
-
task.attributes.each do |key, value|
|
58
|
-
if !isFirst
|
59
|
-
@rakefile.print(",\n#{tab+@one_tab}")
|
60
|
-
end
|
61
|
-
@rakefile.print ":#{key} => \"#{value}\""
|
62
|
-
isFirst = false;
|
63
|
-
end
|
64
|
-
|
65
|
-
if task.has_text?
|
66
|
-
pcdata = task.texts().join
|
67
|
-
if(pcdata.strip() != '')
|
68
|
-
@rakefile.print ":pcdata => \"#{pcdata}\""
|
69
|
-
end
|
70
|
-
end
|
71
|
-
@rakefile.print ")"
|
72
|
-
|
73
|
-
|
74
|
-
if task.elements.size > 0
|
75
|
-
@rakefile.print "{"
|
76
|
-
task.elements.each do |child|
|
77
|
-
@rakefile.print "\n"
|
78
|
-
print_task(child, (tab+@one_tab), '')
|
79
|
-
end
|
80
|
-
@rakefile.print "\n#{tab}}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
xml.elements.each("/project/*") do |node|
|
85
|
-
if node.name != 'target'
|
86
|
-
print_task(node, '', '@ant.')
|
87
|
-
@rakefile.print "\n\n"
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
xml.elements.each("/project/target") do |node|
|
92
|
-
|
93
|
-
task = "\ntask " + create_symbol(node.attributes['name']) +
|
94
|
-
" => [" + create_symbol(node.attributes['depends']) + "] do\n"
|
95
|
-
|
96
|
-
@rakefile.print task
|
97
|
-
|
98
|
-
node.elements.each do |child|
|
99
|
-
print_task(child, @one_tab, '@ant.')
|
100
|
-
@rakefile.print "\n"
|
101
|
-
end
|
102
|
-
@rakefile.print "end\n"
|
103
|
-
end
|
104
|
-
|
data/lib/dsl.rb
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
# A Domain Specific Language is used to introduce a new scope with an embedded set of methods.
|
2
|
-
#
|
3
|
-
# The idea is to avoid polluting the global namespace. Instead of adding methods to Kernel, we
|
4
|
-
# add methods to a new DomainSpecificLanguage, and then we can evaluate code with the new language
|
5
|
-
# using the #eval class method or using the #with method added to Kernel.
|
6
|
-
#
|
7
|
-
# For a similar approach, see http://www.infoq.com/articles/eval-options-in-ruby
|
8
|
-
|
9
|
-
class DomainSpecificLanguage
|
10
|
-
|
11
|
-
# See http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
|
12
|
-
def metaclass; class << self; self; end; end
|
13
|
-
def meta_eval &blk; metaclass.instance_eval &blk; end
|
14
|
-
|
15
|
-
# Adds methods to a metaclass
|
16
|
-
def meta_def name, &blk
|
17
|
-
meta_eval { define_method name, &blk }
|
18
|
-
end
|
19
|
-
|
20
|
-
# See http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc
|
21
|
-
class ReadOnlyReference
|
22
|
-
def initialize(var_name, vars)
|
23
|
-
@getter = eval "lambda { #{var_name} }", vars
|
24
|
-
end
|
25
|
-
def value
|
26
|
-
@getter.call
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
attr_reader :outer_binding, :outer_self
|
31
|
-
|
32
|
-
# instances of a DomainSpecificLanguage are created each time
|
33
|
-
# a block is evaluated with that language. The instance is
|
34
|
-
# intialized with the block's binding.
|
35
|
-
|
36
|
-
def initialize(given_binding)
|
37
|
-
@outer_binding = given_binding
|
38
|
-
@outer_self = ReadOnlyReference.new(:self, given_binding)
|
39
|
-
end
|
40
|
-
|
41
|
-
# some jiggery-pokery to access methods defined in the block's
|
42
|
-
# scope, because when the block is evaluated with the DomainSpecificLanguage,
|
43
|
-
# we use #instance_eval to set <tt>self</tt> to the DomainSpecificLanguage
|
44
|
-
# instance.
|
45
|
-
def method_missing(symbol, *args, &block)
|
46
|
-
if args.empty?
|
47
|
-
r = ReadOnlyReference.new(symbol, outer_binding)
|
48
|
-
meta_def(symbol) { r.value }
|
49
|
-
r.value
|
50
|
-
else
|
51
|
-
outer_self.value.send symbol, *args, &block
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class << self
|
56
|
-
|
57
|
-
# Evaluates a block in the context of a new DomainSpecificlanguage
|
58
|
-
# instance.
|
59
|
-
def eval &block
|
60
|
-
new(block.binding).instance_eval(&block)
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
# We open Kernel and add just one method for introducing DomainSpecificLanguages
|
68
|
-
|
69
|
-
module Kernel
|
70
|
-
|
71
|
-
# Evaluate a block with a DomainSpecificLanguage
|
72
|
-
|
73
|
-
def with dsl_class, &block
|
74
|
-
dsl_class.eval(&block)
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
# Let is a DomainSpecificLanguage that actually creates DomainSpecificLanguages.
|
80
|
-
#
|
81
|
-
# Let works a lot like <tt>let</tt> in Scheme. Your provide a hash of names and value
|
82
|
-
# expressions. The value expressions are evaluated in the outer scope, and then we have
|
83
|
-
# a little domain specific language where the inner scope has the names all bound to the
|
84
|
-
# values. E.g.
|
85
|
-
# <tt>
|
86
|
-
# with Let do
|
87
|
-
# let :x => 100, :y => 50 do
|
88
|
-
# print "#{x + y} should equal fifty"
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
# </tt>
|
92
|
-
#
|
93
|
-
# Within the Let DomainSpecificLanguage, you can declare multiple <tt>let</tt> statements and nest
|
94
|
-
# them as you please.
|
95
|
-
#
|
96
|
-
# One important limitation: you cannot bind a value to a name that is already a local variable.
|
97
|
-
|
98
|
-
class Let < DomainSpecificLanguage
|
99
|
-
|
100
|
-
class Scope < DomainSpecificLanguage
|
101
|
-
|
102
|
-
# initializes a Scope. In addition to the outer binding, we also pass in the
|
103
|
-
# hash of names and values. Note the check to ensure we are not trying to
|
104
|
-
# override a lcoal variable.
|
105
|
-
|
106
|
-
def initialize given_binding, let_clauses = {}
|
107
|
-
let_clauses.each do |symbol, value|
|
108
|
-
var_name = symbol.to_s
|
109
|
-
raise ArgumentError.new("Cannot override local #{var_name}") if eval("local_variables", given_binding).detect { |local| local == var_name }
|
110
|
-
meta_eval { attr_accessor(var_name) }
|
111
|
-
send "#{var_name}=", value
|
112
|
-
end
|
113
|
-
super(given_binding)
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
# Define a new Scope: you're really defining a new DomainSpecificLanguage
|
119
|
-
|
120
|
-
def let let_clauses = {}, &block
|
121
|
-
Scope.new(block.binding, let_clauses).instance_eval(&block)
|
122
|
-
end
|
123
|
-
|
124
|
-
class << self
|
125
|
-
|
126
|
-
# If you just want a one-off
|
127
|
-
# def eval let_clauses = {}, &block
|
128
|
-
# Scope.new(block.binding, let_clauses).instance_eval(&block)
|
129
|
-
# end
|
130
|
-
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
# A DomainSpecificDelegator is a DSL that delegates methods to a class or object.
|
136
|
-
# The main use is to separate the mechanics of scoping from the methods of a utility
|
137
|
-
# class.
|
138
|
-
|
139
|
-
class DomainSpecificDelegator < DomainSpecificLanguage
|
140
|
-
|
141
|
-
class << self
|
142
|
-
|
143
|
-
# insert one or more #delegate_to calls in the class definition, giving a receiver
|
144
|
-
# and a hash. Each hash pair is of the form <tt>verb => method</tt> where verb is the
|
145
|
-
# name you will use in the DSL and method is the method in the receiver that will handle
|
146
|
-
# it.
|
147
|
-
def delegate_to receiver, method_hash
|
148
|
-
@@delegations ||= {}
|
149
|
-
method_hash.each { |verb, method_name| @@delegations[verb.to_s] = [receiver, method_name.to_s] }
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
def method_missing symbol, *args, &block
|
155
|
-
receiver, method_name = *@@delegations[symbol.to_s]
|
156
|
-
if receiver
|
157
|
-
receiver.send method_name, *args, &block
|
158
|
-
else
|
159
|
-
super(symbol, *args, &block)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|