Antwrap 0.5.4-java → 0.6.0-java
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.
- 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: java
|
|
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
|