seeing_is_believing 0.0.4 → 0.0.5
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/Rakefile +29 -0
- data/bin/seeing_is_believing +3 -12
- data/features/binary_errors.feature +44 -0
- data/features/{binary.feature → binary_examples.feature} +43 -20
- data/lib/seeing_is_believing/binary.rb +52 -0
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +1 -2
- data/lib/seeing_is_believing/expression_list.rb +1 -0
- data/lib/seeing_is_believing/{example_use.rb → print_results_next_to_lines.rb} +1 -1
- data/lib/seeing_is_believing/result.rb +21 -2
- data/lib/seeing_is_believing/the_matrix.rb +1 -2
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing.rb +1 -1
- data/spec/expression_list_spec.rb +11 -0
- data/spec/seeing_is_believing_spec.rb +9 -8
- data/spec/syntax_analyzer_spec.rb +4 -2
- metadata +15 -11
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
desc 'run specs'
|
2
|
+
task :spec do
|
3
|
+
sh 'rspec -cf d --fail-fast'
|
4
|
+
end
|
5
|
+
|
6
|
+
desc 'run cukes'
|
7
|
+
task :cuke do
|
8
|
+
sh 'cucumber -t ~@not-implemented -t ~@wip'
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :cuke do
|
12
|
+
desc 'Run work in progress cukes'
|
13
|
+
task :wip do
|
14
|
+
sh 'cucumber -t @wip'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
namespace :spec do
|
19
|
+
desc 'Run work in progress specs'
|
20
|
+
task :wip do
|
21
|
+
sh 'rspec -t wip'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Run work in progress specs and cukes'
|
26
|
+
task wip: ['spec:wip', 'cuke:wip']
|
27
|
+
|
28
|
+
desc 'Run all specs and cukes'
|
29
|
+
task default: [:spec, :cuke]
|
data/bin/seeing_is_believing
CHANGED
@@ -1,17 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path '../../lib', __FILE__
|
4
|
-
require 'seeing_is_believing/example_use'
|
5
4
|
|
6
|
-
|
5
|
+
require 'open3'
|
6
|
+
require 'seeing_is_believing/binary'
|
7
7
|
|
8
|
-
ARGV
|
9
|
-
believer = SeeingIsBelieving::ExampleUse.new File.read(filename), filename
|
10
|
-
$stdout.puts believer.call
|
11
|
-
if believer.has_exception?
|
12
|
-
$stderr.puts believer.exception.message
|
13
|
-
status = 1
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
exit status
|
8
|
+
exit SeeingIsBelieving::Binary.new(ARGV, $stdin, $stdout, $stderr).exitstatus
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Feature: Running the binary unsuccessfully
|
2
|
+
|
3
|
+
Sometimes I mess up and use the program in a way that doesn't work.
|
4
|
+
I'd like it to be helpful in these situations so I can fix my use.
|
5
|
+
|
6
|
+
Scenario: Raising exceptions
|
7
|
+
Given the file "raises_exception.rb":
|
8
|
+
"""
|
9
|
+
raise "ZOMG!"
|
10
|
+
"""
|
11
|
+
And the file "requires_exception_raising_code.rb":
|
12
|
+
"""
|
13
|
+
1 + 1
|
14
|
+
require_relative 'raises_exception'
|
15
|
+
1 + 1
|
16
|
+
"""
|
17
|
+
When I run "seeing_is_believing requires_exception_raising_code.rb"
|
18
|
+
Then stderr is "ZOMG!"
|
19
|
+
And the exit status is 1
|
20
|
+
And stdout is:
|
21
|
+
"""
|
22
|
+
1 + 1 # => 2
|
23
|
+
require_relative 'raises_exception' # ~> RuntimeError: ZOMG!
|
24
|
+
1 + 1
|
25
|
+
"""
|
26
|
+
|
27
|
+
Scenario: Syntactically invalid file
|
28
|
+
Given the file "invalid_syntax.rb":
|
29
|
+
"""
|
30
|
+
'abc
|
31
|
+
"""
|
32
|
+
When I run "seeing_is_believing invalid_syntax.rb"
|
33
|
+
Then stderr is:
|
34
|
+
"""
|
35
|
+
invalid_syntax.rb:1: unterminated string meets end of file
|
36
|
+
"""
|
37
|
+
And the exit status is 1
|
38
|
+
And stdout is empty
|
39
|
+
|
40
|
+
Scenario: Passing a nonexistent file
|
41
|
+
When I run "seeing_is_believing this_file_does_not_exist.rb"
|
42
|
+
Then stderr is "this_file_does_not_exist.rb does not exist!"
|
43
|
+
And the exit status is 1
|
44
|
+
And stdout is empty
|
@@ -1,4 +1,5 @@
|
|
1
|
-
Feature: Running the binary
|
1
|
+
Feature: Running the binary successfully
|
2
|
+
|
2
3
|
They say seeing is believing. So to believe that this works
|
3
4
|
I want to see that it works by making a binary to use the lib.
|
4
5
|
|
@@ -48,23 +49,6 @@ Feature: Running the binary
|
|
48
49
|
c" # => "a\n b\n c"
|
49
50
|
"""
|
50
51
|
|
51
|
-
Scenario: Raising exceptions
|
52
|
-
Given the file "raises_exception.rb":
|
53
|
-
"""
|
54
|
-
1 + 1
|
55
|
-
raise "ZOMG!"
|
56
|
-
1 + 1
|
57
|
-
"""
|
58
|
-
When I run "seeing_is_believing raises_exception.rb"
|
59
|
-
Then stderr is "ZOMG!"
|
60
|
-
And the exit status is 1
|
61
|
-
And stdout is:
|
62
|
-
"""
|
63
|
-
1 + 1 # => 2
|
64
|
-
raise "ZOMG!" # ~> RuntimeError: ZOMG!
|
65
|
-
1 + 1
|
66
|
-
"""
|
67
|
-
|
68
52
|
Scenario: Passing previous output back into input
|
69
53
|
Given the file "previous_output.rb":
|
70
54
|
"""
|
@@ -145,8 +129,47 @@ Feature: Running the binary
|
|
145
129
|
2
|
146
130
|
"""
|
147
131
|
|
132
|
+
@not-implemented
|
133
|
+
Scenario: Doesn't record BEGIN/END since that's apparently a syntax error
|
134
|
+
Given the file "BEGIN_and_END.rb":
|
135
|
+
"""
|
136
|
+
puts 1
|
137
|
+
BEGIN {
|
138
|
+
puts "begin code"
|
139
|
+
some_var = 2
|
140
|
+
}
|
141
|
+
puts 3
|
142
|
+
END {
|
143
|
+
puts "end code"
|
144
|
+
puts some_var
|
145
|
+
}
|
146
|
+
puts 4
|
147
|
+
"""
|
148
|
+
When I run "seeing_is_believing BEGIN_and_END.rb"
|
149
|
+
Then stderr is empty
|
150
|
+
And the exit status is 0
|
151
|
+
And stdout is:
|
152
|
+
"""
|
153
|
+
puts 1 # => nil
|
154
|
+
BEGIN {
|
155
|
+
puts "begin code" # => nil
|
156
|
+
some_var = 2 # => 2
|
157
|
+
}
|
158
|
+
puts 3 # => nil
|
159
|
+
END {
|
160
|
+
puts "end code" # => nil
|
161
|
+
puts some_var # => nil
|
162
|
+
}
|
163
|
+
puts 4 # => nil
|
164
|
+
|
165
|
+
# >> begin code
|
166
|
+
# >> 1
|
167
|
+
# >> 3
|
168
|
+
# >> 4
|
169
|
+
# >> end code
|
170
|
+
# >> 2
|
171
|
+
"""
|
172
|
+
|
148
173
|
Scenario: Requiring other files
|
149
|
-
Scenario: Syntactically invalid file
|
150
|
-
Scenario: Passing a nonexistent file
|
151
174
|
Scenario: Evaluating a file that requires other files, from a different directory
|
152
175
|
Scenario: Passing the file on stdin
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'seeing_is_believing/print_results_next_to_lines'
|
2
|
+
|
3
|
+
class SeeingIsBelieving
|
4
|
+
class Binary
|
5
|
+
attr_accessor :argv, :stdin, :stdout, :stderr
|
6
|
+
|
7
|
+
def initialize(argv, stdin, stdout, stderr)
|
8
|
+
self.argv = argv
|
9
|
+
self.stdin = stdin
|
10
|
+
self.stdout = stdout
|
11
|
+
self.stderr = stderr
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
return if @already_called
|
16
|
+
@already_called = true
|
17
|
+
|
18
|
+
unless File.exist? filename
|
19
|
+
@exitstatus = 1
|
20
|
+
stderr.puts "#{filename} does not exist!"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
out, err, syntax_status = Open3.capture3('ruby', '-c', filename)
|
25
|
+
unless syntax_status.success?
|
26
|
+
@exitstatus = 1
|
27
|
+
stderr.puts err
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
believer = SeeingIsBelieving::PrintResultsNextToLines.new File.read(filename), filename
|
32
|
+
stdout.puts believer.call
|
33
|
+
if believer.has_exception?
|
34
|
+
stderr.puts believer.exception.message
|
35
|
+
@exitstatus = 1
|
36
|
+
else
|
37
|
+
@exitstatus = 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def exitstatus
|
42
|
+
call
|
43
|
+
@exitstatus
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def filename
|
49
|
+
argv.first
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -11,7 +11,6 @@
|
|
11
11
|
# I did look at Ripper, and it will invoke on_kw("__FILE__")
|
12
12
|
# when it sees this.
|
13
13
|
|
14
|
-
require 'yaml'
|
15
14
|
require 'open3'
|
16
15
|
require 'fileutils'
|
17
16
|
require 'seeing_is_believing/error'
|
@@ -99,7 +98,7 @@ class SeeingIsBelieving
|
|
99
98
|
end
|
100
99
|
|
101
100
|
def deserialize_result
|
102
|
-
|
101
|
+
Marshal.load stdout
|
103
102
|
end
|
104
103
|
|
105
104
|
def record_error
|
@@ -1,10 +1,29 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'seeing_is_believing/has_exception'
|
2
3
|
require 'seeing_is_believing/tracks_line_numbers_seen'
|
3
4
|
|
4
5
|
class SeeingIsBelieving
|
5
6
|
class Result
|
6
7
|
|
7
|
-
Line
|
8
|
+
class Line
|
9
|
+
include HasException
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
def_delegators :@array, :[], :<<, :any?, :join, :to_ary, :to_a
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@array ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(ary_or_line)
|
19
|
+
if Array === ary_or_line
|
20
|
+
@array == ary_or_line
|
21
|
+
else
|
22
|
+
@array == ary_or_line &&
|
23
|
+
has_exception? == ary_or_line.has_exception?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
8
27
|
|
9
28
|
include HasException
|
10
29
|
include TracksLineNumbersSeen
|
@@ -42,7 +61,7 @@ class SeeingIsBelieving
|
|
42
61
|
# probably not really useful, just exists to satisfy the tests, which specified too simple of an interface
|
43
62
|
def to_a
|
44
63
|
(min_line_number..max_line_number).map do |line_number|
|
45
|
-
[line_number, [*self[line_number], *Array(self[line_number].exception)]]
|
64
|
+
[line_number, [*self[line_number].to_ary, *Array(self[line_number].exception)]]
|
46
65
|
end
|
47
66
|
end
|
48
67
|
|
@@ -7,7 +7,6 @@ real_stderr = STDERR
|
|
7
7
|
STDOUT = $stdout = fake_stdout = StringIO.new
|
8
8
|
STDERR = $stderr = fake_stderr = StringIO.new
|
9
9
|
|
10
|
-
require 'yaml'
|
11
10
|
require 'seeing_is_believing/result'
|
12
11
|
$seeing_is_believing_current_result = SeeingIsBelieving::Result.new
|
13
12
|
|
@@ -15,5 +14,5 @@ at_exit do
|
|
15
14
|
$seeing_is_believing_current_result.stdout = fake_stdout.string
|
16
15
|
$seeing_is_believing_current_result.stderr = fake_stderr.string
|
17
16
|
|
18
|
-
real_stdout.write
|
17
|
+
real_stdout.write Marshal.dump $seeing_is_believing_current_result
|
19
18
|
end
|
data/lib/seeing_is_believing.rb
CHANGED
@@ -57,7 +57,7 @@ class SeeingIsBelieving
|
|
57
57
|
"begin;"\
|
58
58
|
"#{code}\n"\
|
59
59
|
"rescue Exception;"\
|
60
|
-
"line_number = $!.backtrace.first[/:\\d+:/][1..-2].to_i;"\
|
60
|
+
"line_number = $!.backtrace.grep(/\#{__FILE__}/).first[/:\\d+:/][1..-2].to_i;"\
|
61
61
|
"$seeing_is_believing_current_result.record_exception line_number, $!;"\
|
62
62
|
"end"
|
63
63
|
end
|
@@ -131,4 +131,15 @@ describe SeeingIsBelieving::ExpressionList do
|
|
131
131
|
stream.string.should include "GENERATED"
|
132
132
|
stream.string.should include "REDUCED"
|
133
133
|
end
|
134
|
+
|
135
|
+
# in reality, the problem may just lie with our lib
|
136
|
+
# but it should be correct in most cases
|
137
|
+
it 'Raises a syntax error if it cannot generate the expression' do
|
138
|
+
generations = ["'"]
|
139
|
+
expect do
|
140
|
+
described_class.new(
|
141
|
+
on_complete: -> { "" }, generator: -> { generations.shift }
|
142
|
+
).call
|
143
|
+
end.to raise_error SyntaxError
|
144
|
+
end
|
134
145
|
end
|
@@ -125,10 +125,11 @@ describe SeeingIsBelieving do
|
|
125
125
|
|
126
126
|
result[3].should == []
|
127
127
|
result.to_a.size.should == 3
|
128
|
+
end
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
130
|
+
it 'records the backtrace on the errors' do
|
131
|
+
result = invoke("12\nraise Exception, 'omg!'\n12")
|
132
|
+
result.exception.backtrace.should be_a_kind_of Array
|
132
133
|
end
|
133
134
|
|
134
135
|
it 'does not fuck up __LINE__ macro' do
|
@@ -149,9 +150,8 @@ describe SeeingIsBelieving do
|
|
149
150
|
values_for("def meth \n return 1 if true \n end \n meth").should == [[], [], ['nil'], ['1']]
|
150
151
|
values_for("def meth \n return 1 if false \n end \n meth").should == [[], [], ['nil'], ['nil']]
|
151
152
|
values_for("-> { \n return 1 \n }.call" ).should == [[], [], ['1']]
|
152
|
-
|
153
|
-
|
154
|
-
end
|
153
|
+
# this doesn't work because the return detecting code is a very conservative regexp
|
154
|
+
# values_for("-> { return 1 }.call" ).should == [['1']]
|
155
155
|
end
|
156
156
|
|
157
157
|
it 'does not affect its environment' do
|
@@ -201,6 +201,7 @@ describe SeeingIsBelieving do
|
|
201
201
|
values_for("1+1\nDATA.read\n__END__\n....").should == [['2'], ['"...."']]
|
202
202
|
end
|
203
203
|
|
204
|
-
|
205
|
-
|
204
|
+
it 'raises a SyntaxError when the whole program is invalid' do
|
205
|
+
expect { invoke '"' }.to raise_error SyntaxError
|
206
|
+
end
|
206
207
|
end
|
@@ -121,10 +121,12 @@ describe SeeingIsBelieving::SyntaxAnalyzer do
|
|
121
121
|
will_return["o.return"].should be_false
|
122
122
|
will_return[":return"].should be_false
|
123
123
|
will_return["'return'"].should be_false
|
124
|
-
# will_return["'return\nreturn\nreturn'"].should be_false
|
125
124
|
will_return["def a\nreturn 1\nend"].should be_false
|
126
125
|
will_return["-> {\nreturn 1\n}"].should be_false
|
127
126
|
will_return["Proc.new {\nreturn 1\n}"].should be_false
|
128
|
-
|
127
|
+
pending "this doesn't work because the return detecting code is an insufficient regexp" do
|
128
|
+
will_return["'return\nreturn\nreturn'"].should be_false
|
129
|
+
will_return["return \\\n1"].should be_true
|
130
|
+
end
|
129
131
|
end
|
130
132
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seeing_is_believing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70333793492220 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.12.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70333793492220
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: cucumber
|
27
|
-
requirement: &
|
27
|
+
requirement: &70333793491440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.2.1
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70333793491440
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: ichannel
|
38
|
-
requirement: &
|
38
|
+
requirement: &70333793490760 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 5.1.1
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70333793490760
|
47
47
|
description: Records the results of every line of code in your file (intended to be
|
48
48
|
like xmpfilter), inspired by Bret Victor's JavaScript example in his talk "Inventing
|
49
49
|
on Principle"
|
@@ -57,18 +57,21 @@ files:
|
|
57
57
|
- .gitignore
|
58
58
|
- Gemfile
|
59
59
|
- Gemfile.lock
|
60
|
+
- Rakefile
|
60
61
|
- Readme.md
|
61
62
|
- bin/seeing_is_believing
|
62
|
-
- features/
|
63
|
+
- features/binary_errors.feature
|
64
|
+
- features/binary_examples.feature
|
63
65
|
- features/step_definitions/steps.rb
|
64
66
|
- features/support/env.rb
|
65
67
|
- lib/seeing_is_believing.rb
|
68
|
+
- lib/seeing_is_believing/binary.rb
|
66
69
|
- lib/seeing_is_believing/error.rb
|
67
70
|
- lib/seeing_is_believing/evaluate_by_moving_files.rb
|
68
|
-
- lib/seeing_is_believing/example_use.rb
|
69
71
|
- lib/seeing_is_believing/expression_list.rb
|
70
72
|
- lib/seeing_is_believing/hard_core_ensure.rb
|
71
73
|
- lib/seeing_is_believing/has_exception.rb
|
74
|
+
- lib/seeing_is_believing/print_results_next_to_lines.rb
|
72
75
|
- lib/seeing_is_believing/result.rb
|
73
76
|
- lib/seeing_is_believing/syntax_analyzer.rb
|
74
77
|
- lib/seeing_is_believing/the_matrix.rb
|
@@ -105,7 +108,8 @@ signing_key:
|
|
105
108
|
specification_version: 3
|
106
109
|
summary: Records results of every line of code in your file
|
107
110
|
test_files:
|
108
|
-
- features/
|
111
|
+
- features/binary_errors.feature
|
112
|
+
- features/binary_examples.feature
|
109
113
|
- features/step_definitions/steps.rb
|
110
114
|
- features/support/env.rb
|
111
115
|
- spec/evaluate_by_moving_files_spec.rb
|