seeing_is_believing 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Readme.md +62 -1
- data/features/xmpfilter-style.feature +46 -0
- data/lib/seeing_is_believing/binary/annotate_marked_lines.rb +36 -14
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/wrap_expressions.rb +14 -2
- data/spec/wrap_expressions_spec.rb +21 -16
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae473580cc4e716bb259237bd9a3f9f0e3983591
|
4
|
+
data.tar.gz: ac008a8042513f1facb360b0056c68f62abc29bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1d3d802588b733162f26ef0a55985b9dd1987759f96f45e6af5de45ba531654fb6e92a2db8c6498ce4fc6a8ed0dee44bbc9bbac0d3d01e98b698e903484d186
|
7
|
+
data.tar.gz: 7268519db2a550356f6ca29044ac68177678dd6509f9bcdcd6f24c23676eae14d79167b8a88ee5cb3aa84ce0e76d6ae87259127c4390863863c5ae442af2845d
|
data/Readme.md
CHANGED
@@ -44,12 +44,73 @@ end
|
|
44
44
|
`$ seeing_is_believing simple_example.rb` will print:
|
45
45
|
|
46
46
|
```ruby
|
47
|
-
|
48
47
|
5.times do |i| # => 5
|
49
48
|
i * 2 # => 0, 2, 4, 6, 8
|
50
49
|
end # => 5
|
51
50
|
```
|
52
51
|
|
52
|
+
`$ seeing_is_believing simple_example.rb --json` will print:
|
53
|
+
|
54
|
+
```json
|
55
|
+
{"stdout":"","stderr":"","exitstatus":0,"exception":null,"lines":{"1":["5"],"2":["0","2","4","6","8"],"3":["5"]}}
|
56
|
+
```
|
57
|
+
|
58
|
+
Protips
|
59
|
+
=======
|
60
|
+
|
61
|
+
These things have been useful for integrating.
|
62
|
+
|
63
|
+
If you want to execute from some specific dir (eg if your editor is in the wrong dir)
|
64
|
+
try using `Dir.chdir` at the top of the script.
|
65
|
+
Eg I used that [here](https://github.com/JoshCheek/seeing_is_believing/issues/58#issuecomment-91600783)
|
66
|
+
so I could run with a full Rails app available in "Completely against the real env".
|
67
|
+
|
68
|
+
If you want some specific file to be available in that environment, require the fullpath to the file.
|
69
|
+
Eg I used that [here](https://github.com/JoshCheek/seeing_is_believing/issues/58#issuecomment-91600783)
|
70
|
+
to load up the Rils schema in "Running against the real schema".
|
71
|
+
|
72
|
+
You can also set the `$LOAD_PATH` to a gem you're working on and then require files as if
|
73
|
+
it was installed.
|
74
|
+
|
75
|
+
You work with `gets` by setting `$stdin` to the `DATA` segment and writing inputs there.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
$stdin = DATA
|
79
|
+
|
80
|
+
puts "What's your name?"
|
81
|
+
name = gets.chomp
|
82
|
+
puts "What's your favourite colour?"
|
83
|
+
colour = gets.chomp
|
84
|
+
puts "#{name}'s favourite colour is #{colour}."
|
85
|
+
|
86
|
+
# >> What's your name?
|
87
|
+
# >> What's your favourite colour?
|
88
|
+
# >> Josh's favourite colour is brown.
|
89
|
+
|
90
|
+
__END__
|
91
|
+
Josh
|
92
|
+
brown
|
93
|
+
```
|
94
|
+
|
95
|
+
Rescue lines you expect to explode so that it displays the expected result and continues evaluating.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
lambda { |x| x }.call() rescue $! # => #<ArgumentError: wrong number of arguments (given 0, expected 1)>
|
99
|
+
lambda { |x| x }.call(1) # => 1
|
100
|
+
lambda { |x| x }.call(1, 2) rescue $! # => #<ArgumentError: wrong number of arguments (given 2, expected 1)>
|
101
|
+
```
|
102
|
+
|
103
|
+
Use `fork` to look at what a program does when run two different ways.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class A
|
107
|
+
fork && raise("omg") # => nil
|
108
|
+
rescue
|
109
|
+
$! # => #<RuntimeError: omg>
|
110
|
+
else
|
111
|
+
:nothing_raised # => :nothing_raised
|
112
|
+
end # => #<RuntimeError: omg>, :nothing_raised
|
113
|
+
```
|
53
114
|
|
54
115
|
Use The Lib
|
55
116
|
===========
|
@@ -319,6 +319,52 @@ Feature: Xmpfilter style
|
|
319
319
|
"""
|
320
320
|
|
321
321
|
|
322
|
+
Scenario: When there are no results for the previous line it looks further back (#77)
|
323
|
+
Given the file "heredocs_and_blank_lines.rb":
|
324
|
+
"""
|
325
|
+
# =>
|
326
|
+
|
327
|
+
<<DOC
|
328
|
+
1
|
329
|
+
DOC
|
330
|
+
# =>
|
331
|
+
|
332
|
+
2
|
333
|
+
|
334
|
+
# =>
|
335
|
+
|
336
|
+
if true
|
337
|
+
3
|
338
|
+
# =>
|
339
|
+
else
|
340
|
+
4
|
341
|
+
# =>
|
342
|
+
end
|
343
|
+
"""
|
344
|
+
When I run "seeing_is_believing --xmpfilter-style heredocs_and_blank_lines.rb"
|
345
|
+
Then stdout is:
|
346
|
+
"""
|
347
|
+
# =>
|
348
|
+
|
349
|
+
<<DOC
|
350
|
+
1
|
351
|
+
DOC
|
352
|
+
# => "1\n"
|
353
|
+
|
354
|
+
2
|
355
|
+
|
356
|
+
# => 2
|
357
|
+
|
358
|
+
if true
|
359
|
+
3
|
360
|
+
# => 3
|
361
|
+
else
|
362
|
+
4
|
363
|
+
# =>
|
364
|
+
end
|
365
|
+
"""
|
366
|
+
|
367
|
+
|
322
368
|
|
323
369
|
Scenario: Xmpfilter uses the same comment formatting as normal
|
324
370
|
Given the file "xmpfilter_result_lengths.rb":
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'seeing_is_believing/code'
|
3
3
|
|
4
|
-
|
5
4
|
# *sigh* need to find a way to join the annotators.
|
6
5
|
# They are sinful ugly, kinda hard to work with,
|
7
6
|
# and absurdly duplicated.
|
@@ -11,16 +10,37 @@ class SeeingIsBelieving
|
|
11
10
|
# Based on the behaviour of xmpfilger (a binary in the rcodetools gem)
|
12
11
|
# See https://github.com/JoshCheek/seeing_is_believing/issues/44 for more details
|
13
12
|
class AnnotateMarkedLines
|
13
|
+
def self.map_markers_to_linenos(program, markers)
|
14
|
+
value_regex = markers[:value][:regex]
|
15
|
+
recordable_lines = []
|
16
|
+
inspect_linenos = []
|
17
|
+
pp_map = {}
|
18
|
+
WrapExpressions.call program, before_each: -> line_number {
|
19
|
+
recordable_lines << line_number
|
20
|
+
''
|
21
|
+
}
|
22
|
+
|
23
|
+
Code.new(program).inline_comments.each do |c|
|
24
|
+
next unless c.text[value_regex]
|
25
|
+
if c.whitespace_col == 0
|
26
|
+
lineno = c.line_number
|
27
|
+
loop do
|
28
|
+
lineno -= 1
|
29
|
+
break if recordable_lines.include?(lineno) || lineno.zero?
|
30
|
+
end
|
31
|
+
pp_map[c.line_number] = lineno
|
32
|
+
else
|
33
|
+
inspect_linenos << c.line_number
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
return inspect_linenos, pp_map
|
38
|
+
end
|
39
|
+
|
14
40
|
def self.code_rewriter(markers)
|
15
41
|
lambda do |program|
|
16
|
-
inspect_linenos =
|
17
|
-
pp_linenos
|
18
|
-
value_regex = markers[:value][:regex]
|
19
|
-
Code.new(program).inline_comments.each do |c|
|
20
|
-
next unless c.text[value_regex]
|
21
|
-
c.whitespace_col == 0 ? pp_linenos << c.line_number - 1
|
22
|
-
: inspect_linenos << c.line_number
|
23
|
-
end
|
42
|
+
inspect_linenos, pp_map = map_markers_to_linenos(program, markers)
|
43
|
+
pp_linenos = pp_map.values
|
24
44
|
|
25
45
|
should_inspect = false
|
26
46
|
should_pp = false
|
@@ -81,6 +101,7 @@ class SeeingIsBelieving
|
|
81
101
|
include_lines << exception_lineno
|
82
102
|
end
|
83
103
|
|
104
|
+
_, pp_map = self.class.map_markers_to_linenos(@body, @options[:markers])
|
84
105
|
new_body = RewriteComments.call @body, include_lines: include_lines do |comment|
|
85
106
|
exception_on_line = exception_lineno == comment.line_number
|
86
107
|
annotate_this_line = comment.text[value_regex]
|
@@ -93,12 +114,13 @@ class SeeingIsBelieving
|
|
93
114
|
whitespace = " " if whitespace.empty?
|
94
115
|
[whitespace, FormatComment.call(0, exception_prefix, exception_result, @options)]
|
95
116
|
elsif normal_annotation
|
96
|
-
|
97
|
-
[comment.whitespace, FormatComment.call(comment.text_col, value_prefix,
|
117
|
+
annotation = @results[comment.line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
|
118
|
+
[comment.whitespace, FormatComment.call(comment.text_col, value_prefix, annotation, @options)]
|
98
119
|
elsif pp_annotation
|
99
|
-
result
|
100
|
-
|
101
|
-
|
120
|
+
result = @results[pp_map[comment.line_number], :pp]
|
121
|
+
annotation = result.map { |result| result.chomp }.join("\n,") # ["1\n2", "1\n2", ...
|
122
|
+
swap_leading_whitespace_in_multiline_comment(annotation)
|
123
|
+
comment_lines = annotation.each_line.map.with_index do |comment_line, result_offest|
|
102
124
|
if result_offest == 0
|
103
125
|
FormatComment.call(comment.whitespace_col, value_prefix, comment_line.chomp, @options)
|
104
126
|
else
|
@@ -98,11 +98,17 @@ class SeeingIsBelieving
|
|
98
98
|
case ast.type
|
99
99
|
when :args, :redo, :retry, :alias, :undef, :null_node
|
100
100
|
# no op
|
101
|
-
when :defs, :
|
101
|
+
when :defs, :module
|
102
102
|
add_to_wrappings ast
|
103
103
|
add_children ast, true
|
104
104
|
when :rescue, :ensure, :return, :break, :next, :splat, :kwsplat
|
105
105
|
add_children ast
|
106
|
+
when :class
|
107
|
+
name, * = ast.children
|
108
|
+
namespace, * = name.children
|
109
|
+
add_to_wrappings ast
|
110
|
+
wrap_recursive namespace
|
111
|
+
add_children ast, true
|
106
112
|
when :if
|
107
113
|
if ast.location.kind_of? Parser::Source::Map::Ternary
|
108
114
|
add_to_wrappings ast unless ast.children.any? { |child| code.void_value? child }
|
@@ -196,8 +202,14 @@ class SeeingIsBelieving
|
|
196
202
|
add_to_wrappings ast
|
197
203
|
end
|
198
204
|
add_children ast
|
199
|
-
when :str
|
205
|
+
when :str
|
206
|
+
add_to_wrappings ast
|
207
|
+
|
208
|
+
when :dstr, :regexp
|
200
209
|
add_to_wrappings ast
|
210
|
+
ast.children
|
211
|
+
.select { |child| child.type == :begin }
|
212
|
+
.each { |child| add_children child }
|
201
213
|
|
202
214
|
when :hash
|
203
215
|
# method arguments might not have braces around them
|
@@ -217,9 +217,9 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
217
217
|
expect(wrap("alias $a $b")).to eq "alias $a $b"
|
218
218
|
end
|
219
219
|
|
220
|
-
it 'wraps syscalls,
|
220
|
+
it 'wraps syscalls, and the code interpolated into them' do
|
221
221
|
expect(wrap("`a\nb`")).to eq "<`a\nb`>"
|
222
|
-
expect(wrap("`a\n\#{1\n2\n3}b`")).to eq "<`a\n\#{1
|
222
|
+
expect(wrap("`a\n\#{1\n2\n3}b`")).to eq "<`a\n\#{<1>\n<2>\n3}b`>"
|
223
223
|
end
|
224
224
|
end
|
225
225
|
|
@@ -586,12 +586,10 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
586
586
|
expect(wrap("/a\nb/i")).to eq "</a\nb/i>"
|
587
587
|
end
|
588
588
|
|
589
|
-
|
590
|
-
# when the end of the line was not back inside the regexp
|
591
|
-
it 'wraps regexes with interpolation, but not the interpolated portion' do
|
589
|
+
it 'wraps regexes with interpolation, including the interpolated portion' do
|
592
590
|
expect(wrap("/a\#{1}/")).to eq "</a\#{1}/>"
|
593
|
-
expect(wrap("/a\n\#{1}\nb/")).to eq "</a\n\#{1}\nb/>"
|
594
|
-
expect(wrap("/a\n\#{1\n}b/")).to eq "</a\n\#{1
|
591
|
+
expect(wrap("/a\n\#{1}\nb/")).to eq "</a\n\#{<1>}\nb/>"
|
592
|
+
expect(wrap("/a\n\#{1\n}b/")).to eq "</a\n\#{<1>\n}b/>"
|
595
593
|
end
|
596
594
|
end
|
597
595
|
|
@@ -612,12 +610,10 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
612
610
|
expect(wrap(%'"a\nb"')).to eq %'<"a\nb">'
|
613
611
|
end
|
614
612
|
|
615
|
-
|
616
|
-
# when the end of the line was not back inside the string
|
617
|
-
it 'wraps strings with interpolation, but not the interpolated portion' do
|
613
|
+
it 'wraps strings with interpolation, including the interpolated portion' do
|
618
614
|
expect(wrap('"a#{1}"')).to eq '<"a#{1}">'
|
619
|
-
expect(wrap(%'"a\n\#{1}\nb"')).to eq %'<"a\n\#{1}\nb">'
|
620
|
-
expect(wrap(%'"a\n\#{1\n}b"')).to eq %'<"a\n\#{1
|
615
|
+
expect(wrap(%'"a\n\#{1}\nb"')).to eq %'<"a\n\#{<1>}\nb">'
|
616
|
+
expect(wrap(%'"a\n\#{1\n}b"')).to eq %'<"a\n\#{<1>\n}b">'
|
621
617
|
end
|
622
618
|
|
623
619
|
it 'wraps %, %q, %Q' do
|
@@ -709,21 +705,30 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
709
705
|
end
|
710
706
|
|
711
707
|
describe 'class definitions' do
|
712
|
-
it 'does
|
708
|
+
it 'does wraps the class definition, and body' do
|
713
709
|
expect(wrap("class A\n1\nend")).to eq "<class A\n<1>\nend>"
|
714
710
|
end
|
715
711
|
|
716
|
-
it 'does
|
712
|
+
it 'does wraps the superclass definition' do
|
717
713
|
expect(wrap("class A < B\nend")).to eq "<class A < <B>\nend>"
|
718
714
|
end
|
719
715
|
|
720
|
-
it 'wraps the rescue body' do
|
716
|
+
it 'wraps the rescue, else, ensure body' do
|
717
|
+
expect(wrap("class A < B\n1\nrescue\n2\nelse\n3\nensure\n4\nend")).to eq "<class A < <B>\n<1>\nrescue\n<2>\nelse\n<3>\nensure\n<4>\nend>"
|
718
|
+
end
|
719
|
+
|
720
|
+
it 'wraps the else body' do
|
721
721
|
expect(wrap("class A < B\n1\nrescue\n2\nend")).to eq "<class A < <B>\n<1>\nrescue\n<2>\nend>"
|
722
722
|
end
|
723
723
|
|
724
|
-
it '
|
724
|
+
it 'wraps the singleton class' do
|
725
725
|
expect(wrap("class << self\n end")).to eq "<class << <self>\n end>"
|
726
726
|
end
|
727
|
+
|
728
|
+
it 'wraps the namespace' do
|
729
|
+
expect(wrap("class A::B\nend")).to eq "<class <A>::B\nend>"
|
730
|
+
expect(wrap("class (\n1\nObject\n)::String\nend")).to eq "<class <(\n<1>\n<Object>\n)>::String\nend>"
|
731
|
+
end
|
727
732
|
end
|
728
733
|
|
729
734
|
describe 'module definitions' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seeing_is_believing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Cheek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -261,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
261
|
version: '0'
|
262
262
|
requirements: []
|
263
263
|
rubyforge_project: seeing_is_believing
|
264
|
-
rubygems_version: 2.
|
264
|
+
rubygems_version: 2.5.1
|
265
265
|
signing_key:
|
266
266
|
specification_version: 4
|
267
267
|
summary: Records results of every line of code in your file
|