smalruby-editor 0.1.6-x86-mingw32 → 0.1.7-x86-mingw32

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.

Potentially problematic release.


This version of smalruby-editor might be problematic. Click here for more details.

Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/blocks/hardware.js.coffee.erb +40 -3
  3. data/app/assets/stylesheets/toolbox.css.scss.erb +1 -6
  4. data/app/controllers/source_codes_controller.rb +5 -1
  5. data/app/models/concerns/ruby_to_block/block/base.rb +251 -0
  6. data/app/models/concerns/ruby_to_block/block/character.rb +42 -0
  7. data/app/models/concerns/ruby_to_block/block/character_event.rb +27 -0
  8. data/app/models/concerns/ruby_to_block/block/character_method_call.rb +29 -0
  9. data/app/models/concerns/ruby_to_block/block/character_new.rb +7 -0
  10. data/app/models/concerns/ruby_to_block/block/character_operation.rb +80 -0
  11. data/app/models/concerns/ruby_to_block/block/control_if.rb +45 -0
  12. data/app/models/concerns/ruby_to_block/block/control_loop.rb +19 -0
  13. data/app/models/concerns/ruby_to_block/block/control_sleep.rb +18 -0
  14. data/app/models/concerns/ruby_to_block/block/do.rb +24 -0
  15. data/app/models/concerns/ruby_to_block/block/else.rb +12 -0
  16. data/app/models/concerns/ruby_to_block/block/end.rb +26 -0
  17. data/app/models/concerns/ruby_to_block/block/events_on_click.rb +14 -0
  18. data/app/models/concerns/ruby_to_block/block/events_on_key_push_or_down.rb +17 -0
  19. data/app/models/concerns/ruby_to_block/block/events_on_start.rb +14 -0
  20. data/app/models/concerns/ruby_to_block/block/hardware_init_hardware.rb +14 -0
  21. data/app/models/concerns/ruby_to_block/block/hardware_led_off.rb +16 -0
  22. data/app/models/concerns/ruby_to_block/block/hardware_led_on.rb +16 -0
  23. data/app/models/concerns/ruby_to_block/block/hardware_on_sensor_change.rb +17 -0
  24. data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_off.rb +18 -0
  25. data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_on.rb +23 -0
  26. data/app/models/concerns/ruby_to_block/block/hardware_sensor_value.rb +23 -0
  27. data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car.rb +26 -0
  28. data/app/models/concerns/ruby_to_block/block/looks_hide.rb +8 -0
  29. data/app/models/concerns/ruby_to_block/block/looks_say.rb +20 -0
  30. data/app/models/concerns/ruby_to_block/block/looks_show.rb +8 -0
  31. data/app/models/concerns/ruby_to_block/block/looks_vanish.rb +8 -0
  32. data/app/models/concerns/ruby_to_block/block/math_number.rb +14 -0
  33. data/app/models/concerns/ruby_to_block/block/motion_change_x_by.rb +20 -0
  34. data/app/models/concerns/ruby_to_block/block/motion_change_y_by.rb +20 -0
  35. data/app/models/concerns/ruby_to_block/block/motion_move.rb +15 -0
  36. data/app/models/concerns/ruby_to_block/block/motion_point_towards_character.rb +24 -0
  37. data/app/models/concerns/ruby_to_block/block/motion_point_towards_mouse.rb +9 -0
  38. data/app/models/concerns/ruby_to_block/block/motion_reach_wall.rb +24 -0
  39. data/app/models/concerns/ruby_to_block/block/motion_rotate_left.rb +20 -0
  40. data/app/models/concerns/ruby_to_block/block/motion_rotate_right.rb +20 -0
  41. data/app/models/concerns/ruby_to_block/block/motion_self_angle.rb +23 -0
  42. data/app/models/concerns/ruby_to_block/block/motion_self_x.rb +23 -0
  43. data/app/models/concerns/ruby_to_block/block/motion_self_y.rb +23 -0
  44. data/app/models/concerns/ruby_to_block/block/motion_set_angle.rb +15 -0
  45. data/app/models/concerns/ruby_to_block/block/motion_set_x.rb +38 -0
  46. data/app/models/concerns/ruby_to_block/block/motion_set_y.rb +15 -0
  47. data/app/models/concerns/ruby_to_block/block/motion_turn.rb +8 -0
  48. data/app/models/concerns/ruby_to_block/block/motion_turn_if_reach_wall.rb +8 -0
  49. data/app/models/concerns/ruby_to_block/block/null.rb +17 -0
  50. data/app/models/concerns/ruby_to_block/block/operators_compare.rb +36 -0
  51. data/app/models/concerns/ruby_to_block/block/operators_false.rb +8 -0
  52. data/app/models/concerns/ruby_to_block/block/operators_true.rb +8 -0
  53. data/app/models/concerns/ruby_to_block/block/require_smalruby.rb +7 -0
  54. data/app/models/concerns/ruby_to_block/block/ruby_comment.rb +16 -0
  55. data/app/models/concerns/ruby_to_block/block/ruby_expression.rb +14 -0
  56. data/app/models/concerns/ruby_to_block/block/ruby_statement.rb +23 -0
  57. data/app/models/concerns/ruby_to_block/block/sensing_hit.rb +23 -0
  58. data/app/models/concerns/ruby_to_block/block/sound_play.rb +15 -0
  59. data/app/models/concerns/ruby_to_block/block/sound_preset_sounds.rb +31 -0
  60. data/app/models/concerns/ruby_to_block/block/text.rb +15 -0
  61. data/app/models/concerns/ruby_to_block/block/value.rb +12 -0
  62. data/app/models/concerns/ruby_to_block/block.rb +97 -0
  63. data/app/models/concerns/ruby_to_block/context.rb +97 -0
  64. data/app/models/concerns/ruby_to_block/formatter.rb +26 -0
  65. data/app/models/concerns/ruby_to_block.rb +17 -360
  66. data/app/models/source_code.rb +3 -1
  67. data/app/views/editor/_toolbox.html.haml +16 -0
  68. data/lib/smalruby_editor/version.rb +3 -3
  69. data/public/assets/{application-64a390efe879c386a5950515064f062d.css → application-28b7bed56c5389dfa372e972c75b6676.css} +17 -10
  70. data/public/assets/application-28b7bed56c5389dfa372e972c75b6676.css.gz +0 -0
  71. data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js → application-4f747690ebc8ec4815ae36021fdb2c44.js} +135 -0
  72. data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js.gz → application-4f747690ebc8ec4815ae36021fdb2c44.js.gz} +0 -0
  73. data/public/assets/manifest-332a5a1668194028b55103e0ea45c054.json +1 -1
  74. data/smalruby-editor.gemspec +1 -1
  75. data/spec/acceptance/block_mode/blocks/hardware/two_wheel_drive_car.feature +69 -0
  76. data/spec/acceptance/ruby_mode/translate.feature +1 -1
  77. data/spec/controllers/source_codes_controller_spec.rb +14 -11
  78. data/spec/models/concerns/ruby_to_block/block/character_method_call_spec.rb +175 -0
  79. data/spec/models/concerns/ruby_to_block/block/control_if_spec.rb +75 -0
  80. data/spec/models/concerns/ruby_to_block/block/control_loop_spec.rb +68 -0
  81. data/spec/models/concerns/ruby_to_block/block/events_on_start_spec.rb +120 -0
  82. data/spec/models/concerns/ruby_to_block/block/hardware_spec.rb +120 -0
  83. data/spec/models/concerns/ruby_to_block/block/looks_say_spec.rb +79 -0
  84. data/spec/models/concerns/ruby_to_block/block/looks_spec.rb +74 -0
  85. data/spec/models/concerns/ruby_to_block/block/motion_move_spec.rb +63 -0
  86. data/spec/models/concerns/ruby_to_block/block/motion_reach_wall_spec.rb +67 -0
  87. data/spec/models/concerns/ruby_to_block/block/motion_spec.rb +392 -0
  88. data/spec/models/concerns/ruby_to_block/block/motion_turn_spec.rb +54 -0
  89. data/spec/models/concerns/ruby_to_block/block/require_smalruby_spec.rb +39 -0
  90. data/spec/models/concerns/ruby_to_block/block/ruby_comment_spec.rb +55 -0
  91. data/spec/models/concerns/ruby_to_block/block/ruby_statement_spec.rb +113 -0
  92. data/spec/models/concerns/ruby_to_block/block/shared/block_examples.rb +44 -0
  93. data/spec/models/concerns/ruby_to_block/block/sound_spec.rb +46 -0
  94. data/spec/models/concerns/ruby_to_block/block_spec.rb +49 -0
  95. data/spec/models/concerns/ruby_to_block_spec.rb +421 -217
  96. data/spec/support/ruby_to_block.rb +10 -0
  97. metadata +108 -10
  98. data/public/assets/application-64a390efe879c386a5950515064f062d.css.gz +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53e0d4cc07184d7d779bce31a30099140c72d191
4
- data.tar.gz: ee93d3bd4b1a53590e2d0fb0af8d95851de81736
3
+ metadata.gz: 0bd06fb1b52286227744f48188c8f7da643f328e
4
+ data.tar.gz: 9f26a444410952686966a504032f23732dfc80f4
5
5
  SHA512:
6
- metadata.gz: 998812bd17c0f42e82fac22a223219082807267f674e06158c50365ae88d1d325efd7f6a0a8364d6ca80ac4839708d7892201e2a94201cb46ad2016097b9a869
7
- data.tar.gz: 540eb8e5125b96e2ae2ae8f2500dc2b76a9ef6d541e0a51efc7d63ce9c8b73abdbbbcb9575da2d0d69c47a4fdb8f5907023c0099388ff02febfbf32bbfe8eaff
6
+ metadata.gz: 147b02a2fa9819acd85149a19b8346d1e420eafe80ed8a6b846cdfe6dd0b54ccaa3b04e852fdc1de9f6e191bc7ae3a929dfdf2fefc9ce57e9ec541910d21934d
7
+ data.tar.gz: 3e6f91f3cfd1837d861cf488f757097d9afaec3d6eb0b9c0ebd07b1e96c9512d84147e3eae9764d5b45996fb8ead1252cc38ed743c27b86cb991caba2fc489f7
@@ -235,13 +235,50 @@ Blockly.Blocks['<%= n %>'] =
235
235
  @setTooltip('')
236
236
 
237
237
  Blockly.Ruby['<%= n %>'] = (block) ->
238
- pin = @getFieldValue('PIN') #p sensor("A0").value
239
- #p sensor("A0").value.class
240
- #p(sensor("A0").value / 6)
238
+ pin = @getFieldValue('PIN')
241
239
 
242
240
  pos = Blockly.Ruby.valueToCode(@, 'POS', Blockly.Ruby.ORDER_FUNCTION_CALL) || '5'
243
241
  Blockly.Ruby.characterMethodCall_("servo(#{Blockly.Ruby.quote_(pin)}).position = #{pos}")
244
242
 
243
+ # 「車」サブジャンル
244
+
245
+ # 「2WD車[▼ピン]を進める」ブロック
246
+ # 「2WD車[▼ピン]をバックさせる」ブロック
247
+ # 「2WD車[▼ピン]を左に曲げる」ブロック
248
+ # 「2WD車[▼ピン]を右に曲げる」ブロック
249
+ # 「2WD車[▼ピン]を止める」ブロック
250
+ <%
251
+ [
252
+ ['forward', '進める'],
253
+ ['backward', 'バックさせる'],
254
+ ['turn_left', '左に曲げる'],
255
+ ['turn_right', '右に曲げる'],
256
+ ['stop', '止める'],
257
+ ].each do |method, label|
258
+ n = "#{category}_two_wheel_drive_car_#{method}"
259
+ %>
260
+
261
+ Blockly.Blocks['<%= n %>'] =
262
+ init: ()->
263
+ dropdown = (["D#{n}", "D#{n}"] for n in [2..10])
264
+
265
+ @setHelpUrl('')
266
+ @setColour(<%= color %>)
267
+ @appendDummyInput()
268
+ .appendField('2WD車')
269
+ .appendField(new Blockly.FieldDropdown(dropdown), 'PIN')
270
+ .appendField('を<%= label %>')
271
+ @setInputsInline(true)
272
+ @setPreviousStatement(true)
273
+ @setNextStatement(true)
274
+ @setTooltip('')
275
+
276
+ Blockly.Ruby['<%= n %>'] = (block) ->
277
+ pin = @getFieldValue('PIN')
278
+
279
+ Blockly.Ruby.characterMethodCall_("two_wheel_drive_car(#{Blockly.Ruby.quote_(pin)}).<%= method %>")
280
+ <% end %>
281
+
245
282
  # 「ボタン」サブジャンル
246
283
 
247
284
  # 条件:ボタン[▼]を押している
@@ -42,10 +42,9 @@
42
42
  208
43
43
  208
44
44
  208
45
+ 208
45
46
  ).map(&:to_i)
46
47
 
47
- ruby_genre_index = hues.index(340) + 1
48
-
49
48
  colors = hues.map { |h|
50
49
  [hsv_to_rgb(h, 100, 80), hsv_to_rgb(h, 100, 100)]
51
50
  }
@@ -55,10 +54,6 @@
55
54
  %>
56
55
 
57
56
  #\:<%= ids[index] %> {
58
- <% if index == ruby_genre_index %>
59
- display: none;
60
-
61
- <% end %>
62
57
  .blocklyTreeRow {
63
58
  padding-top: 0.25em;
64
59
  padding-bottom: 0.25em;
@@ -61,7 +61,11 @@ class SourceCodesController < ApplicationController
61
61
  source_code = SourceCode.new(source_code_params)
62
62
  render text: source_code.to_blocks
63
63
  rescue
64
- head :bad_request
64
+ if Rails.env == 'development'
65
+ raise
66
+ else
67
+ head :bad_request
68
+ end
65
69
  end
66
70
 
67
71
  private
@@ -0,0 +1,251 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyToBlock
4
+ module Block
5
+ # すべてのブロックのベースクラス
6
+ class Base
7
+ attr_accessor :parent
8
+ attr_accessor :prev_sibling
9
+ attr_accessor :sibling
10
+ attr_accessor :fields
11
+ attr_accessor :values
12
+ attr_accessor :statements
13
+
14
+ def self.inherited(child)
15
+ Block.register(child)
16
+ end
17
+
18
+ def self.blocknize(regexp, options = {})
19
+ klass = (class << self; self; end)
20
+ klass.instance_eval do
21
+ define_method(:regexp_string) do
22
+ regexp
23
+ end
24
+
25
+ %w(
26
+ statement
27
+ value
28
+ indent
29
+ inline
30
+ priority
31
+ ).each do |name|
32
+ sym = name.to_sym
33
+ if options.key?(sym)
34
+ v = options[sym]
35
+ if v.is_a?(TrueClass) || v.is_a?(FalseClass)
36
+ sym = "#{name}?".to_sym
37
+ end
38
+ define_method(sym) do
39
+ v
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def self.type
47
+ name.sub('RubyToBlock::Block::', '').underscore
48
+ end
49
+
50
+ # 正規表現を返す
51
+ def self.regexp
52
+ @regexp ||= Regexp.new(regexp_string)
53
+ end
54
+
55
+ # ステートメントかどうかを返す
56
+ #
57
+ # trueの場合、Block.statement_regexpに追加される
58
+ def self.statement?
59
+ false
60
+ end
61
+
62
+ # 値かどうかを返す
63
+ #
64
+ # trueの場合、Block.value_regexpに追加される
65
+ def self.value?
66
+ false
67
+ end
68
+
69
+ # 正規表現の優先度を返す
70
+ def self.priority
71
+ 0
72
+ end
73
+
74
+ # インデントする必要があるかどうかを返す
75
+ def self.indent?
76
+ false
77
+ end
78
+
79
+ # インラインのブロックかどうかを返す
80
+ def self.inline?
81
+ false
82
+ end
83
+
84
+ # 正規表現にマッチしたデータを解析する
85
+ #
86
+ # @return [true] これ以上解析する必要がない
87
+ # @return [false] 解析できなかったのでさらなる解析が必要
88
+ def self.process_match_data(md, context)
89
+ true
90
+ end
91
+
92
+ # 値を格納した文字列を解析する
93
+ #
94
+ # @return [true] これ以上解析する必要がない
95
+ # @return [false] 解析できなかったのでさらなる解析が必要
96
+ def self.process_value_string(context, block, string, name)
97
+ # HACK: 最初と最後の括弧を取り除く
98
+ string = string[1..-2] while string[0] == '(' && string[-1] == ')'
99
+
100
+ value_md = Block.value_regexp.match(string)
101
+ return false unless value_md
102
+
103
+ _current_block = context.current_block
104
+ context.current_block = block
105
+ context.value_name_stack.push(name)
106
+
107
+ unless Block.process_match_data(value_md, context)
108
+ Block.process_match_data(value_md, context, 'ruby_expression')
109
+ end
110
+
111
+ context.value_name_stack.pop
112
+ context.current_block = _current_block
113
+
114
+ true
115
+ end
116
+
117
+ # elseを発見した時の処理
118
+ #
119
+ # @return [true] これ以上処理する必要がない
120
+ # @return [false] 処理できなかった
121
+ def self.process_else(context)
122
+ false
123
+ end
124
+
125
+ # endを発見した時の処理
126
+ #
127
+ # @return [true] これ以上処理する必要がない
128
+ # @return [false] 処理できなかった
129
+ def self.process_end(context)
130
+ context.current_block = context.statement[1]
131
+ context.statement_stack.pop
132
+
133
+ true
134
+ end
135
+
136
+ def initialize(options = {})
137
+ @fields = options[:fields] || {}
138
+ @values = options[:values] || {}
139
+ @statements = options[:statements] || {}
140
+
141
+ if @statements.length > 0
142
+ @statements.values.each do |s|
143
+ s.parent = self
144
+ end
145
+ end
146
+ end
147
+
148
+ def to_xml(parent)
149
+ e = parent.add_element('block', 'type' => type)
150
+ e.add_attribute('inline', 'true') if inline?
151
+ fields_to_xml(e)
152
+ values_to_xml(e)
153
+ statements_to_xml(e)
154
+ sibling_to_xml(e)
155
+ e
156
+ end
157
+
158
+ def type
159
+ @type ||= self.class.type
160
+ end
161
+
162
+ def inline?
163
+ @inline ||= self.class.inline?
164
+ end
165
+
166
+ def null?
167
+ false
168
+ end
169
+
170
+ def [](name)
171
+ @fields[name]
172
+ end
173
+
174
+ def add_statement(name, block)
175
+ b = @statements[name]
176
+ if b
177
+ b = b.sibling while b.sibling
178
+ b.sibling = block
179
+ else
180
+ block.parent = self
181
+ @statements[name] = block
182
+ end
183
+ self
184
+ end
185
+
186
+ def add_value(name, block)
187
+ b = @values[name]
188
+ if b
189
+ b = b.sibling while b.sibling
190
+ b.sibling = block
191
+ else
192
+ block.parent = self
193
+ @values[name] = block
194
+ end
195
+ self
196
+ end
197
+
198
+ def sibling=(block)
199
+ block.parent = parent
200
+ @sibling = block
201
+ block.prev_sibling = self
202
+ end
203
+
204
+ def indent_level
205
+ b = self
206
+ level = 0
207
+ while b.parent
208
+ b = b.parent
209
+ level += 1 if b.class.indent?
210
+ end
211
+ level
212
+ end
213
+
214
+ private
215
+
216
+ def fields_to_xml(parent)
217
+ @fields.each do |k, v|
218
+ e = parent.add_element('field', 'name' => k.to_s)
219
+ if v.is_a?(String)
220
+ e.text = v
221
+ else
222
+ # TODO
223
+ end
224
+ end
225
+ end
226
+
227
+ def values_to_xml(parent)
228
+ @values.each do |k, v|
229
+ next if v.null?
230
+ e = parent.add_element('value', 'name' => k.to_s)
231
+ v.to_xml(e)
232
+ end
233
+ end
234
+
235
+ def statements_to_xml(parent)
236
+ @statements.each do |k, v|
237
+ next if v.null?
238
+ e = parent.add_element('statement', 'name' => k.to_s)
239
+ v.to_xml(e)
240
+ end
241
+ end
242
+
243
+ def sibling_to_xml(parent)
244
+ return nil unless @sibling
245
+
246
+ e = parent.add_element('next')
247
+ @sibling.to_xml(e)
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,42 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ # ソースコードに含まれるキャラクターを表現するクラス
5
+ class Character < Base
6
+ # rubocop:disable LineLength
7
+ blocknize '^\s*(\S+)\s*=\s*Character\.new\(costume:\s*"(\s*[^"]+\s*)"\s*,\s*x:\s*(\s*\d+\s*)\s*,\s*y:\s*(\s*\d+\s*)\s*,\s*angle:\s*(\s*\d+\s*)\)\s*$',
8
+ statement: true
9
+ # rubocop:enable LineLength
10
+
11
+ attr_accessor :name
12
+ attr_accessor :costumes
13
+ attr_accessor :x
14
+ attr_accessor :y
15
+ attr_accessor :angle
16
+
17
+ def self.process_match_data(md, context)
18
+ md2 = regexp.match(md[type])
19
+ name = md2[1]
20
+ context[:characters][name] = new(name: name, costumes: [md2[2]],
21
+ x: md2[3], y: md2[4], angle: md2[5])
22
+
23
+ true
24
+ end
25
+
26
+ def initialize(options)
27
+ @name = options[:name]
28
+ @costumes = options[:costumes]
29
+ @x = options[:x]
30
+ @y = options[:y]
31
+ @angle = options[:angle]
32
+ end
33
+
34
+ def to_xml(parent)
35
+ parent.add_element('character',
36
+ 'name' => @name,
37
+ 'x' => @x, 'y' => @y, 'angle' => @angle,
38
+ 'costumes' => @costumes.join(','))
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class CharacterEvent < CharacterMethodCall
4
+ def self.process_end(context)
5
+ context.receiver_stack.pop
6
+ context.character_stack.pop
7
+ super
8
+ end
9
+
10
+ def self.add_character_event_blocks(context, name, block)
11
+ do_block = Block.new('null')
12
+ block.add_statement(:DO, do_block)
13
+
14
+ character = get_character(context, name)
15
+ context.character_stack.push(character)
16
+
17
+ character_new_block, _ =
18
+ add_child_or_create_character_new_block(context, name, block)
19
+
20
+ context.receiver_stack.push(character)
21
+
22
+ context.statement_stack.push([type, character_new_block])
23
+ context.current_block = do_block
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class CharacterMethodCall < Base
4
+ include CharacterOperation
5
+
6
+ def self.process_match_data(md, context)
7
+ md2 = regexp.match(md[type])
8
+
9
+ block = new
10
+ _, context.current_block =
11
+ *add_child_or_create_character_new_block(context, md2[1], block)
12
+
13
+ true
14
+ end
15
+
16
+ def self.add_character_method_call_block(context, name, block,
17
+ values = {})
18
+ _, context.current_block =
19
+ *add_child_or_create_character_new_block(context, name, block)
20
+
21
+ values.each do |k, v|
22
+ process_value_string(context, block, v, k)
23
+ end
24
+
25
+ block
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class CharacterNew < Base
4
+ include CharacterOperation
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,80 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ # キャラクターのメソッドや属性に共通するメソッドや定数を定義するモジュール
5
+ module CharacterOperation
6
+ extend ActiveSupport::Concern
7
+
8
+ CHAR_RE = '(?:(\S+)\.)?'
9
+
10
+ attr_accessor :character
11
+
12
+ module ClassMethods
13
+ # コンテキストからキャラクターを取得する
14
+ #
15
+ # キャラクターの名前がnil、または'self'の場合はコンテキストのレシー
16
+ # バの名前を利用する。
17
+ #
18
+ # コンテキストからキャラクターが取得できない場合は例外が発生する。
19
+ #
20
+ # @param [RubyToBlock::Context] context コンテキスト
21
+ # @param [String] name キャラクターの名前
22
+ # @return [Character] キャラクター
23
+ def get_character(context, name)
24
+ name = context.receiver.try(:name) if !name || name == 'self'
25
+ fail unless context.characters.key?(name)
26
+ context.characters[name]
27
+ end
28
+
29
+ # 必要であればcharacter_newブロックを作成してから指定したブロッ
30
+ # クをcharacter_newブロックの子供として追加する
31
+ #
32
+ # @param [RubyToBlock::Context] context コンテキスト
33
+ # @param [String] name キャラクターの名前
34
+ # @param [ブロック] block ブロックのインスタンス
35
+ # @return [Array<ブロック, ブロック>]
36
+ # 最初の要素がcharacter_newブロック、次の要素がカレントブロックの配列
37
+ def add_child_or_create_character_new_block(context, name, block)
38
+ character = get_character(context, name)
39
+
40
+ block.character = character
41
+
42
+ cb = context.current_block
43
+ if cb && cb.type == 'character_new' && cb.character == character
44
+ cb.add_statement(:DO, block)
45
+ [cb, cb]
46
+ elsif character == context.receiver
47
+ cb.sibling = block
48
+ [cb.parent, block]
49
+ else
50
+ character_new =
51
+ create_character_new_block(context, character, block)
52
+ [character_new, character_new]
53
+ end
54
+ end
55
+
56
+ # character_newブロックを生成する
57
+ #
58
+ # @param [RubyToBlock::Context] context コンテキスト
59
+ # @param [RubyToBlock::Block::Character] character キャラクター
60
+ # @param [RubyToBlock::Block::Baseのサブクラス] block ブロック
61
+ # @return [RubyToBlock::Block::CharacterNew] character_newブロック
62
+ def create_character_new_block(context, character, block)
63
+ character_new_block = Block.new('character_new',
64
+ fields: { NAME: character.name },
65
+ statements: { DO: block })
66
+ character_new_block.character = character
67
+
68
+ cb = context.current_block
69
+ if cb && cb.type != 'character_new'
70
+ cb.sibling = character_new_block
71
+ else
72
+ context.blocks.push(character_new_block)
73
+ end
74
+
75
+ character_new_block
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,45 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class ControlIf < Base
4
+ blocknize '^\s*if\s+(.*?)\s*$',
5
+ statement: true, indent: true, inline: true
6
+
7
+ def self.process_match_data(md, context)
8
+ then_block = Block.new('null')
9
+ block = new(statements: { THEN: then_block })
10
+
11
+ if context.current_block
12
+ context.current_block.sibling = block
13
+ else
14
+ context.blocks.push(block)
15
+ end
16
+
17
+ md2 = regexp.match(md[type])
18
+ process_value_string(context, block, md2[1], :COND)
19
+
20
+ context.current_block = then_block
21
+
22
+ context.statement_stack.push([type, block])
23
+
24
+ true
25
+ end
26
+
27
+ def self.process_else(context)
28
+ block = context.statement_block
29
+ else_block = Block.new('null')
30
+ block.add_statement(:ELSE, else_block)
31
+ context.current_block = else_block
32
+
33
+ true
34
+ end
35
+
36
+ def type
37
+ if @statements.key?(:ELSE)
38
+ 'control_if_else'
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class ControlLoop < Base
4
+ blocknize '^\s*loop\s+do\s*$', statement: true, indent: true
5
+
6
+ def self.process_match_data(md, context)
7
+ return false unless context.receiver
8
+
9
+ do_block = Block.new('null')
10
+ block = new(statements: { DO: do_block })
11
+ context.statement_stack.push([type, block])
12
+ context.current_block.sibling = block
13
+ context.current_block = do_block
14
+
15
+ true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class ControlSleep < Base
5
+ blocknize '^\s*sleep\((.+)\)\s*$', statement: true, inline: true
6
+
7
+ def self.process_match_data(md, context)
8
+ block = new
9
+ context.add_block(block)
10
+
11
+ md2 = regexp.match(md[type])
12
+ process_value_string(context, block, md2[1], :SEC)
13
+
14
+ true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class Do < RubyStatement
4
+ blocknize '^.*?\s*do\s*$',
5
+ statement: true, priority: -1
6
+
7
+ def self.process_match_data(md, context)
8
+ block = new(fields: { STATEMENT: md.string })
9
+ context.add_block(block)
10
+ context.statement_stack.push([type, block])
11
+ true
12
+ end
13
+
14
+ def self.process_end(context)
15
+ context.add_block(new(fields: { STATEMENT: 'end' }))
16
+ super
17
+ end
18
+
19
+ def type
20
+ 'ruby_statement'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class Else < Base
5
+ blocknize '^\s*else\s*$', statement: true
6
+
7
+ def self.process_match_data(md, context)
8
+ Block.process_else(context)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class End < Base
5
+ blocknize '^\s*end$', statement: true
6
+
7
+ def self.process_match_data(md, context)
8
+ ends_num = 1
9
+ context.lines.each do |l|
10
+ md2 = Block.statement_regexp.match(l)
11
+ type = md2.names.find { |n| md2[n.to_sym] }
12
+ if type == 'end'
13
+ ends_num += 1
14
+ elsif Block[type].indent?
15
+ ends_num -= 1
16
+ end
17
+ end
18
+ if context.statement && ends_num <= context.statement_stack.length
19
+ Block.process_end(context)
20
+ else
21
+ false
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end