seeing_is_believing 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +0 -1
- data/features/flags.feature +39 -0
- data/features/regression.feature +154 -0
- data/features/xmpfilter-style.feature +57 -0
- data/lib/seeing_is_believing/binary/annotate_every_line.rb +11 -4
- data/lib/seeing_is_believing/binary/annotate_marked_lines.rb +11 -5
- data/lib/seeing_is_believing/binary/config.rb +9 -0
- data/lib/seeing_is_believing/binary/data_structures.rb +1 -0
- data/lib/seeing_is_believing/binary/interline_align.rb +57 -0
- data/lib/seeing_is_believing/customize_pp.rb +5 -0
- data/lib/seeing_is_believing/event_stream/consumer.rb +39 -43
- data/lib/seeing_is_believing/event_stream/producer.rb +24 -31
- data/lib/seeing_is_believing/safe.rb +93 -39
- data/lib/seeing_is_believing/the_matrix.rb +10 -10
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/wrap_expressions.rb +24 -5
- data/spec/binary/config_spec.rb +17 -2
- data/spec/event_stream_spec.rb +1 -0
- data/spec/seeing_is_believing_spec.rb +58 -53
- data/spec/spec_helper.rb +22 -0
- data/spec/spec_helper_spec.rb +16 -0
- data/spec/wrap_expressions_spec.rb +35 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9dd0b2eff60a43943a68255a2278300ad4d687d
|
4
|
+
data.tar.gz: c85b26392092e308c2a2dc0fdbaf41371da88a8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21a4e75fa8f2191b74c4305e879f5e53ad67680c3091089a83d0af64cfecc687ef86e1ebd76341717710d18e9c2d57479f0b11017f28cd8cf42da60d4092ecff
|
7
|
+
data.tar.gz: 2afc31b2a89c7f6d0a4ee544b8eb8acdcfceef34c4ae6fce57a0c46f30d2501117fa45628f2100849332715f80bd85d3927bbc4cfab81d34093ad9d67ee98eaf
|
data/Gemfile
CHANGED
data/features/flags.feature
CHANGED
@@ -528,3 +528,42 @@ Feature: Using flags
|
|
528
528
|
Then the exit status is 0
|
529
529
|
And stderr is empty
|
530
530
|
And stdout is "1 # => 1"
|
531
|
+
|
532
|
+
Scenario: --interline-align and --no-interline-align determine whether adjacent lines with the same number of results get lined up, it defaults to --align
|
533
|
+
Given the file "interline_alignment.rb":
|
534
|
+
"""
|
535
|
+
3.times do |num|
|
536
|
+
num
|
537
|
+
.to_s
|
538
|
+
end
|
539
|
+
"""
|
540
|
+
When I run "seeing_is_believing interline_alignment.rb"
|
541
|
+
Then stderr is empty
|
542
|
+
And the exit status is 0
|
543
|
+
And stdout is:
|
544
|
+
"""
|
545
|
+
3.times do |num| # => 3
|
546
|
+
num # => 0, 1, 2
|
547
|
+
.to_s # => "0", "1", "2"
|
548
|
+
end # => 3
|
549
|
+
"""
|
550
|
+
When I run "seeing_is_believing --interline-align interline_alignment.rb"
|
551
|
+
Then stderr is empty
|
552
|
+
And the exit status is 0
|
553
|
+
And stdout is:
|
554
|
+
"""
|
555
|
+
3.times do |num| # => 3
|
556
|
+
num # => 0, 1, 2
|
557
|
+
.to_s # => "0", "1", "2"
|
558
|
+
end # => 3
|
559
|
+
"""
|
560
|
+
When I run "seeing_is_believing --no-interline-align interline_alignment.rb"
|
561
|
+
Then stderr is empty
|
562
|
+
And the exit status is 0
|
563
|
+
And stdout is:
|
564
|
+
"""
|
565
|
+
3.times do |num| # => 3
|
566
|
+
num # => 0, 1, 2
|
567
|
+
.to_s # => "0", "1", "2"
|
568
|
+
end # => 3
|
569
|
+
"""
|
data/features/regression.feature
CHANGED
@@ -503,3 +503,157 @@ Feature:
|
|
503
503
|
__END__
|
504
504
|
"""
|
505
505
|
|
506
|
+
@not-implemented
|
507
|
+
Scenario: Interpolating in a heredoc and walking backwards with xmpfilter style to figure out which expression to record (#83)
|
508
|
+
Given the file "heredoc_woes.rb":
|
509
|
+
"""
|
510
|
+
<<-HERE # =>
|
511
|
+
1#{1+1}3
|
512
|
+
HERE
|
513
|
+
# =>
|
514
|
+
"""
|
515
|
+
When I run "seeing_is_believing -x heredoc_woes.rb"
|
516
|
+
Then stdout is:
|
517
|
+
"""
|
518
|
+
<<-HERE # => "123\n"
|
519
|
+
1#{1+1}3
|
520
|
+
HERE
|
521
|
+
# => "123\n"
|
522
|
+
"""
|
523
|
+
|
524
|
+
Scenario: Executing correctly in a hostile world
|
525
|
+
Given the file "hostile_world.rb":
|
526
|
+
"""
|
527
|
+
# SiB works, but Ruby will explode while trying to make the exception
|
528
|
+
# if we do it later, so we'll make it up here
|
529
|
+
zde = (1/0 rescue $!)
|
530
|
+
|
531
|
+
if RUBY_VERSION != "2.0.0" # this breaks Ruby itself on v2.0.0
|
532
|
+
class Hash
|
533
|
+
undef []
|
534
|
+
undef []=
|
535
|
+
undef fetch
|
536
|
+
end
|
537
|
+
end
|
538
|
+
class IO
|
539
|
+
undef sync
|
540
|
+
undef <<
|
541
|
+
undef flush
|
542
|
+
undef puts
|
543
|
+
undef close
|
544
|
+
end
|
545
|
+
class Queue
|
546
|
+
undef <<
|
547
|
+
undef shift
|
548
|
+
undef clear
|
549
|
+
end
|
550
|
+
class Symbol
|
551
|
+
undef ==
|
552
|
+
undef to_s
|
553
|
+
undef inspect
|
554
|
+
end
|
555
|
+
class String
|
556
|
+
undef ==
|
557
|
+
undef to_s
|
558
|
+
undef to_str
|
559
|
+
undef inspect
|
560
|
+
undef to_i
|
561
|
+
end
|
562
|
+
class Fixnum
|
563
|
+
undef <
|
564
|
+
undef <<
|
565
|
+
undef ==
|
566
|
+
def next # "redefining instead of undefing b/c it comes from Integer"
|
567
|
+
end
|
568
|
+
undef to_s
|
569
|
+
undef inspect
|
570
|
+
end
|
571
|
+
class Array
|
572
|
+
undef pack
|
573
|
+
undef <<
|
574
|
+
undef to_ary
|
575
|
+
undef grep
|
576
|
+
undef first
|
577
|
+
undef []
|
578
|
+
undef []=
|
579
|
+
undef each
|
580
|
+
undef map
|
581
|
+
undef join
|
582
|
+
undef size
|
583
|
+
undef to_s
|
584
|
+
end
|
585
|
+
class << Marshal
|
586
|
+
undef dump
|
587
|
+
undef load
|
588
|
+
end
|
589
|
+
module Kernel
|
590
|
+
undef kind_of?
|
591
|
+
undef block_given?
|
592
|
+
end
|
593
|
+
module Enumerable
|
594
|
+
undef map
|
595
|
+
end
|
596
|
+
class SystemExit
|
597
|
+
undef status
|
598
|
+
end
|
599
|
+
class Exception
|
600
|
+
undef message
|
601
|
+
# undef backtrace # https://bugs.ruby-lang.org/issues/12925
|
602
|
+
def class
|
603
|
+
"totally the wrong thing"
|
604
|
+
end
|
605
|
+
end
|
606
|
+
class << Thread
|
607
|
+
undef new
|
608
|
+
undef current
|
609
|
+
end
|
610
|
+
class Thread
|
611
|
+
undef join
|
612
|
+
undef abort_on_exception
|
613
|
+
end
|
614
|
+
class Class
|
615
|
+
undef new
|
616
|
+
undef allocate
|
617
|
+
undef singleton_class
|
618
|
+
undef class_eval
|
619
|
+
end
|
620
|
+
class BasicObject
|
621
|
+
undef initialize
|
622
|
+
end
|
623
|
+
class Module
|
624
|
+
undef ===
|
625
|
+
undef define_method
|
626
|
+
undef instance_method
|
627
|
+
end
|
628
|
+
class UnboundMethod
|
629
|
+
undef bind
|
630
|
+
end
|
631
|
+
class Method
|
632
|
+
undef call
|
633
|
+
end
|
634
|
+
class Proc
|
635
|
+
undef call
|
636
|
+
undef to_proc
|
637
|
+
end
|
638
|
+
class NilClass
|
639
|
+
undef to_s
|
640
|
+
end
|
641
|
+
|
642
|
+
# ---
|
643
|
+
|
644
|
+
class Zomg
|
645
|
+
end
|
646
|
+
|
647
|
+
Zomg # =>
|
648
|
+
class << Zomg
|
649
|
+
attr_accessor :inspect
|
650
|
+
end
|
651
|
+
Zomg.inspect = "lolol"
|
652
|
+
Zomg # =>
|
653
|
+
raise zde
|
654
|
+
"""
|
655
|
+
When I run "seeing_is_believing -x hostile_world.rb"
|
656
|
+
Then stdout includes 'Zomg # => Zomg'
|
657
|
+
And stdout includes 'Zomg # => lolol'
|
658
|
+
And stdout includes '# ~> ZeroDivisionError'
|
659
|
+
And stdout includes '# ~> divided by 0'
|
@@ -72,6 +72,24 @@ Feature: Xmpfilter style
|
|
72
72
|
# :wibble=>{:magic_word=>"xyzzy"}}
|
73
73
|
"""
|
74
74
|
|
75
|
+
Scenario: --xmpfilter-style, when displayed on the next line, prints the string across multiple lines
|
76
|
+
Given the file "xmpfilter-prev-line-is-multiline-string.rb":
|
77
|
+
"""
|
78
|
+
"0123456789\nabcdefghij\n0123456789\n0123456789\n0123456789\n0123456789\n" # =>
|
79
|
+
# =>
|
80
|
+
"""
|
81
|
+
When I run "seeing_is_believing --xmpfilter-style xmpfilter-prev-line-is-multiline-string.rb"
|
82
|
+
Then stdout is:
|
83
|
+
"""
|
84
|
+
"0123456789\nabcdefghij\n0123456789\n0123456789\n0123456789\n0123456789\n" # => "0123456789\nabcdefghij\n0123456789\n0123456789\n0123456789\n0123456789\n"
|
85
|
+
# => "0123456789\n" +
|
86
|
+
# "abcdefghij\n" +
|
87
|
+
# "0123456789\n" +
|
88
|
+
# "0123456789\n" +
|
89
|
+
# "0123456789\n" +
|
90
|
+
# "0123456789\n"
|
91
|
+
"""
|
92
|
+
|
75
93
|
Scenario: --xmpfilter-style overrides previous multiline results
|
76
94
|
Given the file "xmpfilter-prev-line2.rb":
|
77
95
|
"""
|
@@ -410,3 +428,42 @@ Feature: Xmpfilter style
|
|
410
428
|
# ~>
|
411
429
|
# ~> xm...
|
412
430
|
"""
|
431
|
+
|
432
|
+
Scenario: --interline-align and --no-interline-align determine whether adjacent lines with the same number of results get lined up, it defaults to --align
|
433
|
+
Given the file "xmpfilter_interline_alignment.rb":
|
434
|
+
"""
|
435
|
+
3.times do |num|
|
436
|
+
num # =>
|
437
|
+
.to_s # =>
|
438
|
+
end
|
439
|
+
"""
|
440
|
+
When I run "seeing_is_believing -x xmpfilter_interline_alignment.rb"
|
441
|
+
Then stderr is empty
|
442
|
+
And the exit status is 0
|
443
|
+
And stdout is:
|
444
|
+
"""
|
445
|
+
3.times do |num|
|
446
|
+
num # => 0, 1, 2
|
447
|
+
.to_s # => "0", "1", "2"
|
448
|
+
end
|
449
|
+
"""
|
450
|
+
When I run "seeing_is_believing -x --interline-align xmpfilter_interline_alignment.rb"
|
451
|
+
Then stderr is empty
|
452
|
+
And the exit status is 0
|
453
|
+
And stdout is:
|
454
|
+
"""
|
455
|
+
3.times do |num|
|
456
|
+
num # => 0, 1, 2
|
457
|
+
.to_s # => "0", "1", "2"
|
458
|
+
end
|
459
|
+
"""
|
460
|
+
When I run "seeing_is_believing -x --no-interline-align xmpfilter_interline_alignment.rb"
|
461
|
+
Then stderr is empty
|
462
|
+
And the exit status is 0
|
463
|
+
And stdout is:
|
464
|
+
"""
|
465
|
+
3.times do |num|
|
466
|
+
num # => 0, 1, 2
|
467
|
+
.to_s # => "0", "1", "2"
|
468
|
+
end
|
469
|
+
"""
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'seeing_is_believing/binary/interline_align'
|
2
|
+
|
1
3
|
class SeeingIsBelieving
|
2
4
|
module Binary
|
3
5
|
class AnnotateEveryLine
|
@@ -6,9 +8,10 @@ class SeeingIsBelieving
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def initialize(body, results, options={})
|
9
|
-
@options
|
10
|
-
@body
|
11
|
-
@results
|
11
|
+
@options = options
|
12
|
+
@body = body
|
13
|
+
@results = results
|
14
|
+
@interline_align = InterlineAlign.new(results)
|
12
15
|
end
|
13
16
|
|
14
17
|
def call
|
@@ -26,7 +29,11 @@ class SeeingIsBelieving
|
|
26
29
|
result = sprintf "%s: %s", @results.exception.class_name, @results.exception.message.gsub("\n", '\n')
|
27
30
|
FormatComment.call(line.size, exception_text, result, options)
|
28
31
|
elsif @results[line_number].any?
|
29
|
-
|
32
|
+
if @options[:interline_align]
|
33
|
+
result = @interline_align.call line_number, @results[line_number].map { |result| result.gsub "\n", '\n' }
|
34
|
+
else
|
35
|
+
result = @results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
|
36
|
+
end
|
30
37
|
FormatComment.call(line.size, value_text, result, options)
|
31
38
|
else
|
32
39
|
''
|
@@ -82,9 +82,10 @@ class SeeingIsBelieving
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def initialize(body, results, options={})
|
85
|
-
@options
|
86
|
-
@body
|
87
|
-
@results
|
85
|
+
@options = options
|
86
|
+
@body = body
|
87
|
+
@results = results
|
88
|
+
@interline_align = InterlineAlign.new(results)
|
88
89
|
end
|
89
90
|
|
90
91
|
# seems like maybe this should respect the alignment strategy (not what xmpfilter does, but there are other ways I'd like to deviate anyway)
|
@@ -114,8 +115,13 @@ class SeeingIsBelieving
|
|
114
115
|
whitespace = " " if whitespace.empty?
|
115
116
|
[whitespace, FormatComment.call(0, exception_prefix, exception_result, @options)]
|
116
117
|
elsif normal_annotation
|
117
|
-
|
118
|
-
|
118
|
+
if @options[:interline_align]
|
119
|
+
annotation = @interline_align.call comment.line_number, @results[comment.line_number].map { |result| result.gsub "\n", '\n' }
|
120
|
+
[comment.whitespace, FormatComment.call(comment.text_col, value_prefix, annotation, @options)]
|
121
|
+
else
|
122
|
+
annotation = @results[comment.line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
|
123
|
+
[comment.whitespace, FormatComment.call(comment.text_col, value_prefix, annotation, @options)]
|
124
|
+
end
|
119
125
|
elsif pp_annotation
|
120
126
|
result = @results[pp_map[comment.line_number], :pp]
|
121
127
|
annotation = result.map { |result| result.chomp }.join("\n,") # ["1\n2", "1\n2", ...
|
@@ -102,6 +102,7 @@ class SeeingIsBelieving
|
|
102
102
|
self.lib_options.rewrite_code = AnnotateMarkedLines.code_rewriter(markers)
|
103
103
|
self.remove_value_prefixes = false
|
104
104
|
self.lib_options.require_files << 'pp'
|
105
|
+
self.lib_options.require_files << 'seeing_is_believing/customize_pp'
|
105
106
|
|
106
107
|
when '-i', '--inherit-exitstatus', '--inherit-exit-status'
|
107
108
|
self.inherit_exitstatus = true
|
@@ -186,6 +187,12 @@ class SeeingIsBelieving
|
|
186
187
|
end
|
187
188
|
end
|
188
189
|
|
190
|
+
when '--interline-align'
|
191
|
+
self.annotator_options.interline_align = true
|
192
|
+
|
193
|
+
when '--no-interline-align'
|
194
|
+
self.annotator_options.interline_align = false
|
195
|
+
|
189
196
|
when '--shebang'
|
190
197
|
executable = args.shift
|
191
198
|
if executable
|
@@ -301,6 +308,8 @@ Options:
|
|
301
308
|
chunk (DEFAULT) => each chunk of code is at the same alignment
|
302
309
|
file => the entire file is at the same alignment
|
303
310
|
line => each line is at its own alignment
|
311
|
+
--[no-]-interline-align # align results on adjacent lines when they have the same number of results
|
312
|
+
defautls to --align
|
304
313
|
-t, --timeout-seconds s # how long to evaluate the source file before timing out
|
305
314
|
0 means it will never timeout (this is the default)
|
306
315
|
accepts floating point values (e.g. 0.5 would timeout after half a second)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class SeeingIsBelieving
|
2
|
+
module Binary
|
3
|
+
class InterlineAlign
|
4
|
+
def initialize(results)
|
5
|
+
@results = results
|
6
|
+
@format_strings = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(lineno, results)
|
10
|
+
format_string_for_line(lineno) % results
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_accessor :results
|
16
|
+
|
17
|
+
def format_string_for_line(lineno)
|
18
|
+
group = groups_with_same_number_of_results(@results)[lineno]
|
19
|
+
format_string_for(results, group, lineno)
|
20
|
+
end
|
21
|
+
|
22
|
+
def groups_with_same_number_of_results(results)
|
23
|
+
@grouped_by_no_results ||= begin
|
24
|
+
length = 0
|
25
|
+
groups = 1.upto(results.num_lines)
|
26
|
+
.slice_before { |num|
|
27
|
+
new_length = results[num].length
|
28
|
+
slice = length != new_length
|
29
|
+
length = new_length
|
30
|
+
slice
|
31
|
+
}.to_a
|
32
|
+
|
33
|
+
groups.each_with_object Hash.new do |group, lineno_to_group|
|
34
|
+
group.each { |lineno| lineno_to_group[lineno] = group }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def format_string_for(results, group, lineno)
|
40
|
+
@format_strings[lineno] ||= begin
|
41
|
+
index = group.index lineno
|
42
|
+
group
|
43
|
+
.map { |lineno| results[lineno] }
|
44
|
+
.transpose
|
45
|
+
.map { |col|
|
46
|
+
lengths = col.map(&:length)
|
47
|
+
max = lengths.max
|
48
|
+
crnt = lengths[index]
|
49
|
+
"%-#{crnt}s,#{" "*(max-crnt)} "
|
50
|
+
}
|
51
|
+
.join
|
52
|
+
.sub(/, *$/, "")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|