ruby-processing 1.0.8 → 1.0.9
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/CHANGELOG +6 -0
- data/lib/core/core.jar +0 -0
- data/lib/core/jruby-complete.jar +0 -0
- data/lib/ruby-processing.rb +5 -10
- data/lib/ruby-processing/app.rb +139 -98
- data/lib/ruby-processing/exporters/applet_exporter.rb +4 -1
- data/lib/ruby-processing/exporters/application_exporter.rb +5 -1
- data/lib/ruby-processing/exporters/base_exporter.rb +3 -2
- data/lib/ruby-processing/runner.rb +54 -46
- data/lib/ruby-processing/runners/base.rb +6 -7
- data/lib/ruby-processing/runners/live.rb +4 -3
- data/lib/ruby-processing/runners/watch.rb +33 -27
- data/library/control_panel/control_panel.rb +24 -23
- data/samples/anar/data/java_args.txt +1 -0
- data/samples/anar/extrusion.rb +49 -0
- data/samples/anar/l_system.rb +86 -0
- data/samples/anar/library/anar/anar.jar +0 -0
- data/samples/anar/many_shapes.rb +98 -0
- data/samples/empathy.rb +73 -0
- data/samples/gravity.rb +113 -0
- data/samples/peasy_cam/data/java_args.txt +1 -0
- data/samples/peasy_cam/hello_peasy.rb +29 -0
- data/samples/peasy_cam/hilbert_fractal.rb +40 -0
- data/samples/peasy_cam/library/PeasyCam/PeasyCam.jar +0 -0
- data/samples/peasy_cam/library/hilbert/hilbert.rb +99 -0
- data/samples/processing_app/3D/form/brick_tower.rb +3 -3
- data/samples/processing_app/basics/data/characters_strings/characters_strings.rb +5 -7
- data/samples/processing_app/basics/form/triangle_strip.rb +11 -11
- data/samples/processing_app/basics/input/keyboard.rb +2 -8
- data/samples/processing_app/basics/input/keyboard_2.rb +4 -4
- data/samples/processing_app/basics/input/keyboard_functions.rb +12 -21
- metadata +41 -64
@@ -40,7 +40,10 @@ module Processing
|
|
40
40
|
@necessary_files = [@main_file_path]
|
41
41
|
@necessary_files += Dir["#{RP5_ROOT}/lib/{*,**}"]
|
42
42
|
@necessary_files += @real_requires
|
43
|
-
|
43
|
+
NECESSARY_FOLDERS.each do |folder|
|
44
|
+
resource_path = File.join(@main_folder, folder)
|
45
|
+
@necessary_files << resource_path if File.exists?(resource_path)
|
46
|
+
end
|
44
47
|
@necessary_files += Dir["#{RP5_ROOT}/lib/templates/applet/{*,**}"]
|
45
48
|
@necessary_files += Dir.glob("library/{#{@libraries.join(",")}}") unless @libraries.empty?
|
46
49
|
@necessary_files.uniq!
|
@@ -42,7 +42,10 @@ module Processing
|
|
42
42
|
@necessary_files = [@main_file_path]
|
43
43
|
@necessary_files += Dir["#{RP5_ROOT}/lib/{*,**}"]
|
44
44
|
@necessary_files += @real_requires
|
45
|
-
|
45
|
+
NECESSARY_FOLDERS.each do |folder|
|
46
|
+
resource_path = File.join(@main_folder, folder)
|
47
|
+
@necessary_files << resource_path if File.exists?(resource_path)
|
48
|
+
end
|
46
49
|
@necessary_files.uniq!
|
47
50
|
cp_r(@necessary_files, File.join(@dest, @prefix))
|
48
51
|
cp_r(@libraries, File.join(@dest, @prefix, "library")) unless @libraries.empty?
|
@@ -66,6 +69,7 @@ module Processing
|
|
66
69
|
move @dest + "/run.exe", "#{runnable}.exe"
|
67
70
|
chmod 0755, runnable
|
68
71
|
chmod 0755, "#{runnable}.exe"
|
72
|
+
chmod 0755, File.join(@dest, 'Contents', 'MacOS', 'JavaApplicationStub')
|
69
73
|
end
|
70
74
|
|
71
75
|
def symlink_library_into_place
|
@@ -10,6 +10,7 @@ module Processing
|
|
10
10
|
|
11
11
|
DEFAULT_DIMENSIONS = {'width' => '100', 'height' => '100'}
|
12
12
|
DEFAULT_DESCRIPTION = ''
|
13
|
+
NECESSARY_FOLDERS = ['data', 'lib', 'vendor']
|
13
14
|
|
14
15
|
# Returns the filepath, basename, and directory name of the sketch.
|
15
16
|
def get_main_file(file)
|
@@ -42,7 +43,7 @@ module Processing
|
|
42
43
|
|
43
44
|
# Searches the source for a title.
|
44
45
|
def extract_title(source)
|
45
|
-
match = source.match(/#{@info[:class_name]}\.new.*?:title\s=>\s["'](
|
46
|
+
match = source.match(/#{@info[:class_name]}\.new.*?:title\s=>\s["'](.+?)["']/m)
|
46
47
|
match ? match[1] : File.basename(@file, '.rb').titleize
|
47
48
|
end
|
48
49
|
|
@@ -89,7 +90,7 @@ module Processing
|
|
89
90
|
requirements = []
|
90
91
|
partial_paths = []
|
91
92
|
loop do
|
92
|
-
matchdata = code.match(
|
93
|
+
matchdata = code.match(/^.*[^::\.\w](require|load)\b.*$/)
|
93
94
|
break unless matchdata
|
94
95
|
line = matchdata[0].gsub('__FILE__', "'#{@main_file_path}'")
|
95
96
|
line = line.gsub(/\b(require|load)\b/, 'partial_paths << ')
|
@@ -2,45 +2,45 @@ require 'ostruct'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
module Processing
|
5
|
-
|
5
|
+
|
6
6
|
# Utility class to handle the different commands that the 'rp5' command
|
7
7
|
# offers. Able to run, watch, live, create, app, applet, and unpack
|
8
8
|
class Runner
|
9
|
-
|
9
|
+
|
10
10
|
HELP_MESSAGE = <<-EOS
|
11
|
-
|
11
|
+
|
12
12
|
Ruby-Processing is a little shim between Processing and JRuby that helps
|
13
13
|
you create sketches of code art.
|
14
|
-
|
14
|
+
|
15
15
|
Usage:
|
16
16
|
rp5 [run | watch | live | create | app | applet | unpack] path/to/sketch
|
17
|
-
|
17
|
+
|
18
18
|
Examples:
|
19
19
|
rp5 unpack samples
|
20
20
|
rp5 run samples/jwishy.rb
|
21
21
|
rp5 create some_new_sketch --bare 640 480
|
22
22
|
rp5 watch some_new_sketch.rb
|
23
23
|
rp5 applet some_new_sketch.rb
|
24
|
-
|
24
|
+
|
25
25
|
Everything Else:
|
26
|
-
http://wiki.github.com/jashkenas/ruby-processing
|
27
|
-
|
26
|
+
http://wiki.github.com/jashkenas/ruby-processing
|
27
|
+
|
28
28
|
EOS
|
29
|
-
|
29
|
+
|
30
30
|
# Start running a ruby-processing sketch from the passed-in arguments
|
31
31
|
def self.execute
|
32
32
|
runner = new
|
33
33
|
runner.parse_options(ARGV)
|
34
34
|
runner.execute!
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
# Dispatch central.
|
38
38
|
def execute!
|
39
39
|
case @options.action
|
40
|
-
when 'run' then run(@options.path)
|
41
|
-
when 'watch' then watch(@options.path)
|
40
|
+
when 'run' then run(@options.path, @options.args)
|
41
|
+
when 'watch' then watch(@options.path, @options.args)
|
42
|
+
when 'live' then live(@options.path, @options.args)
|
42
43
|
when 'create' then create(@options.path, @options.args, @options.bare)
|
43
|
-
when 'live' then live(@options.path)
|
44
44
|
when 'app' then app(@options.path)
|
45
45
|
when 'applet' then applet(@options.path)
|
46
46
|
when 'unpack' then unpack(@options.path)
|
@@ -50,52 +50,53 @@ module Processing
|
|
50
50
|
show_help
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Parse the command-line options. Keep it simple.
|
55
55
|
def parse_options(args)
|
56
56
|
@options = OpenStruct.new
|
57
57
|
@options.bare = !!args.delete('--bare')
|
58
|
+
@options.jruby = !!args.delete('--jruby')
|
58
59
|
@options.action = args[0] || nil
|
59
60
|
@options.path = args[1] || File.basename(Dir.pwd + '.rb')
|
60
61
|
@options.args = args[2..-1] || []
|
61
62
|
end
|
62
|
-
|
63
|
+
|
63
64
|
# Create a fresh Ruby-Processing sketch, with the necessary
|
64
65
|
# boilerplate filled out.
|
65
66
|
def create(sketch, args, bare)
|
66
67
|
Processing::Creator.new.create!(sketch, args, bare)
|
67
68
|
end
|
68
|
-
|
69
|
+
|
69
70
|
# Just simply run a ruby-processing sketch.
|
70
|
-
def run(sketch)
|
71
|
+
def run(sketch, args)
|
71
72
|
ensure_exists(sketch)
|
72
|
-
spin_up('run.rb', sketch)
|
73
|
+
spin_up('run.rb', sketch, args)
|
73
74
|
end
|
74
|
-
|
75
|
+
|
75
76
|
# Run a sketch, keeping an eye on it's file, and reloading
|
76
77
|
# whenever it changes.
|
77
|
-
def watch(sketch)
|
78
|
+
def watch(sketch, args)
|
78
79
|
ensure_exists(sketch)
|
79
|
-
spin_up('watch.rb', sketch)
|
80
|
+
spin_up('watch.rb', sketch, args)
|
80
81
|
end
|
81
|
-
|
82
|
+
|
82
83
|
# Run a sketch, opening its guts to IRB, letting you play with it.
|
83
|
-
def live(sketch)
|
84
|
+
def live(sketch, args)
|
84
85
|
ensure_exists(sketch)
|
85
|
-
spin_up('live.rb', sketch)
|
86
|
+
spin_up('live.rb', sketch, args)
|
86
87
|
end
|
87
|
-
|
88
|
+
|
88
89
|
# Generate a cross-platform application of a given Ruby-Processing sketch.
|
89
90
|
def app(sketch)
|
90
91
|
Processing::ApplicationExporter.new.export!(sketch)
|
91
92
|
end
|
92
|
-
|
93
|
+
|
93
94
|
# Generate an applet and HTML page for a given sketch.
|
94
95
|
def applet(sketch)
|
95
96
|
Processing::AppletExporter.new.export!(sketch)
|
96
97
|
end
|
97
|
-
|
98
|
-
# Install the included samples to a given path, where you can run and
|
98
|
+
|
99
|
+
# Install the included samples to a given path, where you can run and
|
99
100
|
# alter them to your heart's content.
|
100
101
|
def unpack(dir)
|
101
102
|
require 'fileutils'
|
@@ -103,52 +104,59 @@ module Processing
|
|
103
104
|
puts usage and return unless dir.match(/\A(samples|library)\Z/)
|
104
105
|
FileUtils.cp_r("#{RP5_ROOT}/#{dir}", "#{Dir.pwd}/#{dir}")
|
105
106
|
end
|
106
|
-
|
107
|
+
|
107
108
|
# Display the current version of Ruby-Processing.
|
108
109
|
def show_version
|
109
|
-
puts "Ruby-Processing version #{Processing
|
110
|
+
puts "Ruby-Processing version #{Processing::VERSION}"
|
110
111
|
end
|
111
|
-
|
112
|
+
|
112
113
|
# Show the standard help/usage message.
|
113
114
|
def show_help
|
114
115
|
puts HELP_MESSAGE
|
115
116
|
end
|
116
|
-
|
117
|
-
|
117
|
+
|
118
|
+
|
118
119
|
private
|
119
|
-
|
120
|
-
# Trade in this Ruby instance for a JRuby instance, loading in a
|
120
|
+
|
121
|
+
# Trade in this Ruby instance for a JRuby instance, loading in a
|
121
122
|
# starter script and passing it some arguments.
|
122
|
-
|
123
|
+
# If --jruby is passed, use the installed version of jruby, instead of
|
124
|
+
# our vendored jarred one (useful for gems).
|
125
|
+
def spin_up(starter_script, sketch, args)
|
123
126
|
runner = "#{RP5_ROOT}/lib/ruby-processing/runners/#{starter_script}"
|
124
127
|
java_args = discover_java_args(sketch)
|
125
|
-
command =
|
126
|
-
|
128
|
+
command = @options.jruby ?
|
129
|
+
['jruby', java_args, runner, sketch, args].flatten :
|
130
|
+
['java', java_args, '-cp', jruby_complete, 'org.jruby.Main', runner, sketch, args].flatten
|
131
|
+
exec *command
|
127
132
|
# exec replaces the Ruby process with the JRuby one.
|
128
133
|
end
|
129
|
-
|
134
|
+
|
130
135
|
# If you need to pass in arguments to Java, such as the ones on this page:
|
131
136
|
# http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html
|
132
137
|
# then type them into a java_args.txt in your data directory next to your sketch.
|
133
138
|
def discover_java_args(sketch)
|
134
139
|
arg_file = "#{File.dirname(sketch)}/data/java_args.txt"
|
135
|
-
|
140
|
+
args = dock_icon
|
141
|
+
args += File.read(arg_file).split(/\s+/) if File.exists?(arg_file)
|
142
|
+
args.map! {|arg| "-J#{arg}" } if @options.jruby
|
143
|
+
args
|
136
144
|
end
|
137
|
-
|
145
|
+
|
138
146
|
def ensure_exists(sketch)
|
139
147
|
puts "Couldn't find: #{sketch}" and exit unless File.exists?(sketch)
|
140
148
|
end
|
141
|
-
|
149
|
+
|
142
150
|
def jruby_complete
|
143
151
|
File.join(RP5_ROOT, 'lib/core/jruby-complete.jar')
|
144
152
|
end
|
145
|
-
|
153
|
+
|
146
154
|
# On the Mac, we can display a fat, shiny ruby in the Dock.
|
147
155
|
def dock_icon
|
148
156
|
mac = RUBY_PLATFORM.match(/darwin/i) || (RUBY_PLATFORM == 'java' && ENV_JAVA['os.name'].match(/mac/i))
|
149
|
-
mac ? "-Xdock:name=Ruby-Processing -Xdock:icon=#{RP5_ROOT}/lib/templates/application/Contents/Resources/sketch.icns" :
|
157
|
+
mac ? ["-Xdock:name=Ruby-Processing", "-Xdock:icon=#{RP5_ROOT}/lib/templates/application/Contents/Resources/sketch.icns"] : []
|
150
158
|
end
|
151
|
-
|
159
|
+
|
152
160
|
end # class Runner
|
153
|
-
|
161
|
+
|
154
162
|
end # module Processing
|
@@ -1,5 +1,6 @@
|
|
1
1
|
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../")
|
2
|
-
|
2
|
+
SKETCH_PATH = ARGV.shift
|
3
|
+
SKETCH_ROOT = File.dirname(SKETCH_PATH) unless defined? SKETCH_ROOT
|
3
4
|
|
4
5
|
require 'ruby-processing'
|
5
6
|
require 'ruby-processing/app'
|
@@ -7,8 +8,6 @@ require 'ruby-processing/app'
|
|
7
8
|
|
8
9
|
module Processing
|
9
10
|
|
10
|
-
SKETCH_PATH = ARGV[0]
|
11
|
-
|
12
11
|
# For use with "bare" sketches that don't want to define a class or methods
|
13
12
|
SKETCH_TEMPLATE = <<-EOS
|
14
13
|
class Sketch < Processing::App
|
@@ -31,13 +30,13 @@ module Processing
|
|
31
30
|
has_methods = !!source.match(/^[^#]*(def\s+setup|def\s+draw)/)
|
32
31
|
|
33
32
|
if has_sketch
|
34
|
-
load
|
33
|
+
load SKETCH_PATH
|
35
34
|
Processing::App.sketch_class.new if !$app
|
36
35
|
return
|
37
36
|
else
|
38
37
|
require 'erb'
|
39
38
|
code = ERB.new(SKETCH_TEMPLATE).result(binding)
|
40
|
-
Object.class_eval code,
|
39
|
+
Object.class_eval code, SKETCH_PATH, 0
|
41
40
|
Processing::App.sketch_class.new if !$app
|
42
41
|
end
|
43
42
|
end
|
@@ -48,7 +47,7 @@ module Processing
|
|
48
47
|
if Processing.online?
|
49
48
|
# Fuck the following lines. Fucking Java can go sit on broken glass.
|
50
49
|
source = ''
|
51
|
-
url = java.net.URL.new(JRUBY_APPLET.get_code_base,
|
50
|
+
url = java.net.URL.new(JRUBY_APPLET.get_code_base, SKETCH_PATH)
|
52
51
|
input = java.io.BufferedReader.new(java.io.InputStreamReader.new(url.open_stream))
|
53
52
|
while line = input.read_line do
|
54
53
|
source << (line + "\n") if line
|
@@ -56,7 +55,7 @@ module Processing
|
|
56
55
|
input.close
|
57
56
|
else
|
58
57
|
# Ahhh, much better.
|
59
|
-
source = File.read(
|
58
|
+
source = File.read(SKETCH_PATH)
|
60
59
|
end
|
61
60
|
source
|
62
61
|
end
|
@@ -3,9 +3,10 @@
|
|
3
3
|
# or will start with your sketch.
|
4
4
|
|
5
5
|
require "#{File.dirname(__FILE__)}/base.rb"
|
6
|
+
Processing.load_and_run_sketch
|
7
|
+
|
8
|
+
ARGV.clear # So that IRB doesn't try to load them as files.
|
6
9
|
|
7
10
|
require 'irb'
|
8
|
-
ARGV[0] = nil # To keep IRB from trying to run it multiple times.
|
9
11
|
IRB.setup(__FILE__)
|
10
|
-
|
11
|
-
IRB.start()
|
12
|
+
IRB.start
|
@@ -1,25 +1,25 @@
|
|
1
1
|
require "#{File.dirname(__FILE__)}/base.rb"
|
2
2
|
|
3
|
-
module Processing
|
4
|
-
|
5
|
-
# A sketch loader, observer, and reloader, to tighten
|
3
|
+
module Processing
|
4
|
+
|
5
|
+
# A sketch loader, observer, and reloader, to tighten
|
6
6
|
# the feedback between code and effect.
|
7
7
|
class Watcher
|
8
|
-
|
8
|
+
|
9
9
|
# Sic a new Processing::Watcher on the sketch
|
10
10
|
def initialize
|
11
|
-
@file =
|
11
|
+
@file = SKETCH_PATH
|
12
12
|
@time = Time.now
|
13
13
|
# Doesn't work well enough for now.
|
14
14
|
# record_state_of_ruby
|
15
|
-
Processing.load_and_run_sketch unless $app
|
16
15
|
start_watching
|
17
16
|
end
|
18
|
-
|
19
|
-
|
17
|
+
|
18
|
+
|
20
19
|
# Kicks off a thread to watch the sketch, reloading Ruby-Processing
|
21
20
|
# and restarting the sketch whenever it changes.
|
22
21
|
def start_watching
|
22
|
+
@runner = Thread.start { report_errors { Processing.load_and_run_sketch } } unless $app
|
23
23
|
thread = Thread.start do
|
24
24
|
loop do
|
25
25
|
file_mtime = File.stat(@file).mtime
|
@@ -29,22 +29,28 @@ module Processing
|
|
29
29
|
# Taking it out the reset until it can be made to work more reliably
|
30
30
|
# rewind_to_recorded_state
|
31
31
|
GC.start
|
32
|
-
|
33
|
-
Processing.load_and_run_sketch
|
34
|
-
rescue StandardError, ScriptError
|
35
|
-
print "Error in your sketch: ", $!, "\n"
|
36
|
-
end
|
32
|
+
@runner = Thread.start { report_errors { Processing.load_and_run_sketch } }
|
37
33
|
end
|
38
34
|
sleep 0.33
|
39
35
|
end
|
40
36
|
end
|
41
37
|
thread.join
|
42
38
|
end
|
43
|
-
|
44
|
-
|
45
|
-
#
|
39
|
+
|
40
|
+
# Convenience function to report errors when loading and running a sketch,
|
41
|
+
# instead of having them eaten by the thread they are loaded in.
|
42
|
+
def report_errors
|
43
|
+
yield
|
44
|
+
rescue Exception => e
|
45
|
+
puts "Exception occured while running sketch #{File.basename SKETCH_PATH}:"
|
46
|
+
puts e.to_s
|
47
|
+
puts e.backtrace.join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Used to completely remove all traces of the current sketch,
|
46
51
|
# so that it can be loaded afresh. Go down into modules to find it, even.
|
47
52
|
def wipe_out_current_app!
|
53
|
+
@runner.kill if @runner.alive?
|
48
54
|
app = $app
|
49
55
|
return unless app
|
50
56
|
app.no_loop
|
@@ -54,15 +60,15 @@ module Processing
|
|
54
60
|
constant_names = app.class.to_s.split(/::/)
|
55
61
|
app_class_name = constant_names.pop
|
56
62
|
obj = constant_names.inject(Object) {|o, name| o.send(:const_get, name) }
|
57
|
-
obj.send(:remove_const, app_class_name)
|
63
|
+
obj.send(:remove_const, app_class_name)
|
58
64
|
end
|
59
|
-
|
65
|
+
|
60
66
|
# The following methods were intended to make the watcher clean up all code
|
61
67
|
# loaded in from the sketch, gems, etc, and have them be reloaded properly
|
62
68
|
# when the sketch is.... but it seems that this is neither a very good idea
|
63
|
-
# or a very possible one. If you can make the scheme work, please do,
|
69
|
+
# or a very possible one. If you can make the scheme work, please do,
|
64
70
|
# otherwise the following methods will probably be removed soonish.
|
65
|
-
|
71
|
+
|
66
72
|
# Do the best we can to take a picture of the current Ruby interpreter.
|
67
73
|
# For now, this means top-level constants and loaded .rb files.
|
68
74
|
def record_state_of_ruby
|
@@ -71,19 +77,19 @@ module Processing
|
|
71
77
|
@saved_features = $LOADED_FEATURES.dup
|
72
78
|
@saved_globals = Kernel.global_variables.dup
|
73
79
|
end
|
74
|
-
|
75
|
-
|
80
|
+
|
81
|
+
|
76
82
|
# Try to go back to the recorded Ruby state.
|
77
83
|
def rewind_to_recorded_state
|
78
84
|
new_constants = Object.send(:constants).reject {|c| @saved_constants.include?(c) }
|
79
85
|
new_load_paths = $LOAD_PATH.reject {|p| @saved_load_paths.include?(p) }
|
80
86
|
new_features = $LOADED_FEATURES.reject {|f| @saved_features.include?(f) }
|
81
87
|
new_globals = Kernel.global_variables.reject {|g| @saved_globals.include?(g) }
|
82
|
-
|
88
|
+
|
83
89
|
Processing::App.recursively_remove_constants(Object, new_constants)
|
84
90
|
new_load_paths.each {|p| $LOAD_PATH.delete(p) }
|
85
91
|
new_features.each {|f| $LOADED_FEATURES.delete(f) }
|
86
|
-
new_globals.each do |g|
|
92
|
+
new_globals.each do |g|
|
87
93
|
begin
|
88
94
|
eval("#{g} = nil") # There's no way to undef a global variable in Ruby
|
89
95
|
rescue NameError => e
|
@@ -91,8 +97,8 @@ module Processing
|
|
91
97
|
end
|
92
98
|
end
|
93
99
|
end
|
94
|
-
|
95
|
-
|
100
|
+
|
101
|
+
|
96
102
|
# Used to clean up declared constants in code that needs to be reloaded.
|
97
103
|
def recursively_remove_constants(base, constant_names)
|
98
104
|
constants = constant_names.map {|name| base.const_get(name) }
|
@@ -104,7 +110,7 @@ module Processing
|
|
104
110
|
constants.each {|c| recursively_remove_constants(c, c.constants) if c }
|
105
111
|
constant_names.each {|name| base.send(:remove_const, name.to_sym) if name }
|
106
112
|
end
|
107
|
-
|
113
|
+
|
108
114
|
end
|
109
115
|
end
|
110
116
|
|