to_source 0.1.3 → 0.2.16
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/.gitignore +6 -6
- data/.rspec +1 -0
- data/.travis.yml +12 -1
- data/Changelog.md +115 -0
- data/Gemfile +5 -3
- data/Gemfile.devtools +67 -0
- data/Guardfile +18 -0
- data/LICENSE +21 -0
- data/README.md +52 -0
- data/Rakefile +3 -8
- data/TODO +9 -0
- data/bin/to_source +17 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +26 -0
- data/config/site.reek +97 -0
- data/config/yardstick.yml +2 -0
- data/lib/to_source/command.rb +106 -0
- data/lib/to_source/emitter/access.rb +28 -0
- data/lib/to_source/emitter/actual_arguments.rb +89 -0
- data/lib/to_source/emitter/alias.rb +27 -0
- data/lib/to_source/emitter/assignment.rb +119 -0
- data/lib/to_source/emitter/attribute_assignment.rb +28 -0
- data/lib/to_source/emitter/begin.rb +71 -0
- data/lib/to_source/emitter/binary_operator.rb +63 -0
- data/lib/to_source/emitter/binary_operator_method.rb +58 -0
- data/lib/to_source/emitter/block.rb +29 -0
- data/lib/to_source/emitter/block_argument.rb +23 -0
- data/lib/to_source/emitter/block_pass.rb +23 -0
- data/lib/to_source/emitter/case.rb +85 -0
- data/lib/to_source/emitter/class.rb +44 -0
- data/lib/to_source/emitter/concat_arguments.rb +28 -0
- data/lib/to_source/emitter/default_arguments.rb +22 -0
- data/lib/to_source/emitter/define.rb +99 -0
- data/lib/to_source/emitter/defined.rb +24 -0
- data/lib/to_source/emitter/element_assignment.rb +29 -0
- data/lib/to_source/emitter/element_reference.rb +25 -0
- data/lib/to_source/emitter/empty_body.rb +21 -0
- data/lib/to_source/emitter/ensure.rb +50 -0
- data/lib/to_source/emitter/ensure_body.rb +27 -0
- data/lib/to_source/emitter/execute_string.rb +22 -0
- data/lib/to_source/emitter/formal_arguments.rb +212 -0
- data/lib/to_source/emitter/if.rb +96 -0
- data/lib/to_source/emitter/iter.rb +27 -0
- data/lib/to_source/emitter/keyword_value.rb +67 -0
- data/lib/to_source/emitter/literal/dynamic.rb +178 -0
- data/lib/to_source/emitter/literal.rb +232 -0
- data/lib/to_source/emitter/loop.rb +40 -0
- data/lib/to_source/emitter/match3.rb +25 -0
- data/lib/to_source/emitter/module.rb +28 -0
- data/lib/to_source/emitter/multiple_assignment.rb +49 -0
- data/lib/to_source/emitter/nth_ref.rb +22 -0
- data/lib/to_source/emitter/op_assign1.rb +27 -0
- data/lib/to_source/emitter/op_assign2.rb +27 -0
- data/lib/to_source/emitter/pattern_arguments.rb +24 -0
- data/lib/to_source/emitter/rescue.rb +28 -0
- data/lib/to_source/emitter/rescue_condition.rb +93 -0
- data/lib/to_source/emitter/scope.rb +24 -0
- data/lib/to_source/emitter/scope_name.rb +23 -0
- data/lib/to_source/emitter/scoped_name.rb +28 -0
- data/lib/to_source/emitter/send.rb +133 -0
- data/lib/to_source/emitter/send_with_arguments.rb +103 -0
- data/lib/to_source/emitter/singleton_class.rb +38 -0
- data/lib/to_source/emitter/splat.rb +24 -0
- data/lib/to_source/emitter/splat_when.rb +23 -0
- data/lib/to_source/emitter/static.rb +52 -0
- data/lib/to_source/emitter/super.rb +92 -0
- data/lib/to_source/emitter/to_array.rb +22 -0
- data/lib/to_source/emitter/to_string.rb +24 -0
- data/lib/to_source/emitter/toplevel.rb +24 -0
- data/lib/to_source/emitter/unary_operator_method.rb +27 -0
- data/lib/to_source/emitter/unless.rb +45 -0
- data/lib/to_source/emitter/util.rb +28 -0
- data/lib/to_source/emitter/when.rb +63 -0
- data/lib/to_source/emitter/yield.rb +28 -0
- data/lib/to_source/emitter/z_super.rb +24 -0
- data/lib/to_source/emitter.rb +278 -0
- data/lib/to_source/state.rb +144 -0
- data/lib/to_source.rb +78 -11
- data/spec/spec_helper.rb +11 -0
- data/spec/unit/to_source/class_methods/run_spec.rb +1254 -0
- data/to_source.gemspec +16 -14
- metadata +160 -20
- data/.rvmrc +0 -1
- data/Readme.md +0 -38
- data/lib/to_source/core_ext/node.rb +0 -22
- data/lib/to_source/version.rb +0 -3
- data/lib/to_source/visitor.rb +0 -377
- data/test/to_source/visitor_test.rb +0 -202
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# Emitter for unary operator method
|
|
4
|
+
class UnaryOperatorMethod < Send
|
|
5
|
+
|
|
6
|
+
UNARY_MAPPING = {
|
|
7
|
+
:-@ => :-,
|
|
8
|
+
:+@ => :+,
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# Perform dispatch
|
|
14
|
+
#
|
|
15
|
+
# @return [undefined]
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
#
|
|
19
|
+
def dispatch
|
|
20
|
+
name = node.name
|
|
21
|
+
emit(UNARY_MAPPING.fetch(name, name))
|
|
22
|
+
visit(receiver)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# Emitter for unless
|
|
4
|
+
class Unless < self
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# Perform dispatch
|
|
9
|
+
#
|
|
10
|
+
# @return [undefined]
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
#
|
|
14
|
+
def dispatch
|
|
15
|
+
emit('unless ')
|
|
16
|
+
visit(condition)
|
|
17
|
+
indented do
|
|
18
|
+
visit(else_body)
|
|
19
|
+
end
|
|
20
|
+
emit_end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Emit condition
|
|
24
|
+
#
|
|
25
|
+
# @return [undefined]
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
def condition
|
|
30
|
+
node.condition
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Emit else
|
|
34
|
+
#
|
|
35
|
+
# @return [undefined]
|
|
36
|
+
#
|
|
37
|
+
# @api private
|
|
38
|
+
#
|
|
39
|
+
def else_body
|
|
40
|
+
node.else
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# base class for utility emitters
|
|
4
|
+
class Util < self
|
|
5
|
+
# Emitter for delimited bodies
|
|
6
|
+
class DelimitedBody < self
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Perform dispatch
|
|
11
|
+
#
|
|
12
|
+
# @return [undefined]
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def dispatch
|
|
17
|
+
body = node
|
|
18
|
+
max = body.length - 1
|
|
19
|
+
body.each_with_index do |member, index|
|
|
20
|
+
visit(member)
|
|
21
|
+
emit(', ') if index < max
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# Emitter for when nodes
|
|
4
|
+
class When < self
|
|
5
|
+
|
|
6
|
+
handle(Rubinius::AST::When)
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Perform dispatch
|
|
11
|
+
#
|
|
12
|
+
# @return [undefined]
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def dispatch
|
|
17
|
+
emit('when ')
|
|
18
|
+
emit_single
|
|
19
|
+
emit_conditions
|
|
20
|
+
emit_splat
|
|
21
|
+
indented do
|
|
22
|
+
visit(node.body)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Emit single
|
|
27
|
+
#
|
|
28
|
+
# @return [undefined]
|
|
29
|
+
#
|
|
30
|
+
# @api private
|
|
31
|
+
#
|
|
32
|
+
def emit_single
|
|
33
|
+
single = node.single
|
|
34
|
+
visit(single) if single
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Emit splat
|
|
38
|
+
#
|
|
39
|
+
# @return [undefined]
|
|
40
|
+
#
|
|
41
|
+
# @api private
|
|
42
|
+
#
|
|
43
|
+
def emit_splat
|
|
44
|
+
splat = node.splat
|
|
45
|
+
return unless splat
|
|
46
|
+
visit(splat)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Emit conditions
|
|
50
|
+
#
|
|
51
|
+
# @return [undefined]
|
|
52
|
+
#
|
|
53
|
+
# @api private
|
|
54
|
+
#
|
|
55
|
+
def emit_conditions
|
|
56
|
+
conditions = node.conditions
|
|
57
|
+
return unless conditions
|
|
58
|
+
run(Util::DelimitedBody, conditions.body)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# Emitter for yield nodes
|
|
4
|
+
class Yield < self
|
|
5
|
+
|
|
6
|
+
handle(Rubinius::AST::Yield)
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Perform dispatch
|
|
11
|
+
#
|
|
12
|
+
# @return [undefined]
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def dispatch
|
|
17
|
+
emit('yield')
|
|
18
|
+
arguments = node.arguments
|
|
19
|
+
unless arguments.array.empty?
|
|
20
|
+
emit('(')
|
|
21
|
+
visit(arguments)
|
|
22
|
+
emit(')')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
class Emitter
|
|
3
|
+
# Emitter for zsuper nodes
|
|
4
|
+
class ZSuper < self
|
|
5
|
+
|
|
6
|
+
handle(Rubinius::AST::ZSuper)
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
# Perform dispatch
|
|
11
|
+
#
|
|
12
|
+
# @return [undefined]
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
def dispatch
|
|
17
|
+
emit('super')
|
|
18
|
+
block = node.block
|
|
19
|
+
visit(block) if block
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
# Abstract base class for emitter
|
|
3
|
+
class Emitter
|
|
4
|
+
include Adamantium::Flat, Equalizer.new(:node)
|
|
5
|
+
|
|
6
|
+
# The emitter registry
|
|
7
|
+
REGISTRY = {}
|
|
8
|
+
|
|
9
|
+
# Build emitter for node
|
|
10
|
+
#
|
|
11
|
+
# @param [Rubinius::AST::Node] node
|
|
12
|
+
# @param [Array] buffer
|
|
13
|
+
#
|
|
14
|
+
# @return [Emitter]
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
#
|
|
18
|
+
def self.build(node, buffer = [])
|
|
19
|
+
REGISTRY.fetch(node.class).new(node, buffer)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Run emitter for node
|
|
23
|
+
#
|
|
24
|
+
# @param [Rubinius::AST::Node] node
|
|
25
|
+
#
|
|
26
|
+
# @return [String]
|
|
27
|
+
#
|
|
28
|
+
# @api private
|
|
29
|
+
#
|
|
30
|
+
def self.run(node)
|
|
31
|
+
build(node).source
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Declare predicates
|
|
35
|
+
#
|
|
36
|
+
# @return [undefined]
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
#
|
|
40
|
+
def self.predicate(*names)
|
|
41
|
+
names.each do |name|
|
|
42
|
+
define_predicate(name)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private_class_method :predicate
|
|
47
|
+
|
|
48
|
+
# Declare node delegators
|
|
49
|
+
#
|
|
50
|
+
# @return [undefined]
|
|
51
|
+
#
|
|
52
|
+
# @api private
|
|
53
|
+
#
|
|
54
|
+
def self.delegate(*names)
|
|
55
|
+
names.each do |name|
|
|
56
|
+
define_delegator(name)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private_class_method :delegate
|
|
61
|
+
|
|
62
|
+
# Register emitter for node class
|
|
63
|
+
#
|
|
64
|
+
# @param [Class:Rubinius::AST::Node] node_class
|
|
65
|
+
#
|
|
66
|
+
# @return [undefined]
|
|
67
|
+
#
|
|
68
|
+
# @api private
|
|
69
|
+
#
|
|
70
|
+
def self.handle(node_class)
|
|
71
|
+
REGISTRY[node_class]=self
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private_class_method :handle
|
|
75
|
+
|
|
76
|
+
# Define node delegator
|
|
77
|
+
#
|
|
78
|
+
# @param [Symbol] name
|
|
79
|
+
#
|
|
80
|
+
# @return [undefined]
|
|
81
|
+
#
|
|
82
|
+
# @api private
|
|
83
|
+
#
|
|
84
|
+
def self.define_delegator(name)
|
|
85
|
+
define_method(name) do
|
|
86
|
+
node.public_send(name)
|
|
87
|
+
end
|
|
88
|
+
private(name)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private_class_method :define_delegator
|
|
92
|
+
|
|
93
|
+
# Define predicate
|
|
94
|
+
#
|
|
95
|
+
# @param [Symbol] name
|
|
96
|
+
#
|
|
97
|
+
# @return [undefined]
|
|
98
|
+
#
|
|
99
|
+
# @api private
|
|
100
|
+
#
|
|
101
|
+
def self.define_predicate(name)
|
|
102
|
+
predicate = :"#{name}?"
|
|
103
|
+
define_method(predicate) do
|
|
104
|
+
!!send(name)
|
|
105
|
+
end
|
|
106
|
+
private(predicate)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private_class_method :define_delegator
|
|
110
|
+
|
|
111
|
+
# Return buffer
|
|
112
|
+
#
|
|
113
|
+
# @return [Array<Command>]
|
|
114
|
+
#
|
|
115
|
+
# @api private
|
|
116
|
+
#
|
|
117
|
+
attr_reader :buffer
|
|
118
|
+
|
|
119
|
+
# Return node
|
|
120
|
+
#
|
|
121
|
+
# @return [Rubinius::AST::Node]
|
|
122
|
+
#
|
|
123
|
+
# @api private
|
|
124
|
+
#
|
|
125
|
+
attr_reader :node
|
|
126
|
+
|
|
127
|
+
# Initialize object
|
|
128
|
+
#
|
|
129
|
+
# @param [Rubinius::AST::Node] node
|
|
130
|
+
# @param [Array<Command>] buffer
|
|
131
|
+
#
|
|
132
|
+
# @return [undefined]
|
|
133
|
+
#
|
|
134
|
+
# @api private
|
|
135
|
+
#
|
|
136
|
+
def initialize(node, buffer)
|
|
137
|
+
@node, @buffer = node, buffer
|
|
138
|
+
dispatch
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Return source
|
|
142
|
+
#
|
|
143
|
+
# @return [String]
|
|
144
|
+
#
|
|
145
|
+
# @api private
|
|
146
|
+
#
|
|
147
|
+
def source
|
|
148
|
+
buffer.each_with_object(State.new) do |command, state|
|
|
149
|
+
state.execute(command)
|
|
150
|
+
end.source
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
# Push command
|
|
156
|
+
#
|
|
157
|
+
# @param [Command] command
|
|
158
|
+
#
|
|
159
|
+
# @return [undefined]
|
|
160
|
+
#
|
|
161
|
+
# @api private
|
|
162
|
+
#
|
|
163
|
+
def push(command)
|
|
164
|
+
buffer.push(command)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Emit new line
|
|
168
|
+
#
|
|
169
|
+
# @return [undefined]
|
|
170
|
+
#
|
|
171
|
+
# @api private
|
|
172
|
+
#
|
|
173
|
+
def new_line
|
|
174
|
+
emit("\n")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Emit single whitespace
|
|
178
|
+
#
|
|
179
|
+
# @return [undefined]
|
|
180
|
+
#
|
|
181
|
+
# @api private
|
|
182
|
+
#
|
|
183
|
+
def space
|
|
184
|
+
emit(' ')
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Emit end keyword
|
|
188
|
+
#
|
|
189
|
+
# @return [undefined]
|
|
190
|
+
#
|
|
191
|
+
# @api private
|
|
192
|
+
#
|
|
193
|
+
def emit_end
|
|
194
|
+
emit(:end)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Push indent command
|
|
198
|
+
#
|
|
199
|
+
# @return [undefined]
|
|
200
|
+
#
|
|
201
|
+
# @api private
|
|
202
|
+
#
|
|
203
|
+
def indent
|
|
204
|
+
push(Command::Shift::INDENT)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Push unindent command
|
|
208
|
+
#
|
|
209
|
+
# @return [undefined]
|
|
210
|
+
#
|
|
211
|
+
# @api private
|
|
212
|
+
#
|
|
213
|
+
def unindent
|
|
214
|
+
push(Command::Shift::UNINDENT)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Push token with content
|
|
218
|
+
#
|
|
219
|
+
# @param [String] content
|
|
220
|
+
#
|
|
221
|
+
# @return [undefined]
|
|
222
|
+
#
|
|
223
|
+
# @api private
|
|
224
|
+
#
|
|
225
|
+
def emit(content)
|
|
226
|
+
push(Command::Token.new(content))
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Run block indented
|
|
230
|
+
#
|
|
231
|
+
# @return [undefined]
|
|
232
|
+
#
|
|
233
|
+
# @api private
|
|
234
|
+
#
|
|
235
|
+
def indented
|
|
236
|
+
indent
|
|
237
|
+
yield
|
|
238
|
+
unindent
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Run block in parantheses
|
|
242
|
+
#
|
|
243
|
+
# @return [undefined]
|
|
244
|
+
#
|
|
245
|
+
# @api private
|
|
246
|
+
#
|
|
247
|
+
def parantheses
|
|
248
|
+
emit('(')
|
|
249
|
+
yield
|
|
250
|
+
emit(')')
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Visit descendant node
|
|
254
|
+
#
|
|
255
|
+
# @param [Rubinius::AST::Node] node
|
|
256
|
+
#
|
|
257
|
+
# @return [undefined]
|
|
258
|
+
#
|
|
259
|
+
# @api private
|
|
260
|
+
#
|
|
261
|
+
def visit(node)
|
|
262
|
+
self.class.build(node, buffer)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Run emitter on buffer
|
|
266
|
+
#
|
|
267
|
+
# @param [Class:Emitter] emitter
|
|
268
|
+
# @param [Rubinius::AST::Node] node
|
|
269
|
+
#
|
|
270
|
+
# @return [undefined]
|
|
271
|
+
#
|
|
272
|
+
# @api private
|
|
273
|
+
#
|
|
274
|
+
def run(emitter, node = self.node)
|
|
275
|
+
emitter.new(node, buffer)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
module ToSource
|
|
2
|
+
# Emitter state
|
|
3
|
+
class State
|
|
4
|
+
|
|
5
|
+
# Return last command
|
|
6
|
+
#
|
|
7
|
+
# @return [Command]
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
#
|
|
11
|
+
attr_reader :last
|
|
12
|
+
|
|
13
|
+
# Return current indentation level
|
|
14
|
+
#
|
|
15
|
+
# @return [Fixnum]
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
#
|
|
19
|
+
attr_reader :identation
|
|
20
|
+
|
|
21
|
+
# Return buffer
|
|
22
|
+
#
|
|
23
|
+
# @return [Array]
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
attr_reader :buffer
|
|
28
|
+
|
|
29
|
+
# Initialize object
|
|
30
|
+
#
|
|
31
|
+
# @return [undefined]
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
#
|
|
35
|
+
def initialize
|
|
36
|
+
@last = Command::NULL
|
|
37
|
+
@indentation = 0
|
|
38
|
+
@buffer = []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Execute command
|
|
42
|
+
#
|
|
43
|
+
# @param [Command] command
|
|
44
|
+
#
|
|
45
|
+
# @return [self]
|
|
46
|
+
#
|
|
47
|
+
# @api private
|
|
48
|
+
#
|
|
49
|
+
def execute(command)
|
|
50
|
+
command.run(self)
|
|
51
|
+
@last = command
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Write string to buffer
|
|
56
|
+
#
|
|
57
|
+
# @param [String] string
|
|
58
|
+
#
|
|
59
|
+
# @return [self]
|
|
60
|
+
#
|
|
61
|
+
# @api private
|
|
62
|
+
#
|
|
63
|
+
def write(string)
|
|
64
|
+
@buffer << string
|
|
65
|
+
self
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Return source
|
|
69
|
+
#
|
|
70
|
+
# @return [String]
|
|
71
|
+
#
|
|
72
|
+
# @api private
|
|
73
|
+
#
|
|
74
|
+
def source
|
|
75
|
+
buffer.join('')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Push command
|
|
79
|
+
#
|
|
80
|
+
# @param [Command] command
|
|
81
|
+
#
|
|
82
|
+
# @return [self]
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
#
|
|
86
|
+
def push(command)
|
|
87
|
+
indent
|
|
88
|
+
write(command.content)
|
|
89
|
+
self
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Indent line if needed
|
|
93
|
+
#
|
|
94
|
+
# @return [self]
|
|
95
|
+
#
|
|
96
|
+
# @api private
|
|
97
|
+
#
|
|
98
|
+
def indent
|
|
99
|
+
return unless blank?
|
|
100
|
+
write(' ' * @indentation)
|
|
101
|
+
self
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Test for blank line
|
|
105
|
+
#
|
|
106
|
+
# @return [true]
|
|
107
|
+
# if line is blank
|
|
108
|
+
#
|
|
109
|
+
# @return [false]
|
|
110
|
+
# otherwise
|
|
111
|
+
#
|
|
112
|
+
# @api private
|
|
113
|
+
#
|
|
114
|
+
def blank?
|
|
115
|
+
buffer.last == "\n"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Write newline
|
|
119
|
+
#
|
|
120
|
+
# @return [self]
|
|
121
|
+
#
|
|
122
|
+
# @api private
|
|
123
|
+
#
|
|
124
|
+
def new_line
|
|
125
|
+
write("\n")
|
|
126
|
+
self
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Perform shift by width
|
|
130
|
+
#
|
|
131
|
+
# @param [Fixnum] width
|
|
132
|
+
#
|
|
133
|
+
# @return [self]
|
|
134
|
+
#
|
|
135
|
+
# @api private
|
|
136
|
+
#
|
|
137
|
+
def shift(width)
|
|
138
|
+
@indentation += width
|
|
139
|
+
@indentation = 0 if @indentation < 0
|
|
140
|
+
new_line
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|