blockenspiel 0.4.3 → 0.4.4
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/Blockenspiel.rdoc +5 -1
- data/History.rdoc +7 -0
- data/README.rdoc +6 -2
- data/Version +1 -1
- data/ext/unmixer_mri/extconf.rb +10 -10
- data/ext/unmixer_mri/unmixer_mri.c +10 -10
- data/lib/blockenspiel.rb +7 -7
- data/lib/blockenspiel/builder.rb +52 -52
- data/lib/blockenspiel/dsl_setup.rb +86 -86
- data/lib/blockenspiel/errors.rb +18 -18
- data/lib/blockenspiel/impl.rb +116 -116
- data/lib/blockenspiel/unmixer_rubinius.rb +22 -22
- data/lib/blockenspiel/unmixer_unimplemented.rb +17 -17
- data/lib/blockenspiel/version.rb +9 -9
- data/lib/blockenspiel/versionomy.rb +11 -13
- data/test/tc_basic.rb +38 -38
- data/test/tc_behaviors.rb +36 -36
- data/test/tc_dsl_attrs.rb +37 -37
- data/test/tc_dsl_methods.rb +86 -86
- data/test/tc_dynamic.rb +39 -39
- data/test/tc_embedded_block.rb +29 -28
- data/test/tc_mixins.rb +103 -68
- data/test/tc_modules.rb +49 -49
- data/test/tc_version.rb +59 -0
- metadata +27 -29
- data/lib/blockenspiel_unmixer_jruby.jar +0 -0
data/Blockenspiel.rdoc
CHANGED
|
@@ -326,10 +326,14 @@ multiple threads trying to mix methods into the same object concurrently.
|
|
|
326
326
|
|
|
327
327
|
=== Development and support
|
|
328
328
|
|
|
329
|
-
Documentation is available at http://
|
|
329
|
+
Documentation is available at http://dazuma.github.com/blockenspiel/rdoc
|
|
330
330
|
|
|
331
331
|
Source code is hosted on Github at http://github.com/dazuma/blockenspiel
|
|
332
332
|
|
|
333
|
+
Contributions are welcome. Fork the project on Github.
|
|
334
|
+
|
|
335
|
+
Build status: {<img src="https://secure.travis-ci.org/dazuma/blockenspiel.png" />}[http://travis-ci.org/dazuma/blockenspiel]
|
|
336
|
+
|
|
333
337
|
Report bugs on Github issues at http://github.org/dazuma/blockenspiel/issues
|
|
334
338
|
|
|
335
339
|
Contact the author at dazuma at gmail dot com.
|
data/History.rdoc
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
=== 0.4.4 / 2012-06-27
|
|
2
|
+
|
|
3
|
+
* Under JRuby 1.9 mode, if two threads mixed into the same object, the calls sometimes went to the wrong place. Fixed.
|
|
4
|
+
* The VERSION constant behaved very oddly under Rubinius 1.9 mode. Fixed.
|
|
5
|
+
* Eliminate some warnings.
|
|
6
|
+
* Integrate with Travis CI.
|
|
7
|
+
|
|
1
8
|
=== 0.4.3 / 2011-06-22
|
|
2
9
|
|
|
3
10
|
* MRI C extension experienced a compile error under the current MRI head (e.g. 1.9.3). Fixed.
|
data/README.rdoc
CHANGED
|
@@ -74,10 +74,14 @@ For an extended analysis of different ways to implement DSL blocks, see
|
|
|
74
74
|
|
|
75
75
|
=== Development and support
|
|
76
76
|
|
|
77
|
-
Documentation is available at http://
|
|
77
|
+
Documentation is available at http://dazuma.github.com/blockenspiel/rdoc
|
|
78
78
|
|
|
79
79
|
Source code is hosted on Github at http://github.com/dazuma/blockenspiel
|
|
80
80
|
|
|
81
|
+
Contributions are welcome. Fork the project on Github.
|
|
82
|
+
|
|
83
|
+
Build status: {<img src="https://secure.travis-ci.org/dazuma/blockenspiel.png" />}[http://travis-ci.org/dazuma/blockenspiel]
|
|
84
|
+
|
|
81
85
|
Report bugs on Github issues at http://github.org/dazuma/blockenspiel/issues
|
|
82
86
|
|
|
83
87
|
Contact the author at dazuma at gmail dot com.
|
|
@@ -105,7 +109,7 @@ Luis Lavena.
|
|
|
105
109
|
|
|
106
110
|
=== License
|
|
107
111
|
|
|
108
|
-
Copyright 2008-
|
|
112
|
+
Copyright 2008-2012 Daniel Azuma.
|
|
109
113
|
|
|
110
114
|
All rights reserved.
|
|
111
115
|
|
data/Version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.4.
|
|
1
|
+
0.4.4
|
data/ext/unmixer_mri/extconf.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# Blockenspiel native library builder
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# -----------------------------------------------------------------------------
|
|
6
6
|
# Copyright 2010-2011 Daniel Azuma
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# All rights reserved.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
|
14
14
|
# this list of conditions and the following disclaimer.
|
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
|
20
20
|
# derived from this software without specific prior written permission.
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
if ::RUBY_DESCRIPTION =~ /^jruby\s/
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
::File.open('Makefile', 'w'){ |f_| f_.write(".PHONY: install\ninstall:\n") }
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
else
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
require 'mkmf'
|
|
44
44
|
have_header('ruby/backward/classext.h')
|
|
45
45
|
create_makefile 'blockenspiel/unmixer_mri'
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
end
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/*
|
|
2
2
|
-----------------------------------------------------------------------------
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
Blockenspiel unmixer (MRI implementation)
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
-----------------------------------------------------------------------------
|
|
7
7
|
Copyright 2008-2011 Daniel Azuma
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
All rights reserved.
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
Redistribution and use in source and binary forms, with or without
|
|
12
12
|
modification, are permitted provided that the following conditions are met:
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
* Redistributions of source code must retain the above copyright notice,
|
|
15
15
|
this list of conditions and the following disclaimer.
|
|
16
16
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* Neither the name of the copyright holder, nor the names of any other
|
|
20
20
|
contributors to this software, may be used to endorse or promote products
|
|
21
21
|
derived from this software without specific prior written permission.
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
24
24
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
25
25
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
written by Patrick Farley, anonymous z, Dan Manges, and Clint Bishop.
|
|
41
41
|
http://rubyforge.org/projects/mixology
|
|
42
42
|
http://github.com/dan-manges/mixology/tree/master
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
It has been stripped down and modified for compatibility with Ruby 1.9.
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
Note that this C extension is specific to MRI.
|
|
47
47
|
*/
|
|
48
48
|
|
|
@@ -95,9 +95,9 @@ static VALUE do_unmix(VALUE self, VALUE receiver, VALUE module) {
|
|
|
95
95
|
|
|
96
96
|
void Init_unmixer_mri() {
|
|
97
97
|
#ifndef RUBINIUS
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
VALUE container = rb_singleton_class(rb_define_module_under(rb_define_module("Blockenspiel"), "Unmixer"));
|
|
100
100
|
rb_define_method(container, "unmix", do_unmix, 2);
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
#endif
|
|
103
103
|
}
|
data/lib/blockenspiel.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# Blockenspiel entry point
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# -----------------------------------------------------------------------------
|
|
6
6
|
# Copyright 2008-2011 Daniel Azuma
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# All rights reserved.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
|
14
14
|
# this list of conditions and the following disclaimer.
|
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
|
20
20
|
# derived from this software without specific prior written permission.
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
# == Blockenspiel
|
|
38
|
-
#
|
|
38
|
+
#
|
|
39
39
|
# The Blockenspiel module provides a namespace for Blockenspiel, as well as
|
|
40
40
|
# the main entry point method "invoke".
|
|
41
41
|
|
data/lib/blockenspiel/builder.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# Blockenspiel dynamic target construction
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# -----------------------------------------------------------------------------
|
|
6
6
|
# Copyright 2008-2011 Daniel Azuma
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# All rights reserved.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
|
14
14
|
# this list of conditions and the following disclaimer.
|
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
|
20
20
|
# derived from this software without specific prior written permission.
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -35,37 +35,37 @@
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
module Blockenspiel
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
|
|
40
40
|
# === Dynamically construct a target
|
|
41
|
-
#
|
|
41
|
+
#
|
|
42
42
|
# These methods are available in a block passed to Blockenspiel#invoke and
|
|
43
43
|
# can be used to dynamically define what methods are available from a block.
|
|
44
44
|
# See Blockenspiel#invoke for more information.
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
class Builder
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
include ::Blockenspiel::DSL
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
|
|
50
|
+
|
|
51
51
|
# This is a base class for dynamically constructed targets.
|
|
52
52
|
# The actual target class is an anonymous subclass of this base class.
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
class Target # :nodoc:
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
include ::Blockenspiel::DSL
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
|
|
58
|
+
|
|
59
59
|
# Add a method specification to the subclass.
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
def self._add_methodinfo(name_, block_, yields_)
|
|
62
62
|
(@_blockenspiel_methodinfo ||= {})[name_] = [block_, yields_]
|
|
63
63
|
module_eval("def #{name_}(*params_, &block_); self.class._invoke_methodinfo(:#{name_}, params_, block_); end\n")
|
|
64
64
|
end
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
|
|
66
|
+
|
|
67
67
|
# Attempt to invoke the given method on the subclass.
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
def self._invoke_methodinfo(name_, params_, block_)
|
|
70
70
|
info_ = @_blockenspiel_methodinfo[name_]
|
|
71
71
|
case info_[1]
|
|
@@ -76,72 +76,72 @@ module Blockenspiel
|
|
|
76
76
|
end
|
|
77
77
|
info_[0].call(*params_, &block_)
|
|
78
78
|
end
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
end
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
|
|
82
|
+
|
|
83
83
|
# Sets up the dynamic target class.
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
def initialize # :nodoc:
|
|
86
86
|
@target_class = ::Class.new(::Blockenspiel::Builder::Target)
|
|
87
87
|
@target_class.dsl_methods(false)
|
|
88
88
|
end
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
|
|
90
|
+
|
|
91
91
|
# Creates a new instance of the dynamic target class
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
def _create_target # :nodoc:
|
|
94
94
|
@target_class.new
|
|
95
95
|
end
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
|
|
97
|
+
|
|
98
98
|
# === Declare a DSL method.
|
|
99
|
-
#
|
|
99
|
+
#
|
|
100
100
|
# This call creates a method that can be called from the DSL block.
|
|
101
101
|
# Provide a name for the method, a block defining the method's
|
|
102
102
|
# implementation, and an optional hash of options.
|
|
103
|
-
#
|
|
103
|
+
#
|
|
104
104
|
# By default, a method of the same name is also made available to
|
|
105
105
|
# parameterless blocks. To change the name of the parameterless method,
|
|
106
106
|
# provide its name as the value of the <tt>:dsl_method</tt> option.
|
|
107
107
|
# To disable this method for parameterless blocks, set the
|
|
108
108
|
# <tt>:dsl_method</tt> option to +false+.
|
|
109
|
-
#
|
|
109
|
+
#
|
|
110
110
|
# The <tt>:mixin</tt> option is a deprecated alias for
|
|
111
111
|
# <tt>:dsl_method</tt>.
|
|
112
|
-
#
|
|
112
|
+
#
|
|
113
113
|
# === Warning about the +return+ keyword
|
|
114
|
-
#
|
|
114
|
+
#
|
|
115
115
|
# Because you are implementing your method using a block, remember the
|
|
116
116
|
# distinction between <tt>Proc.new</tt> and +lambda+. Invoking +return+
|
|
117
117
|
# from the former does not return from the block, but returns from the
|
|
118
118
|
# surrounding method scope. Since normal blocks passed to methods are
|
|
119
119
|
# of the former type, be very careful about using the +return+ keyword:
|
|
120
|
-
#
|
|
120
|
+
#
|
|
121
121
|
# add_method(:foo) do |param|
|
|
122
122
|
# puts "foo called with parameter "+param.inspect
|
|
123
123
|
# return "a return value" # DOESN'T WORK LIKE YOU EXPECT!
|
|
124
124
|
# end
|
|
125
|
-
#
|
|
125
|
+
#
|
|
126
126
|
# To return a value from the method you are creating, set the evaluation
|
|
127
127
|
# value at the end of the block:
|
|
128
|
-
#
|
|
128
|
+
#
|
|
129
129
|
# add_method(:foo) do |param|
|
|
130
130
|
# puts "foo called with parameter "+param.inspect
|
|
131
131
|
# "a return value" # Returns from method foo
|
|
132
132
|
# end
|
|
133
|
-
#
|
|
133
|
+
#
|
|
134
134
|
# If you must use the +return+ keyword, create your block as a lambda
|
|
135
135
|
# as in this example:
|
|
136
|
-
#
|
|
136
|
+
#
|
|
137
137
|
# code = lambda do |param|
|
|
138
138
|
# puts "foo called with parameter "+param.inspect
|
|
139
139
|
# return "a return value" # Returns from method foo
|
|
140
140
|
# end
|
|
141
141
|
# add_method(:foo, &code)
|
|
142
|
-
#
|
|
142
|
+
#
|
|
143
143
|
# === Accepting a block argument
|
|
144
|
-
#
|
|
144
|
+
#
|
|
145
145
|
# If you want your method to take a block, you have several options
|
|
146
146
|
# depending on your Ruby version. If you are running the standard Matz
|
|
147
147
|
# Ruby interpreter (MRI) version 1.8.7 or later (including 1.9.x), or a
|
|
@@ -151,16 +151,16 @@ module Blockenspiel
|
|
|
151
151
|
# Ruby doesn't support invoking such a block with +yield+.
|
|
152
152
|
# For example, to create a method named "foo" that takes one parameter
|
|
153
153
|
# and a block, do this:
|
|
154
|
-
#
|
|
154
|
+
#
|
|
155
155
|
# add_method(:foo) do |param, &block|
|
|
156
156
|
# puts "foo called with parameter "+param.inspect
|
|
157
157
|
# puts "the block returned "+block.call.inspect
|
|
158
158
|
# end
|
|
159
|
-
#
|
|
159
|
+
#
|
|
160
160
|
# In your DSL, you can then call:
|
|
161
|
-
#
|
|
161
|
+
#
|
|
162
162
|
# foo("hello"){ "a value" }
|
|
163
|
-
#
|
|
163
|
+
#
|
|
164
164
|
# If you are using MRI 1.8.6, or another Ruby interpreter that doesn't
|
|
165
165
|
# fully support this syntax (such as JRuby versions older than 1.5),
|
|
166
166
|
# Blockenspiel provides an alternative in the form of the <tt>:block</tt>
|
|
@@ -170,7 +170,7 @@ module Blockenspiel
|
|
|
170
170
|
# prepend or append, respectively, the block (as a +Proc+ object) to
|
|
171
171
|
# the parameter list. If the caller does not include a block when
|
|
172
172
|
# calling your DSL method, nil is prepended/appended. For example:
|
|
173
|
-
#
|
|
173
|
+
#
|
|
174
174
|
# add_method(:foo, :block => :last) do |param, block|
|
|
175
175
|
# puts "foo called with parameter "+param.inspect
|
|
176
176
|
# if block
|
|
@@ -179,11 +179,11 @@ module Blockenspiel
|
|
|
179
179
|
# puts "no block passed"
|
|
180
180
|
# end
|
|
181
181
|
# end
|
|
182
|
-
#
|
|
182
|
+
#
|
|
183
183
|
# The <tt>:receive_block</tt> option is a deprecated alternative.
|
|
184
184
|
# Setting <tt>:receive_block => true</tt> is currently equivalent to
|
|
185
185
|
# setting <tt>:block => :last</tt>.
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
def add_method(name_, opts_={}, &block_)
|
|
188
188
|
receive_block_ = opts_[:receive_block] ? :last : opts_[:block]
|
|
189
189
|
receive_block_ = :first if receive_block_ && receive_block_ != :last
|
|
@@ -194,8 +194,8 @@ module Blockenspiel
|
|
|
194
194
|
@target_class.dsl_method(dsl_method_name_, name_)
|
|
195
195
|
end
|
|
196
196
|
end
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
end
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
|
|
200
|
+
|
|
201
201
|
end
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# Blockenspiel DSL definition
|
|
4
|
-
#
|
|
4
|
+
#
|
|
5
5
|
# -----------------------------------------------------------------------------
|
|
6
6
|
# Copyright 2008-2011 Daniel Azuma
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# All rights reserved.
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Redistribution and use in source and binary forms, with or without
|
|
11
11
|
# modification, are permitted provided that the following conditions are met:
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# * Redistributions of source code must retain the above copyright notice,
|
|
14
14
|
# this list of conditions and the following disclaimer.
|
|
15
15
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# * Neither the name of the copyright holder, nor the names of any other
|
|
19
19
|
# contributors to this software, may be used to endorse or promote products
|
|
20
20
|
# derived from this software without specific prior written permission.
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
23
23
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
24
24
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
@@ -38,30 +38,30 @@ require 'thread'
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
module Blockenspiel
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
|
|
43
43
|
# === DSL setup methods
|
|
44
|
-
#
|
|
44
|
+
#
|
|
45
45
|
# These class methods are available after you have included the
|
|
46
46
|
# Blockenspiel::DSL module.
|
|
47
|
-
#
|
|
47
|
+
#
|
|
48
48
|
# By default, a class that has DSL capability will automatically make
|
|
49
49
|
# all public methods available to parameterless blocks, except for the
|
|
50
50
|
# +initialize+ method, any methods whose names begin with an underscore,
|
|
51
51
|
# and any methods whose names end with an equals sign.
|
|
52
|
-
#
|
|
52
|
+
#
|
|
53
53
|
# If you want to change this behavior, use the directives defined here to
|
|
54
54
|
# control exactly which methods are available to parameterless blocks.
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
module DSLSetupMethods
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
|
|
58
|
+
|
|
59
59
|
# :stopdoc:
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
# Called when DSLSetupMethods extends a class.
|
|
62
62
|
# This sets up the current class, and adds a hook that causes
|
|
63
63
|
# any subclass of the current class also to be set up.
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
def self.extended(klass_)
|
|
66
66
|
unless klass_.instance_variable_defined?(:@_blockenspiel_module)
|
|
67
67
|
_setup_class(klass_)
|
|
@@ -77,14 +77,14 @@ module Blockenspiel
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
# :startdoc:
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
|
|
83
|
+
|
|
84
84
|
# Set up a class.
|
|
85
85
|
# Creates a DSL module for this class, optionally delegating to the superclass's module.
|
|
86
86
|
# Also initializes the class's methods hash and active flag.
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
def self._setup_class(klass_) # :nodoc:
|
|
89
89
|
superclass_ = klass_.superclass
|
|
90
90
|
superclass_ = nil unless superclass_.respond_to?(:_get_blockenspiel_module)
|
|
@@ -99,10 +99,10 @@ module Blockenspiel
|
|
|
99
99
|
klass_.instance_variable_set(:@_blockenspiel_methods, {})
|
|
100
100
|
klass_.instance_variable_set(:@_blockenspiel_active, nil)
|
|
101
101
|
end
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
|
|
103
|
+
|
|
104
104
|
# Automatically make the given method a DSL method according to the current setting.
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
def _blockenspiel_auto_dsl_method(symbol_) # :nodoc:
|
|
107
107
|
if @_blockenspiel_active
|
|
108
108
|
dsl_method(symbol_)
|
|
@@ -112,23 +112,23 @@ module Blockenspiel
|
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
|
|
116
|
+
|
|
117
117
|
# Hook called when a method is added.
|
|
118
118
|
# This calls _blockenspiel_auto_dsl_method to auto-handle the method,
|
|
119
119
|
# possibly making it a DSL method according to the current setting.
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
def method_added(symbol_) # :nodoc:
|
|
122
122
|
_blockenspiel_auto_dsl_method(symbol_)
|
|
123
123
|
super
|
|
124
124
|
end
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
|
|
126
|
+
|
|
127
127
|
# Custom include method. Calls the main include implementation, but also
|
|
128
128
|
# goes through the public methods of the included module and calls
|
|
129
129
|
# _blockenspiel_auto_dsl_method on each to make them DSL methods
|
|
130
130
|
# (possibly) according to the current setting.
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
def _blockenspiel_custom_include(*modules_) # :nodoc:
|
|
133
133
|
_blockenspiel_default_include(*modules_)
|
|
134
134
|
modules_.reverse_each do |mod_|
|
|
@@ -137,19 +137,19 @@ module Blockenspiel
|
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
|
|
141
|
+
|
|
142
142
|
# Get this class's corresponding DSL module
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
def _get_blockenspiel_module # :nodoc:
|
|
145
145
|
@_blockenspiel_module
|
|
146
146
|
end
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
|
|
148
|
+
|
|
149
149
|
# Get information on the given DSL method name.
|
|
150
150
|
# Possible values are the name of the delegate method, false for method disabled,
|
|
151
151
|
# or nil for method never defined.
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
def _get_blockenspiel_delegate(name_) # :nodoc:
|
|
154
154
|
delegate_ = @_blockenspiel_methods[name_]
|
|
155
155
|
if delegate_.nil? && @_blockenspiel_superclass
|
|
@@ -158,20 +158,20 @@ module Blockenspiel
|
|
|
158
158
|
delegate_
|
|
159
159
|
end
|
|
160
160
|
end
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
|
|
162
|
+
|
|
163
163
|
# Make a particular method available to parameterless DSL blocks.
|
|
164
|
-
#
|
|
164
|
+
#
|
|
165
165
|
# To explicitly make a method available to parameterless blocks:
|
|
166
166
|
# dsl_method :my_method
|
|
167
|
-
#
|
|
167
|
+
#
|
|
168
168
|
# To explicitly exclude a method from parameterless blocks:
|
|
169
169
|
# dsl_method :my_method, false
|
|
170
|
-
#
|
|
170
|
+
#
|
|
171
171
|
# To explicitly make a method available to parameterless blocks, but
|
|
172
172
|
# point it to a method of a different name on the target class:
|
|
173
173
|
# dsl_method :my_method, :target_class_method
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
def dsl_method(name_, delegate_=nil)
|
|
176
176
|
name_ = name_.to_sym
|
|
177
177
|
if delegate_
|
|
@@ -184,35 +184,35 @@ module Blockenspiel
|
|
|
184
184
|
@_blockenspiel_module.module_eval("def #{name_}(*params_, &block_); val_ = ::Blockenspiel._target_dispatch(self, :#{name_}, params_, block_); ::Blockenspiel::NO_VALUE.equal?(val_) ? super(*params_, &block_) : val_; end\n")
|
|
185
185
|
end
|
|
186
186
|
end
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
|
|
188
|
+
|
|
189
189
|
# Control the behavior of methods with respect to parameterless blocks,
|
|
190
190
|
# or make a list of methods available to parameterless blocks in bulk.
|
|
191
|
-
#
|
|
191
|
+
#
|
|
192
192
|
# To enable automatic exporting of methods to parameterless blocks.
|
|
193
193
|
# After executing this command, all public methods defined in the class
|
|
194
194
|
# will be available on parameterless blocks, until
|
|
195
195
|
# <tt>dsl_methods false</tt> is called:
|
|
196
196
|
# dsl_methods true
|
|
197
|
-
#
|
|
197
|
+
#
|
|
198
198
|
# To disable automatic exporting of methods to parameterless blocks.
|
|
199
199
|
# After executing this command, methods defined in this class will be
|
|
200
200
|
# excluded from parameterless blocks, until <tt>dsl_methods true</tt>
|
|
201
201
|
# is called:
|
|
202
202
|
# dsl_methods false
|
|
203
|
-
#
|
|
203
|
+
#
|
|
204
204
|
# To make a list of methods available to parameterless blocks in bulk:
|
|
205
205
|
# dsl_methods :my_method1, :my_method2, ...
|
|
206
|
-
#
|
|
206
|
+
#
|
|
207
207
|
# You can also point dsl methods to a method of a different name on the
|
|
208
208
|
# target class, by using a hash syntax, as follows:
|
|
209
209
|
# dsl_methods :my_method1 => :target_class_method1,
|
|
210
210
|
# :my_method2 => :target_class_method2
|
|
211
|
-
#
|
|
211
|
+
#
|
|
212
212
|
# You can mix non-renamed and renamed method declarations as long as
|
|
213
213
|
# the renamed (hash) methods are at the end. e.g.:
|
|
214
214
|
# dsl_methods :my_method1, :my_method2 => :target_class_method2
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
def dsl_methods(*names_)
|
|
217
217
|
if names_.size == 0 || names_ == [true]
|
|
218
218
|
@_blockenspiel_active = true
|
|
@@ -229,10 +229,10 @@ module Blockenspiel
|
|
|
229
229
|
end
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
|
|
233
|
+
|
|
234
234
|
# A DSL-friendly attr_accessor.
|
|
235
|
-
#
|
|
235
|
+
#
|
|
236
236
|
# This creates the usual "name" and "name=" methods in the current
|
|
237
237
|
# class that can be used in the usual way. However, its implementation
|
|
238
238
|
# of the "name" method (the getter) also takes an optional parameter
|
|
@@ -240,26 +240,26 @@ module Blockenspiel
|
|
|
240
240
|
# setter syntax cannot be used in a parameterless block, since it is
|
|
241
241
|
# syntactically indistinguishable from a local variable assignment.
|
|
242
242
|
# The "name" method is exposed as a dsl_method.
|
|
243
|
-
#
|
|
243
|
+
#
|
|
244
244
|
# For example:
|
|
245
|
-
#
|
|
245
|
+
#
|
|
246
246
|
# dsl_attr_accessor :foo
|
|
247
|
-
#
|
|
247
|
+
#
|
|
248
248
|
# enables the following:
|
|
249
|
-
#
|
|
249
|
+
#
|
|
250
250
|
# my_block do |param|
|
|
251
251
|
# param.foo = 1 # Usual setter syntax works
|
|
252
252
|
# param.foo 2 # Alternate setter syntax also works
|
|
253
253
|
# puts param.foo # Usual getter syntax still works
|
|
254
254
|
# end
|
|
255
|
-
#
|
|
255
|
+
#
|
|
256
256
|
# my_block do
|
|
257
257
|
# # foo = 1 # Usual setter syntax does NOT work since it
|
|
258
258
|
# # looks like a local variable assignment
|
|
259
259
|
# foo 2 # Alternate setter syntax does work
|
|
260
260
|
# puts foo # Usual getter syntax still works
|
|
261
261
|
# end
|
|
262
|
-
|
|
262
|
+
|
|
263
263
|
def dsl_attr_accessor(*names_)
|
|
264
264
|
names_.each do |name_|
|
|
265
265
|
unless name_.kind_of?(::String) || name_.kind_of?(::Symbol)
|
|
@@ -273,29 +273,29 @@ module Blockenspiel
|
|
|
273
273
|
dsl_method(name_)
|
|
274
274
|
end
|
|
275
275
|
end
|
|
276
|
-
|
|
277
|
-
|
|
276
|
+
|
|
277
|
+
|
|
278
278
|
# A DSL-friendly attr_writer.
|
|
279
|
-
#
|
|
279
|
+
#
|
|
280
280
|
# This creates the usual "name=" method in the current class that can
|
|
281
281
|
# be used in the usual way. However, it also creates the method "name",
|
|
282
282
|
# which also functions as a setter (but not a getter). This is done
|
|
283
283
|
# because the usual setter syntax cannot be used in a parameterless
|
|
284
284
|
# block, since it is syntactically indistinguishable from a local
|
|
285
285
|
# variable assignment. The "name" method is exposed as a dsl_method.
|
|
286
|
-
#
|
|
286
|
+
#
|
|
287
287
|
# For example:
|
|
288
|
-
#
|
|
288
|
+
#
|
|
289
289
|
# dsl_attr_writer :foo
|
|
290
|
-
#
|
|
290
|
+
#
|
|
291
291
|
# is functionally equivalent to:
|
|
292
|
-
#
|
|
292
|
+
#
|
|
293
293
|
# attr_writer :foo
|
|
294
294
|
# alias_method :foo, :foo=
|
|
295
295
|
# dsl_method :foo
|
|
296
|
-
#
|
|
296
|
+
#
|
|
297
297
|
# which enables the following:
|
|
298
|
-
#
|
|
298
|
+
#
|
|
299
299
|
# my_block do |param|
|
|
300
300
|
# param.foo = 1 # Usual setter syntax works
|
|
301
301
|
# param.foo 2 # Alternate setter syntax also works
|
|
@@ -305,7 +305,7 @@ module Blockenspiel
|
|
|
305
305
|
# # looks like a local variable assignment
|
|
306
306
|
# foo(2) # Alternate setter syntax does work
|
|
307
307
|
# end
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
def dsl_attr_writer(*names_)
|
|
310
310
|
names_.each do |name_|
|
|
311
311
|
attr_writer(name_)
|
|
@@ -313,49 +313,49 @@ module Blockenspiel
|
|
|
313
313
|
dsl_method(name_)
|
|
314
314
|
end
|
|
315
315
|
end
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
|
|
317
|
+
|
|
318
318
|
end
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
|
|
320
|
+
|
|
321
321
|
# === DSL activation module
|
|
322
|
-
#
|
|
322
|
+
#
|
|
323
323
|
# Include this module in a class to mark this class as a DSL class and
|
|
324
324
|
# make it possible for its methods to be called from a block that does not
|
|
325
325
|
# take a parameter.
|
|
326
|
-
#
|
|
326
|
+
#
|
|
327
327
|
# After you include this module, you can use the directives defined in
|
|
328
328
|
# DSLSetupMethods to control what methods are available to DSL blocks
|
|
329
329
|
# that do not take parameters.
|
|
330
|
-
|
|
330
|
+
|
|
331
331
|
module DSL
|
|
332
|
-
|
|
332
|
+
|
|
333
333
|
def self.included(klass_) # :nodoc:
|
|
334
334
|
unless klass_.kind_of?(::Class)
|
|
335
335
|
raise ::Blockenspiel::BlockenspielError, "You cannot include Blockenspiel::DSL in a module (yet)"
|
|
336
336
|
end
|
|
337
337
|
klass_.extend(::Blockenspiel::DSLSetupMethods)
|
|
338
338
|
end
|
|
339
|
-
|
|
339
|
+
|
|
340
340
|
end
|
|
341
|
-
|
|
342
|
-
|
|
341
|
+
|
|
342
|
+
|
|
343
343
|
# === DSL activation base class
|
|
344
|
-
#
|
|
344
|
+
#
|
|
345
345
|
# Subclasses of this base class are considered DSL classes.
|
|
346
346
|
# Methods of the class can be made available to be called from a block that
|
|
347
347
|
# doesn't take an explicit block parameter.
|
|
348
348
|
# You may use the directives defined in DSLSetupMethods to control how
|
|
349
349
|
# methods of the class are handled in such blocks.
|
|
350
|
-
#
|
|
350
|
+
#
|
|
351
351
|
# Subclassing this base class is functionally equivalent to simply
|
|
352
352
|
# including Blockenspiel::DSL in the class.
|
|
353
|
-
|
|
353
|
+
|
|
354
354
|
class Base
|
|
355
|
-
|
|
355
|
+
|
|
356
356
|
include ::Blockenspiel::DSL
|
|
357
|
-
|
|
357
|
+
|
|
358
358
|
end
|
|
359
|
-
|
|
360
|
-
|
|
359
|
+
|
|
360
|
+
|
|
361
361
|
end
|