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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/blocks/hardware.js.coffee.erb +40 -3
- data/app/assets/stylesheets/toolbox.css.scss.erb +1 -6
- data/app/controllers/source_codes_controller.rb +5 -1
- data/app/models/concerns/ruby_to_block/block/base.rb +251 -0
- data/app/models/concerns/ruby_to_block/block/character.rb +42 -0
- data/app/models/concerns/ruby_to_block/block/character_event.rb +27 -0
- data/app/models/concerns/ruby_to_block/block/character_method_call.rb +29 -0
- data/app/models/concerns/ruby_to_block/block/character_new.rb +7 -0
- data/app/models/concerns/ruby_to_block/block/character_operation.rb +80 -0
- data/app/models/concerns/ruby_to_block/block/control_if.rb +45 -0
- data/app/models/concerns/ruby_to_block/block/control_loop.rb +19 -0
- data/app/models/concerns/ruby_to_block/block/control_sleep.rb +18 -0
- data/app/models/concerns/ruby_to_block/block/do.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/else.rb +12 -0
- data/app/models/concerns/ruby_to_block/block/end.rb +26 -0
- data/app/models/concerns/ruby_to_block/block/events_on_click.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/events_on_key_push_or_down.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/events_on_start.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/hardware_init_hardware.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/hardware_led_off.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/hardware_led_on.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/hardware_on_sensor_change.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_off.rb +18 -0
- data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_on.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/hardware_sensor_value.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car.rb +26 -0
- data/app/models/concerns/ruby_to_block/block/looks_hide.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/looks_say.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/looks_show.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/looks_vanish.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/math_number.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/motion_change_x_by.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_change_y_by.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_move.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_point_towards_character.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/motion_point_towards_mouse.rb +9 -0
- data/app/models/concerns/ruby_to_block/block/motion_reach_wall.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/motion_rotate_left.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_rotate_right.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_angle.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_x.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_y.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_angle.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_x.rb +38 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_y.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_turn.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/motion_turn_if_reach_wall.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/null.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/operators_compare.rb +36 -0
- data/app/models/concerns/ruby_to_block/block/operators_false.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/operators_true.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/require_smalruby.rb +7 -0
- data/app/models/concerns/ruby_to_block/block/ruby_comment.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/ruby_expression.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/ruby_statement.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/sensing_hit.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/sound_play.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/sound_preset_sounds.rb +31 -0
- data/app/models/concerns/ruby_to_block/block/text.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/value.rb +12 -0
- data/app/models/concerns/ruby_to_block/block.rb +97 -0
- data/app/models/concerns/ruby_to_block/context.rb +97 -0
- data/app/models/concerns/ruby_to_block/formatter.rb +26 -0
- data/app/models/concerns/ruby_to_block.rb +17 -360
- data/app/models/source_code.rb +3 -1
- data/app/views/editor/_toolbox.html.haml +16 -0
- data/lib/smalruby_editor/version.rb +3 -3
- data/public/assets/{application-64a390efe879c386a5950515064f062d.css → application-28b7bed56c5389dfa372e972c75b6676.css} +17 -10
- data/public/assets/application-28b7bed56c5389dfa372e972c75b6676.css.gz +0 -0
- data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js → application-4f747690ebc8ec4815ae36021fdb2c44.js} +135 -0
- data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js.gz → application-4f747690ebc8ec4815ae36021fdb2c44.js.gz} +0 -0
- data/public/assets/manifest-332a5a1668194028b55103e0ea45c054.json +1 -1
- data/smalruby-editor.gemspec +1 -1
- data/spec/acceptance/block_mode/blocks/hardware/two_wheel_drive_car.feature +69 -0
- data/spec/acceptance/ruby_mode/translate.feature +1 -1
- data/spec/controllers/source_codes_controller_spec.rb +14 -11
- data/spec/models/concerns/ruby_to_block/block/character_method_call_spec.rb +175 -0
- data/spec/models/concerns/ruby_to_block/block/control_if_spec.rb +75 -0
- data/spec/models/concerns/ruby_to_block/block/control_loop_spec.rb +68 -0
- data/spec/models/concerns/ruby_to_block/block/events_on_start_spec.rb +120 -0
- data/spec/models/concerns/ruby_to_block/block/hardware_spec.rb +120 -0
- data/spec/models/concerns/ruby_to_block/block/looks_say_spec.rb +79 -0
- data/spec/models/concerns/ruby_to_block/block/looks_spec.rb +74 -0
- data/spec/models/concerns/ruby_to_block/block/motion_move_spec.rb +63 -0
- data/spec/models/concerns/ruby_to_block/block/motion_reach_wall_spec.rb +67 -0
- data/spec/models/concerns/ruby_to_block/block/motion_spec.rb +392 -0
- data/spec/models/concerns/ruby_to_block/block/motion_turn_spec.rb +54 -0
- data/spec/models/concerns/ruby_to_block/block/require_smalruby_spec.rb +39 -0
- data/spec/models/concerns/ruby_to_block/block/ruby_comment_spec.rb +55 -0
- data/spec/models/concerns/ruby_to_block/block/ruby_statement_spec.rb +113 -0
- data/spec/models/concerns/ruby_to_block/block/shared/block_examples.rb +44 -0
- data/spec/models/concerns/ruby_to_block/block/sound_spec.rb +46 -0
- data/spec/models/concerns/ruby_to_block/block_spec.rb +49 -0
- data/spec/models/concerns/ruby_to_block_spec.rb +421 -217
- data/spec/support/ruby_to_block.rb +10 -0
- metadata +108 -10
- data/public/assets/application-64a390efe879c386a5950515064f062d.css.gz +0 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class RubyComment < Base
|
5
|
+
blocknize '^\s*\#\ (.*)$', statement: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
md2 = regexp.match(md[type])
|
9
|
+
block = new(fields: { COMMENT: md2[1] })
|
10
|
+
context.add_block(block)
|
11
|
+
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class RubyExpression < Value
|
5
|
+
blocknize '^.*$', value: true, priority: -Float::INFINITY
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
context.add_value(new(fields: { EXP: md.string }))
|
9
|
+
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class RubyStatement < Base
|
4
|
+
blocknize '^.*$', statement: true, priority: -Float::INFINITY
|
5
|
+
|
6
|
+
def self.process_match_data(md, context)
|
7
|
+
block = new(fields: { STATEMENT: md.string })
|
8
|
+
context.add_block(block)
|
9
|
+
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def fields_to_xml(e)
|
16
|
+
@fields[:STATEMENT] =
|
17
|
+
@fields[:STATEMENT].sub(/^ {0,#{indent_level * 2}}/, '')
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class SensingHit < Value
|
5
|
+
blocknize '^\s*hit\?\(([^)]+)\)\s*$', value: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
return false unless context.receiver
|
9
|
+
|
10
|
+
md2 = regexp.match(md[type])
|
11
|
+
name = md2[1]
|
12
|
+
name.strip!
|
13
|
+
c = context.characters[name]
|
14
|
+
|
15
|
+
return false unless c
|
16
|
+
|
17
|
+
context.add_value(new(fields: { CHAR: name }))
|
18
|
+
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class SoundPlay < CharacterMethodCall
|
5
|
+
blocknize '^\s*' + CHAR_RE + 'play\(name:\s*(.+)\)\s*$',
|
6
|
+
statement: true, inline: 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], new, NAME: md2[2])
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class SoundPresetSounds < Value
|
5
|
+
blocknize '^\s*"([^"]*?\.wav)"\s*$', value: true, priority: 1
|
6
|
+
|
7
|
+
# TODO: 自動生成する
|
8
|
+
SOUNDS = %w(
|
9
|
+
piano_do.wav
|
10
|
+
piano_re.wav
|
11
|
+
piano_mi.wav
|
12
|
+
piano_fa.wav
|
13
|
+
piano_so.wav
|
14
|
+
piano_ra.wav
|
15
|
+
piano_si.wav
|
16
|
+
piano_do_2.wav
|
17
|
+
)
|
18
|
+
|
19
|
+
def self.process_match_data(md, context)
|
20
|
+
md2 = regexp.match(md[type])
|
21
|
+
if SOUNDS.include?(md2[1])
|
22
|
+
context.add_value(new(fields: { NAME: md2[1] }))
|
23
|
+
else
|
24
|
+
context.add_value(Text.new(fields: { TEXT: md2[1] }))
|
25
|
+
end
|
26
|
+
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class Text < Value
|
5
|
+
blocknize '^\s*"([^"]*)"\s*$', value: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
md2 = regexp.match(md[type])
|
9
|
+
context.add_value(new(fields: { TEXT: md2[1] }))
|
10
|
+
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module RubyToBlock
|
4
|
+
# ブロック群を表現するモジュール
|
5
|
+
module Block
|
6
|
+
@blocks = {}
|
7
|
+
|
8
|
+
# ブロックのインスタンスを生成する
|
9
|
+
def self.new(type, *args)
|
10
|
+
@blocks[type].new(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
# ステートメントを表現するブロックの正規表現を返す
|
14
|
+
def self.statement_regexp
|
15
|
+
@statement_regexp ||= make_regexp(:statement?)
|
16
|
+
end
|
17
|
+
|
18
|
+
# 値を表現するブロックの正規表現を返す
|
19
|
+
def self.value_regexp
|
20
|
+
@value_regexp ||= make_regexp(:value?)
|
21
|
+
end
|
22
|
+
|
23
|
+
# ブロックを登録する
|
24
|
+
def self.register(klass)
|
25
|
+
@blocks[klass.type] = klass
|
26
|
+
end
|
27
|
+
|
28
|
+
# ブロックの正規表現を返す
|
29
|
+
def self.regexp(type)
|
30
|
+
@blocks[type.to_s].regexp
|
31
|
+
end
|
32
|
+
|
33
|
+
# MatchDataを処理する
|
34
|
+
def self.process_match_data(md, context, type = nil)
|
35
|
+
type = md.names.find { |n| md[n.to_sym] } unless type
|
36
|
+
@blocks[type].process_match_data(md, context)
|
37
|
+
rescue
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
# elseを処理する
|
42
|
+
def self.process_else(context)
|
43
|
+
st = context.statement
|
44
|
+
@blocks[st.first].process_else(context)
|
45
|
+
rescue
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
# endを処理する
|
50
|
+
def self.process_end(context)
|
51
|
+
st = context.statement
|
52
|
+
@blocks[st.first].process_end(context)
|
53
|
+
rescue
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
# ブロックを表現するクラスを返す
|
58
|
+
def self.[](type)
|
59
|
+
@blocks[type.to_s]
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.make_regexp(method_symbol)
|
63
|
+
regexps = @blocks.values.select(&method_symbol).sort_by(&:priority)
|
64
|
+
.reverse.map { |klass|
|
65
|
+
"(?<#{klass.type}>#{klass.regexp_string})"
|
66
|
+
}
|
67
|
+
Regexp.new(regexps.join('|'), 'x')
|
68
|
+
end
|
69
|
+
private_class_method :make_regexp
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
preloads = %w(
|
74
|
+
base
|
75
|
+
value
|
76
|
+
character_operation
|
77
|
+
character_method_call
|
78
|
+
character_event
|
79
|
+
).map { |s|
|
80
|
+
"#{s}.rb"
|
81
|
+
}
|
82
|
+
preloads.each do |preload|
|
83
|
+
path = Pathname(__FILE__).dirname.join('block', preload)
|
84
|
+
silence_warnings do
|
85
|
+
load path.expand_path
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
block_pattern = Pathname(__FILE__).dirname.join('block', '*.rb')
|
90
|
+
block_files = Pathname.glob(block_pattern)
|
91
|
+
block_files.each do |path|
|
92
|
+
next if preloads.include?(path.basename)
|
93
|
+
|
94
|
+
silence_warnings do
|
95
|
+
load path.expand_path
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module RubyToBlock
|
4
|
+
# ソースコード解析の状態を表現するクラス
|
5
|
+
class Context
|
6
|
+
attr_accessor :current_line
|
7
|
+
attr_accessor :lines
|
8
|
+
attr_accessor :characters
|
9
|
+
attr_accessor :character_stack
|
10
|
+
attr_accessor :receiver_stack
|
11
|
+
attr_accessor :statement_stack
|
12
|
+
attr_accessor :value_name_stack
|
13
|
+
attr_accessor :blocks
|
14
|
+
attr_accessor :current_block
|
15
|
+
|
16
|
+
def initialize(lines)
|
17
|
+
@lines = lines
|
18
|
+
@characters = {}
|
19
|
+
@character_stack = []
|
20
|
+
@receiver_stack = []
|
21
|
+
@statement_stack = []
|
22
|
+
@value_name_stack = []
|
23
|
+
@blocks = []
|
24
|
+
@current_block = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# 次の行に移動して、改行を含むその行の文字列を返す
|
28
|
+
#
|
29
|
+
# @return [String] 改行を含む次の行の文字列
|
30
|
+
def next_line
|
31
|
+
self.current_line = lines.shift
|
32
|
+
end
|
33
|
+
|
34
|
+
# 次の行を参照する
|
35
|
+
#
|
36
|
+
# @return [String] 次の行の文字列
|
37
|
+
def look_next_line
|
38
|
+
lines.first
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_block(block)
|
42
|
+
if current_block
|
43
|
+
# HACK: コメントは下の行に関係することが多いため対象外としている
|
44
|
+
if current_block.type == 'character_new' &&
|
45
|
+
block.type != 'character_new' && block.type != 'ruby_comment'
|
46
|
+
current_block.add_statement(:DO, block)
|
47
|
+
block = current_block
|
48
|
+
else
|
49
|
+
current_block.sibling = block
|
50
|
+
end
|
51
|
+
else
|
52
|
+
blocks.push(block)
|
53
|
+
end
|
54
|
+
self.current_block = block
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_value(block)
|
59
|
+
fail unless current_block || value_name
|
60
|
+
|
61
|
+
current_block.add_value(value_name, block)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def [](symbol)
|
66
|
+
send(symbol)
|
67
|
+
end
|
68
|
+
|
69
|
+
def []=(symbol, val)
|
70
|
+
send("#{symbol}=", val)
|
71
|
+
end
|
72
|
+
|
73
|
+
def receiver
|
74
|
+
@receiver_stack.last
|
75
|
+
end
|
76
|
+
|
77
|
+
def character
|
78
|
+
@character_stack.last
|
79
|
+
end
|
80
|
+
|
81
|
+
def statement
|
82
|
+
@statement_stack.last
|
83
|
+
end
|
84
|
+
|
85
|
+
def statement_type
|
86
|
+
statement.first
|
87
|
+
end
|
88
|
+
|
89
|
+
def statement_block
|
90
|
+
statement[1]
|
91
|
+
end
|
92
|
+
|
93
|
+
def value_name
|
94
|
+
@value_name_stack.last
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module RubyToBlock
|
4
|
+
# XMLをフォーマットするクラス
|
5
|
+
#
|
6
|
+
# REXML::Formatters::Prettyでは行頭、行末などのスペースが1つになって
|
7
|
+
# しまうため、このクラスではそれらを修正している
|
8
|
+
class Formatter < REXML::Formatters::Pretty
|
9
|
+
def initialize
|
10
|
+
super(2, true)
|
11
|
+
self.compact = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_text(node, output)
|
15
|
+
s = node.to_s
|
16
|
+
s.gsub!(/\s/, ' ')
|
17
|
+
if !node.is_a?(REXML::Text) ||
|
18
|
+
node.is_a?(REXML::Text) && !node.parent.whitespace
|
19
|
+
s.squeeze!(' ')
|
20
|
+
end
|
21
|
+
s = wrap(s, @width - @level)
|
22
|
+
s = indent_text(s, @level, ' ', true)
|
23
|
+
output << (' ' * @level + s)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|