seeing_is_believing 2.0.0.beta3 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a95d8680853f82d8aee58a8ba40d16a113662f20
4
- data.tar.gz: 6e9fecb99be2adf05d75bb42d2c8a37de1ff1c7b
3
+ metadata.gz: ae86d44e9afffb2928ac761a5bf8f6810ec1c996
4
+ data.tar.gz: 4c37f23d51da74cde81e85f2c48b1928daeedce9
5
5
  SHA512:
6
- metadata.gz: 291941c2ca6975b233ecfe9f8428f40638331839ec29591d955333d49a3bf975ed0478ca67059e41a7583ddd8b18e9140a9f632b8242665d8fdfed939e8bf319
7
- data.tar.gz: 138ae24e20da808a5ea5eb31bcc9ab4eede0163054a130478f79f1e00842b5c56b073f104c98c952f77e0b5698ca6e626691e4818137db136811eaa4e64fff30
6
+ metadata.gz: 08e8e66324e9360ee680327765f7d633a0862ab22237148ddd49d0bfc78ebfaa89f9466a4390dc5404126aa791256cbb437aa346ebbfc22c904a231fab042c35
7
+ data.tar.gz: bd56f998a57e28b06bcfc04782feb64ccb1e7466503cec372b08f9f77102a70df4c05dd7e9079f45b441ed2c72ded198d02aedc653c8be2c43d69448e48a286f
data/Readme.md CHANGED
@@ -4,12 +4,12 @@ Seeing Is Believing
4
4
  ===================
5
5
 
6
6
  Evaluates a file, recording the results of each line of code.
7
- You can then use this to display output values like Bret Victor does with JavaScript in his talk [Inventing on Principle][inventing_on_principle].
7
+ You can then use this to display output values like Bret Victor does with JavaScript in his talk [Inventing on Principle](http://vimeo.com/36579366).
8
8
  Except, obviously, his is like a million times better.
9
9
 
10
10
  Also comes with a binary to show how it might be used.
11
11
 
12
- For whatever reason, I can't embed videos, but **here's a ~1 minute [video][video]** showing it off.
12
+ For whatever reason, I can't embed videos, but **here's a ~1 minute [video](http://vimeo.com/58766950)** showing it off.
13
13
 
14
14
  Works in Ruby 1.9 and 2.0
15
15
 
@@ -17,25 +17,16 @@ Use The Binary
17
17
  ==============
18
18
 
19
19
  ```ruby
20
- # $ seeing_is_believing proving_grounds/basic_functionality.rb
20
+ $ cat simple_example.rb
21
21
  5.times do |i|
22
- i * 2 # => 0, 2, 4, 6, 8
23
- end # => 5
24
-
25
- def meth(n)
26
- n # => "12", "34"
27
- end # => nil
22
+ i * 2
23
+ end
28
24
 
29
- # some invocations
30
- meth "12" # => "12"
31
- meth "34" # => "34"
32
- ```
33
25
 
34
- ```ruby
35
- # $ bin/seeing_is_believing proving_grounds/raises_exception.rb
36
- 1 + 1 # => 2
37
- raise "ZOMG!" # ~> RuntimeError: ZOMG!
38
- 1 + 1
26
+ $ seeing_is_believing simple_example.rb
27
+ 5.times do |i| # => 5
28
+ i * 2 # => 0, 2, 4, 6, 8
29
+ end # => 5
39
30
  ```
40
31
 
41
32
  Use The Lib
@@ -43,113 +34,38 @@ Use The Lib
43
34
 
44
35
  ```ruby
45
36
  require 'seeing_is_believing'
46
-
47
- believer = SeeingIsBelieving.new("%w[a b c].each do |i|
37
+ believer = SeeingIsBelieving.new("[:a, :b, :c].each do |i|
48
38
  i.upcase
49
39
  end")
50
40
 
51
- result = believer.call
52
- result # => #<SeeingIsBelieving::Result:0x007f832298e340 @max_line_number=3, @min_line_number=1, @results={2=>#<SeeingIsBelieving::Result::Line:0x007f832298df30 @array=["\"A\"", "\"B\"", "\"C\""]>, 3=>#<SeeingIsBelieving::Result::Line:0x007f832298db98 @array=["[\"a\", \"b\", \"c\"]"]>}, @stdout="", @stderr="">
53
-
54
- result.to_a # => [#<SeeingIsBelieving::Result::Line:0x007f832299adc0 @array=[]>,
55
- # #<SeeingIsBelieving::Result::Line:0x007f832298df30 @array=['"A"', '"B"', '"C"']>,
56
- # #<SeeingIsBelieving::Result::Line:0x007f832298db98 @array=['["a", "b", "c"]']>]
41
+ result = believer.call # => #<SIB::Result @results={1=>#<SIB:Line["[:a, :b, :c]"] no exception>, 2=>#<SIB:Line[":A", ":B", ":C"] no exception>, 3=>#<SIB:Line["[:a, :b, :c]"] no exception>}\n @stdout=""\n @stderr=""\n @exitstatus=0\n @bug_in_sib=nil>
57
42
 
58
- result[2] # => #<SeeingIsBelieving::Result::Line:0x007f832298df30 @array=['"A"', '"B"', '"C"']>
43
+ result[2] # => #<SIB:Line[":A", ":B", ":C"] no exception>
44
+ result[2][0] # => ":A"
45
+ result[2][1] # => ":B"
46
+ result[2][2] # => ":C"
47
+ result[2].join(", ") # => ":A, :B, :C"
59
48
 
60
- # this result object is a thin wrapper around its array
61
- result[2][0] # => '"A"'
62
- result[2][1] # => '"B"'
63
- result[2][2] # => '"C"'
64
- result[2].join(", ") # => '"A", "B", "C"'
49
+ result.stdout # => ""
50
+ result.stderr # => ""
51
+ result.exception # => nil
65
52
  ```
66
53
 
67
54
  Install
68
55
  =======
69
56
 
57
+ Currently requires Ruby 1.9 or 2.0 I don't have specific plans to make it available on 1.8,
58
+ but it could happen.
70
59
 
71
60
  $ gem install seeing_is_believing
72
61
 
73
- Or if you haven't fixed your gem home, and you aren't using any version managers:
74
-
75
- $ sudo gem install seeing_is_believing
76
-
77
- Rubygems is allowing pushes again, but if it goes back down, you can install like this:
78
-
79
- $ git clone https://github.com/JoshCheek/seeing_is_believing/
80
- $ cd seeing_is_believing
81
- $ gem build seeing_is_believing.gemspec
82
- $ gem install seeing_is_believing-0.0.8.gem
83
- $ cd ..
84
- $ rm -rf "./seeing_is_believing"
85
-
86
- Sublime Text 2 Integration
87
- ==========================
88
-
89
- See [sublime-text-2-seeing-is-believing](https://github.com/JoshCheek/sublime-text-2-seeing-is-believing).
90
-
91
62
 
92
- TextMate Integration
93
- ====================
63
+ Editor Integration
64
+ ==================
94
65
 
95
- Note: This assumes you've already set up Ruby to work with TextMate.
96
- If not, you'll need to start there. [Here](https://rvm.io/integration/textmate/)
97
- are instructions for RVM (I recommend the wrapper approach).
98
- [Here](http://uberfork.com/post/12280974742/integrate-rbenv-with-textmate)
99
- are instructions for rbenv.
100
-
101
- Go to the bundle editor, create a new command (I put it in the Ruby bundle)
102
- You can name it what you want, I went with "seeing is believing annotate all lines"
103
-
104
- ```shell
105
- #!/bin/bash
106
-
107
- # set result length because TextMate has difficulty displaying long lines
108
- default_options=""
109
- default_options="$default_options -Ku"
110
- default_options="$default_options --result-length 200"
111
- default_options="$default_options --alignment-strategy chunk"
112
- default_options="$default_options --timeout 12"
113
-
114
- if [ -z "$TM_FILEPATH" ]; then
115
- "${TM_RUBY}" -S seeing_is_believing $default_options
116
- else
117
- "${TM_RUBY}" -S seeing_is_believing $default_options --as "$TM_FILEPATH"
118
- fi
119
- ```
120
-
121
- You can also make one for annotating only the lines you have marked.
122
- I named it "seeing is believing annotate marked lines"
123
-
124
- ```shell
125
- #!/bin/bash
126
-
127
- # set result length because TextMate has difficulty displaying long lines
128
- default_options=""
129
- default_options="$default_options --xmpfilter-style"
130
- default_options="$default_options -Ku"
131
- default_options="$default_options --result-length 200"
132
- default_options="$default_options --alignment-strategy chunk"
133
- default_options="$default_options --timeout 12"
134
-
135
- if [ -z "$TM_FILEPATH" ]; then
136
- "${TM_RUBY}" -S seeing_is_believing $default_options
137
- else
138
- "${TM_RUBY}" -S seeing_is_believing $default_options --as "$TM_FILEPATH"
139
- fi
140
- ```
141
-
142
- And you'll probably want one to clean out the outpt
143
-
144
- ```shell
145
- #!/bin/bash
146
- "${TM_RUBY}" -S seeing_is_believing -Ku --clean
147
- ```
148
-
149
- You can bind them to whatever keys you want, but I'll recomend (for consistency with what I chose for the Sublime bundle)
150
- * annotate all lines -> Command Option b
151
- * annotate marked lines -> Command Option n
152
- * remove annotations -> Command Option v
66
+ * [sublime-text-2-seeing-is-believing](https://github.com/JoshCheek/sublime-text-2-seeing-is-believing)
67
+ * [TextMate 1](https://github.com/JoshCheek/text_mate_1-seeing-is_believing)
68
+ * [TextMate 2](https://github.com/JoshCheek/text_mate_2-seeing-is_believing)
153
69
 
154
70
  Emacs Integration
155
71
  =================
@@ -173,20 +89,15 @@ or current buffer contents with the output of running it through
173
89
  Known Issues
174
90
  ============
175
91
 
176
- * `BEGIN/END` breaks things and I probably won't take the time to fix it, becuase it's nontrivial and its really meant for command-line scripts, but there is currently a cuke for it
92
+ * `BEGIN/END` breaks things and I probably won't ever fix it, becuase it's annoying and its really meant for command-line scripts... but there is currently a spec for it
177
93
  * `exit!` ignores callbacks that `SeeingIsBelieving` uses to communicate the results back to the main app. If you call it, `SeeingIsBelieving` will blow up. We could "fix" this by overriding it, but I feel like that would violate the meaning of `exit!`, so basically, just don't call that method.
94
+ * The code to find the data segment is naive, and could wind up interpolating results into a string or something
178
95
 
179
96
  Todo
180
97
  ====
181
98
 
182
99
  * Sublime: Merge xmpfilter option into main after 2.0 release
183
- * Make TextMate 1 and 2 bundles
184
- * Go through each cuke and spec, implementing however many not-implemented ones that we can
185
- * Make sure the examples in this readme all still make sense (mountain berry fields?)
186
- * Go through Peter's email about how to make the use of Parser better
187
100
  * Make a new video
188
- * Add versions to the debugging output
189
- * Shorten the debugging output
190
101
 
191
102
  Shit that will probably never get done (or if it does, won't be until after 2.0)
192
103
  ================================================================================
@@ -215,7 +126,3 @@ License
215
126
  0. You just DO WHAT THE FUCK YOU WANT TO.
216
127
 
217
128
 
218
-
219
- [inventing_on_principle]: http://vimeo.com/36579366
220
- [textmate-integration]: https://raw.github.com/JoshCheek/seeing_is_believing/master/textmate-integration.png
221
- [video]: http://vimeo.com/58766950
@@ -93,7 +93,7 @@ Feature: Running the binary unsuccessfully
93
93
  """
94
94
 
95
95
  Scenario: Total Fucking Failure
96
- Given the file "sib_will_utterly_die.rb" "BEGIN {}"
96
+ Given the file "sib_will_utterly_die.rb" "__TOTAL_FUCKING_FAILURE__"
97
97
  When I run "seeing_is_believing sib_will_utterly_die.rb"
98
98
  Then stderr is not empty
99
99
  And the exit status is 2
@@ -196,47 +196,6 @@ Feature: Running the binary successfully
196
196
  2
197
197
  """
198
198
 
199
- @not-implemented
200
- Scenario: Doesn't record BEGIN/END since that's apparently a syntax error
201
- Given the file "BEGIN_and_END.rb":
202
- """
203
- puts 1
204
- BEGIN {
205
- puts "begin code"
206
- some_var = 2
207
- }
208
- puts 3
209
- END {
210
- puts "end code"
211
- puts some_var
212
- }
213
- puts 4
214
- """
215
- When I run "seeing_is_believing BEGIN_and_END.rb"
216
- Then stderr is empty
217
- And the exit status is 0
218
- And stdout is:
219
- """
220
- puts 1 # => nil
221
- BEGIN {
222
- puts "begin code" # => nil
223
- some_var = 2 # => 2
224
- }
225
- puts 3 # => nil
226
- END {
227
- puts "end code" # => nil
228
- puts some_var # => nil
229
- }
230
- puts 4 # => nil
231
-
232
- # >> begin code
233
- # >> 1
234
- # >> 3
235
- # >> 4
236
- # >> end code
237
- # >> 2
238
- """
239
-
240
199
  Scenario: Reading from stdin
241
200
  Given the stdin content "hi!"
242
201
  And the file "reads_from_stdin.rb":
@@ -184,6 +184,19 @@ Feature: Using flags
184
184
  When I run "seeing_is_believing --line-length 14 line_lengths2.rb"
185
185
  Then stdout is "12345"
186
186
 
187
+ Scenario: --xmpfilter-style respects the line formatting (but not currently alignment strategies, it just preserves submitted alignment)
188
+ Given the file "line_lengths3.rb":
189
+ """
190
+ '1' * 30 # =>
191
+ # =>
192
+ """
193
+ When I run "seeing_is_believing --xmpfilter-style --line-length 19 line_lengths3.rb"
194
+ Then stdout is:
195
+ """
196
+ '1' * 30 # => "1...
197
+ # => "1111111111...
198
+ """
199
+
187
200
 
188
201
  Scenario: --require
189
202
  Given the file "print_1.rb" "puts 1"
@@ -292,7 +305,6 @@ Feature: Using flags
292
305
  """
293
306
 
294
307
 
295
- @not-implemented
296
308
  Scenario: --clean on an invalid file will clean
297
309
  When I run 'seeing_is_believing --clean -e "1+ # => lkj"'
298
310
  Then stderr is empty
@@ -105,7 +105,7 @@ Feature:
105
105
  __END__
106
106
  """
107
107
  When I run "seeing_is_believing modified_result.rb"
108
- Then stdout is:
108
+ Then stdout is exactly:
109
109
  """
110
110
  1 # => 1
111
111
  2 # => 2
@@ -6,3 +6,7 @@ Haiti.configure do |config|
6
6
  config.bin_dir = File.expand_path '../../../bin', __FILE__
7
7
  end
8
8
 
9
+
10
+ Then 'stdout is exactly:' do |code|
11
+ @last_executed.stdout.should == eval_curlies(code)
12
+ end
@@ -11,6 +11,18 @@ class SeeingIsBelieving
11
11
  DISPLAYABLE_ERROR_STATUS = 1 # e.g. there was an error, but the output is legit (we can display exceptions)
12
12
  NONDISPLAYABLE_ERROR_STATUS = 2 # e.g. an error like incorrect invocation or syntax that can't be displayed in the input program
13
13
 
14
+ VALUE_MARKER = "# => "
15
+ EXCEPTION_MARKER = "# ~> "
16
+ STDOUT_MARKER = "# >> "
17
+ STDERR_MARKER = "# !> "
18
+
19
+ VALUE_REGEX = /\A#\s*=>/
20
+ EXCEPTION_REGEX = /\A#\s*~>/
21
+ STDOUT_REGEX = /\A#\s*>>/
22
+ STDERR_REGEX = /\A#\s*!>/
23
+
24
+
25
+
14
26
  attr_accessor :argv, :stdin, :stdout, :stderr, :timeout_error, :unexpected_exception
15
27
 
16
28
  def initialize(argv, stdin, stdout, stderr)
@@ -138,7 +150,7 @@ class SeeingIsBelieving
138
150
  end
139
151
 
140
152
  def print_program
141
- stdout.puts interpolated_program
153
+ stdout.print interpolated_program
142
154
  end
143
155
 
144
156
  def syntax_error_notice
@@ -2,6 +2,7 @@ require 'stringio'
2
2
  require 'seeing_is_believing/has_exception'
3
3
  require 'seeing_is_believing/binary/comment_formatter'
4
4
 
5
+ require 'seeing_is_believing/binary'
5
6
  require 'seeing_is_believing/binary/clean_body'
6
7
  require 'seeing_is_believing/binary/rewrite_comments'
7
8
  require 'seeing_is_believing/binary/comment_lines'
@@ -22,7 +23,7 @@ class SeeingIsBelieving
22
23
  method_from_options :debugger
23
24
 
24
25
  attr_accessor :results, :body
25
- def initialize(uncleaned_body, options={})
26
+ def initialize(uncleaned_body, options={}, &annotater)
26
27
  self.options = options
27
28
  self.body = CleanBody.call uncleaned_body, !xmpfilter_style
28
29
  self.results = SeeingIsBelieving.call body,
@@ -38,49 +39,13 @@ class SeeingIsBelieving
38
39
 
39
40
  def call
40
41
  @new_body ||= begin
41
- # uhm, these basically look like strategies for commenting.
42
42
  new_body = if xmpfilter_style
43
- RewriteComments.call body do |line_number, line, whitespace, comment|
44
- # FIXME: can we centralize these regexes?
45
- if !comment[/\A#\s*=>/]
46
- [whitespace, comment]
47
- elsif line.empty?
48
- # should go through comment formatter
49
- [whitespace, "# => #{results[line_number-1].map { |result| result.gsub "\n", '\n' }.join(', ')}"] # FIXME: NEED TO CONSIDER THE LINE LENGTH
50
- else
51
- # should go through comment formatter
52
- [whitespace, "# => #{results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')}"] # FIXME: NEED TO CONSIDER THE LINE LENGTH
53
- end
54
- end
55
- else
56
- alignment_strategy = options[:alignment_strategy].new body, start_line, end_line
57
- CommentLines.call body do |line, line_number|
58
- options = options().merge pad_to: alignment_strategy.line_length_for(line_number)
59
- if line_number < start_line || end_line < line_number
60
- ''
61
- elsif results[line_number].has_exception?
62
- exception = results[line_number].exception
63
- result = sprintf "%s: %s", exception.class_name, exception.message.gsub("\n", '\n')
64
- CommentFormatter.new(line.size, "# ~> ", result, options).call
65
- elsif results[line_number].any?
66
- result = results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
67
- CommentFormatter.call(line.size, "# => ", result, options)
68
- else
69
- ''
70
- end
71
- end
72
- end
73
-
74
- output = stdout_ouptut_for(results) <<
75
- stderr_ouptut_for(results) <<
76
- exception_output_for(results)
43
+ body_with_updated_annotations
44
+ else
45
+ body_with_everything_annotated
46
+ end
77
47
 
78
- if new_body["\n__END__\n"]
79
- new_body.sub! "\n__END__\n", "\n#{output}__END__\n"
80
- else
81
- new_body << "\n" unless new_body.end_with? "\n"
82
- new_body << output
83
- end
48
+ add_stdout_stderr_and_exceptions_to new_body
84
49
 
85
50
  debugger.context "OUTPUT"
86
51
  new_body
@@ -91,11 +56,60 @@ class SeeingIsBelieving
91
56
 
92
57
  attr_accessor :body, :options, :alignment_strategy
93
58
 
59
+ # doesn't currently realign output markers, do we want to do that?
60
+ def body_with_updated_annotations
61
+ RewriteComments.call body do |line_number, line_to_whitespace, whitespace, comment|
62
+ if !comment[VALUE_REGEX]
63
+ [whitespace, comment]
64
+ elsif line_to_whitespace.empty?
65
+ result = results[line_number-1].map { |result| result.gsub "\n", '\n' }.join(', ')
66
+ [whitespace, CommentFormatter.call(whitespace.size, VALUE_MARKER, result, options)]
67
+ else
68
+ result = results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
69
+ [whitespace, CommentFormatter.call(line_to_whitespace.size + whitespace.size, VALUE_MARKER, result, options)]
70
+ end
71
+ end
72
+ end
73
+
74
+ def body_with_everything_annotated
75
+ alignment_strategy = options[:alignment_strategy].new body, start_line, end_line
76
+ CommentLines.call body do |line, line_number|
77
+ options = options().merge pad_to: alignment_strategy.line_length_for(line_number)
78
+ if line_number < start_line || end_line < line_number
79
+ ''
80
+ elsif results[line_number].has_exception?
81
+ exception = results[line_number].exception
82
+ result = sprintf "%s: %s", exception.class_name, exception.message.gsub("\n", '\n')
83
+ CommentFormatter.call(line.size, EXCEPTION_MARKER, result, options)
84
+ elsif results[line_number].any?
85
+ result = results[line_number].map { |result| result.gsub "\n", '\n' }.join(', ')
86
+ CommentFormatter.call(line.size, VALUE_MARKER, result, options)
87
+ else
88
+ ''
89
+ end
90
+ end
91
+ end
92
+
93
+ def add_stdout_stderr_and_exceptions_to(new_body)
94
+ output = stdout_ouptut_for(results) <<
95
+ stderr_ouptut_for(results) <<
96
+ exception_output_for(results)
97
+
98
+ # this technically could find an __END__ in a string or whatever
99
+ # going to just ignore that, though
100
+ if new_body[/^__END__$/]
101
+ new_body.sub! "\n__END__", "\n#{output}__END__"
102
+ else
103
+ new_body << "\n" unless new_body.end_with? "\n"
104
+ new_body << output
105
+ end
106
+ end
107
+
94
108
  def stdout_ouptut_for(results)
95
109
  return '' unless results.has_stdout?
96
110
  output = "\n"
97
111
  results.stdout.each_line do |line|
98
- output << CommentFormatter.call(0, "# >> ", line.chomp, options()) << "\n"
112
+ output << CommentFormatter.call(0, STDOUT_MARKER, line.chomp, options()) << "\n"
99
113
  end
100
114
  output
101
115
  end
@@ -104,7 +118,7 @@ class SeeingIsBelieving
104
118
  return '' unless results.has_stderr?
105
119
  output = "\n"
106
120
  results.stderr.each_line do |line|
107
- output << CommentFormatter.call(0, "# !> ", line.chomp, options()) << "\n"
121
+ output << CommentFormatter.call(0, STDERR_MARKER, line.chomp, options()) << "\n"
108
122
  end
109
123
  output
110
124
  end
@@ -113,13 +127,13 @@ class SeeingIsBelieving
113
127
  return '' unless results.has_exception?
114
128
  exception = results.exception
115
129
  output = "\n"
116
- output << CommentFormatter.new(0, "# ~> ", exception.class_name, options).call << "\n"
130
+ output << CommentFormatter.new(0, EXCEPTION_MARKER, exception.class_name, options).call << "\n"
117
131
  exception.message.each_line do |line|
118
- output << CommentFormatter.new(0, "# ~> ", line.chomp, options).call << "\n"
132
+ output << CommentFormatter.new(0, EXCEPTION_MARKER, line.chomp, options).call << "\n"
119
133
  end
120
- output << "# ~>\n"
134
+ output << EXCEPTION_MARKER.sub(/\s+$/, '') << "\n"
121
135
  exception.backtrace.each do |line|
122
- output << CommentFormatter.new(0, "# ~> ", line.chomp, options).call << "\n"
136
+ output << CommentFormatter.new(0, EXCEPTION_MARKER, line.chomp, options).call << "\n"
123
137
  end
124
138
  output
125
139
  end
@@ -18,7 +18,9 @@ class SeeingIsBelieving
18
18
  end
19
19
 
20
20
  def call
21
- buffer, parser, rewriter, ast, comments = ParserHelpers.initialize_parser code, 'strip_comments'
21
+ buffer, parser, rewriter = ParserHelpers.initialize_parser code, 'strip_comments'
22
+ comments = ParserHelpers.comments_from parser, buffer
23
+
22
24
  removed_comments = { result: [], exception: [], stdout: [], stderr: [] }
23
25
 
24
26
  comments.each do |comment|
@@ -76,7 +78,7 @@ class SeeingIsBelieving
76
78
  current_chunk = 0
77
79
  last_line_seen = -100
78
80
  chunks_to_comment = comments.chunk do |comment|
79
- line, col = buffer.decompose_position comment.location.begin_pos
81
+ line = comment.location.begin_pos.line
80
82
  if last_line_seen.next == line
81
83
  last_line_seen = line
82
84
  current_chunk
@@ -2,6 +2,8 @@ require 'seeing_is_believing/parser_helpers'
2
2
 
3
3
  class SeeingIsBelieving
4
4
  class Binary
5
+
6
+ # could possibly be sped up by just reflecting on the tokens instead of the whole ast
5
7
  class CommentableLines
6
8
 
7
9
  include ParserHelpers
@@ -12,8 +14,8 @@ class SeeingIsBelieving
12
14
 
13
15
  def initialize(code)
14
16
  self.code = code
15
- self.buffer, self.parser, self.rewriter, self.root, self.comments =
16
- initialize_parser(code, 'strip_comments')
17
+ self.buffer, self.parser, self.rewriter = initialize_parser(code, 'finding_commentable_lines')
18
+ self.root, self.comments = parser.parse_with_comments(buffer)
17
19
  end
18
20
 
19
21
  def call
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'stringio'
4
4
  require 'seeing_is_believing/version'
5
+ require 'seeing_is_believing/binary'
5
6
  require 'seeing_is_believing/debugger'
6
7
  require 'seeing_is_believing/binary/align_file'
7
8
  require 'seeing_is_believing/binary/align_line'
@@ -145,7 +146,7 @@ Usage: seeing_is_believing [options] [filename]
145
146
  -l, --start-line n # line number to begin showing results on
146
147
  -L, --end-line n # line number to stop showing results on
147
148
  -d, --line-length n # max length of the entire line (only truncates results, not source lines)
148
- -D, --result-length n # max length of the portion after the "# => "
149
+ -D, --result-length n # max length of the portion after the "#{VALUE_MARKER}"
149
150
  -s, --alignment-strategy name # select the alignment strategy:
150
151
  chunk (DEFAULT) => each chunk of code is at the same alignment
151
152
  file => the entire file is at the same alignment
@@ -168,53 +169,53 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
168
169
 
169
170
  Run the file f.rb
170
171
  $ echo __FILE__ > f.rb; seeing_is_believing f.rb
171
- __FILE__ # => "f.rb"
172
+ __FILE__ #{VALUE_MARKER}"f.rb"
172
173
 
173
174
  Aligning comments
174
175
  $ ruby -e 'puts "123\\n4\\n\\n567890"' > f.rb
175
176
 
176
177
 
177
178
  $ seeing_is_believing f.rb -s line
178
- 123 # => 123
179
- 4 # => 4
179
+ 123 #{VALUE_MARKER}123
180
+ 4 #{VALUE_MARKER}4
180
181
 
181
- 567890 # => 567890
182
+ 567890 #{VALUE_MARKER}567890
182
183
 
183
184
 
184
185
  $ seeing_is_believing f.rb -s chunk
185
- 123 # => 123
186
- 4 # => 4
186
+ 123 #{VALUE_MARKER}123
187
+ 4 #{VALUE_MARKER}4
187
188
 
188
- 567890 # => 567890
189
+ 567890 #{VALUE_MARKER}567890
189
190
 
190
191
 
191
192
  $ seeing_is_believing f.rb -s file
192
- 123 # => 123
193
- 4 # => 4
193
+ 123 #{VALUE_MARKER}123
194
+ 4 #{VALUE_MARKER}4
194
195
 
195
- 567890 # => 567890
196
+ 567890 #{VALUE_MARKER}567890
196
197
 
197
198
  Run against standard input
198
199
  $ echo '3.times { |i| puts i }' | seeing_is_believing
199
- 2.times { |i| puts i } # => 2
200
+ 2.times { |i| puts i } #{VALUE_MARKER}2
200
201
 
201
- # >> 0
202
- # >> 1
202
+ #{STDOUT_MARKER}0
203
+ #{STDOUT_MARKER}1
203
204
 
204
205
  Run against a library you're working on by fixing the load path
205
206
  $ seeing_is_believing -I lib f.rb
206
207
 
207
208
  Load up some library (can be used in tandem with -I)
208
209
  $ seeing_is_believing -r pp -e 'pp [[*1..15],[*15..30]]; nil'
209
- pp [[*1..15],[*15..30]]; nil # => nil
210
+ pp [[*1..15],[*15..30]]; nil #{VALUE_MARKER}nil
210
211
 
211
- # >> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
212
- # >> [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]
212
+ #{STDOUT_MARKER}[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
213
+ #{STDOUT_MARKER} [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]
213
214
 
214
215
  Only update the lines you've marked
215
216
  $ ruby -e 'puts "1\\n2 # =>\\n3"' | seeing_is_believing -x
216
217
  1
217
- 2 # => 2
218
+ 2 #{VALUE_MARKER}2
218
219
  3
219
220
 
220
221
  Set a timeout (especially useful if running via an editor)
@@ -223,11 +224,11 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
223
224
 
224
225
  Set the encoding to utf-8
225
226
  $ seeing_is_believing -Ku -e '"⛄ "'
226
- "⛄ " # => "⛄ "
227
+ "⛄ " #{VALUE_MARKER}"⛄ "
227
228
 
228
229
  The exit status will be 1 if the error is displayable inline
229
230
  $ seeing_is_believing -e 'raise "omg"'; echo $?
230
- raise "omg" # ~> RuntimeError: omg
231
+ raise "omg" #{EXCEPTION_MARKER}RuntimeError: omg
231
232
  1
232
233
 
233
234
  The exit status will be 2 if the error is not displayable
@@ -236,15 +237,15 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
236
237
  2
237
238
 
238
239
  Run with previous output
239
- $ echo "1+1 # => old-value" | seeing_is_believing
240
- 1+1 # => 2
240
+ $ echo "1+1 #{VALUE_MARKER}old-value" | seeing_is_believing
241
+ 1+1 #{VALUE_MARKER}2
241
242
 
242
- $ echo "1+1 # => old-value" | seeing_is_believing --clean
243
+ $ echo "1+1 #{VALUE_MARKER}old-value" | seeing_is_believing --clean
243
244
  1+1
244
245
 
245
246
  If your Ruby binary is named something else (e.g. ruby2.0)
246
247
  $ ruby2.0 -S seeing_is_believing --shebang ruby2.0 -e '123'
247
- 123 # => 123
248
+ 123 #{VALUE_MARKER}123
248
249
 
249
250
  HELP_SCREEN
250
251
  end
@@ -4,7 +4,8 @@ class SeeingIsBelieving
4
4
  class Binary
5
5
  module RewriteComments
6
6
  def self.call(code, &mapping)
7
- buffer, parser, rewriter, ast, comments = ParserHelpers.initialize_parser code, 'strip_comments'
7
+ buffer, parser, rewriter = ParserHelpers.initialize_parser code, 'rewrite_comments'
8
+ ast, comments = parser.parse_with_comments buffer
8
9
 
9
10
  comments.each do |comment|
10
11
  next unless comment.type == :inline
@@ -1,15 +1,36 @@
1
1
  require 'parser/current'
2
2
  class SeeingIsBelieving
3
3
  module ParserHelpers
4
+
5
+ # override #process so it does not raise an error on
6
+ # fatal parsings (we want to keep going if possible,
7
+ # this allows us to find comments in syntactically invalid files
8
+ class NullDiagnostics < Parser::Diagnostic::Engine
9
+ def process(*)
10
+ # no op
11
+ end
12
+ end
13
+
4
14
  extend self
5
15
 
6
16
  def initialize_parser(code, name)
7
- buffer = Parser::Source::Buffer.new(name)
8
- buffer.source = code
9
- parser = Parser::CurrentRuby.new
10
- root, comments = parser.parse_with_comments buffer
11
- rewriter = Parser::Source::Rewriter.new buffer
12
- [buffer, parser, rewriter, root, comments]
17
+ buffer = Parser::Source::Buffer.new(name)
18
+ buffer.source = code
19
+
20
+ builder = Parser::Builders::Default.new
21
+ builder.emit_file_line_as_literals = false
22
+
23
+ parser = Parser::CurrentRuby.new builder
24
+ rewriter = Parser::Source::Rewriter.new buffer
25
+
26
+ [buffer, parser, rewriter]
27
+ end
28
+
29
+ # useful b/c it can find comments even in syntactically invalid code
30
+ def comments_from(parser, buffer)
31
+ parser.instance_variable_set(:@diagnostics, NullDiagnostics.new) # seems really fucking risky
32
+ success, comments, tokens, * = parser.tokenize buffer # experimentally, seems to be what these things return
33
+ comments
13
34
  end
14
35
 
15
36
  # this is the scardest fucking method I think I've ever written.
@@ -21,7 +42,6 @@ class SeeingIsBelieving
21
42
  ast.kind_of?(Parser::AST::Node) &&
22
43
  (ast.type == :dstr || ast.type == :str) &&
23
44
  (location = ast.location) &&
24
- (location.respond_to?(:begin)) &&
25
45
  (the_begin = location.begin) &&
26
46
  (the_begin.source =~ /^\<\<-?/)
27
47
  end
@@ -1,3 +1,3 @@
1
1
  class SeeingIsBelieving
2
- VERSION = '2.0.0.beta3'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -45,7 +45,8 @@ class SeeingIsBelieving
45
45
  self.after_all = wrappings.fetch :after_all, ''.freeze
46
46
  self.before_each = wrappings.fetch :before_each, -> * { '' }
47
47
  self.after_each = wrappings.fetch :after_each, -> * { '' }
48
- self.buffer, _, self.rewriter, self.root, _ = initialize_parser(program, 'program-without-annotations')
48
+ self.buffer, parser, self.rewriter = initialize_parser(program, 'program-without-annotations')
49
+ self.root = parser.parse buffer
49
50
  self.wrappings = {}
50
51
  rescue Parser::SyntaxError => e
51
52
  raise ::SyntaxError, e.message
@@ -58,8 +59,15 @@ class SeeingIsBelieving
58
59
  if root # file may be empty
59
60
  rewriter.insert_before root.location.expression, before_all
60
61
 
61
- wrappings.each do |line_num, (range, last_col)|
62
+
63
+ wrappings.each do |line_num, (range, last_col, meta)|
62
64
  rewriter.insert_before range, before_each.call(line_num)
65
+ if meta == :wrap_in_braces
66
+ rewriter.insert_before range, '{'
67
+ rewriter.insert_after range, '}'
68
+ elsif meta == :total_fucking_failure
69
+ rewriter.replace range, '.....TOTAL FUCKING FAILURE!.....'
70
+ end
63
71
  rewriter.insert_after range, after_each.call(line_num)
64
72
  end
65
73
 
@@ -78,12 +86,12 @@ class SeeingIsBelieving
78
86
 
79
87
  attr_accessor :program, :before_all, :after_all, :before_each, :after_each, :buffer, :root, :rewriter, :wrappings
80
88
 
81
- def add_to_wrappings(range_or_ast)
89
+ def add_to_wrappings(range_or_ast, meta=nil)
82
90
  range = range_or_ast
83
91
  range = range_or_ast.location.expression if range.kind_of? ::AST::Node
84
92
  line, col = buffer.decompose_position range.end_pos
85
- _, prev_col = wrappings[line]
86
- wrappings[line] = (!wrappings[line] || prev_col < col ? [range, col] : wrappings[line] )
93
+ _, prev_col, _ = wrappings[line]
94
+ wrappings[line] = (!wrappings[line] || prev_col < col ? [range, col, meta] : wrappings[line] )
87
95
  end
88
96
 
89
97
  def add_children(ast, omit_first = false)
@@ -228,7 +236,10 @@ class SeeingIsBelieving
228
236
 
229
237
  begin_pos = ast.location.expression.begin_pos
230
238
  range = Parser::Source::Range.new(buffer, begin_pos, end_pos)
231
- add_to_wrappings range
239
+
240
+ meta = nil
241
+ meta = :total_fucking_failure if message == :__TOTAL_FUCKING_FAILURE__
242
+ add_to_wrappings range, meta
232
243
  add_children ast
233
244
  when :begin
234
245
  last_child = ast.children.last
@@ -242,6 +253,13 @@ class SeeingIsBelieving
242
253
  add_children ast
243
254
  when :str, :dstr, :xstr, :regexp
244
255
  add_to_wrappings heredoc_hack ast
256
+
257
+ when :hash
258
+ meta = :wrap_in_braces
259
+ meta = nil if ast.location.begin
260
+ add_to_wrappings ast, meta
261
+ add_children ast
262
+
245
263
  else
246
264
  add_to_wrappings ast
247
265
  add_children ast
@@ -125,17 +125,17 @@ describe SeeingIsBelieving do
125
125
  values_for("-> { \n return 1 \n }.call" ).should == [[], ['1'], ['1']]
126
126
  values_for("-> { return 1 }.call" ).should == [['1']]
127
127
 
128
- pending "we'd like this to record 1 and nil, but currently we dont' differentiate between inline and multiline if statements" do
128
+ pending "would be really cool if this would record 1 and nil, but it probably won't ever happen." do
129
+ # Currently we dont' differentiate between inline and multiline if statements,
130
+ # also, we can't wrap the whole statement since it's void value, which means we'd have to introduce
131
+ # the idea of multiple wrappings for the same line, which I just don't care enough about to consider
129
132
  values_for("def meth \n return 1 if true \n end \n meth").should == [[], ['1'], [], ['1']] # records true instead of 1
130
133
  values_for("def meth \n return 1 if false \n end \n meth").should == [[], ['nil'], [], ['nil']] # records false instead of nil
131
134
  end
132
135
  end
133
136
 
134
137
  it 'does not try to record the keyword next' do
135
- # tbh, I don't even really know what I want in this case. Maybe record nothing since there is no arg to next?
136
- pending 'broken because of misordering in the rewriter' do
137
- values_for("(1..2).each do |i|\nnext if i == 1\ni\nend").should == [['1..2'], [], ['true', 'false'], ['1..2']]
138
- end
138
+ values_for("(1..2).each do |i|\nnext if i == 1\ni\nend").should == [['1..2'], ['true', 'false'], ['2'], ['1..2']]
139
139
  end
140
140
 
141
141
  it 'does not try to record the keyword redo' do
@@ -152,25 +152,28 @@ describe SeeingIsBelieving do
152
152
  end
153
153
 
154
154
  it 'does not try to record the keyword retry' do
155
- pending 'uhhh, what do I want here?' do
156
- values_for(<<-DOC).should == [[], [], [], ['nil']]
157
- def meth
158
- rescue
159
- retry
160
- end
161
- DOC
162
- end
155
+ values_for(<<-DOC).should == [[], [], [], [], ['nil']]
156
+ def meth
157
+ rescue
158
+ retry
159
+ end
160
+ meth
161
+ DOC
163
162
  end
164
163
 
165
164
  it 'does not try to record the keyword retry' do
166
- pending 'uhhh, what do I want here?' do
167
- values_for(<<-DOC).should == [[], ['0'], [], ['nil']]
168
- (0..2).each do |n|
169
- n
170
- break
171
- end
172
- DOC
173
- end
165
+ values_for(<<-DOC).should == [['0..2'], ['0'], [], ['nil']]
166
+ (0..2).each do |n|
167
+ n
168
+ break
169
+ end
170
+ DOC
171
+ values_for(<<-DOC).should == [['0..2'], ['0'], ['10'], ['10']]
172
+ (0..2).each do |n|
173
+ n
174
+ break 10
175
+ end
176
+ DOC
174
177
  end
175
178
 
176
179
  it 'does not affect its environment' do
@@ -319,6 +322,22 @@ describe SeeingIsBelieving do
319
322
  end
320
323
  end
321
324
 
325
+ it 'does not record BEGIN and END', not_implemented: true do
326
+ expect { invoke <<-CODE }.to_not raise_error
327
+ puts 1
328
+ BEGIN {
329
+ puts "begin code"
330
+ some_var = 2
331
+ }
332
+ puts 3
333
+ END {
334
+ puts "end code"
335
+ puts some_var
336
+ }
337
+ puts 4
338
+ CODE
339
+ end
340
+
322
341
  context 'when given a debugger' do
323
342
  let(:stream) { StringIO.new }
324
343
  let(:debugger) { SeeingIsBelieving::Debugger.new stream: stream }
@@ -1,9 +1,5 @@
1
1
  require 'seeing_is_believing/wrap_expressions'
2
2
 
3
- # eventually make this not wrap BEGIN and END
4
- # but for now, leave it b/c it's convenient to be able to make it blow up
5
- # Probably replace this with some macro like __INVALID_SYNTAX__ that blows it up :)
6
-
7
3
  describe SeeingIsBelieving::WrapExpressions do
8
4
  def wrap(code)
9
5
  described_class.call code,
@@ -15,6 +11,10 @@ describe SeeingIsBelieving::WrapExpressions do
15
11
  expect { wrap '+' }.to raise_error SyntaxError
16
12
  end
17
13
 
14
+ it 'can inject syntax errors with __TOTAL_FUCKING_FAILURE__' do
15
+ wrap('__TOTAL_FUCKING_FAILURE__').should == '<.....TOTAL FUCKING FAILURE!.....>'
16
+ end
17
+
18
18
  describe 'wrapping the body' do
19
19
  let(:options) { { before_all: "[",
20
20
  after_all: "]",
@@ -514,6 +514,10 @@ describe SeeingIsBelieving::WrapExpressions do
514
514
  wrap("{\n1 => 2}").should == "<{\n1 => 2}>"
515
515
  wrap("{\n1 => 2,\n:abc => 3,\ndef: 4\n}").should == "<{\n1 => <2>,\n:abc => <3>,\ndef: <4>\n}>"
516
516
  end
517
+
518
+ it 'wraps explicit braces around recorded in method invocations' do
519
+ wrap("a(\nb: 1, c: 2\n)").should == "<a(\n<{b: 1, c: 2}>\n)>"
520
+ end
517
521
  end
518
522
 
519
523
  describe 'array literals' do
@@ -761,4 +765,32 @@ describe SeeingIsBelieving::WrapExpressions do
761
765
  end
762
766
  end
763
767
  end
768
+
769
+ describe 'BEGIN/END' do
770
+ # not implemented b/c we cannot wrap around these either.
771
+ # So what does it mean to wrap around?
772
+ # mabe this?
773
+ # 1
774
+ # BEGIN {}
775
+ # 2
776
+ # END {}
777
+ # 3
778
+ #
779
+ # becomes
780
+ # BEGIN {}
781
+ # END {}
782
+ # [<1>
783
+ # <2>
784
+ # <3>]
785
+ #
786
+ # idk, but then we also need to deal with the fact that we're changing result of __LINE__
787
+ # which we could do with some meta, just replacing it with the literal when we parse it
788
+ # but still, moving this out of here will be really annoying, and no one is going to use it, so fuck it
789
+ it 'does not record them', not_implemented: true do
790
+ wrap("BEGIN {}").should == "BEGIN {}"
791
+ wrap("END {}").should == "END {}"
792
+ wrap("BEGIN {\n123\n}").should == "BEGIN {\n<123>\n}"
793
+ wrap("END {\n123\n}").should == "END {\n<123>\n}"
794
+ end
795
+ end
764
796
  end
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: 2.0.0.beta3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Cheek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-14 00:00:00.000000000 Z
11
+ date: 2013-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -166,9 +166,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
166
166
  version: '0'
167
167
  required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  requirements:
169
- - - '>'
169
+ - - '>='
170
170
  - !ruby/object:Gem::Version
171
- version: 1.3.1
171
+ version: '0'
172
172
  requirements: []
173
173
  rubyforge_project: seeing_is_believing
174
174
  rubygems_version: 2.0.5
@@ -192,4 +192,3 @@ test_files:
192
192
  - spec/line_spec.rb
193
193
  - spec/seeing_is_believing_spec.rb
194
194
  - spec/wrap_expressions_spec.rb
195
- has_rdoc: