seeing_is_believing 2.2.0 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Changelog.md +33 -0
  4. data/bin/seeing_is_believing +1 -1
  5. data/features/errors.feature +3 -3
  6. data/features/examples.feature +6 -6
  7. data/features/flags.feature +51 -196
  8. data/features/regression.feature +12 -3
  9. data/features/safe.feature +33 -0
  10. data/features/support/env.rb +20 -0
  11. data/features/xmpfilter-style.feature +156 -0
  12. data/lib/seeing_is_believing.rb +17 -35
  13. data/lib/seeing_is_believing/binary.rb +81 -176
  14. data/lib/seeing_is_believing/binary/align_chunk.rb +5 -7
  15. data/lib/seeing_is_believing/binary/align_file.rb +4 -5
  16. data/lib/seeing_is_believing/binary/align_line.rb +4 -4
  17. data/lib/seeing_is_believing/binary/annotate_end_of_file.rb +60 -0
  18. data/lib/seeing_is_believing/binary/annotate_every_line.rb +64 -0
  19. data/lib/seeing_is_believing/binary/annotate_xmpfilter_style.rb +133 -0
  20. data/lib/seeing_is_believing/binary/comment_formatter.rb +19 -5
  21. data/lib/seeing_is_believing/binary/comment_lines.rb +1 -1
  22. data/lib/seeing_is_believing/binary/commentable_lines.rb +1 -1
  23. data/lib/seeing_is_believing/binary/interpret_flags.rb +149 -0
  24. data/lib/seeing_is_believing/binary/parse_args.rb +96 -104
  25. data/lib/seeing_is_believing/binary/remove_annotations.rb +95 -0
  26. data/lib/seeing_is_believing/binary/rewrite_comments.rb +8 -30
  27. data/lib/seeing_is_believing/code.rb +99 -0
  28. data/lib/seeing_is_believing/evaluate_by_moving_files.rb +27 -19
  29. data/lib/seeing_is_believing/evaluate_with_eval_in.rb +27 -0
  30. data/lib/seeing_is_believing/event_stream/consumer.rb +111 -0
  31. data/lib/seeing_is_believing/event_stream/events.rb +16 -0
  32. data/lib/seeing_is_believing/event_stream/producer.rb +106 -0
  33. data/lib/seeing_is_believing/event_stream/update_result.rb +21 -0
  34. data/lib/seeing_is_believing/inspect_expressions.rb +24 -0
  35. data/lib/seeing_is_believing/parser_helpers.rb +1 -11
  36. data/lib/seeing_is_believing/result.rb +14 -56
  37. data/lib/seeing_is_believing/the_matrix.rb +14 -14
  38. data/lib/seeing_is_believing/version.rb +1 -1
  39. data/lib/seeing_is_believing/wrap_expressions.rb +32 -9
  40. data/seeing_is_believing.gemspec +7 -7
  41. data/spec/binary/comment_formatter_spec.rb +169 -18
  42. data/spec/binary/comment_lines_spec.rb +1 -1
  43. data/spec/binary/interpret_flags_spec.rb +307 -0
  44. data/spec/binary/parse_args_spec.rb +93 -91
  45. data/spec/binary/{clean_body_spec.rb → remove_annotations_spec.rb} +29 -22
  46. data/spec/binary/rewrite_comments_spec.rb +13 -13
  47. data/spec/code_spec.rb +49 -0
  48. data/spec/debugger_spec.rb +1 -1
  49. data/spec/evaluate_by_moving_files_spec.rb +7 -3
  50. data/spec/event_stream_spec.rb +390 -0
  51. data/spec/hard_core_ensure_spec.rb +1 -1
  52. data/spec/seeing_is_believing_spec.rb +137 -40
  53. data/spec/spec_helper.rb +3 -3
  54. data/spec/wrap_expressions_spec.rb +48 -35
  55. metadata +58 -35
  56. data/lib/seeing_is_believing/binary/add_annotations.rb +0 -144
  57. data/lib/seeing_is_believing/binary/clean_body.rb +0 -95
  58. data/lib/seeing_is_believing/has_exception.rb +0 -27
  59. data/lib/seeing_is_believing/line.rb +0 -90
  60. data/spec/line_spec.rb +0 -86
@@ -1,146 +1,140 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'stringio'
4
- require 'seeing_is_believing/version'
5
- require 'seeing_is_believing/binary'
6
- require 'seeing_is_believing/debugger'
7
- require 'seeing_is_believing/binary/align_file'
8
- require 'seeing_is_believing/binary/align_line'
9
- require 'seeing_is_believing/binary/align_chunk'
3
+ require 'seeing_is_believing/version' # We print the version in the output
10
4
 
11
5
  class SeeingIsBelieving
12
- class Binary
6
+ module Binary
13
7
  class ParseArgs
14
- def self.call(args, outstream)
15
- new(args, outstream).call
8
+ def self.default_markers
9
+ { value: '# => ',
10
+ exception: '# ~> ',
11
+ stdout: '# >> ',
12
+ stderr: '# !> ',
13
+ nextline: '# ',
14
+ }
15
+ end
16
+
17
+ def self.call(args)
18
+ new(args).call
16
19
  end
17
20
 
18
- def initialize(args, outstream)
19
- self.args = args
20
- self.filenames = []
21
- self.outstream = outstream
21
+ def initialize(args)
22
+ self.args = args.dup
22
23
  end
23
24
 
24
25
  def call
25
26
  @result ||= begin
26
27
  until args.empty?
27
28
  case (arg = args.shift)
28
- when '-h', '--help' then options[:help] = self.class.help_screen(false)
29
- when '-h+', '--help+' then options[:help] = self.class.help_screen(true)
30
- when '-c', '--clean' then options[:clean] = true
31
- when '-v', '--version' then options[:version] = true
32
- when '-x', '--xmpfilter-style' then options[:xmpfilter_style] = true
33
- when '-i', '--inherit-exit-status' then options[:inherit_exit_status] = true
34
- when '-j', '--json' then options[:result_as_json] = true
35
- when '-g', '--debug' then options[:debugger] = Debugger.new(stream: outstream, colour: true)
36
- when '-l', '--start-line' then extract_positive_int_for :start_line, arg
37
- when '-L', '--end-line' then extract_positive_int_for :end_line, arg
29
+ when '-h', '--help' then flags[:help] = 'help'
30
+ when '-h+', '--help+' then flags[:help] = 'help+'
31
+ when '-c', '--clean' then flags[:clean] = true
32
+ when '-v', '--version' then flags[:version] = true
33
+ when '-x', '--xmpfilter-style' then flags[:xmpfilter_style] = true
34
+ when '-i', '--inherit-exit-status' then flags[:inherit_exit_status] = true
35
+ when '-j', '--json' then flags[:result_as_json] = true
36
+ when '-g', '--debug' then flags[:debug] = true
37
+ when '--safe' then flags[:safe] = true
38
38
  when '-d', '--line-length' then extract_positive_int_for :max_line_length, arg
39
39
  when '-D', '--result-length' then extract_positive_int_for :max_result_length, arg
40
40
  when '-n', '--number-of-captures' then extract_positive_int_for :number_of_captures, arg
41
41
  when '-t', '--timeout' then extract_non_negative_float_for :timeout, arg
42
- when '-r', '--require' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:require] << filename }
43
- when '-I', '--load-path' then next_arg("#{arg} expected a directory as the following argument but did not see one") { |dir| options[:load_path] << dir }
44
- when '-e', '--program' then next_arg("#{arg} expected a program as the following argument but did not see one") { |program| options[:program] = program }
45
- when '-a', '--as' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:as] = filename }
46
- when '--shebang' then next_arg("#{arg} expects a ruby executable as the following argument but did not see one") { |executable| options[:shebang] = executable }
47
- when '-s', '--alignment-strategy' then extract_alignment_strategy
48
- when /\A-K(.+)/ then options[:encoding] = $1
49
- when '-K', '--encoding' then next_arg("#{arg} expects an encoding, see `man ruby` for possibile values") { |encoding| options[:encoding] = encoding }
50
- when /^-/ then options[:errors] << "Unknown option: #{arg.inspect}" # unknown flags
42
+ when '-r', '--require' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| flags[:require] << filename }
43
+ when '-I', '--load-path' then next_arg("#{arg} expected a directory as the following argument but did not see one") { |dir| flags[:load_path] << dir }
44
+ when '-e', '--program' then next_arg("#{arg} expected a program as the following argument but did not see one") { |program| flags[:program_from_args] = program }
45
+ when '-a', '--as' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| flags[:as] = filename }
46
+ when '--shebang' then next_arg("#{arg} expects a ruby executable as the following argument but did not see one") { |executable| flags[:shebang] = executable }
47
+ when '-s', '--alignment-strategy' then flags[:alignment_strategy] = args.shift
48
+ when /\A-K(.+)/ then flags[:encoding] = $1
49
+ when '-K', '--encoding' then next_arg("#{arg} expects an encoding, see `man ruby` for possibile values") { |encoding| flags[:encoding] = encoding }
50
+ when /^(-.|--.*)$/ then flags[:errors] << "Unknown option: #{arg.inspect}" # unknown flags
51
+ when /^-[^-]/ then args.unshift *normalize_shortflags(arg)
51
52
  else
52
- filenames << arg
53
- options[:filename] = arg
53
+ flags[:filenames] << arg
54
+ flags[:filename] = arg
54
55
  end
55
56
  end
56
- normalize_and_validate
57
- options
57
+ flags
58
58
  end
59
59
  end
60
60
 
61
- private
62
61
 
63
- attr_accessor :filenames, :args, :outstream
64
62
 
63
+ private
65
64
 
66
- def normalize_and_validate
67
- if 1 < filenames.size
68
- options[:errors] << "Can only have one filename, but had: #{filenames.map(&:inspect).join ', '}"
69
- elsif filenames.any? && options[:program]
70
- options[:errors] << "You passed the program in an argument, but have also specified the filename #{filenames.first.inspect}"
71
- end
72
-
73
- if options[:end_line] < options[:start_line]
74
- options[:start_line], options[:end_line] = options[:end_line], options[:start_line]
75
- end
76
- end
65
+ attr_accessor :args
77
66
 
78
- def options
79
- @options ||= {
80
- debugger: Debugger.new(stream: nil),
67
+ def flags
68
+ @flags ||= {
69
+ as: nil,
70
+ filenames: [],
71
+ help: nil,
72
+ encoding: nil,
73
+ debug: false,
81
74
  version: false,
82
75
  clean: false,
83
76
  xmpfilter_style: false,
84
77
  inherit_exit_status: false,
85
- program: nil,
78
+ program_from_args: nil,
86
79
  filename: nil,
87
- start_line: 1,
88
- end_line: Float::INFINITY,
89
80
  max_line_length: Float::INFINITY,
90
81
  max_result_length: Float::INFINITY,
91
82
  number_of_captures: Float::INFINITY,
92
83
  timeout: 0, # timeout lib treats this as infinity
93
84
  errors: [],
94
- require: [],
85
+ require: ['seeing_is_believing/the_matrix'],
95
86
  load_path: [],
96
- alignment_strategy: AlignChunk,
87
+ alignment_strategy: 'chunk',
97
88
  shebang: 'ruby',
98
89
  result_as_json: false,
90
+ markers: self.class.default_markers,
91
+ short_help_screen: self.class.help_screen(false),
92
+ long_help_screen: self.class.help_screen(true),
93
+ safe: false,
99
94
  }
100
95
  end
101
96
 
102
-
103
- def extract_alignment_strategy
104
- strategies = {
105
- 'file' => AlignFile,
106
- 'chunk' => AlignChunk,
107
- 'line' => AlignLine,
108
- }
109
- next_arg "alignment-strategy expected an alignment strategy as the following argument but did not see one" do |strategy_name|
110
- if strategies[strategy_name]
111
- options[:alignment_strategy] = strategies[strategy_name]
112
- else
113
- options[:errors] << "alignment-strategy does not know #{strategy_name}, only knows: #{strategies.keys.join(', ')}"
114
- end
97
+ def normalize_shortflags(consolidated_shortflag)
98
+ shortflags = consolidated_shortflag[1..-1].chars.to_a # to_a for 1.9.3 -.-
99
+ plusidx = shortflags.index('+') || 0
100
+ if 0 < plusidx
101
+ shortflags[plusidx-1] << '+'
102
+ shortflags.delete_at plusidx
115
103
  end
104
+ shortflags.map { |flag| "-#{flag}" }
116
105
  end
117
106
 
118
107
  def next_arg(error_message, &success_block)
119
108
  arg = args.shift
120
- arg ? success_block.call(arg) : (options[:errors] << error_message)
109
+ arg ? success_block.call(arg) : (flags[:errors] << error_message)
121
110
  end
122
111
 
123
112
  def extract_positive_int_for(key, flag)
124
113
  string = args.shift
125
114
  int = string.to_i
126
115
  if int.to_s == string && 0 < int
127
- options[key] = int
116
+ flags[key] = int
128
117
  else
129
- options[:errors] << "#{flag} expects a positive integer argument"
118
+ flags[:errors] << "#{flag} expects a positive integer argument"
130
119
  end
131
120
  end
132
121
 
133
122
  def extract_non_negative_float_for(key, flag)
134
123
  float = Float args.shift
135
124
  raise if float < 0
136
- options[key] = float
125
+ flags[key] = float
137
126
  rescue
138
- options[:errors] << "#{flag} expects a positive float or integer argument"
127
+ flags[:errors] << "#{flag} expects a positive float or integer argument"
139
128
  end
140
-
141
129
  end
142
130
 
143
- def ParseArgs.help_screen(include_examples)
131
+ def ParseArgs.help_screen(include_examples, markers=default_markers)
132
+ value_marker = markers.fetch(:value)
133
+ exception_marker = markers.fetch(:exception)
134
+ stdout_marker = markers.fetch(:stdout)
135
+ stderr_marker = markers.fetch(:stderr)
136
+ nextline_marker = markers.fetch(:nextline)
137
+
144
138
  <<FLAGS + if include_examples then <<EXAMPLES else '' end
145
139
  Usage: seeing_is_believing [options] [filename]
146
140
 
@@ -148,10 +142,8 @@ Usage: seeing_is_believing [options] [filename]
148
142
 
149
143
  If no filename is provided, the binary will read the program from standard input.
150
144
 
151
- -l, --start-line n # line number to begin showing results on
152
- -L, --end-line n # line number to stop showing results on
153
145
  -d, --line-length n # max length of the entire line (only truncates results, not source lines)
154
- -D, --result-length n # max length of the portion after the "#{VALUE_MARKER}"
146
+ -D, --result-length n # max length of the portion after the "#{value_marker}"
155
147
  -n, --number-of-captures n # how many results to capture for a given line
156
148
  if you had 1 million results on a line, it could take a long time to record
157
149
  and serialize them, you might limit it to 1000 results as an optimization
@@ -180,53 +172,53 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
180
172
 
181
173
  Run the file f.rb
182
174
  $ echo __FILE__ > f.rb; seeing_is_believing f.rb
183
- __FILE__ #{VALUE_MARKER}"f.rb"
175
+ __FILE__ #{value_marker}"f.rb"
184
176
 
185
177
  Aligning comments
186
178
  $ ruby -e 'puts "123\\n4\\n\\n567890"' > f.rb
187
179
 
188
180
 
189
181
  $ seeing_is_believing f.rb -s line
190
- 123 #{VALUE_MARKER}123
191
- 4 #{VALUE_MARKER}4
182
+ 123 #{value_marker}123
183
+ 4 #{value_marker}4
192
184
 
193
- 567890 #{VALUE_MARKER}567890
185
+ 567890 #{value_marker}567890
194
186
 
195
187
 
196
188
  $ seeing_is_believing f.rb -s chunk
197
- 123 #{VALUE_MARKER}123
198
- 4 #{VALUE_MARKER}4
189
+ 123 #{value_marker}123
190
+ 4 #{value_marker}4
199
191
 
200
- 567890 #{VALUE_MARKER}567890
192
+ 567890 #{value_marker}567890
201
193
 
202
194
 
203
195
  $ seeing_is_believing f.rb -s file
204
- 123 #{VALUE_MARKER}123
205
- 4 #{VALUE_MARKER}4
196
+ 123 #{value_marker}123
197
+ 4 #{value_marker}4
206
198
 
207
- 567890 #{VALUE_MARKER}567890
199
+ 567890 #{value_marker}567890
208
200
 
209
201
  Run against standard input
210
202
  $ echo '3.times { |i| puts i }' | seeing_is_believing
211
- 2.times { |i| puts i } #{VALUE_MARKER}2
203
+ 2.times { |i| puts i } #{value_marker}2
212
204
 
213
- #{STDOUT_MARKER}0
214
- #{STDOUT_MARKER}1
205
+ #{stdout_marker}0
206
+ #{stdout_marker}1
215
207
 
216
208
  Run against a library you're working on by fixing the load path
217
209
  $ seeing_is_believing -I lib f.rb
218
210
 
219
211
  Load up some library (can be used in tandem with -I)
220
212
  $ seeing_is_believing -r pp -e 'pp [[*1..15],[*15..30]]; nil'
221
- pp [[*1..15],[*15..30]]; nil #{VALUE_MARKER}nil
213
+ pp [[*1..15],[*15..30]]; nil #{value_marker}nil
222
214
 
223
- #{STDOUT_MARKER}[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
224
- #{STDOUT_MARKER} [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]
215
+ #{stdout_marker}[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
216
+ #{stdout_marker} [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]]
225
217
 
226
218
  Only update the lines you've marked
227
219
  $ ruby -e 'puts "1\\n2 # =>\\n3"' | seeing_is_believing -x
228
220
  1
229
- 2 #{VALUE_MARKER}2
221
+ 2 #{value_marker}2
230
222
  3
231
223
 
232
224
  Set a timeout (especially useful if running via an editor)
@@ -235,11 +227,11 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
235
227
 
236
228
  Set the encoding to utf-8
237
229
  $ seeing_is_believing -Ku -e '"⛄ "'
238
- "⛄ " #{VALUE_MARKER}"⛄ "
230
+ "⛄ " #{value_marker}"⛄ "
239
231
 
240
232
  The exit status will be 1 if the error is displayable inline
241
233
  $ seeing_is_believing -e 'raise "omg"'; echo $?
242
- raise "omg" #{EXCEPTION_MARKER}RuntimeError: omg
234
+ raise "omg" #{exception_marker}RuntimeError: omg
243
235
  1
244
236
 
245
237
  The exit status will be 2 if the error is not displayable
@@ -248,15 +240,15 @@ Examples: A few examples, for a more comprehensive set of examples, check out fe
248
240
  2
249
241
 
250
242
  Run with previous output
251
- $ echo "1+1 #{VALUE_MARKER}old-value" | seeing_is_believing
252
- 1+1 #{VALUE_MARKER}2
243
+ $ echo "1+1 #{value_marker}old-value" | seeing_is_believing
244
+ 1+1 #{value_marker}2
253
245
 
254
- $ echo "1+1 #{VALUE_MARKER}old-value" | seeing_is_believing --clean
246
+ $ echo "1+1 #{value_marker}old-value" | seeing_is_believing --clean
255
247
  1+1
256
248
 
257
249
  If your Ruby binary is named something else (e.g. ruby2.0)
258
250
  $ ruby2.0 -S seeing_is_believing --shebang ruby2.0 -e '123'
259
- 123 #{VALUE_MARKER}123
251
+ 123 #{value_marker}123
260
252
  EXAMPLES
261
253
  end
262
254
  end
@@ -0,0 +1,95 @@
1
+ require 'seeing_is_believing/binary' # Defines the regexes to locate the markers
2
+ require 'seeing_is_believing/parser_helpers' # We have to parse the file to find the comments
3
+
4
+ class SeeingIsBelieving
5
+ module Binary
6
+ class RemoveAnnotations
7
+ def self.call(code, should_clean_values, markers)
8
+ new(code, should_clean_values, markers).call
9
+ end
10
+
11
+ def initialize(code, should_clean_values, markers)
12
+ self.should_clean_values = should_clean_values
13
+ self.code = code
14
+ self.markers = markers
15
+ end
16
+
17
+ def call
18
+ code_obj = Code.new(code, 'strip_comments')
19
+ removed_comments = { result: [], exception: [], stdout: [], stderr: [] }
20
+
21
+ # TODO: This is why you sometimes have to run it 2x to get it to correctly reset whitespace
22
+ # should wipe out the full_range rather than just the comment_range
23
+ code_obj.inline_comments.each do |comment|
24
+ case comment.text
25
+ when value_regex
26
+ if should_clean_values
27
+ # puts "REMOVING VALUE: #{comment.text}"
28
+ removed_comments[:result] << comment
29
+ code_obj.rewriter.remove comment.comment_range
30
+ end
31
+ when exception_regex
32
+ # puts "REMOVING EXCEPTION: #{comment.text}"
33
+ removed_comments[:exception] << comment
34
+ code_obj.rewriter.remove comment.comment_range
35
+ when stdout_regex
36
+ # puts "REMOVING STDOUT: #{comment.text}"
37
+ removed_comments[:stdout] << comment
38
+ code_obj.rewriter.remove comment.comment_range
39
+ when stderr_regex
40
+ # puts "REMOVING STDERR: #{comment.text}"
41
+ removed_comments[:stderr] << comment
42
+ code_obj.rewriter.remove comment.comment_range
43
+ end
44
+ end
45
+
46
+ remove_whitespace_preceding_comments(code_obj.buffer, code_obj.rewriter, removed_comments)
47
+ code_obj.rewriter.process
48
+ end
49
+
50
+ private
51
+
52
+ attr_accessor :code, :should_clean_values, :buffer, :markers
53
+
54
+ def remove_whitespace_preceding_comments(buffer, rewriter, removed_comments)
55
+ removed_comments[:result].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, false }
56
+ removed_comments[:exception].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
57
+ removed_comments[:stdout].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
58
+ removed_comments[:stderr].each { |comment| remove_whitespace_before comment.comment_range.begin_pos, buffer, rewriter, true }
59
+ end
60
+
61
+ # any whitespace before the index (on the same line) will be removed
62
+ # if the preceding whitespace is at the beginning of the line, the newline will be removed
63
+ # if there is a newline before all of that, and remove_preceding_newline is true, it will be removed as well
64
+ def remove_whitespace_before(index, buffer, rewriter, remove_preceding_newline)
65
+ end_pos = index
66
+ begin_pos = end_pos - 1
67
+ begin_pos -= 1 while code[begin_pos] =~ /\s/ && code[begin_pos] != "\n"
68
+ begin_pos -= 1 if code[begin_pos] == "\n"
69
+ begin_pos -= 1 if code[begin_pos] == "\n" && remove_preceding_newline
70
+ return if begin_pos.next == end_pos
71
+ rewriter.remove Parser::Source::Range.new(buffer, begin_pos.next, end_pos)
72
+ end
73
+
74
+ def value_regex
75
+ @value_regex ||= marker_to_regex markers[:value]
76
+ end
77
+
78
+ def exception_regex
79
+ @exception_regex ||= marker_to_regex markers[:exception]
80
+ end
81
+
82
+ def stdout_regex
83
+ @stdout_regex ||= marker_to_regex markers[:stdout]
84
+ end
85
+
86
+ def stderr_regex
87
+ @stderr_regex ||= marker_to_regex markers[:stderr]
88
+ end
89
+
90
+ def marker_to_regex(marker)
91
+ /\A#{Regexp.escape marker.sub(/\s+$/, '')}/
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,38 +1,16 @@
1
- require 'seeing_is_believing/parser_helpers'
1
+ require 'seeing_is_believing/code'
2
2
 
3
3
  class SeeingIsBelieving
4
- class Binary
4
+ module Binary
5
5
  module RewriteComments
6
6
  def self.call(code, &mapping)
7
- buffer, parser, rewriter = ParserHelpers.initialize_parser code, 'rewrite_comments'
8
- ast, comments = parser.parse_with_comments buffer
9
-
10
- comments.each do |comment|
11
- next unless comment.type == :inline
12
- # find whitespace
13
- last_char = comment.location.expression.begin_pos
14
- first_char = last_char
15
- first_char -= 1 while first_char > 0 && buffer.source[first_char-1] =~ /[ \t]/
16
- preceeding_whitespace = buffer.source[first_char...last_char]
17
- preceeding_whitespace_range = Parser::Source::Range.new buffer, first_char, last_char
18
-
19
- # find line
20
- last_char = first_char
21
- first_char -= 1 while first_char > 0 && buffer.source[first_char-1] !~ /[\r\n]/
22
- line = buffer.source[first_char...last_char]
23
-
24
- # get results
25
- new_whitespace, new_comment = mapping.call(comment.location.line,
26
- line,
27
- preceeding_whitespace,
28
- comment.text)
29
-
30
- # update code
31
- rewriter.replace preceeding_whitespace_range, new_whitespace
32
- rewriter.replace comment.location.expression, new_comment
7
+ code = Code.new(code)
8
+ code.inline_comments.each do |comment|
9
+ new_whitespace, new_comment = mapping.call comment
10
+ code.rewriter.replace comment.whitespace_range, new_whitespace
11
+ code.rewriter.replace comment.comment_range, new_comment
33
12
  end
34
-
35
- rewriter.process
13
+ code.rewriter.process
36
14
  end
37
15
  end
38
16
  end