smalruby-editor 0.1.6 → 0.1.7

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.
Files changed (92) 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.rb +17 -360
  6. data/app/models/concerns/ruby_to_block/block.rb +97 -0
  7. data/app/models/concerns/ruby_to_block/block/base.rb +251 -0
  8. data/app/models/concerns/ruby_to_block/block/character.rb +42 -0
  9. data/app/models/concerns/ruby_to_block/block/character_event.rb +27 -0
  10. data/app/models/concerns/ruby_to_block/block/character_method_call.rb +29 -0
  11. data/app/models/concerns/ruby_to_block/block/character_new.rb +7 -0
  12. data/app/models/concerns/ruby_to_block/block/character_operation.rb +80 -0
  13. data/app/models/concerns/ruby_to_block/block/control_if.rb +45 -0
  14. data/app/models/concerns/ruby_to_block/block/control_loop.rb +19 -0
  15. data/app/models/concerns/ruby_to_block/block/control_sleep.rb +18 -0
  16. data/app/models/concerns/ruby_to_block/block/do.rb +24 -0
  17. data/app/models/concerns/ruby_to_block/block/else.rb +12 -0
  18. data/app/models/concerns/ruby_to_block/block/end.rb +26 -0
  19. data/app/models/concerns/ruby_to_block/block/events_on_click.rb +14 -0
  20. data/app/models/concerns/ruby_to_block/block/events_on_key_push_or_down.rb +17 -0
  21. data/app/models/concerns/ruby_to_block/block/events_on_start.rb +14 -0
  22. data/app/models/concerns/ruby_to_block/block/hardware_init_hardware.rb +14 -0
  23. data/app/models/concerns/ruby_to_block/block/hardware_led_off.rb +16 -0
  24. data/app/models/concerns/ruby_to_block/block/hardware_led_on.rb +16 -0
  25. data/app/models/concerns/ruby_to_block/block/hardware_on_sensor_change.rb +17 -0
  26. data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_off.rb +18 -0
  27. data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_on.rb +23 -0
  28. data/app/models/concerns/ruby_to_block/block/hardware_sensor_value.rb +23 -0
  29. data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car.rb +26 -0
  30. data/app/models/concerns/ruby_to_block/block/looks_hide.rb +8 -0
  31. data/app/models/concerns/ruby_to_block/block/looks_say.rb +20 -0
  32. data/app/models/concerns/ruby_to_block/block/looks_show.rb +8 -0
  33. data/app/models/concerns/ruby_to_block/block/looks_vanish.rb +8 -0
  34. data/app/models/concerns/ruby_to_block/block/math_number.rb +14 -0
  35. data/app/models/concerns/ruby_to_block/block/motion_change_x_by.rb +20 -0
  36. data/app/models/concerns/ruby_to_block/block/motion_change_y_by.rb +20 -0
  37. data/app/models/concerns/ruby_to_block/block/motion_move.rb +15 -0
  38. data/app/models/concerns/ruby_to_block/block/motion_point_towards_character.rb +24 -0
  39. data/app/models/concerns/ruby_to_block/block/motion_point_towards_mouse.rb +9 -0
  40. data/app/models/concerns/ruby_to_block/block/motion_reach_wall.rb +24 -0
  41. data/app/models/concerns/ruby_to_block/block/motion_rotate_left.rb +20 -0
  42. data/app/models/concerns/ruby_to_block/block/motion_rotate_right.rb +20 -0
  43. data/app/models/concerns/ruby_to_block/block/motion_self_angle.rb +23 -0
  44. data/app/models/concerns/ruby_to_block/block/motion_self_x.rb +23 -0
  45. data/app/models/concerns/ruby_to_block/block/motion_self_y.rb +23 -0
  46. data/app/models/concerns/ruby_to_block/block/motion_set_angle.rb +15 -0
  47. data/app/models/concerns/ruby_to_block/block/motion_set_x.rb +38 -0
  48. data/app/models/concerns/ruby_to_block/block/motion_set_y.rb +15 -0
  49. data/app/models/concerns/ruby_to_block/block/motion_turn.rb +8 -0
  50. data/app/models/concerns/ruby_to_block/block/motion_turn_if_reach_wall.rb +8 -0
  51. data/app/models/concerns/ruby_to_block/block/null.rb +17 -0
  52. data/app/models/concerns/ruby_to_block/block/operators_compare.rb +36 -0
  53. data/app/models/concerns/ruby_to_block/block/operators_false.rb +8 -0
  54. data/app/models/concerns/ruby_to_block/block/operators_true.rb +8 -0
  55. data/app/models/concerns/ruby_to_block/block/require_smalruby.rb +7 -0
  56. data/app/models/concerns/ruby_to_block/block/ruby_comment.rb +16 -0
  57. data/app/models/concerns/ruby_to_block/block/ruby_expression.rb +14 -0
  58. data/app/models/concerns/ruby_to_block/block/ruby_statement.rb +23 -0
  59. data/app/models/concerns/ruby_to_block/block/sensing_hit.rb +23 -0
  60. data/app/models/concerns/ruby_to_block/block/sound_play.rb +15 -0
  61. data/app/models/concerns/ruby_to_block/block/sound_preset_sounds.rb +31 -0
  62. data/app/models/concerns/ruby_to_block/block/text.rb +15 -0
  63. data/app/models/concerns/ruby_to_block/block/value.rb +12 -0
  64. data/app/models/concerns/ruby_to_block/context.rb +97 -0
  65. data/app/models/concerns/ruby_to_block/formatter.rb +26 -0
  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/smalruby-editor.gemspec +1 -1
  70. data/spec/acceptance/block_mode/blocks/hardware/two_wheel_drive_car.feature +69 -0
  71. data/spec/acceptance/ruby_mode/translate.feature +1 -1
  72. data/spec/controllers/source_codes_controller_spec.rb +14 -11
  73. data/spec/models/concerns/ruby_to_block/block/character_method_call_spec.rb +175 -0
  74. data/spec/models/concerns/ruby_to_block/block/control_if_spec.rb +75 -0
  75. data/spec/models/concerns/ruby_to_block/block/control_loop_spec.rb +68 -0
  76. data/spec/models/concerns/ruby_to_block/block/events_on_start_spec.rb +120 -0
  77. data/spec/models/concerns/ruby_to_block/block/hardware_spec.rb +120 -0
  78. data/spec/models/concerns/ruby_to_block/block/looks_say_spec.rb +79 -0
  79. data/spec/models/concerns/ruby_to_block/block/looks_spec.rb +74 -0
  80. data/spec/models/concerns/ruby_to_block/block/motion_move_spec.rb +63 -0
  81. data/spec/models/concerns/ruby_to_block/block/motion_reach_wall_spec.rb +67 -0
  82. data/spec/models/concerns/ruby_to_block/block/motion_spec.rb +392 -0
  83. data/spec/models/concerns/ruby_to_block/block/motion_turn_spec.rb +54 -0
  84. data/spec/models/concerns/ruby_to_block/block/require_smalruby_spec.rb +39 -0
  85. data/spec/models/concerns/ruby_to_block/block/ruby_comment_spec.rb +55 -0
  86. data/spec/models/concerns/ruby_to_block/block/ruby_statement_spec.rb +113 -0
  87. data/spec/models/concerns/ruby_to_block/block/shared/block_examples.rb +44 -0
  88. data/spec/models/concerns/ruby_to_block/block/sound_spec.rb +46 -0
  89. data/spec/models/concerns/ruby_to_block/block_spec.rb +49 -0
  90. data/spec/models/concerns/ruby_to_block_spec.rb +421 -217
  91. data/spec/support/ruby_to_block.rb +10 -0
  92. metadata +108 -10
@@ -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
@@ -0,0 +1,14 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class EventsOnClick < CharacterEvent
4
+ blocknize '^\s*' + CHAR_RE + 'on\(:click\)\s+do\s*$',
5
+ statement: true, indent: true
6
+
7
+ def self.process_match_data(md, context)
8
+ md2 = regexp.match(md[type])
9
+ add_character_event_blocks(context, md2[1], new)
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class EventsOnKeyPushOrDown < CharacterEvent
4
+ # rubocop:disable LineLength
5
+ blocknize '^\s*' + CHAR_RE + 'on\(:key_(down|push),\s*([^),]+)\)\s+do\s*$',
6
+ statement: true, indent: true
7
+ # rubocop:enable LineLength
8
+
9
+ def self.process_match_data(md, context)
10
+ md2 = regexp.match(md[type])
11
+ add_character_event_blocks(context, md2[1],
12
+ new(fields: { KEY: md2[3], POD: md2[2] }))
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class EventsOnStart < CharacterEvent
4
+ blocknize '^\s*' + CHAR_RE + 'on\(:start\)\s+do\s*$',
5
+ statement: true, indent: true
6
+
7
+ def self.process_match_data(md, context)
8
+ md2 = regexp.match(md[type])
9
+ add_character_event_blocks(context, md2[1], new)
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareInitHardware < Base
5
+ blocknize '^\s*init_hardware\s*$', statement: true
6
+
7
+ def self.process_match_data(md, context)
8
+ context.blocks.push(new)
9
+
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareLedOff < CharacterMethodCall
5
+ blocknize '^\s*' + CHAR_RE + 'led\("(D(?:[2-9]|1[0-3]))"\).off\s*$',
6
+ statement: true
7
+
8
+ def self.process_match_data(md, context)
9
+ md2 = regexp.match(md[type])
10
+ add_character_method_call_block(context, md2[1],
11
+ new(fields: { PIN: md2[2] }))
12
+ true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareLedOn < CharacterMethodCall
5
+ blocknize '^\s*' + CHAR_RE + 'led\("(D(?:[2-9]|1[0-3]))"\).on\s*$',
6
+ statement: true
7
+
8
+ def self.process_match_data(md, context)
9
+ md2 = regexp.match(md[type])
10
+ add_character_method_call_block(context, md2[1],
11
+ new(fields: { PIN: md2[2] }))
12
+ true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class HardwareOnSensorChange < CharacterEvent
4
+ # rubocop:disable LineLength
5
+ blocknize '^\s*' + CHAR_RE + 'on\(:sensor_change,\s*"(A[0-5])"\s*\)\s+do\s*$',
6
+ statement: true, indent: true
7
+ # rubocop:enable LineLength
8
+
9
+ def self.process_match_data(md, context)
10
+ md2 = regexp.match(md[type])
11
+ add_character_event_blocks(context, md2[1],
12
+ new(fields: { PIN: md2[2] }))
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareRgbLedOff < CharacterMethodCall
5
+ # rubocop:disable LineLength
6
+ blocknize '^\s*' + CHAR_RE + 'rgb_led_(anode|cathode)\("(D[39])"\)\.off\s*$',
7
+ statement: true
8
+ # rubocop:enable LineLength
9
+
10
+ def self.process_match_data(md, context)
11
+ md2 = regexp.match(md[type])
12
+ block = new(fields: { AC: md2[2], PIN: md2[3] })
13
+ add_character_method_call_block(context, md2[1], block)
14
+ true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareRgbLedOn < CharacterMethodCall
5
+ # rubocop:disable LineLength
6
+ blocknize '^\s*' + CHAR_RE + 'rgb_led_(anode|cathode)\("(D[39])"\).on\(color:\s*\[(\d+),\s*(\d+),\s*(\d+)\]\)\s*$',
7
+ statement: true
8
+ # rubocop:enable LineLength
9
+
10
+ def self.process_match_data(md, context)
11
+ md2 = regexp.match(md[type])
12
+
13
+ color = [md2[4], md2[5], md2[6]].map(&:to_i)
14
+ return false if color.any? { |c| c < 0 || c > 255 }
15
+ color_code = '#' + color.map { |c| sprintf('%02x', c) }.join
16
+ block = new(fields: { AC: md2[2], PIN: md2[3], COLOUR: color_code })
17
+
18
+ add_character_method_call_block(context, md2[1], block)
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module RubyToBlock
2
+ module Block
3
+ class HardwareSensorValue < Value
4
+ include CharacterOperation
5
+
6
+ blocknize '^\s*' + CHAR_RE + 'sensor\(\s*"(A[0-5])"\s*\)\.value\s*$',
7
+ value: true
8
+
9
+ def self.process_match_data(md, context)
10
+ md2 = regexp.match(md[type])
11
+
12
+ character = get_character(context, md2[1])
13
+ return false if context.receiver != character
14
+
15
+ block = new(fields: { PIN: md2[2] })
16
+ context.add_value(block)
17
+ block.character = character
18
+
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # -*- coding: utf-8 -*-
2
+ module RubyToBlock
3
+ module Block
4
+ class HardwareTwoWheelDriveCar < CharacterMethodCall
5
+ # rubocop:disable LineLength
6
+ blocknize '^\s*' + CHAR_RE + 'two_wheel_drive_car\("(D(?:[2-9]|10))"\).(forward|backward|turn_left|turn_right|stop)\s*$',
7
+ statement: true
8
+ # rubocop:enable LineLength
9
+
10
+ attr_accessor :method_name
11
+
12
+ def self.process_match_data(md, context)
13
+ md2 = regexp.match(md[type])
14
+ block =
15
+ add_character_method_call_block(context, md2[1],
16
+ new(fields: { PIN: md2[2] }))
17
+ block.method_name = md2[3]
18
+ true
19
+ end
20
+
21
+ def type
22
+ "hardware_two_wheel_drive_car_#{method_name}"
23
+ end
24
+ end
25
+ end
26
+ end