seeing_is_believing 3.0.0.beta.4 → 3.0.0.beta.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -8
  3. data/Rakefile +1 -1
  4. data/Readme.md +65 -25
  5. data/bin/seeing_is_believing +1 -0
  6. data/docs/sib-streaming.gif +0 -0
  7. data/features/deprecated-flags.feature +62 -2
  8. data/features/errors.feature +12 -7
  9. data/features/examples.feature +143 -4
  10. data/features/flags.feature +89 -29
  11. data/features/regression.feature +58 -14
  12. data/features/support/env.rb +4 -0
  13. data/features/xmpfilter-style.feature +181 -36
  14. data/lib/seeing_is_believing.rb +44 -33
  15. data/lib/seeing_is_believing/binary.rb +31 -88
  16. data/lib/seeing_is_believing/binary/align_chunk.rb +30 -11
  17. data/lib/seeing_is_believing/binary/annotate_end_of_file.rb +10 -16
  18. data/lib/seeing_is_believing/binary/annotate_every_line.rb +5 -25
  19. data/lib/seeing_is_believing/binary/annotate_marked_lines.rb +136 -0
  20. data/lib/seeing_is_believing/binary/comment_lines.rb +8 -10
  21. data/lib/seeing_is_believing/binary/commentable_lines.rb +20 -26
  22. data/lib/seeing_is_believing/binary/config.rb +392 -0
  23. data/lib/seeing_is_believing/binary/data_structures.rb +57 -0
  24. data/lib/seeing_is_believing/binary/engine.rb +104 -0
  25. data/lib/seeing_is_believing/binary/{comment_formatter.rb → format_comment.rb} +6 -6
  26. data/lib/seeing_is_believing/binary/remove_annotations.rb +29 -28
  27. data/lib/seeing_is_believing/binary/rewrite_comments.rb +42 -43
  28. data/lib/seeing_is_believing/code.rb +105 -49
  29. data/lib/seeing_is_believing/debugger.rb +6 -5
  30. data/lib/seeing_is_believing/error.rb +6 -17
  31. data/lib/seeing_is_believing/evaluate_by_moving_files.rb +78 -129
  32. data/lib/seeing_is_believing/event_stream/consumer.rb +114 -64
  33. data/lib/seeing_is_believing/event_stream/events.rb +169 -11
  34. data/lib/seeing_is_believing/event_stream/handlers/debug.rb +57 -0
  35. data/lib/seeing_is_believing/event_stream/handlers/record_exitstatus.rb +18 -0
  36. data/lib/seeing_is_believing/event_stream/handlers/stream_json_events.rb +45 -0
  37. data/lib/seeing_is_believing/event_stream/handlers/update_result.rb +39 -0
  38. data/lib/seeing_is_believing/event_stream/producer.rb +25 -24
  39. data/lib/seeing_is_believing/hash_struct.rb +206 -0
  40. data/lib/seeing_is_believing/result.rb +20 -3
  41. data/lib/seeing_is_believing/the_matrix.rb +20 -12
  42. data/lib/seeing_is_believing/version.rb +1 -1
  43. data/lib/seeing_is_believing/wrap_expressions.rb +55 -115
  44. data/lib/seeing_is_believing/wrap_expressions_with_inspect.rb +14 -0
  45. data/seeing_is_believing.gemspec +1 -1
  46. data/spec/binary/alignment_specs.rb +27 -0
  47. data/spec/binary/comment_lines_spec.rb +3 -2
  48. data/spec/binary/config_spec.rb +657 -0
  49. data/spec/binary/engine_spec.rb +97 -0
  50. data/spec/binary/{comment_formatter_spec.rb → format_comment_spec.rb} +2 -2
  51. data/spec/binary/marker_spec.rb +71 -0
  52. data/spec/binary/options_spec.rb +0 -0
  53. data/spec/binary/remove_annotations_spec.rb +31 -18
  54. data/spec/binary/rewrite_comments_spec.rb +26 -11
  55. data/spec/code_spec.rb +190 -6
  56. data/spec/debugger_spec.rb +4 -0
  57. data/spec/evaluate_by_moving_files_spec.rb +38 -20
  58. data/spec/event_stream_spec.rb +265 -116
  59. data/spec/hash_struct_spec.rb +514 -0
  60. data/spec/seeing_is_believing_spec.rb +108 -46
  61. data/spec/spec_helper.rb +9 -0
  62. data/spec/wrap_expressions_spec.rb +207 -172
  63. metadata +30 -18
  64. data/docs/for-presentations +0 -33
  65. data/lib/seeing_is_believing/binary/annotate_xmpfilter_style.rb +0 -128
  66. data/lib/seeing_is_believing/binary/interpret_flags.rb +0 -156
  67. data/lib/seeing_is_believing/binary/parse_args.rb +0 -263
  68. data/lib/seeing_is_believing/event_stream/update_result.rb +0 -24
  69. data/lib/seeing_is_believing/inspect_expressions.rb +0 -21
  70. data/lib/seeing_is_believing/parser_helpers.rb +0 -82
  71. data/spec/binary/interpret_flags_spec.rb +0 -332
  72. data/spec/binary/parse_args_spec.rb +0 -415
@@ -1,28 +1,26 @@
1
1
  require 'seeing_is_believing/binary/commentable_lines'
2
2
 
3
3
  class SeeingIsBelieving
4
- # spec/binary/comment_lines_spec.rb
5
4
  module Binary
6
-
7
5
  # takes a body and a block
8
6
  # passes the block the line
9
7
  # the block returns the comment to add at the end of it
10
8
  class CommentLines
11
- def self.call(code, &commenter)
12
- new(code, &commenter).call
9
+ def self.call(raw_code, &commenter)
10
+ new(raw_code, &commenter).call
13
11
  end
14
12
 
15
- def initialize(code, &commenter)
16
- self.code, self.commenter = code, commenter
13
+ def initialize(raw_code, &commenter)
14
+ self.raw_code, self.commenter = raw_code, commenter
17
15
  end
18
16
 
19
17
  def call
20
18
  @call ||= begin
21
- commentable_lines = CommentableLines.new code
19
+ commentable_lines = CommentableLines.new raw_code
22
20
  commentable_lines.call.each do |line_number, (index_of_newline, col)|
23
21
  first_index = last_index = index_of_newline
24
- first_index -= 1 while first_index > 0 && code[first_index-1] != "\n"
25
- comment_text = commenter.call code[first_index...last_index], line_number
22
+ first_index -= 1 while first_index > 0 && raw_code[first_index-1] != "\n"
23
+ comment_text = commenter.call raw_code[first_index...last_index], line_number
26
24
  range = Parser::Source::Range.new(commentable_lines.buffer, first_index, last_index)
27
25
  commentable_lines.rewriter.insert_after range, comment_text
28
26
  end
@@ -32,7 +30,7 @@ class SeeingIsBelieving
32
30
 
33
31
  private
34
32
 
35
- attr_accessor :code, :commenter
33
+ attr_accessor :raw_code, :commenter
36
34
  end
37
35
  end
38
36
  end
@@ -1,24 +1,16 @@
1
- require 'seeing_is_believing/parser_helpers'
1
+ require 'seeing_is_believing/code'
2
2
 
3
3
  class SeeingIsBelieving
4
4
  module Binary
5
5
 
6
- # could possibly be sped up by just reflecting on the tokens instead of the whole ast
7
- #
8
- # specs for this class are in spec/binary/comment_lines_spec.rb
9
- # because it was extracted from that class
10
6
  class CommentableLines
11
-
12
- include ParserHelpers
13
-
14
7
  def self.call(code)
15
8
  new(code).call
16
9
  end
17
10
 
18
11
  def initialize(code)
19
12
  self.code = code
20
- self.buffer, self.parser, self.rewriter = initialize_parser(code, 'finding_commentable_lines')
21
- self.root, self.comments = parser.parse_with_comments(buffer)
13
+ self.code_obj = Code.new(code, 'finding_commentable_lines')
22
14
  end
23
15
 
24
16
  def call
@@ -26,18 +18,28 @@ class SeeingIsBelieving
26
18
  line_num_to_location = line_nums_to_last_index_and_col(buffer)
27
19
  remove_lines_after_data_segment line_num_to_location
28
20
  remove_lines_whose_newline_is_escaped line_num_to_location
29
- remove_lines_ending_in_comments line_num_to_location, comments
21
+ remove_lines_ending_in_comments line_num_to_location, code_obj.raw_comments
30
22
  remove_lines_inside_of_strings_and_things line_num_to_location, root
31
23
  line_num_to_location
32
24
  end
33
25
  end
34
26
 
35
- attr_reader :buffer, :rewriter
27
+ def buffer
28
+ code_obj.buffer
29
+ end
30
+
31
+ def rewriter
32
+ code_obj.rewriter
33
+ end
36
34
 
37
35
  private
38
36
 
39
37
  attr_writer :buffer, :rewriter
40
- attr_accessor :code, :parser, :root, :comments
38
+ attr_accessor :code, :code_obj
39
+
40
+ def root
41
+ code_obj.root
42
+ end
41
43
 
42
44
  def line_nums_to_last_index_and_col(buffer)
43
45
  line_num_to_location = code.each_char
@@ -83,7 +85,7 @@ class SeeingIsBelieving
83
85
 
84
86
  def ranges_of_atomic_expressions(ast, found_ranges)
85
87
  return found_ranges unless ast.kind_of? ::AST::Node
86
- if no_comment_zone?(ast) && heredoc?(ast)
88
+ if no_comment_zone?(ast) && code_obj.heredoc?(ast)
87
89
  begin_pos = ast.location.heredoc_body.begin_pos
88
90
  end_pos = ast.location.heredoc_end.end_pos.next
89
91
  found_ranges << (begin_pos...end_pos)
@@ -110,18 +112,10 @@ class SeeingIsBelieving
110
112
  end
111
113
 
112
114
  def remove_lines_after_data_segment(line_num_to_location)
113
- data_segment_line, _ = line_num_to_location.find do |line_number, (end_index, col)|
114
- if end_index == 7
115
- code.start_with? '__END__'
116
- elsif end_index < 7
117
- false
118
- else
119
- code[(end_index-8)...end_index] == "\n__END__"
120
- end
121
- end
122
- return unless data_segment_line
123
- max_line = line_num_to_location.keys.max
124
- data_segment_line.upto(max_line) { |line_number| line_num_to_location.delete line_number }
115
+ end_index = code_obj.body_range.end_pos
116
+ body_end = code_obj.index_to_linenum end_index
117
+ file_end = line_num_to_location.keys.max
118
+ body_end.upto(file_end) { |line_number| line_num_to_location.delete line_number }
125
119
  end
126
120
  end
127
121
  end
@@ -0,0 +1,392 @@
1
+ # encoding: utf-8
2
+ require 'seeing_is_believing'
3
+ require 'seeing_is_believing/binary/data_structures'
4
+
5
+ # one of these will be the alignment strategy
6
+ require 'seeing_is_believing/binary/align_file'
7
+ require 'seeing_is_believing/binary/align_line'
8
+ require 'seeing_is_believing/binary/align_chunk'
9
+
10
+ # one of these will annotate the bdoy
11
+ require 'seeing_is_believing/binary/annotate_every_line'
12
+ require 'seeing_is_believing/binary/annotate_marked_lines'
13
+
14
+
15
+ class SeeingIsBelieving
16
+ module Binary
17
+ class Config < HashStruct
18
+ DeprecatedArgMessage = Binary::ErrorMessage.for :args do
19
+ def to_s
20
+ "Deprecated: `#{args.join ' '}` #{explanation}"
21
+ end
22
+ end
23
+
24
+ predicate(:print_version) { false }
25
+ predicate(:print_cleaned) { false }
26
+ predicate(:print_help) { false }
27
+ predicate(:print_event_stream) { false }
28
+ predicate(:result_as_json) { false }
29
+ predicate(:inherit_exitstatus) { false }
30
+ predicate(:remove_value_prefixes) { true }
31
+ predicate(:debug) { false }
32
+ attribute(:body) { nil }
33
+ attribute(:filename) { nil }
34
+ attribute(:errors) { [] }
35
+ attribute(:deprecations) { [] }
36
+ attribute(:timeout_seconds) { 0 }
37
+ attribute(:annotator) { AnnotateEveryLine }
38
+ attribute(:debugger) { Debugger::Null }
39
+ attribute(:markers) { Markers.new }
40
+ attribute(:help_screen) { |c| Binary.help_screen c.markers }
41
+ attribute(:lib_options) { SeeingIsBelieving::Options.new }
42
+ attribute(:annotator_options) { AnnotatorOptions.new }
43
+
44
+ def add_error(explanation)
45
+ errors << ErrorMessage.new(explanation: explanation)
46
+ end
47
+
48
+ def parse_args(args)
49
+ as = nil
50
+ filenames = []
51
+ args = args.dup
52
+
53
+ extract_positive_int_for = lambda do |flagname, &on_success|
54
+ string = args.shift
55
+ int = string.to_i
56
+ if int.to_s == string && 0 < int
57
+ on_success.call int
58
+ else
59
+ add_error "#{flagname} expects a positive integer argument"
60
+ end
61
+ string
62
+ end
63
+
64
+ extract_non_negative_float_for = lambda do |flagname, &on_success|
65
+ begin
66
+ string = args.shift
67
+ float = Float string
68
+ raise if float < 0
69
+ on_success.call float
70
+ string
71
+ rescue
72
+ add_error "#{flagname} expects a positive float or integer argument"
73
+ end
74
+ end
75
+
76
+ saw_deprecated = lambda do |explanation, *args|
77
+ self.deprecations << DeprecatedArgMessage.new(explanation: explanation, args: args)
78
+ end
79
+
80
+ next_arg = lambda do |flagname, argtype, &on_success|
81
+ arg = args.shift
82
+ arg ? on_success.call(arg) :
83
+ add_error("#{flagname} needs an argument (#{argtype})")
84
+ arg
85
+ end
86
+
87
+ until args.empty?
88
+ case (arg = args.shift)
89
+ when '-c', '--clean'
90
+ self.print_cleaned = true
91
+
92
+ when '-v', '--version'
93
+ self.print_version = true
94
+
95
+ when '-x', '--xmpfilter-style'
96
+ self.annotator = AnnotateMarkedLines
97
+ self.lib_options.rewrite_code = AnnotateMarkedLines.code_rewriter(markers)
98
+ self.remove_value_prefixes = false
99
+ self.lib_options.require_files << 'pp'
100
+
101
+ when '-i', '--inherit-exitstatus', '--inherit-exit-status'
102
+ self.inherit_exitstatus = true
103
+ arg.include?("exit-status") &&
104
+ saw_deprecated.call("Dash has been removed for consistency, use --inherit-exitstatus", arg)
105
+
106
+ when '-j', '--json'
107
+ self.result_as_json = true
108
+
109
+ when '--stream'
110
+ self.print_event_stream = true
111
+
112
+ when '-h', '--help'
113
+ self.print_help = true
114
+ self.help_screen = Binary.help_screen(markers)
115
+
116
+ when '-h+', '--help+'
117
+ self.print_help = true
118
+ self.help_screen = Binary.help_screen_extended(markers)
119
+
120
+ when '-g', '--debug'
121
+ self.debug = true
122
+
123
+ when '-d', '--line-length'
124
+ extract_positive_int_for.call arg do |n|
125
+ self.annotator_options.max_line_length = n
126
+ end
127
+
128
+ when '-D', '--result-length'
129
+ extract_positive_int_for.call arg do |n|
130
+ self.annotator_options.max_result_length = n
131
+ end
132
+
133
+ when '-n', '--max-line-captures', '--number-of-captures'
134
+ extracted = extract_positive_int_for.call arg do |n|
135
+ self.lib_options.max_line_captures = n
136
+ end
137
+ seen = [arg]
138
+ seen << extracted if extracted
139
+ '--number-of-captures' == arg && saw_deprecated.call("use --max-line-captures instead", *seen)
140
+
141
+ when '-t', '--timeout-seconds', '--timeout'
142
+ extracted = extract_non_negative_float_for.call arg do |n|
143
+ self.timeout_seconds = n
144
+ self.lib_options.timeout_seconds = n
145
+ end
146
+ '--timeout' == arg && saw_deprecated.call("use --timeout-seconds instead", arg, extracted)
147
+
148
+ when '-r', '--require'
149
+ next_arg.call arg, "a filename" do |filename|
150
+ self.lib_options.require_files << filename
151
+ end
152
+
153
+ when '-I', '--load-path'
154
+ next_arg.call arg, "a directory" do |dir|
155
+ self.lib_options.load_path_dirs << dir
156
+ end
157
+
158
+ when '-e', '--program'
159
+ next_arg.call arg, "the program body" do |program|
160
+ self.body = program
161
+ end
162
+
163
+ when '-a', '--as'
164
+ next_arg.call arg, "a filename" do |filename|
165
+ as = filename
166
+ end
167
+
168
+ when '-s', '--alignment-strategy'
169
+ strategies = {'file' => AlignFile, 'chunk' => AlignChunk, 'line' => AlignLine}
170
+ strategy_names = strategies.keys.inspect
171
+ next_arg.call arg, "one of these alignment strategies: #{strategy_names}" do |name|
172
+ if strategies[name]
173
+ self.annotator_options.alignment_strategy = strategies[name]
174
+ else
175
+ add_error("#{arg} got the alignment strategy #{name.inspect}, expected one of: #{strategy_names}")
176
+ end
177
+ end
178
+
179
+ when '--shebang'
180
+ executable = args.shift
181
+ if executable
182
+ saw_deprecated.call "SiB now uses the Ruby it was invoked with", arg, executable
183
+ else
184
+ add_error("#{arg} expected an arg: path to a ruby executable")
185
+ saw_deprecated.call "SiB now uses the Ruby it was invoked with", arg
186
+ end
187
+
188
+ when /\A-K(.+)/
189
+ self.lib_options.encoding = $1
190
+
191
+ when '-K', '--encoding'
192
+ next_arg.call arg, "an encoding" do |encoding|
193
+ self.lib_options.encoding = encoding
194
+ end
195
+
196
+ when /^(-.|--.*)$/
197
+ add_error("#{arg} is not an option, see the help screen (-h) for a list of options")
198
+
199
+ when /^-[^-]/
200
+ args.unshift *arg.scan(/[^-]\+?/).map { |flag| "-#{flag}" }
201
+
202
+ else
203
+ filenames << arg
204
+ end
205
+ end
206
+
207
+ filenames.size > 1 &&
208
+ add_error("can only have one filename but found #{filenames.map(&:inspect).join ', '}")
209
+
210
+ result_as_json? && annotator == AnnotateMarkedLines &&
211
+ add_error("SiB does not currently support output with both json and xmpfilter... maybe v4 :)")
212
+
213
+ print_event_stream? && (result_as_json? || annotator == AnnotateMarkedLines) &&
214
+ add_error("can only have one output format, --stream is not compatible with --json, -x, and --xmpfilter-style")
215
+
216
+ self.filename = filenames.first
217
+ self.lib_options.filename = as || filename
218
+ self.lib_options.debugger = debugger
219
+ self.annotator_options.markers = markers
220
+
221
+ self
222
+ end
223
+
224
+ def finalize(stdin, stdout, stderr, file_class)
225
+ if print_event_stream?
226
+ require 'seeing_is_believing/event_stream/handlers/stream_json_events'
227
+ lib_options.event_handler = EventStream::Handlers::StreamJsonEvents.new(stdout)
228
+ end
229
+
230
+ if debug?
231
+ self.debugger = Debugger.new stream: stderr, colour: true
232
+ self.lib_options.debugger = debugger
233
+ end
234
+
235
+ if filename && body
236
+ add_error("Cannot give a program body and a filename to get the program body from.")
237
+ elsif filename && file_class.exist?(filename)
238
+ self.lib_options.stdin = stdin
239
+ self.body = file_class.read filename
240
+ elsif filename
241
+ add_error("#{filename} does not exist!")
242
+ elsif body
243
+ self.lib_options.stdin = stdin
244
+ elsif print_version? || print_help? || errors.any?
245
+ self.body = ""
246
+ else
247
+ self.body = stdin.read
248
+ end
249
+
250
+ self
251
+ end
252
+
253
+ end
254
+ end
255
+
256
+ def Binary.help_screen(markers)
257
+ value = markers[:value][:prefix]
258
+ stdout = markers[:stdout][:prefix]
259
+
260
+ <<FLAGS
261
+ Usage: seeing_is_believing [options] [filename]
262
+
263
+ seeing_is_believing is a program and library that will evaluate a Ruby file and capture/display the results.
264
+
265
+ Notes:
266
+
267
+ * If no filename or program (-e flag) are provided, the program will read from standard input.
268
+ * The process's stdin will be passed to the program unless the program body is on stdin.
269
+ * The exit status will be:
270
+ 0 - No errors
271
+ 1 - Displayable error (e.g. code raises an exception while running)
272
+ 2 - Non-displayable error (e.g. a syntax error, a timeout)
273
+ n - The program's exit status if the --inherit-exitstatus flag is set
274
+
275
+ Options:
276
+ -d, --line-length n # max length of the entire line (only truncates results, not source lines)
277
+ -D, --result-length n # max length of the portion after the "#{value}"
278
+ -n, --max-line-captures n # how many results to capture for a given line
279
+ if you had 1 million results on a line, it could take a long time to record
280
+ and serialize them, you might limit it to 1000 results as an optimization
281
+ -s, --alignment-strategy name # select the alignment strategy:
282
+ chunk (DEFAULT) => each chunk of code is at the same alignment
283
+ file => the entire file is at the same alignment
284
+ line => each line is at its own alignment
285
+ -t, --timeout-seconds s # how long to evaluate the source file before timing out
286
+ 0 means it will never timeout (this is the default)
287
+ accepts floating point values (e.g. 0.5 would timeout after half a second)
288
+ -I, --load-path dir # a dir that should be added to the $LOAD_PATH
289
+ -r, --require file # additional files to be required before running the program
290
+ -e, --program program-body # pass the program body to execute as an argument
291
+ -K, --encoding encoding # sets file encoding, equivalent to Ruby's -Kx (see `man ruby` for valid values)
292
+ -a, --as filename # run the program as if it was the specified filename
293
+ -c, --clean # remove annotations from previous runs of seeing_is_believing
294
+ -g, --debug # print debugging information
295
+ -x, --xmpfilter-style # annotate marked lines instead of every line
296
+ -j, --json # print results in json format (i.e. so another program can consume them)
297
+ -i, --inherit-exitstatus # exit with the exit status of the program being evaluated
298
+ --stream # a JSON stream of every event ias it is seen (such as recording a line)
299
+ -v, --version # print the version (#{VERSION})
300
+ -h, --help # help screen without examples
301
+ -h+, --help+ # help screen with examples
302
+ FLAGS
303
+ end
304
+
305
+ def Binary.help_screen_extended(markers)
306
+ value = markers[:value][:prefix]
307
+ stdout = markers[:stdout][:prefix]
308
+ help_screen(markers) << <<EXAMPLES
309
+ Examples: A few examples, for a more comprehensive set of examples, check out features/flags.feature
310
+ NOTE: $'1\\n2' is the bash string literal for Ruby's "1\\n2"
311
+
312
+ Run the file myfile.rb
313
+ $ echo __FILE__ > myfile.rb; seeing_is_believing myfile.rb
314
+ __FILE__ #{value}"myfile.rb"
315
+
316
+ Run against standard input
317
+ $ echo ':program' | seeing_is_believing
318
+ :program #{value}:program
319
+
320
+ Pass the program in an argument
321
+ $ seeing_is_believing -e ':program'
322
+ :program #{value}:program
323
+
324
+ Remove previous output
325
+ $ seeing_is_believing -e ":program" | seeing_is_believing --clean
326
+ :program
327
+
328
+ Aligning comments
329
+ $ seeing_is_believing -s line -e $'123\\n4\\n\\n567890'
330
+ 123 #{value}123
331
+ 4 #{value}4
332
+
333
+ 567890 #{value}567890
334
+
335
+
336
+ $ seeing_is_believing -s chunk -e $'123\\n4\\n\\n567890'
337
+ 123 #{value}123
338
+ 4 #{value}4
339
+
340
+ 567890 #{value}567890
341
+
342
+
343
+ $ seeing_is_believing -s file -e $'123\\n4\\n\\n567890'
344
+ 123 #{value}123
345
+ 4 #{value}4
346
+
347
+ 567890 #{value}567890
348
+
349
+ Run against a library you're working on by fixing the load path
350
+ $ seeing_is_believing -I ./lib f.rb
351
+
352
+ Require a file before yours is run (can be used in tandem with -I)
353
+ $ seeing_is_believing -r pp -e 'pp [[*1..5]]*5'
354
+ pp [[*1..5]]*5 #{value}[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
355
+
356
+ #{stdout}[[1, 2, 3, 4, 5],
357
+ #{stdout} [1, 2, 3, 4, 5],
358
+ #{stdout} [1, 2, 3, 4, 5],
359
+ #{stdout} [1, 2, 3, 4, 5],
360
+ #{stdout} [1, 2, 3, 4, 5]]
361
+
362
+ Only update the lines you've marked
363
+ $ seeing_is_believing -x -e $'1\\n2 # =>\\n3' |
364
+ 1
365
+ 2 #{value}2
366
+ 3
367
+
368
+ Display a complex structure across multiple lines
369
+ $ seeing_is_believing -x -e $'{foo: 42, bar: {baz: 1, buz: 2, fuz: 3}, wibble: {magic_word: "xyzzy"}}\\n#{value}'
370
+ {foo: 42, bar: {baz: 1, buz: 2, fuz: 3}, wibble: {magic_word: "xyzzy"}}
371
+ #{value} {:foo=>42,
372
+ # :bar=>{:baz=>1, :buz=>2, :fuz=>3},
373
+ # :wibble=>{:magic_word=>"xyzzy"}}
374
+
375
+ Display a stream of events as they are seen
376
+ $ seeing_is_believing -e $':a\\n:b\\n:c' --stream
377
+ ["ruby_version",{"value":#{RUBY_VERSION.inspect}}]
378
+ ["sib_version",{"value":#{SeeingIsBelieving::VERSION.inspect}}]
379
+ ["filename",{"value":"/var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20150116-49548-kr0xop/program.rb"}]
380
+ ["max_line_captures",{"value":-1,"is_infinity":true}]
381
+ ["num_lines",{"value":3}]
382
+ ["line_result",{"type":"inspect","line_number":1,"inspected":":a"}]
383
+ ["line_result",{"type":"inspect","line_number":2,"inspected":":b"}]
384
+ ["line_result",{"type":"inspect","line_number":3,"inspected":":c"}]
385
+ ["event_stream_closed",{"side":"producer"}]
386
+ ["stderr_closed",{"side":"producer"}]
387
+ ["stdout_closed",{"side":"producer"}]
388
+ ["exitstatus",{"value":0}]
389
+ ["finished",{}]
390
+ EXAMPLES
391
+ end
392
+ end