seeing_is_believing 3.0.0.beta.5 → 3.0.0.beta.6
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 +4 -4
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/.travis.yml +1 -1
- data/Rakefile +28 -18
- data/Readme.md +22 -13
- data/bin/seeing_is_believing +0 -1
- data/features/errors.feature +3 -3
- data/features/examples.feature +65 -0
- data/features/flags.feature +19 -0
- data/lib/seeing_is_believing/binary.rb +1 -1
- data/lib/seeing_is_believing/binary/align_chunk.rb +0 -8
- data/lib/seeing_is_believing/binary/commentable_lines.rb +7 -12
- data/lib/seeing_is_believing/binary/config.rb +18 -6
- data/lib/seeing_is_believing/binary/engine.rb +11 -6
- data/lib/seeing_is_believing/binary/remove_annotations.rb +17 -19
- data/lib/seeing_is_believing/error.rb +2 -2
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +8 -6
- data/lib/seeing_is_believing/event_stream/consumer.rb +55 -24
- data/lib/seeing_is_believing/event_stream/events.rb +11 -0
- data/lib/seeing_is_believing/event_stream/handlers/record_exit_events.rb +26 -0
- data/lib/seeing_is_believing/event_stream/handlers/stream_json_events.rb +0 -22
- data/lib/seeing_is_believing/event_stream/handlers/update_result.rb +1 -0
- data/lib/seeing_is_believing/result.rb +5 -15
- data/lib/seeing_is_believing/version.rb +1 -1
- data/seeing_is_believing.gemspec +3 -2
- data/spec/binary/config_spec.rb +25 -8
- data/spec/binary/engine_spec.rb +12 -5
- data/spec/evaluate_by_moving_files_spec.rb +17 -4
- data/spec/event_stream_spec.rb +45 -10
- data/spec/seeing_is_believing_spec.rb +29 -4
- data/spec/wrap_expressions_spec.rb +6 -1
- metadata +23 -10
- data/Changelog.md +0 -33
- data/lib/seeing_is_believing/event_stream/handlers/record_exitstatus.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8715640842e97ae16fececb478cf4356169e1fdc
|
4
|
+
data.tar.gz: a2bfb634547740e23c0a71710a953496350fb2b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4bbbaaa3640d0dd4b42051eb7416efb940af2b5b7a78df277c8047ec0a91e10b725e0c68a0d0ebf961d20583579ea231c1c2fd90504aded08ce81e20675b9e4
|
7
|
+
data.tar.gz: 319db0b7ee9047fa6c051659f8da8320f83828141e3e47e38448078f87720e7847c35e773ea50331684d644a70917129f0d2e91890aa535023472d797aa0a211
|
data/.gitignore
CHANGED
@@ -1,4 +1,19 @@
|
|
1
|
+
# Transient test files
|
1
2
|
proving_grounds/*
|
3
|
+
|
4
|
+
# Don't accidentally commit gems generated from the source code
|
2
5
|
*.gem
|
6
|
+
|
7
|
+
# Since it's a gem, don't lock it down to specific versions
|
3
8
|
Gemfile.lock
|
9
|
+
|
10
|
+
# local notes about what I'm working on
|
4
11
|
todo
|
12
|
+
|
13
|
+
# Bundler stores its configuration information here
|
14
|
+
.bundle
|
15
|
+
|
16
|
+
# Where I'm vendoring gems for the standalone environment
|
17
|
+
# Going with this location b/c Bundler winds up creating this dir anyway
|
18
|
+
# to make `require "bundler/setup"` work
|
19
|
+
bundle
|
data/.rspec
ADDED
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
@@ -1,29 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'bundler'
|
2
|
+
|
3
|
+
desc 'Have Bundler setup a standalone environment -- run tests in this, b/c its faster and safer'
|
4
|
+
task :build do
|
5
|
+
# Running without rubygems # http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone
|
6
|
+
sh 'bundle install --standalone --binstubs bundle/bin'
|
4
7
|
end
|
5
8
|
|
6
|
-
desc '
|
7
|
-
task :
|
8
|
-
|
9
|
+
desc 'Remove generated and irrelevant files'
|
10
|
+
task :clean do
|
11
|
+
rm_rf [
|
12
|
+
'bundle',
|
13
|
+
'.bundle',
|
14
|
+
'Gemfile.lock',
|
15
|
+
'proving_grounds',
|
16
|
+
*Dir['*.gem'],
|
17
|
+
]
|
9
18
|
end
|
10
19
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
sh 'cucumber -t @wip'
|
15
|
-
end
|
20
|
+
file :bundle do
|
21
|
+
$stderr.puts "\e[31mLooks like the gems aren\'t installed, run `rake build` to install them\e[39m"
|
22
|
+
exit 1
|
16
23
|
end
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
sh 'rspec -t wip'
|
22
|
-
end
|
25
|
+
desc 'Run specs'
|
26
|
+
task spec: :bundle do
|
27
|
+
sh 'ruby', '--disable-gem', *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] }, '-S', 'bundle/bin/rspec'
|
23
28
|
end
|
24
29
|
|
25
|
-
desc 'Run
|
26
|
-
task
|
30
|
+
desc 'Run cukes'
|
31
|
+
task cuke: :bundle do
|
32
|
+
sh 'ruby', '--disable-gem', *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] }, '-S', 'bundle/bin/cucumber', '--tags', '~@not-implemented'
|
33
|
+
end
|
27
34
|
|
28
35
|
desc 'Run all specs and cukes'
|
29
36
|
task default: [:spec, :cuke]
|
37
|
+
|
38
|
+
desc 'Install dependencies and run tests (mainly for Travis CI)'
|
39
|
+
task ci: [:build, :spec, :cuke]
|
data/Readme.md
CHANGED
@@ -64,19 +64,25 @@ Currently requires Ruby 1.9 or 2.x
|
|
64
64
|
Editor Integration
|
65
65
|
==================
|
66
66
|
|
67
|
-
* [
|
67
|
+
* [Atom](https://github.com/JoshCheek/atom-seeing-is-believing) (prob has best installation instructions, overall best integration, but config and filesystem events are iffy)
|
68
|
+
* [Sublime 2 and 3](https://github.com/JoshCheek/sublime-text-2-and-3-seeing-is-believing) (works reasonably, but isn't integrated with the package manager)
|
68
69
|
* [TextMate 1](https://github.com/JoshCheek/text_mate_1-seeing-is_believing)
|
69
|
-
* [TextMate 2](https://github.com/JoshCheek/text_mate_2-seeing-is_believing)
|
70
|
-
|
70
|
+
* [TextMate 2](https://github.com/JoshCheek/text_mate_2-seeing-is_believing) (TM2 is actually looking really nice these days -- Josh Cheek, 18 Feb 2015)
|
71
|
+
|
72
|
+
Vim
|
73
|
+
===
|
74
|
+
|
75
|
+
I didn't write either of these, but they both support Seeing Is Beleiving. I've looked through the code, it works reasonably. One of them, I wound up having to edit the installed package, don't remember which.
|
76
|
+
|
77
|
+
* [vim-ruby-xmpfilter](https://github.com/t9md/vim-ruby-xmpfilter)
|
71
78
|
* [vim-seeing-is-believing](https://github.com/hwartig/vim-seeing-is-believing)
|
72
|
-
* [atom-seeing-is-believing](https://github.com/JoshCheek/atom-seeing-is-believing) (prob has best installation instructions)
|
73
79
|
|
74
80
|
Emacs Integration
|
75
81
|
=================
|
76
82
|
|
77
83
|
Add this function to your Emacs configuration:
|
78
84
|
|
79
|
-
|
85
|
+
```scheme
|
80
86
|
(defun seeing-is-believing ()
|
81
87
|
"Replace the current region (or the whole buffer, if none) with the output
|
82
88
|
of seeing_is_believing."
|
@@ -84,7 +90,7 @@ of seeing_is_believing."
|
|
84
90
|
(let ((beg (if (region-active-p) (region-beginning) (point-min)))
|
85
91
|
(end (if (region-active-p) (region-end) (point-max))))
|
86
92
|
(shell-command-on-region beg end "seeing_is_believing" nil 'replace)))
|
87
|
-
|
93
|
+
```
|
88
94
|
|
89
95
|
You can now call `seeing-is-believing` to replace the current region
|
90
96
|
or current buffer contents with the output of running it through
|
@@ -95,8 +101,8 @@ Known Issues
|
|
95
101
|
|
96
102
|
* `begin; else; break; end` this code (an else without a resecue) will emit a warning in Ruby, and is omitted from `Parser`'s AST.
|
97
103
|
As such, I doubt that anyone will ever write it. But if you were to write it, it would blow up, because SiB rewrites your code, wrapping every expression that could have a value.
|
98
|
-
This code will be wrapped. But using the value is syntactically invalid in Ruby, because it constitutes a "void value expression" (aka a
|
99
|
-
I can't easily check it to seee if it's void since it's not in the parsed AST. But it's so edge
|
104
|
+
This code will be wrapped. But using the value is **syntactically** invalid in Ruby, because it constitutes a "void value expression" (aka a pointless timesink and the cause of many bugs in SiB).
|
105
|
+
Unfortunately, I can't easily check it to seee if it's void since it's not in the parsed AST. But it's so edge that I don't think it's worth worrying about.
|
100
106
|
|
101
107
|
Version 2
|
102
108
|
=========
|
@@ -109,11 +115,14 @@ Version 3
|
|
109
115
|
These need to be done before release:
|
110
116
|
|
111
117
|
* Add default to number of captures (1000), require user to explicitly set it to infinity
|
112
|
-
*
|
113
|
-
*
|
114
|
-
*
|
115
|
-
*
|
116
|
-
*
|
118
|
+
* Expose markers via the CLI
|
119
|
+
* Spruce up editor integration
|
120
|
+
* Integrate with package managers where they are available
|
121
|
+
* Expose options to use the streaming API (update as events are seen)
|
122
|
+
* Ship with Traveling Ruby so that new users can just press a button and it works,
|
123
|
+
rather than having to figure out all the compmlex ecosystem around installing
|
124
|
+
* Would be nice to have real integration with Emacs
|
125
|
+
* Would be nice to support Ruby Mine
|
117
126
|
|
118
127
|
Version 4
|
119
128
|
=========
|
data/bin/seeing_is_believing
CHANGED
data/features/errors.feature
CHANGED
@@ -69,10 +69,10 @@ Feature: Running the binary unsuccessfully
|
|
69
69
|
And the exit status is 2
|
70
70
|
And stdout is empty
|
71
71
|
|
72
|
-
Scenario: Passing unknown
|
72
|
+
Scenario: Passing unknown flags
|
73
73
|
Given the file "some_file" "1"
|
74
|
-
When I run "seeing_is_believing --unknown-
|
75
|
-
Then stderr is 'Error: --unknown-
|
74
|
+
When I run "seeing_is_believing --unknown-flag"
|
75
|
+
Then stderr is 'Error: --unknown-flag is not a flag, see the help screen (-h) for a list of options'
|
76
76
|
And the exit status is 2
|
77
77
|
And stdout is empty
|
78
78
|
|
data/features/examples.feature
CHANGED
@@ -259,6 +259,71 @@ Feature: Running the binary successfully
|
|
259
259
|
And the exit status is 0
|
260
260
|
|
261
261
|
|
262
|
+
@not-implemented
|
263
|
+
Scenario: Fork records data in parent and child, parent exec does not affect it.
|
264
|
+
Given the file "fork_exec_parent.rb":
|
265
|
+
"""
|
266
|
+
:both
|
267
|
+
if fork #
|
268
|
+
:parent
|
269
|
+
exec 'echo', 'hello'
|
270
|
+
else
|
271
|
+
sleep 1
|
272
|
+
:child
|
273
|
+
end
|
274
|
+
:child
|
275
|
+
|
276
|
+
# >> hello
|
277
|
+
"""
|
278
|
+
When I run "seeing_is_believing fork_exec_parent.rb"
|
279
|
+
Then stdout is:
|
280
|
+
"""
|
281
|
+
:both # => :both
|
282
|
+
if fork #
|
283
|
+
:parent # => :parent
|
284
|
+
exec 'echo', 'hello'
|
285
|
+
else
|
286
|
+
sleep 1 # => 1
|
287
|
+
:child # => :child
|
288
|
+
end
|
289
|
+
:child # => :child
|
290
|
+
|
291
|
+
# >> hello
|
292
|
+
"""
|
293
|
+
|
294
|
+
@not-implemented
|
295
|
+
Scenario: Fork records data in parent and child, child exec does not affect it.
|
296
|
+
Given the file "fork_exec_child.rb":
|
297
|
+
"""
|
298
|
+
:both
|
299
|
+
if fork #
|
300
|
+
sleep 1
|
301
|
+
:parent
|
302
|
+
else
|
303
|
+
:child
|
304
|
+
exec 'echo', 'hello'
|
305
|
+
end
|
306
|
+
:parent
|
307
|
+
|
308
|
+
# >> hello
|
309
|
+
"""
|
310
|
+
When I run "seeing_is_believing fork_exec_child.rb"
|
311
|
+
Then stdout is:
|
312
|
+
"""
|
313
|
+
:both # => :both
|
314
|
+
if fork #
|
315
|
+
sleep 1 # => 1
|
316
|
+
:parent # => :parent
|
317
|
+
else
|
318
|
+
:child # => :child
|
319
|
+
exec 'echo', 'hello'
|
320
|
+
end
|
321
|
+
:parent # => :parent
|
322
|
+
|
323
|
+
# >> hello
|
324
|
+
"""
|
325
|
+
|
326
|
+
|
262
327
|
Scenario: Implicit regexp conditional
|
263
328
|
Given the stdin content "abc"
|
264
329
|
And the file "implicit_regex_conditional.rb":
|
data/features/flags.feature
CHANGED
@@ -509,3 +509,22 @@ Feature: Using flags
|
|
509
509
|
"""
|
510
510
|
["sib_version",{"value":"{{SeeingIsBelieving::VERSION}}"}]
|
511
511
|
"""
|
512
|
+
|
513
|
+
Scenario: --stream emits a timeout event and finishes successfully when the process times out.
|
514
|
+
When I run "seeing_is_believing -e 'loop { sleep 1 }' -t 0.01 --stream"
|
515
|
+
Then the exit status is 2
|
516
|
+
And stderr is "Timeout Error after 0.01 seconds!"
|
517
|
+
And stdout includes:
|
518
|
+
"""
|
519
|
+
["finished",{}]
|
520
|
+
"""
|
521
|
+
And stdout includes:
|
522
|
+
"""
|
523
|
+
["timeout",{"seconds":0.01}]
|
524
|
+
"""
|
525
|
+
|
526
|
+
Scenario: --ignore-unknown-flags prevents errors on unknown flags for forward compatibility
|
527
|
+
When I run "seeing_is_believing -e '1' --ignore-unknown-flags --zomg-wat"
|
528
|
+
Then the exit status is 0
|
529
|
+
And stderr is empty
|
530
|
+
And stdout is "1 # => 1"
|
@@ -40,7 +40,7 @@ class SeeingIsBelieving
|
|
40
40
|
engine.evaluate!
|
41
41
|
|
42
42
|
if engine.timed_out?
|
43
|
-
stderr.puts "Timeout Error after #{
|
43
|
+
stderr.puts "Timeout Error after #{engine.timeout_seconds} seconds!"
|
44
44
|
return NONDISPLAYABLE_ERROR_STATUS
|
45
45
|
end
|
46
46
|
|
@@ -37,14 +37,6 @@ class SeeingIsBelieving
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def trim_trailing_whitespace(line_nums_to_indexes)
|
41
|
-
line_nums_to_indexes.each do |num, indexes|
|
42
|
-
index_in_file = indexes[0]
|
43
|
-
num_to_trim = amount_of_preceding_whitespace(index_in_file)
|
44
|
-
indexes.map! { |index| index - num_to_trim }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
40
|
def amount_of_preceding_whitespace(index_of_trailing_newline)
|
49
41
|
index = index_of_trailing_newline - 1
|
50
42
|
index -= 1 while 0 <= index && body[index] !~ /[\S\n]/
|
@@ -42,18 +42,13 @@ class SeeingIsBelieving
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def line_nums_to_last_index_and_col(buffer)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if code[code.size-1] != "\n" # account for the fact that the last line wouldn't have been found above if it doesn't end in a newline
|
53
|
-
line, col = buffer.decompose_position code.size
|
54
|
-
line_num_to_location[line] = [code.size, col]
|
55
|
-
end
|
56
|
-
line_num_to_location
|
45
|
+
code.each_char
|
46
|
+
.with_index
|
47
|
+
.select { |char, index| char == "\n" }
|
48
|
+
.each_with_object(Hash.new) do |(_, index), hash|
|
49
|
+
line, col = buffer.decompose_position index
|
50
|
+
hash[line] = [index, col]
|
51
|
+
end
|
57
52
|
end
|
58
53
|
|
59
54
|
def remove_lines_whose_newline_is_escaped(line_num_to_location)
|
@@ -29,6 +29,7 @@ class SeeingIsBelieving
|
|
29
29
|
predicate(:inherit_exitstatus) { false }
|
30
30
|
predicate(:remove_value_prefixes) { true }
|
31
31
|
predicate(:debug) { false }
|
32
|
+
predicate(:ignore_unknown_flags) { false }
|
32
33
|
attribute(:body) { nil }
|
33
34
|
attribute(:filename) { nil }
|
34
35
|
attribute(:errors) { [] }
|
@@ -46,9 +47,10 @@ class SeeingIsBelieving
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def parse_args(args)
|
49
|
-
|
50
|
-
|
51
|
-
|
50
|
+
args = args.dup
|
51
|
+
as = nil
|
52
|
+
filenames = []
|
53
|
+
unknown_flags = []
|
52
54
|
|
53
55
|
extract_positive_int_for = lambda do |flagname, &on_success|
|
54
56
|
string = args.shift
|
@@ -92,6 +94,9 @@ class SeeingIsBelieving
|
|
92
94
|
when '-v', '--version'
|
93
95
|
self.print_version = true
|
94
96
|
|
97
|
+
when '--ignore-unknown-flags'
|
98
|
+
self.ignore_unknown_flags = true
|
99
|
+
|
95
100
|
when '-x', '--xmpfilter-style'
|
96
101
|
self.annotator = AnnotateMarkedLines
|
97
102
|
self.lib_options.rewrite_code = AnnotateMarkedLines.code_rewriter(markers)
|
@@ -194,7 +199,7 @@ class SeeingIsBelieving
|
|
194
199
|
end
|
195
200
|
|
196
201
|
when /^(-.|--.*)$/
|
197
|
-
|
202
|
+
unknown_flags << arg
|
198
203
|
|
199
204
|
when /^-[^-]/
|
200
205
|
args.unshift *arg.scan(/[^-]\+?/).map { |flag| "-#{flag}" }
|
@@ -204,6 +209,11 @@ class SeeingIsBelieving
|
|
204
209
|
end
|
205
210
|
end
|
206
211
|
|
212
|
+
unknown_flags.each do |flag|
|
213
|
+
break if ignore_unknown_flags?
|
214
|
+
add_error "#{flag} is not a flag, see the help screen (-h) for a list of options"
|
215
|
+
end
|
216
|
+
|
207
217
|
filenames.size > 1 &&
|
208
218
|
add_error("can only have one filename but found #{filenames.map(&:inspect).join ', '}")
|
209
219
|
|
@@ -264,13 +274,13 @@ Usage: seeing_is_believing [options] [filename]
|
|
264
274
|
|
265
275
|
Notes:
|
266
276
|
|
267
|
-
* If no filename or program (-e
|
277
|
+
* If no filename or program (-e option) are provided, the program will read from standard input.
|
268
278
|
* The process's stdin will be passed to the program unless the program body is on stdin.
|
269
279
|
* The exit status will be:
|
270
280
|
0 - No errors
|
271
281
|
1 - Displayable error (e.g. code raises an exception while running)
|
272
282
|
2 - Non-displayable error (e.g. a syntax error, a timeout)
|
273
|
-
n - The program's exit status if the --inherit-exitstatus
|
283
|
+
n - The program's exit status if the --inherit-exitstatus option is set
|
274
284
|
|
275
285
|
Options:
|
276
286
|
-d, --line-length n # max length of the entire line (only truncates results, not source lines)
|
@@ -296,6 +306,8 @@ Options:
|
|
296
306
|
-j, --json # print results in json format (i.e. so another program can consume them)
|
297
307
|
-i, --inherit-exitstatus # exit with the exit status of the program being evaluated
|
298
308
|
--stream # a JSON stream of every event ias it is seen (such as recording a line)
|
309
|
+
--ignore-unknown-flags # don't error when flag is not in this list
|
310
|
+
allows integrating code to support compatibility with future versions of SiB
|
299
311
|
-v, --version # print the version (#{VERSION})
|
300
312
|
-h, --help # help screen without examples
|
301
313
|
-h+, --help+ # help screen with examples
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'seeing_is_believing/code'
|
2
2
|
require 'seeing_is_believing/binary/data_structures'
|
3
3
|
require 'seeing_is_believing/binary/remove_annotations'
|
4
|
-
require 'seeing_is_believing/event_stream/handlers/
|
4
|
+
require 'seeing_is_believing/event_stream/handlers/record_exit_events'
|
5
5
|
|
6
6
|
class SeeingIsBelieving
|
7
7
|
module Binary
|
@@ -38,7 +38,7 @@ class SeeingIsBelieving
|
|
38
38
|
def evaluate!
|
39
39
|
@evaluated || begin
|
40
40
|
SeeingIsBelieving.call normalized_cleaned_body,
|
41
|
-
config.lib_options.merge(event_handler:
|
41
|
+
config.lib_options.merge(event_handler: record_exit_events)
|
42
42
|
@timed_out = false
|
43
43
|
@evaluated = true
|
44
44
|
end
|
@@ -50,7 +50,12 @@ class SeeingIsBelieving
|
|
50
50
|
|
51
51
|
def timed_out?
|
52
52
|
@evaluated || raise(MustEvaluateFirst.new __method__)
|
53
|
-
|
53
|
+
!!timeout_seconds
|
54
|
+
end
|
55
|
+
|
56
|
+
def timeout_seconds
|
57
|
+
@evaluated || raise(MustEvaluateFirst.new __method__)
|
58
|
+
record_exit_events.timeout_seconds
|
54
59
|
end
|
55
60
|
|
56
61
|
def result
|
@@ -71,7 +76,7 @@ class SeeingIsBelieving
|
|
71
76
|
|
72
77
|
def exitstatus
|
73
78
|
@evaluated || raise(MustEvaluateFirst.new __method__)
|
74
|
-
|
79
|
+
record_exit_events.exitstatus
|
75
80
|
end
|
76
81
|
|
77
82
|
private
|
@@ -86,8 +91,8 @@ class SeeingIsBelieving
|
|
86
91
|
@code ||= Code.new(normalized_cleaned_body, config.filename)
|
87
92
|
end
|
88
93
|
|
89
|
-
def
|
90
|
-
@
|
94
|
+
def record_exit_events
|
95
|
+
@record_exit_events ||= SeeingIsBelieving::EventStream::Handlers::RecordExitEvents.new config.lib_options.event_handler
|
91
96
|
end
|
92
97
|
|
93
98
|
def normalized_cleaned_body
|