seeing_is_believing 2.0.0.beta1 → 2.0.0.beta2
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.
- checksums.yaml +7 -0
- data/Readme.md +8 -20
- data/features/examples.feature +1 -3
- data/features/flags.feature +4 -12
- data/features/regression.feature +95 -1
- data/lib/seeing_is_believing.rb +17 -21
- data/lib/seeing_is_believing/binary.rb +3 -3
- data/lib/seeing_is_believing/binary/add_annotations.rb +86 -118
- data/lib/seeing_is_believing/binary/align_chunk.rb +22 -23
- data/lib/seeing_is_believing/binary/align_file.rb +10 -13
- data/lib/seeing_is_believing/binary/align_line.rb +0 -4
- data/lib/seeing_is_believing/binary/arg_parser.rb +11 -11
- data/lib/seeing_is_believing/binary/clean_body.rb +96 -0
- data/lib/seeing_is_believing/binary/comment_formatter.rb +55 -0
- data/lib/seeing_is_believing/binary/comment_lines.rb +37 -0
- data/lib/seeing_is_believing/binary/commentable_lines.rb +158 -0
- data/lib/seeing_is_believing/binary/rewrite_comments.rb +42 -0
- data/lib/seeing_is_believing/result.rb +2 -9
- data/lib/seeing_is_believing/the_matrix.rb +8 -8
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/{program_rewriter.rb → wrap_expressions.rb} +30 -22
- data/spec/binary/arg_parser_spec.rb +7 -7
- data/spec/binary/clean_body_spec.rb +217 -0
- data/spec/binary/comment_formatter_spec.rb +54 -0
- data/spec/binary/comment_lines_spec.rb +847 -0
- data/spec/binary/rewrite_comments_spec.rb +54 -0
- data/spec/seeing_is_believing_spec.rb +1 -2
- data/spec/{program_rewriter_spec.rb → wrap_expressions_spec.rb} +117 -40
- metadata +41 -56
- data/lib/seeing_is_believing/binary/line_formatter.rb +0 -47
- data/lib/seeing_is_believing/binary/remove_previous_annotations.rb +0 -75
- data/lib/seeing_is_believing/queue.rb +0 -55
- data/lib/seeing_is_believing/remove_inline_comments.rb +0 -46
- data/lib/seeing_is_believing/syntax_analyzer.rb +0 -61
- data/lib/seeing_is_believing/tracks_line_numbers_seen.rb +0 -19
- data/spec/binary/line_formatter_spec.rb +0 -53
- data/spec/binary/remove_previous_annotations_spec.rb +0 -198
- data/spec/queue_spec.rb +0 -80
- data/spec/syntax_analyzer_spec.rb +0 -56
@@ -1,47 +0,0 @@
|
|
1
|
-
class SeeingIsBelieving
|
2
|
-
class Binary
|
3
|
-
class LineFormatter
|
4
|
-
attr_accessor :line, :separator, :result, :options
|
5
|
-
|
6
|
-
def initialize(line, separator, result, options)
|
7
|
-
self.line = line
|
8
|
-
self.separator = separator
|
9
|
-
self.result = result.gsub "\n", '\n'
|
10
|
-
self.options = options
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
14
|
-
return line unless sep_plus_result.start_with? separator
|
15
|
-
return line unless formatted_line.start_with? "#{line_with_padding}#{separator}"
|
16
|
-
formatted_line
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def line_length
|
22
|
-
options.fetch :line_length, Float::INFINITY
|
23
|
-
end
|
24
|
-
|
25
|
-
def result_length
|
26
|
-
options.fetch :result_length, Float::INFINITY
|
27
|
-
end
|
28
|
-
|
29
|
-
def sep_plus_result
|
30
|
-
@sep_plus_result ||= truncate "#{separator}#{result}", result_length
|
31
|
-
end
|
32
|
-
|
33
|
-
def formatted_line
|
34
|
-
@formatted_line ||= truncate "#{line_with_padding}#{sep_plus_result}", line_length
|
35
|
-
end
|
36
|
-
|
37
|
-
def line_with_padding
|
38
|
-
"%-#{options[:pad_to]}s" % line
|
39
|
-
end
|
40
|
-
|
41
|
-
def truncate(string, length)
|
42
|
-
return string if string.size <= length
|
43
|
-
string.slice(0, length).sub(/.{0,3}$/) { |last_chars| last_chars.gsub /./, '.' }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'seeing_is_believing/remove_inline_comments'
|
2
|
-
|
3
|
-
class SeeingIsBelieving
|
4
|
-
class Binary
|
5
|
-
class RemovePreviousAnnotations
|
6
|
-
def self.call(code)
|
7
|
-
new(code).call
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(code)
|
11
|
-
self.code = code
|
12
|
-
self.comments = { result: [],
|
13
|
-
exception: [],
|
14
|
-
stdout: [],
|
15
|
-
stderr: [],
|
16
|
-
}
|
17
|
-
end
|
18
|
-
|
19
|
-
def call
|
20
|
-
RemoveInlineComments.call code, additional_rewrites: remove_whitespace_preceeding_comments do |comment|
|
21
|
-
if comment.text[/\A#\s*=>/] then comments[:result] << comment; true
|
22
|
-
elsif comment.text[/\A#\s*~>/] then comments[:exception] << comment; true
|
23
|
-
elsif comment.text[/\A#\s*>>/] then comments[:stdout] << comment; true
|
24
|
-
elsif comment.text[/\A#\s*!>/] then comments[:stderr] << comment; true
|
25
|
-
else false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
attr_accessor :code, :comments
|
33
|
-
|
34
|
-
def remove_whitespace_preceeding_comments
|
35
|
-
lambda do |buffer, rewriter|
|
36
|
-
comments[:result].each { |comment| remove_whitespace_before comment.location.expression.begin_pos, buffer, rewriter, false }
|
37
|
-
comments[:exception].each { |comment| remove_whitespace_before comment.location.expression.begin_pos, buffer, rewriter, true }
|
38
|
-
comments[:stdout].each { |comment| remove_whitespace_before comment.location.expression.begin_pos, buffer, rewriter, true }
|
39
|
-
comments[:stderr].each { |comment| remove_whitespace_before comment.location.expression.begin_pos, buffer, rewriter, true }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# any whitespace before the index (on the same line) will be removed
|
44
|
-
# if the preceeding whitespace is at the beginning of the line, the newline will be removed
|
45
|
-
# if there is a newline before all of that, and remove_preceeding_newline is true, it will be removed as well
|
46
|
-
def remove_whitespace_before(index, buffer, rewriter, remove_preceeding_newline)
|
47
|
-
end_pos = index
|
48
|
-
begin_pos = end_pos - 1
|
49
|
-
begin_pos -= 1 while code[begin_pos] =~ /\s/ && code[begin_pos] != "\n"
|
50
|
-
begin_pos -= 1 if code[begin_pos] == "\n"
|
51
|
-
begin_pos -= 1 if code[begin_pos] == "\n" && remove_preceeding_newline
|
52
|
-
return if begin_pos.next == end_pos
|
53
|
-
rewriter.remove Parser::Source::Range.new(buffer, begin_pos.next, end_pos)
|
54
|
-
end
|
55
|
-
|
56
|
-
# returns comments in groups that are on consecutive lines
|
57
|
-
def adjacent_comments(comments, buffer)
|
58
|
-
comments = comments.sort_by { |comment| comment.location.begin_pos }
|
59
|
-
current_chunk = 0
|
60
|
-
last_line_seen = -100
|
61
|
-
chunks_to_comment = comments.chunk do |comment|
|
62
|
-
line, col = buffer.decompose_position comment.location.begin_pos
|
63
|
-
if last_line_seen.next == line
|
64
|
-
last_line_seen = line
|
65
|
-
current_chunk
|
66
|
-
else
|
67
|
-
last_line_seen = line
|
68
|
-
current_chunk += 1
|
69
|
-
end
|
70
|
-
end
|
71
|
-
chunks_to_comment.map &:last
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
class SeeingIsBelieving
|
2
|
-
class Queue
|
3
|
-
class While
|
4
|
-
attr_accessor :queue, :conditional
|
5
|
-
|
6
|
-
def initialize(queue, &conditional)
|
7
|
-
self.queue, self.conditional = queue, conditional
|
8
|
-
end
|
9
|
-
|
10
|
-
def each(&block)
|
11
|
-
block.call queue.dequeue while !queue.empty? && conditional.call(queue.peek)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class Queue
|
17
|
-
attr_accessor :value_generator
|
18
|
-
|
19
|
-
def initialize(&value_generator)
|
20
|
-
self.value_generator = value_generator
|
21
|
-
end
|
22
|
-
|
23
|
-
def dequeue
|
24
|
-
return if permanently_empty?
|
25
|
-
peek.tap { @next_value = nil }
|
26
|
-
end
|
27
|
-
|
28
|
-
def peek
|
29
|
-
return if permanently_empty?
|
30
|
-
@next_value ||= value_generator.call.tap { |value| @permanently_empty = value.nil? }
|
31
|
-
end
|
32
|
-
|
33
|
-
def empty?
|
34
|
-
permanently_empty? || peek.nil?
|
35
|
-
end
|
36
|
-
|
37
|
-
def each(&block)
|
38
|
-
block.call dequeue until empty?
|
39
|
-
end
|
40
|
-
|
41
|
-
def until(&block)
|
42
|
-
While.new(self) { |*args| !block.call(*args) }
|
43
|
-
end
|
44
|
-
|
45
|
-
def while(&block)
|
46
|
-
While.new self, &block
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def permanently_empty?
|
52
|
-
@permanently_empty
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'parser/current'
|
2
|
-
|
3
|
-
class SeeingIsBelieving
|
4
|
-
module RemoveInlineComments
|
5
|
-
module NonLeading
|
6
|
-
def self.call(code)
|
7
|
-
ranges = []
|
8
|
-
|
9
|
-
nonleading_comments = lambda do |buffer, rewriter|
|
10
|
-
ranges.sort_by(&:begin_pos)
|
11
|
-
.drop_while.with_index(1) { |range, index|
|
12
|
-
line, col = buffer.decompose_position range.begin_pos
|
13
|
-
index == line && col.zero?
|
14
|
-
}
|
15
|
-
.each { |range| rewriter.remove range }
|
16
|
-
end
|
17
|
-
|
18
|
-
RemoveInlineComments.call code, additional_rewrites: nonleading_comments do |comment|
|
19
|
-
ranges << comment.location
|
20
|
-
false
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
extend self
|
26
|
-
|
27
|
-
# selector is a block that will receive the comment object
|
28
|
-
# if it returns true, the comment will be removed
|
29
|
-
def self.call(code, options={}, &selector)
|
30
|
-
selector ||= Proc.new { true }
|
31
|
-
additional_rewrites = options.fetch :additional_rewrites, Proc.new {}
|
32
|
-
buffer = Parser::Source::Buffer.new "strip_comments"
|
33
|
-
buffer.source = code
|
34
|
-
parser = Parser::CurrentRuby.new
|
35
|
-
rewriter = Parser::Source::Rewriter.new(buffer)
|
36
|
-
ast, comments = parser.parse_with_comments(buffer)
|
37
|
-
comments.select { |comment| comment.type == :inline }
|
38
|
-
.select { |comment| selector.call comment }
|
39
|
-
.each { |comment| rewriter.remove comment.location.expression }
|
40
|
-
additional_rewrites.call buffer, rewriter
|
41
|
-
rewriter.process
|
42
|
-
rescue Parser::SyntaxError => e
|
43
|
-
raise SyntaxError, e.message
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'ripper'
|
2
|
-
require 'parser/current'
|
3
|
-
|
4
|
-
class SeeingIsBelieving
|
5
|
-
class SyntaxAnalyzer < Ripper::SexpBuilder
|
6
|
-
|
7
|
-
# HELPERS
|
8
|
-
|
9
|
-
def self.parsed(code)
|
10
|
-
instance = new code
|
11
|
-
instance.parse
|
12
|
-
instance
|
13
|
-
end
|
14
|
-
|
15
|
-
# SYNTACTIC VALIDITY
|
16
|
-
|
17
|
-
def self.begins_multiline_comment?(line)
|
18
|
-
line == '=begin'
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.ends_multiline_comment?(line)
|
22
|
-
line == '=end'
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.begin_and_end_comments_are_complete?(code)
|
26
|
-
code.scan(/^=(?:begin|end)$/)
|
27
|
-
.each_slice(2)
|
28
|
-
.all? { |b, e| b == '=begin' && e == '=end' }
|
29
|
-
end
|
30
|
-
|
31
|
-
# MISC
|
32
|
-
|
33
|
-
def self.begins_data_segment?(line)
|
34
|
-
line == '__END__'
|
35
|
-
end
|
36
|
-
|
37
|
-
# COMMENTS
|
38
|
-
|
39
|
-
def self.line_is_comment?(line)
|
40
|
-
line =~ /^\s*#/
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.ends_in_comment?(code)
|
44
|
-
# must do the newline hack or it totally fucks up on comments like "# Transfer-Encoding: chunked"
|
45
|
-
code =~ /^=end\Z/ || parsed("\n#{code.lines.to_a.last.to_s}").has_comment?
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.unclosed_comment?(code)
|
49
|
-
!begin_and_end_comments_are_complete?(code)
|
50
|
-
end
|
51
|
-
|
52
|
-
def has_comment?
|
53
|
-
@has_comment
|
54
|
-
end
|
55
|
-
|
56
|
-
def on_comment(*)
|
57
|
-
@has_comment = true
|
58
|
-
super
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class SeeingIsBelieving
|
2
|
-
module TracksLineNumbersSeen
|
3
|
-
INITIAL_LINE_NUMBER = 1 # uhm, should this change to 0?
|
4
|
-
|
5
|
-
def track_line_number(line_number)
|
6
|
-
@min_line_number = line_number if line_number < min_line_number
|
7
|
-
@max_line_number = line_number if line_number > max_line_number
|
8
|
-
self
|
9
|
-
end
|
10
|
-
|
11
|
-
def min_line_number
|
12
|
-
@min_line_number || INITIAL_LINE_NUMBER
|
13
|
-
end
|
14
|
-
|
15
|
-
def max_line_number
|
16
|
-
@max_line_number || INITIAL_LINE_NUMBER
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'seeing_is_believing/binary/line_formatter'
|
2
|
-
|
3
|
-
describe SeeingIsBelieving::Binary::LineFormatter do
|
4
|
-
def result_for(line, separator, result, options={})
|
5
|
-
described_class.new(line, separator, result, options).call
|
6
|
-
end
|
7
|
-
|
8
|
-
specify 'it returns the consolidated result if there are no truncations' do
|
9
|
-
result_for('1', '=>', '12345').should == '1=>12345'
|
10
|
-
end
|
11
|
-
|
12
|
-
specify 'result_length truncates a result to the specified length, using elipses up to that length if appropriate' do
|
13
|
-
line = '1'
|
14
|
-
separator = '=>'
|
15
|
-
result = '12345'
|
16
|
-
result_for(line, separator, result, result_length: Float::INFINITY).should == '1=>12345'
|
17
|
-
result_for(line, separator, result, result_length: 7).should == '1=>12345'
|
18
|
-
result_for(line, separator, result, result_length: 6).should == '1=>1...'
|
19
|
-
result_for(line, separator, result, result_length: 5).should == '1=>...'
|
20
|
-
result_for(line, separator, result, result_length: 4).should == '1'
|
21
|
-
result_for(line, separator, result, result_length: 0).should == '1'
|
22
|
-
end
|
23
|
-
|
24
|
-
specify 'line_length truncates a result to the specified length, minus the length of the line' do
|
25
|
-
line = '1'
|
26
|
-
separator = '=>'
|
27
|
-
result = '12345'
|
28
|
-
result_for(line, separator, result).should == '1=>12345'
|
29
|
-
result_for(line, separator, result, line_length: Float::INFINITY).should == '1=>12345'
|
30
|
-
result_for(line, separator, result, line_length: 8).should == '1=>12345'
|
31
|
-
result_for(line, separator, result, line_length: 7).should == '1=>1...'
|
32
|
-
result_for(line, separator, result, line_length: 6).should == '1=>...'
|
33
|
-
result_for(line, separator, result, line_length: 5).should == '1'
|
34
|
-
result_for(line, separator, result, line_length: 0).should == '1'
|
35
|
-
end
|
36
|
-
|
37
|
-
specify 'pad_to will pad the length that the line is displayed in' do
|
38
|
-
result_for('1', '=>', '2', pad_to: 0).should == '1=>2'
|
39
|
-
result_for('1', '=>', '2', pad_to: 1).should == '1=>2'
|
40
|
-
result_for('1', '=>', '2', pad_to: 2).should == '1 =>2'
|
41
|
-
end
|
42
|
-
|
43
|
-
specify 'pad_to is ignored when separator/result will not be printed' do
|
44
|
-
result_for('1', '=>', '12345', pad_to: 2, line_length: 2).should == '1'
|
45
|
-
result_for('1', '=>', '12345', pad_to: 2, result_length: 2).should == '1'
|
46
|
-
end
|
47
|
-
|
48
|
-
specify 'they can all work together' do
|
49
|
-
result_for('1', '=>', '12345', line_length: 100, result_length: 100, pad_to: 2).should == '1 =>12345'
|
50
|
-
result_for('1', '=>', '12345', line_length: 8, result_length: 100, pad_to: 2).should == '1 =>1...'
|
51
|
-
result_for('1', '=>', '12345', line_length: 100, result_length: 6, pad_to: 2).should == '1 =>1...'
|
52
|
-
end
|
53
|
-
end
|
@@ -1,198 +0,0 @@
|
|
1
|
-
require 'seeing_is_believing/binary/remove_previous_annotations'
|
2
|
-
|
3
|
-
describe SeeingIsBelieving::Binary::RemovePreviousAnnotations do
|
4
|
-
def call(code)
|
5
|
-
indentation = code[/\A */]
|
6
|
-
code = code.gsub /^#{indentation}/, ''
|
7
|
-
described_class.call(code).chomp
|
8
|
-
end
|
9
|
-
|
10
|
-
# show some examples of what it should not remove
|
11
|
-
|
12
|
-
example { call("1#=>1").should == "1" }
|
13
|
-
example { call("1 #=>1").should == "1" }
|
14
|
-
example { call("1 #=>1").should == "1" }
|
15
|
-
example { call("1 #=> 1").should == "1" }
|
16
|
-
example { call("1 #=> 1").should == "1" }
|
17
|
-
example { call("1 #=> 1").should == "1" }
|
18
|
-
example { call("\n1 # => 1").should == "\n1" }
|
19
|
-
|
20
|
-
example { call("1#~>1").should == "1" }
|
21
|
-
example { call("1 #~>1").should == "1" }
|
22
|
-
example { call("1 #~>1").should == "1" }
|
23
|
-
example { call("1 #~> 1").should == "1" }
|
24
|
-
example { call("1 #~> 1").should == "1" }
|
25
|
-
example { call("1 #~> 1").should == "1" }
|
26
|
-
example { call("\n1 # ~> 1").should == "\n1" }
|
27
|
-
|
28
|
-
example { call("# >> 1").should == "" }
|
29
|
-
example { call("# !> 1").should == "" }
|
30
|
-
|
31
|
-
example { call(<<-CODE).should == "1" }
|
32
|
-
1
|
33
|
-
# >> 2
|
34
|
-
CODE
|
35
|
-
|
36
|
-
example { call(<<-CODE).should == "1" }
|
37
|
-
1
|
38
|
-
|
39
|
-
# >> 2
|
40
|
-
CODE
|
41
|
-
|
42
|
-
example { call(<<-CODE).should == "1\n" }
|
43
|
-
1
|
44
|
-
|
45
|
-
|
46
|
-
# >> 2
|
47
|
-
CODE
|
48
|
-
|
49
|
-
example { call(<<-CODE).should == "1\n" }
|
50
|
-
1
|
51
|
-
|
52
|
-
|
53
|
-
# >> 2
|
54
|
-
# >> 2
|
55
|
-
# >> 2
|
56
|
-
CODE
|
57
|
-
|
58
|
-
|
59
|
-
example { call(<<-CODE).should == "1\n" }
|
60
|
-
1
|
61
|
-
|
62
|
-
|
63
|
-
# >> 2
|
64
|
-
# >> 3
|
65
|
-
CODE
|
66
|
-
|
67
|
-
example { call(<<-CODE).should == "1" }
|
68
|
-
1
|
69
|
-
# !> 2
|
70
|
-
CODE
|
71
|
-
|
72
|
-
example { call(<<-CODE).should == "1" }
|
73
|
-
1
|
74
|
-
|
75
|
-
# !> 2
|
76
|
-
CODE
|
77
|
-
|
78
|
-
example { call(<<-CODE).should == "1" }
|
79
|
-
1
|
80
|
-
|
81
|
-
# !> 2
|
82
|
-
# !> 3
|
83
|
-
CODE
|
84
|
-
|
85
|
-
example { call(<<-CODE).should == "1\n" }
|
86
|
-
1
|
87
|
-
|
88
|
-
|
89
|
-
# !> 2
|
90
|
-
# !> 2
|
91
|
-
# !> 2
|
92
|
-
CODE
|
93
|
-
|
94
|
-
|
95
|
-
example { call(<<-CODE).should == "1" }
|
96
|
-
1
|
97
|
-
# ~>2
|
98
|
-
CODE
|
99
|
-
|
100
|
-
example { call(<<-CODE).should == "1" }
|
101
|
-
1
|
102
|
-
|
103
|
-
# ~> 2
|
104
|
-
CODE
|
105
|
-
|
106
|
-
example { call(<<-CODE).should == "1" }
|
107
|
-
1
|
108
|
-
|
109
|
-
# ~> 2
|
110
|
-
# ~> 3
|
111
|
-
CODE
|
112
|
-
|
113
|
-
example { call(<<-CODE).should == "1\n" }
|
114
|
-
1
|
115
|
-
|
116
|
-
|
117
|
-
# ~> 2
|
118
|
-
# ~> 2
|
119
|
-
# ~> 2
|
120
|
-
CODE
|
121
|
-
|
122
|
-
example { call(<<-CODE).should == "1\n" }
|
123
|
-
1 # ~> error
|
124
|
-
|
125
|
-
|
126
|
-
# ~> error again
|
127
|
-
CODE
|
128
|
-
|
129
|
-
example { call(<<-CODE).should == "1" }
|
130
|
-
1
|
131
|
-
|
132
|
-
# >> 1
|
133
|
-
# >> 2
|
134
|
-
|
135
|
-
# !> 3
|
136
|
-
# !> 4
|
137
|
-
|
138
|
-
# ~> 5
|
139
|
-
# ~> 6
|
140
|
-
CODE
|
141
|
-
|
142
|
-
example { call(<<-CODE).should == "1" }
|
143
|
-
1
|
144
|
-
|
145
|
-
# >> 1
|
146
|
-
|
147
|
-
# >> 2
|
148
|
-
|
149
|
-
# !> 3
|
150
|
-
|
151
|
-
# !> 4
|
152
|
-
|
153
|
-
# ~> 5
|
154
|
-
|
155
|
-
# ~> 6
|
156
|
-
CODE
|
157
|
-
|
158
|
-
example { call(<<-CODE).should == "1" }
|
159
|
-
1
|
160
|
-
|
161
|
-
# >> 1
|
162
|
-
# >> 2
|
163
|
-
# !> 3
|
164
|
-
# !> 4
|
165
|
-
# ~> 5
|
166
|
-
# ~> 6
|
167
|
-
CODE
|
168
|
-
|
169
|
-
example { call(<<-CODE).should == "1\n3" }
|
170
|
-
1
|
171
|
-
# >> 1
|
172
|
-
# >> 2
|
173
|
-
3
|
174
|
-
# !> 4
|
175
|
-
# !> 5
|
176
|
-
CODE
|
177
|
-
|
178
|
-
example { call(<<-CODE).should == "1\n3\n6" }
|
179
|
-
1
|
180
|
-
# >> 1
|
181
|
-
# >> 2
|
182
|
-
3
|
183
|
-
# !> 4
|
184
|
-
# !> 5
|
185
|
-
6
|
186
|
-
# ~> 7
|
187
|
-
# ~> 8
|
188
|
-
CODE
|
189
|
-
|
190
|
-
example { call(<<-CODE).should == "1\n\nputs \"omg\"" }
|
191
|
-
1 # => 1
|
192
|
-
|
193
|
-
puts "omg" # ~> RuntimeError: omg
|
194
|
-
|
195
|
-
# ~> RuntimeError
|
196
|
-
CODE
|
197
|
-
|
198
|
-
end
|