seeing_is_believing 0.0.16 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +1 -1
- data/Readme.md +2 -1
- data/features/errors.feature +14 -0
- data/features/flags.feature +111 -0
- data/features/step_definitions/steps.rb +6 -1
- data/lib/seeing_is_believing.rb +5 -2
- data/lib/seeing_is_believing/binary.rb +16 -2
- data/lib/seeing_is_believing/binary/align_all.rb +28 -0
- data/lib/seeing_is_believing/binary/align_chunk.rb +37 -0
- data/lib/seeing_is_believing/binary/align_line.rb +29 -0
- data/lib/seeing_is_believing/binary/arg_parser.rb +76 -37
- data/lib/seeing_is_believing/binary/print_results_next_to_lines.rb +9 -21
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +22 -7
- data/lib/seeing_is_believing/has_exception.rb +22 -0
- data/lib/seeing_is_believing/the_matrix.rb +2 -1
- data/lib/seeing_is_believing/version.rb +1 -1
- data/spec/arg_parser_spec.rb +52 -0
- data/spec/seeing_is_believing_spec.rb +5 -0
- metadata +5 -2
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/Readme.md
    CHANGED
    
    | @@ -130,9 +130,10 @@ Known Issues | |
| 130 130 |  | 
| 131 131 | 
             
            * `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
         | 
| 132 132 | 
             
            * Heredocs aren't recorded. It might actually be possible if the ExpressionList were to get smarter
         | 
| 133 | 
            -
            * Return statements are dealt with poorly, causing some situations where you could capture and display a value to not capture
         | 
| 133 | 
            +
            * Return statements and other control-flow changing keywords (next/break/redo/retry) are dealt with poorly, causing some situations where you could capture and display a value to not capture
         | 
| 134 134 | 
             
            * errors come out really shitty if you're calling them from another program like TextMate, would be better to put a line in that shows where the error is.
         | 
| 135 135 | 
             
            * Add a time limit to auto-kill it if it gets stuck or something (e.g. stack overflow is painful to wait for)
         | 
| 136 | 
            +
            * Doesn't handle # ~> -:5: stack level too deep (SystemStackError) gracefully
         | 
| 136 137 |  | 
| 137 138 | 
             
            License
         | 
| 138 139 | 
             
            =======
         | 
    
        data/features/errors.feature
    CHANGED
    
    | @@ -39,3 +39,17 @@ Feature: Running the binary unsuccessfully | |
| 39 39 | 
             
                Then stderr is "this_file_does_not_exist.rb does not exist!"
         | 
| 40 40 | 
             
                And the exit status is 1
         | 
| 41 41 | 
             
                And stdout is empty
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              Scenario: Passing unknown options
         | 
| 44 | 
            +
                Given the file "some_file" "1"
         | 
| 45 | 
            +
                When I run "seeing_is_believing --unknown-option"
         | 
| 46 | 
            +
                Then stderr is 'Unknown option: "--unknown-option"'
         | 
| 47 | 
            +
                And the exit status is 1
         | 
| 48 | 
            +
                And stdout is empty
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              Scenario: Passing an unknown option with a value but forgetting the filename
         | 
| 51 | 
            +
                When I run "seeing_is_believing --unknown-option some-value"
         | 
| 52 | 
            +
                Then stderr is 'Unknown option: "--unknown-option"'
         | 
| 53 | 
            +
                And the exit status is 1
         | 
| 54 | 
            +
                And stdout is empty
         | 
| 55 | 
            +
             | 
    
        data/features/flags.feature
    CHANGED
    
    | @@ -242,3 +242,114 @@ Feature: Using flags | |
| 242 242 | 
             
                Then stderr is empty
         | 
| 243 243 | 
             
                And the exit status is 0
         | 
| 244 244 | 
             
                And stdout includes "Usage"
         | 
| 245 | 
            +
             | 
| 246 | 
            +
              Scenario: --timeout
         | 
| 247 | 
            +
                Given the file "example.rb" "sleep 1"
         | 
| 248 | 
            +
                When I run "seeing_is_believing --timeout 0.1 example.rb"
         | 
| 249 | 
            +
                Then stdout is empty
         | 
| 250 | 
            +
                And the exit status is 1
         | 
| 251 | 
            +
                And stderr is "Timeout Error after 0.1 seconds!"
         | 
| 252 | 
            +
             | 
| 253 | 
            +
              Scenario: --timeout
         | 
| 254 | 
            +
                Given the file "example.rb" "1 + 1"
         | 
| 255 | 
            +
                When I run "seeing_is_believing --timeout 1.0 example.rb"
         | 
| 256 | 
            +
                Then stderr is empty
         | 
| 257 | 
            +
                And the exit status is 0
         | 
| 258 | 
            +
                And stdout is "1 + 1  # => 2"
         | 
| 259 | 
            +
             | 
| 260 | 
            +
              Scenario: --alignment-strategy file
         | 
| 261 | 
            +
                Given the file "file_alignments.rb":
         | 
| 262 | 
            +
                """
         | 
| 263 | 
            +
                # comment
         | 
| 264 | 
            +
                1
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                =begin
         | 
| 267 | 
            +
                multiline comment
         | 
| 268 | 
            +
                =end
         | 
| 269 | 
            +
                1 + 1
         | 
| 270 | 
            +
                1 + 1 + 1
         | 
| 271 | 
            +
                """
         | 
| 272 | 
            +
                When I run "seeing_is_believing --alignment-strategy file file_alignments.rb"
         | 
| 273 | 
            +
                Then stderr is empty
         | 
| 274 | 
            +
                And the exit status is 0
         | 
| 275 | 
            +
                And stdout is:
         | 
| 276 | 
            +
                """
         | 
| 277 | 
            +
                # comment
         | 
| 278 | 
            +
                1          # => 1
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                =begin
         | 
| 281 | 
            +
                multiline comment
         | 
| 282 | 
            +
                =end
         | 
| 283 | 
            +
                1 + 1      # => 2
         | 
| 284 | 
            +
                1 + 1 + 1  # => 3
         | 
| 285 | 
            +
                """
         | 
| 286 | 
            +
             | 
| 287 | 
            +
              Scenario: --alignment-strategy chunk
         | 
| 288 | 
            +
                Given the file "chunk_alignments.rb":
         | 
| 289 | 
            +
                """
         | 
| 290 | 
            +
                # comment
         | 
| 291 | 
            +
                1
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                =begin
         | 
| 294 | 
            +
                multiline comment
         | 
| 295 | 
            +
                =end
         | 
| 296 | 
            +
                1 + 1
         | 
| 297 | 
            +
                1 + 1 + 1
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                1+1+1
         | 
| 300 | 
            +
                1+1
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                1 + 1
         | 
| 303 | 
            +
                # comment in the middle!
         | 
| 304 | 
            +
                1 + 1 + 1 + 1
         | 
| 305 | 
            +
                1 + 1
         | 
| 306 | 
            +
                """
         | 
| 307 | 
            +
                When I run "seeing_is_believing --alignment-strategy chunk chunk_alignments.rb"
         | 
| 308 | 
            +
                Then stderr is empty
         | 
| 309 | 
            +
                And the exit status is 0
         | 
| 310 | 
            +
                And stdout is:
         | 
| 311 | 
            +
                """
         | 
| 312 | 
            +
                # comment
         | 
| 313 | 
            +
                1  # => 1
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                =begin
         | 
| 316 | 
            +
                multiline comment
         | 
| 317 | 
            +
                =end
         | 
| 318 | 
            +
                1 + 1      # => 2
         | 
| 319 | 
            +
                1 + 1 + 1  # => 3
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                1+1+1  # => 3
         | 
| 322 | 
            +
                1+1    # => 2
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                1 + 1          # => 2
         | 
| 325 | 
            +
                # comment in the middle!
         | 
| 326 | 
            +
                1 + 1 + 1 + 1  # => 4
         | 
| 327 | 
            +
                1 + 1          # => 2
         | 
| 328 | 
            +
                """
         | 
| 329 | 
            +
             | 
| 330 | 
            +
              Scenario: --alignment-strategy line
         | 
| 331 | 
            +
                Given the file "line_alignments.rb":
         | 
| 332 | 
            +
                """
         | 
| 333 | 
            +
                # comment
         | 
| 334 | 
            +
                1
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                =begin
         | 
| 337 | 
            +
                multiline comment
         | 
| 338 | 
            +
                =end
         | 
| 339 | 
            +
                1 + 1
         | 
| 340 | 
            +
                1 + 1 + 1
         | 
| 341 | 
            +
                """
         | 
| 342 | 
            +
                When I run "seeing_is_believing --alignment-strategy line line_alignments.rb"
         | 
| 343 | 
            +
                Then stderr is empty
         | 
| 344 | 
            +
                And the exit status is 0
         | 
| 345 | 
            +
                And stdout is:
         | 
| 346 | 
            +
                """
         | 
| 347 | 
            +
                # comment
         | 
| 348 | 
            +
                1  # => 1
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                =begin
         | 
| 351 | 
            +
                multiline comment
         | 
| 352 | 
            +
                =end
         | 
| 353 | 
            +
                1 + 1  # => 2
         | 
| 354 | 
            +
                1 + 1 + 1  # => 3
         | 
| 355 | 
            +
                """
         | 
| @@ -6,6 +6,11 @@ When('I run "$command"')                     { |command|              @last_exec | |
| 6 6 | 
             
            When("I run '$command'")                     { |command|              @last_executed = CommandLineHelpers.execute command, @stdin_data }
         | 
| 7 7 | 
             
            Then(/^(stderr|stdout) is:$/)                { |stream_name, output|  @last_executed.send(stream_name).chomp.should == eval_curlies(output) }
         | 
| 8 8 | 
             
            Then(/^(stderr|stdout) is ["'](.*?)["']$/)   { |stream_name, output|  @last_executed.send(stream_name).chomp.should == eval_curlies(output) }
         | 
| 9 | 
            -
            Then(/^(stderr|stdout) is empty$/)           { |stream_name| | 
| 9 | 
            +
            Then(/^(stderr|stdout) is empty$/)           { |stream_name|
         | 
| 10 | 
            +
              stream = @last_executed.send(stream_name)
         | 
| 11 | 
            +
              if stream != ''
         | 
| 12 | 
            +
                raise "EXPECTED NOTHING, GOT #{stream}"
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
              }
         | 
| 10 15 | 
             
            Then(/^(stderr|stdout) includes "([^"]*)"$/) { |stream_name, content| @last_executed.send(stream_name).should include eval_curlies(content) }
         | 
| 11 16 | 
             
            Then('the exit status is $status')           { |status|               @last_executed.exitstatus.to_s.should == status }
         | 
    
        data/lib/seeing_is_believing.rb
    CHANGED
    
    | @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            require 'stringio'
         | 
| 2 2 | 
             
            require 'tmpdir'
         | 
| 3 | 
            +
            require 'timeout'
         | 
| 3 4 |  | 
| 4 5 | 
             
            require 'seeing_is_believing/queue'
         | 
| 5 6 | 
             
            require 'seeing_is_believing/result'
         | 
| @@ -26,9 +27,10 @@ class SeeingIsBelieving | |
| 26 27 | 
             
                @load_path       = options.fetch :load_path, []
         | 
| 27 28 | 
             
                @encoding        = options.fetch :encoding, nil
         | 
| 28 29 | 
             
                @line_number     = 1
         | 
| 30 | 
            +
                @timeout         = options[:timeout]
         | 
| 29 31 | 
             
              end
         | 
| 30 32 |  | 
| 31 | 
            -
              # I'd  | 
| 33 | 
            +
              # I'd like to refactor this, but I was unsatisfied with the three different things I tried.
         | 
| 32 34 | 
             
              # In the end, I prefer keeping all manipulation of the line number here in the main function
         | 
| 33 35 | 
             
              # And I like that the higher-level construct of how the program gets built can be found here.
         | 
| 34 36 | 
             
              def call
         | 
| @@ -118,7 +120,8 @@ class SeeingIsBelieving | |
| 118 120 | 
             
                                            matrix_filename: matrix_filename,
         | 
| 119 121 | 
             
                                            require:         @require,
         | 
| 120 122 | 
             
                                            load_path:       @load_path,
         | 
| 121 | 
            -
                                            encoding:        @encoding | 
| 123 | 
            +
                                            encoding:        @encoding,
         | 
| 124 | 
            +
                                            timeout:         @timeout)
         | 
| 122 125 | 
             
                                       .call
         | 
| 123 126 | 
             
                                       .track_line_number(max_line_number)
         | 
| 124 127 | 
             
                end
         | 
| @@ -1,11 +1,12 @@ | |
| 1 1 | 
             
            require 'seeing_is_believing'
         | 
| 2 2 | 
             
            require 'seeing_is_believing/binary/arg_parser'
         | 
| 3 3 | 
             
            require 'seeing_is_believing/binary/print_results_next_to_lines'
         | 
| 4 | 
            +
            require 'timeout'
         | 
| 4 5 |  | 
| 5 6 |  | 
| 6 7 | 
             
            class SeeingIsBelieving
         | 
| 7 8 | 
             
              class Binary
         | 
| 8 | 
            -
                attr_accessor :argv, :stdin, :stdout, :stderr
         | 
| 9 | 
            +
                attr_accessor :argv, :stdin, :stdout, :stderr, :timeout_error
         | 
| 9 10 |  | 
| 10 11 | 
             
                def initialize(argv, stdin, stdout, stderr)
         | 
| 11 12 | 
             
                  self.argv   = argv
         | 
| @@ -21,6 +22,7 @@ class SeeingIsBelieving | |
| 21 22 | 
             
                                  elsif has_filename? && file_dne?  then print_file_dne        ; 1
         | 
| 22 23 | 
             
                                  elsif should_clean?               then print_cleaned_program ; 0
         | 
| 23 24 | 
             
                                  elsif invalid_syntax?             then print_syntax_error    ; 1
         | 
| 25 | 
            +
                                  elsif program_timedout?           then print_timeout_error   ; 1
         | 
| 24 26 | 
             
                                  else                                   print_program         ; (results.has_exception? ? 1 : 0)
         | 
| 25 27 | 
             
                                  end
         | 
| 26 28 | 
             
                end
         | 
| @@ -33,6 +35,15 @@ class SeeingIsBelieving | |
| 33 35 | 
             
                  flags[:filename]
         | 
| 34 36 | 
             
                end
         | 
| 35 37 |  | 
| 38 | 
            +
                def program_timedout?
         | 
| 39 | 
            +
                  results
         | 
| 40 | 
            +
                  timeout_error
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def print_timeout_error
         | 
| 44 | 
            +
                  stderr.puts "Timeout Error after #{@flags[:timeout]} seconds!"
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 36 47 | 
             
                def cleaned_body
         | 
| 37 48 | 
             
                  @body ||= PrintResultsNextToLines.remove_previous_output_from \
         | 
| 38 49 | 
             
                    flags[:program] || (file_is_on_stdin? && stdin.read) || File.read(flags[:filename])
         | 
| @@ -44,7 +55,10 @@ class SeeingIsBelieving | |
| 44 55 | 
             
                                                      require:   flags[:require],
         | 
| 45 56 | 
             
                                                      load_path: flags[:load_path],
         | 
| 46 57 | 
             
                                                      encoding:  flags[:encoding],
         | 
| 47 | 
            -
                                                      stdin:     (file_is_on_stdin? ? '' : stdin)
         | 
| 58 | 
            +
                                                      stdin:     (file_is_on_stdin? ? '' : stdin),
         | 
| 59 | 
            +
                                                      timeout:   flags[:timeout]
         | 
| 60 | 
            +
                rescue Timeout::Error
         | 
| 61 | 
            +
                  self.timeout_error = true
         | 
| 48 62 | 
             
                end
         | 
| 49 63 |  | 
| 50 64 | 
             
                def printer
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            class SeeingIsBelieving
         | 
| 2 | 
            +
              class Binary
         | 
| 3 | 
            +
                class AlignAll
         | 
| 4 | 
            +
                  attr_accessor :body, :start_line, :end_line
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(body, start_line, end_line)
         | 
| 7 | 
            +
                    self.body, self.start_line, self.end_line = body, start_line, end_line
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  # max line length of the lines to output (exempting comments) + 2 spaces for padding
         | 
| 11 | 
            +
                  def line_length_for(line_number)
         | 
| 12 | 
            +
                    @max_source_line_length ||= 2 + body.each_line
         | 
| 13 | 
            +
                                                        .map(&:chomp)
         | 
| 14 | 
            +
                                                        .select.with_index(1) { |line, index| start_line <= index && index <= end_line }
         | 
| 15 | 
            +
                                                        .take_while { |line| not start_of_data_segment? line }
         | 
| 16 | 
            +
                                                        .select { |line| not SyntaxAnalyzer.begins_multiline_comment?(line) .. SyntaxAnalyzer.ends_multiline_comment?(line ) }
         | 
| 17 | 
            +
                                                        .reject { |line| SyntaxAnalyzer.ends_in_comment? line }
         | 
| 18 | 
            +
                                                        .map(&:length)
         | 
| 19 | 
            +
                                                        .concat([0])
         | 
| 20 | 
            +
                                                        .max
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def start_of_data_segment?(line)
         | 
| 24 | 
            +
                    SyntaxAnalyzer.begins_data_segment?(line.chomp)
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            class SeeingIsBelieving
         | 
| 2 | 
            +
              class Binary
         | 
| 3 | 
            +
                class AlignChunk
         | 
| 4 | 
            +
                  attr_accessor :body, :start_line, :end_line
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(body, start_line, end_line)
         | 
| 7 | 
            +
                    self.body, self.start_line, self.end_line = body, start_line, end_line
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  # max line length of the the chunk (newline separated sections of code exempting comments) + 2 spaces for padding
         | 
| 11 | 
            +
                  def line_length_for(line_number)
         | 
| 12 | 
            +
                    line_lengths[line_number]
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def line_lengths
         | 
| 16 | 
            +
                    @line_lengths ||= Hash[
         | 
| 17 | 
            +
                      body.each_line
         | 
| 18 | 
            +
                          .map(&:chomp)
         | 
| 19 | 
            +
                          .map.with_index(1) { |line, index| [line, index] }
         | 
| 20 | 
            +
                          .take_while        { |line, index| not start_of_data_segment? line }
         | 
| 21 | 
            +
                          .select            { |line, index| not SyntaxAnalyzer.begins_multiline_comment?(line) .. SyntaxAnalyzer.ends_multiline_comment?(line ) }
         | 
| 22 | 
            +
                          .reject            { |line, index| SyntaxAnalyzer.ends_in_comment? line }
         | 
| 23 | 
            +
                          .slice_before      { |line, index| line == '' }
         | 
| 24 | 
            +
                          .map { |slice|
         | 
| 25 | 
            +
                            max_chunk_length = 2 + slice.map { |line, index| line.length }.max
         | 
| 26 | 
            +
                            slice.map { |line, index| [index, max_chunk_length] }
         | 
| 27 | 
            +
                          }
         | 
| 28 | 
            +
                          .flatten(1)
         | 
| 29 | 
            +
                    ]
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def start_of_data_segment?(line)
         | 
| 33 | 
            +
                    SyntaxAnalyzer.begins_data_segment?(line.chomp)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            class SeeingIsBelieving
         | 
| 2 | 
            +
              class Binary
         | 
| 3 | 
            +
                class AlignLine
         | 
| 4 | 
            +
                  attr_accessor :body, :start_line, :end_line
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(body, start_line, end_line)
         | 
| 7 | 
            +
                    self.body, self.start_line, self.end_line = body, start_line, end_line
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  # length of the line + 2 spaces for padding
         | 
| 11 | 
            +
                  def line_length_for(line_number)
         | 
| 12 | 
            +
                    line_lengths[line_number]
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def line_lengths
         | 
| 16 | 
            +
                    @line_lengths ||= Hash[ body.each_line
         | 
| 17 | 
            +
                                                .map(&:chomp)
         | 
| 18 | 
            +
                                                .each
         | 
| 19 | 
            +
                                                .with_index(1)
         | 
| 20 | 
            +
                                                .map { |line, index| [index, line.length+2] }
         | 
| 21 | 
            +
                                          ]
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def start_of_data_segment?(line)
         | 
| 25 | 
            +
                    SyntaxAnalyzer.begins_data_segment?(line.chomp)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -1,3 +1,8 @@ | |
| 1 | 
            +
            require 'seeing_is_believing/version'
         | 
| 2 | 
            +
            require 'seeing_is_believing/binary/align_all'
         | 
| 3 | 
            +
            require 'seeing_is_believing/binary/align_line'
         | 
| 4 | 
            +
            require 'seeing_is_believing/binary/align_chunk'
         | 
| 5 | 
            +
             | 
| 1 6 | 
             
            class SeeingIsBelieving
         | 
| 2 7 | 
             
              class Binary
         | 
| 3 8 | 
             
                class ArgParser
         | 
| @@ -16,20 +21,22 @@ class SeeingIsBelieving | |
| 16 21 | 
             
                    @result ||= begin
         | 
| 17 22 | 
             
                      until args.empty?
         | 
| 18 23 | 
             
                        case (arg = args.shift)
         | 
| 19 | 
            -
                        when '-h', '--help' | 
| 20 | 
            -
                        when '-v', '--version' | 
| 21 | 
            -
                        when '-c', '--clean' | 
| 22 | 
            -
                        when '-l', '--start-line' | 
| 23 | 
            -
                        when '-L', '--end-line' | 
| 24 | 
            -
                        when '-d', '--line-length' | 
| 25 | 
            -
                        when '-D', '--result-length' | 
| 26 | 
            -
                        when '- | 
| 27 | 
            -
                        when '- | 
| 28 | 
            -
                        when '- | 
| 29 | 
            -
                        when '- | 
| 30 | 
            -
                        when  | 
| 31 | 
            -
                        when '- | 
| 32 | 
            -
                        when  | 
| 24 | 
            +
                        when '-h', '--help'               then options[:help]    = self.class.help_screen
         | 
| 25 | 
            +
                        when '-v', '--version'            then options[:version] = true
         | 
| 26 | 
            +
                        when '-c', '--clean'              then options[:clean]   = true
         | 
| 27 | 
            +
                        when '-l', '--start-line'         then extract_positive_int_for :start_line,    arg
         | 
| 28 | 
            +
                        when '-L', '--end-line'           then extract_positive_int_for :end_line,      arg
         | 
| 29 | 
            +
                        when '-d', '--line-length'        then extract_positive_int_for :line_length,   arg
         | 
| 30 | 
            +
                        when '-D', '--result-length'      then extract_positive_int_for :result_length, arg
         | 
| 31 | 
            +
                        when '-t', '--timeout'            then extract_non_negative_float_for :timeout, arg
         | 
| 32 | 
            +
                        when '-r', '--require'            then next_arg("#{arg} expected a filename as the following argument but did not see one")  { |filename| options[:require]            << filename }
         | 
| 33 | 
            +
                        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 }
         | 
| 34 | 
            +
                        when '-e', '--program'            then next_arg("#{arg} expected a program as the following argument but did not see one")   { |program|  options[:program]            = program }
         | 
| 35 | 
            +
                        when '-a', '--as'                 then next_arg("#{arg} expected a filename as the following argument but did not see one")  { |filename| options[:as]                 = filename }
         | 
| 36 | 
            +
                        when '-s', '--alignment-strategy' then extract_alignment_strategy
         | 
| 37 | 
            +
                        when /\A-K(.+)/                   then options[:encoding] = $1
         | 
| 38 | 
            +
                        when '-K', '--encoding'           then next_arg("#{arg} expects an encoding, see `man ruby` for possibile values") { |encoding| options[:encoding] = encoding }
         | 
| 39 | 
            +
                        when /^-/                         then options[:errors] << "Unknown option: #{arg.inspect}" # unknown flags
         | 
| 33 40 | 
             
                        else
         | 
| 34 41 | 
             
                          filenames << arg
         | 
| 35 42 | 
             
                          options[:filename] = arg
         | 
| @@ -58,18 +65,36 @@ class SeeingIsBelieving | |
| 58 65 |  | 
| 59 66 | 
             
                  def options
         | 
| 60 67 | 
             
                    @options ||= {
         | 
| 61 | 
            -
                      version: | 
| 62 | 
            -
                      clean: | 
| 63 | 
            -
                      program: | 
| 64 | 
            -
                      filename: | 
| 65 | 
            -
                      start_line: | 
| 66 | 
            -
                      line_length: | 
| 67 | 
            -
                      end_line: | 
| 68 | 
            -
                      result_length: | 
| 69 | 
            -
                       | 
| 70 | 
            -
                       | 
| 71 | 
            -
                       | 
| 68 | 
            +
                      version:            false,
         | 
| 69 | 
            +
                      clean:              false,
         | 
| 70 | 
            +
                      program:            nil,
         | 
| 71 | 
            +
                      filename:           nil,
         | 
| 72 | 
            +
                      start_line:         1,
         | 
| 73 | 
            +
                      line_length:        Float::INFINITY,
         | 
| 74 | 
            +
                      end_line:           Float::INFINITY,
         | 
| 75 | 
            +
                      result_length:      Float::INFINITY,
         | 
| 76 | 
            +
                      timeout:            0, # timeout lib treats this as infinity
         | 
| 77 | 
            +
                      errors:             [],
         | 
| 78 | 
            +
                      require:            [],
         | 
| 79 | 
            +
                      load_path:          [],
         | 
| 80 | 
            +
                      alignment_strategy: AlignAll,
         | 
| 81 | 
            +
                    }
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def extract_alignment_strategy
         | 
| 86 | 
            +
                    strategies = {
         | 
| 87 | 
            +
                      'file'  => AlignAll,
         | 
| 88 | 
            +
                      'chunk' => AlignChunk,
         | 
| 89 | 
            +
                      'line'  => AlignLine,
         | 
| 72 90 | 
             
                    }
         | 
| 91 | 
            +
                    next_arg "alignment-strategy expected an alignment strategy as the following argument but did not see one" do |strategy_name|
         | 
| 92 | 
            +
                      if strategies[strategy_name]
         | 
| 93 | 
            +
                        options[:alignment_strategy] = strategies[strategy_name]
         | 
| 94 | 
            +
                      else
         | 
| 95 | 
            +
                        options[:errors] << "alignment-strategy does not know #{strategy_name}, only knows: #{strategies.keys.join(', ')}"
         | 
| 96 | 
            +
                      end
         | 
| 97 | 
            +
                    end
         | 
| 73 98 | 
             
                  end
         | 
| 74 99 |  | 
| 75 100 | 
             
                  def next_arg(error_message, &success_block)
         | 
| @@ -86,6 +111,15 @@ class SeeingIsBelieving | |
| 86 111 | 
             
                      options[:errors] << "#{flag} expects a positive integer argument"
         | 
| 87 112 | 
             
                    end
         | 
| 88 113 | 
             
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  def extract_non_negative_float_for(key, flag)
         | 
| 116 | 
            +
                    float = Float args.shift
         | 
| 117 | 
            +
                    raise if float < 0
         | 
| 118 | 
            +
                    options[key] = float
         | 
| 119 | 
            +
                  rescue
         | 
| 120 | 
            +
                    options[:errors] << "#{flag} expects a positive float or integer argument"
         | 
| 121 | 
            +
                  end
         | 
| 122 | 
            +
             | 
| 89 123 | 
             
                end
         | 
| 90 124 |  | 
| 91 125 | 
             
                def ArgParser.help_screen
         | 
| @@ -96,18 +130,23 @@ Usage: #{$0} [options] [filename] | |
| 96 130 |  | 
| 97 131 | 
             
              If no filename is provided, the binary will read the program from standard input.
         | 
| 98 132 |  | 
| 99 | 
            -
              -l, --start-line n | 
| 100 | 
            -
              -L, --end-line n | 
| 101 | 
            -
              -d, --line-length n | 
| 102 | 
            -
              -D, --result-length n | 
| 103 | 
            -
              - | 
| 104 | 
            -
               | 
| 105 | 
            -
               | 
| 106 | 
            -
               | 
| 107 | 
            -
              - | 
| 108 | 
            -
              - | 
| 109 | 
            -
              - | 
| 110 | 
            -
              - | 
| 133 | 
            +
              -l, --start-line n        # line number to begin showing results on
         | 
| 134 | 
            +
              -L, --end-line n          # line number to stop showing results on
         | 
| 135 | 
            +
              -d, --line-length n       # max length of the entire line (only truncates results, not source lines)
         | 
| 136 | 
            +
              -D, --result-length n     # max length of the portion after the "# => "
         | 
| 137 | 
            +
              -s, --alignment-strategy  # select the alignment strategy:
         | 
| 138 | 
            +
                                          file  (DEFAULT) =>  the entire file is at the same alignment
         | 
| 139 | 
            +
                                          chunk           =>  each chunk of code is at the same alignment
         | 
| 140 | 
            +
                                          line            =>  each line is at its own alignment
         | 
| 141 | 
            +
              -t, --timeout n           # timeout limit in seconds when evaluating source file (ex. -t 0.3 or -t 3)
         | 
| 142 | 
            +
              -I, --load-path dir       # a dir that should be added to the $LOAD_PATH
         | 
| 143 | 
            +
              -r, --require file        # additional files to be required before running the program
         | 
| 144 | 
            +
              -e, --program program     # Pass the program to execute as an argument
         | 
| 145 | 
            +
              -K, --encoding encoding   # sets file encoding, equivalent to Ruby's -Kx (see `man ruby` for valid values)
         | 
| 146 | 
            +
              -a, --as filename         # run the program as if it was the specified filename
         | 
| 147 | 
            +
              -c, --clean               # remove annotations from previous runs of seeing_is_believing
         | 
| 148 | 
            +
              -v, --version             # print the version (#{VERSION})
         | 
| 149 | 
            +
              -h, --help                # this help screen
         | 
| 111 150 | 
             
            HELP_SCREEN
         | 
| 112 151 | 
             
                end
         | 
| 113 152 | 
             
              end
         | 
| @@ -2,6 +2,7 @@ require 'seeing_is_believing/queue' | |
| 2 2 | 
             
            require 'seeing_is_believing/has_exception'
         | 
| 3 3 | 
             
            require 'seeing_is_believing/binary/line_formatter'
         | 
| 4 4 |  | 
| 5 | 
            +
             | 
| 5 6 | 
             
            class SeeingIsBelieving
         | 
| 6 7 | 
             
              class Binary
         | 
| 7 8 | 
             
                class PrintResultsNextToLines
         | 
| @@ -29,11 +30,11 @@ class SeeingIsBelieving | |
| 29 30 | 
             
                  method_from_options :line_length,   Float::INFINITY
         | 
| 30 31 | 
             
                  method_from_options :result_length, Float::INFINITY
         | 
| 31 32 |  | 
| 32 | 
            -
             | 
| 33 33 | 
             
                  def initialize(body, file_result, options={})
         | 
| 34 | 
            -
                    self.body | 
| 35 | 
            -
                    self.options | 
| 36 | 
            -
                    self.file_result | 
| 34 | 
            +
                    self.body               = body
         | 
| 35 | 
            +
                    self.options            = options
         | 
| 36 | 
            +
                    self.file_result        = file_result
         | 
| 37 | 
            +
                    self.alignment_strategy = options[:alignment_strategy].new body, start_line, end_line
         | 
| 37 38 | 
             
                  end
         | 
| 38 39 |  | 
| 39 40 | 
             
                  def new_body
         | 
| @@ -52,7 +53,7 @@ class SeeingIsBelieving | |
| 52 53 |  | 
| 53 54 | 
             
                  private
         | 
| 54 55 |  | 
| 55 | 
            -
                  attr_accessor :body, :file_result, :options
         | 
| 56 | 
            +
                  attr_accessor :body, :file_result, :options, :alignment_strategy
         | 
| 56 57 |  | 
| 57 58 | 
             
                  def add_each_line_until_start_or_data_segment
         | 
| 58 59 | 
             
                    line_queue.until { |line, line_number| line_number == start_line || start_of_data_segment?(line) }
         | 
| @@ -61,7 +62,7 @@ class SeeingIsBelieving | |
| 61 62 |  | 
| 62 63 | 
             
                  def add_lines_with_results_until_end_or_data_segment
         | 
| 63 64 | 
             
                    line_queue.until { |line, line_number| end_line < line_number || start_of_data_segment?(line) }
         | 
| 64 | 
            -
                              .each  { |line, line_number| new_body << format_line(line.chomp, file_result[line_number]) }
         | 
| 65 | 
            +
                              .each  { |line, line_number| new_body << format_line(line.chomp, line_number, file_result[line_number]) }
         | 
| 65 66 | 
             
                  end
         | 
| 66 67 |  | 
| 67 68 | 
             
                  def add_lines_until_data_segment
         | 
| @@ -81,19 +82,6 @@ class SeeingIsBelieving | |
| 81 82 | 
             
                    SyntaxAnalyzer.begins_data_segment?(line.chomp)
         | 
| 82 83 | 
             
                  end
         | 
| 83 84 |  | 
| 84 | 
            -
                  # max line length of the lines to output (exempting comments) + 2 spaces for padding
         | 
| 85 | 
            -
                  def max_source_line_length
         | 
| 86 | 
            -
                    @max_source_line_length ||= 2 + body.each_line
         | 
| 87 | 
            -
                                                        .map(&:chomp)
         | 
| 88 | 
            -
                                                        .select.with_index(1) { |line, index| start_line <= index && index <= end_line }
         | 
| 89 | 
            -
                                                        .take_while { |line| not start_of_data_segment? line }
         | 
| 90 | 
            -
                                                        .select { |line| not SyntaxAnalyzer.begins_multiline_comment?(line) .. SyntaxAnalyzer.ends_multiline_comment?(line ) }
         | 
| 91 | 
            -
                                                        .reject { |line| SyntaxAnalyzer.ends_in_comment? line }
         | 
| 92 | 
            -
                                                        .map(&:length)
         | 
| 93 | 
            -
                                                        .concat([0])
         | 
| 94 | 
            -
                                                        .max
         | 
| 95 | 
            -
                  end
         | 
| 96 | 
            -
             | 
| 97 85 | 
             
                  def add_stdout
         | 
| 98 86 | 
             
                    return unless file_result.has_stdout?
         | 
| 99 87 | 
             
                    new_body << "\n"
         | 
| @@ -110,8 +98,8 @@ class SeeingIsBelieving | |
| 110 98 | 
             
                    end
         | 
| 111 99 | 
             
                  end
         | 
| 112 100 |  | 
| 113 | 
            -
                  def format_line(line, line_results)
         | 
| 114 | 
            -
                    options = options().merge source_length:  | 
| 101 | 
            +
                  def format_line(line, line_number, line_results)
         | 
| 102 | 
            +
                    options = options().merge source_length: alignment_strategy.line_length_for(line_number)
         | 
| 115 103 | 
             
                    formatted_line = if line_results.has_exception?
         | 
| 116 104 | 
             
                                       result = sprintf "%s: %s", line_results.exception.class, line_results.exception.message
         | 
| 117 105 | 
             
                                       LineFormatter.new(line, "#{EXCEPTION_PREFIX} ", result, options).call
         | 
| @@ -11,6 +11,7 @@ | |
| 11 11 | 
             
            # I did look at Ripper, and it will invoke on_kw("__FILE__")
         | 
| 12 12 | 
             
            # when it sees this.
         | 
| 13 13 |  | 
| 14 | 
            +
            require 'yaml'
         | 
| 14 15 | 
             
            require 'open3'
         | 
| 15 16 | 
             
            require 'stringio'
         | 
| 16 17 | 
             
            require 'fileutils'
         | 
| @@ -20,7 +21,7 @@ require 'seeing_is_believing/hard_core_ensure' | |
| 20 21 |  | 
| 21 22 | 
             
            class SeeingIsBelieving
         | 
| 22 23 | 
             
              class EvaluateByMovingFiles
         | 
| 23 | 
            -
                attr_accessor :program, :filename, :error_stream, :input_stream, :matrix_filename, :require_flags, :load_path_flags, :encoding
         | 
| 24 | 
            +
                attr_accessor :program, :filename, :error_stream, :input_stream, :matrix_filename, :require_flags, :load_path_flags, :encoding, :timeout
         | 
| 24 25 |  | 
| 25 26 | 
             
                def initialize(program, filename, options={})
         | 
| 26 27 | 
             
                  self.program         = program
         | 
| @@ -31,6 +32,7 @@ class SeeingIsBelieving | |
| 31 32 | 
             
                  self.require_flags   = options.fetch(:require, []).map { |filename| ['-r', filename] }.flatten
         | 
| 32 33 | 
             
                  self.load_path_flags = options.fetch(:load_path, []).map { |dir| ['-I', dir] }.flatten
         | 
| 33 34 | 
             
                  self.encoding        = options.fetch :encoding, nil
         | 
| 35 | 
            +
                  self.timeout         = options[:timeout]
         | 
| 34 36 | 
             
                end
         | 
| 35 37 |  | 
| 36 38 | 
             
                def call
         | 
| @@ -44,7 +46,7 @@ class SeeingIsBelieving | |
| 44 46 | 
             
                        fail unless exitstatus.success?
         | 
| 45 47 | 
             
                        deserialize_result
         | 
| 46 48 | 
             
                      rescue Exception
         | 
| 47 | 
            -
                         | 
| 49 | 
            +
                        notify_user_of_error if error_implies_bug_in_sib? $!
         | 
| 48 50 | 
             
                        raise $!
         | 
| 49 51 | 
             
                      end
         | 
| 50 52 | 
             
                    },
         | 
| @@ -53,6 +55,10 @@ class SeeingIsBelieving | |
| 53 55 | 
             
                    }
         | 
| 54 56 | 
             
                end
         | 
| 55 57 |  | 
| 58 | 
            +
                def error_implies_bug_in_sib?(error)
         | 
| 59 | 
            +
                  not error.kind_of? Timeout::Error
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 56 62 | 
             
                def file_directory
         | 
| 57 63 | 
             
                  File.dirname filename
         | 
| 58 64 | 
             
                end
         | 
| @@ -95,9 +101,16 @@ class SeeingIsBelieving | |
| 95 101 | 
             
                      input_stream.each_char { |char| process_stdin.write char }
         | 
| 96 102 | 
             
                      process_stdin.close
         | 
| 97 103 | 
             
                    end
         | 
| 98 | 
            -
                     | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 104 | 
            +
                    begin
         | 
| 105 | 
            +
                      Timeout::timeout timeout do
         | 
| 106 | 
            +
                        self.stdout     = out_reader.value
         | 
| 107 | 
            +
                        self.stderr     = err_reader.value
         | 
| 108 | 
            +
                        self.exitstatus = thread.value
         | 
| 109 | 
            +
                      end
         | 
| 110 | 
            +
                    rescue Timeout::Error
         | 
| 111 | 
            +
                      Process.kill "TERM", thread.pid
         | 
| 112 | 
            +
                      raise $!
         | 
| 113 | 
            +
                    end
         | 
| 101 114 | 
             
                  end
         | 
| 102 115 | 
             
                end
         | 
| 103 116 |  | 
| @@ -117,10 +130,12 @@ class SeeingIsBelieving | |
| 117 130 | 
             
                end
         | 
| 118 131 |  | 
| 119 132 | 
             
                def deserialize_result
         | 
| 120 | 
            -
                   | 
| 133 | 
            +
                  result = YAML.load stdout.force_encoding("utf-8")
         | 
| 134 | 
            +
                  result.fix_exception_backtraces_after_yaml_serialization
         | 
| 135 | 
            +
                  result
         | 
| 121 136 | 
             
                end
         | 
| 122 137 |  | 
| 123 | 
            -
                def  | 
| 138 | 
            +
                def notify_user_of_error
         | 
| 124 139 | 
             
                  error_stream.puts "It blew up. Not too surprising given that seeing_is_believing is pretty rough around the edges, but still this shouldn't happen."
         | 
| 125 140 | 
             
                  error_stream.puts "Please log an issue at: https://github.com/JoshCheek/seeing_is_believing/issues"
         | 
| 126 141 | 
             
                  error_stream.puts
         | 
| @@ -2,5 +2,27 @@ class SeeingIsBelieving | |
| 2 2 | 
             
              module HasException
         | 
| 3 3 | 
             
                attr_accessor :exception
         | 
| 4 4 | 
             
                alias has_exception? exception
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                # NOTE:
         | 
| 7 | 
            +
                #   zomg, so YAML doesn't serialize an exception's backtrace
         | 
| 8 | 
            +
                #   and Marshal gets all horked on windows (something like Marshal data too short)
         | 
| 9 | 
            +
                #   so I'm going back to YAML, but independently storing the backtrace
         | 
| 10 | 
            +
                #   It will need to get manually set back onto the exception
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                #   However, there is no Exception#backtrace=, so I have to redefine the method
         | 
| 13 | 
            +
                #   which sucks b/c of cache busting and so forth
         | 
| 14 | 
            +
                #   but that probably doesn't actually matter for any real-world use case of SeeingIsBelieving
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def exception=(exception)
         | 
| 17 | 
            +
                  @exception = exception
         | 
| 18 | 
            +
                  @exception_backtrace = exception.backtrace
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def fix_exception_backtraces_after_yaml_serialization
         | 
| 22 | 
            +
                  return unless exception
         | 
| 23 | 
            +
                  exception_backtrace = @exception_backtrace
         | 
| 24 | 
            +
                  exception.define_singleton_method(:backtrace) { exception_backtrace }
         | 
| 25 | 
            +
                  self
         | 
| 26 | 
            +
                end
         | 
| 5 27 | 
             
              end
         | 
| 6 28 | 
             
            end
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # WARNING: DO NOT REQUIRE THIS FILE, IT WILL FUCK YOU UP!!!!!!
         | 
| 2 2 |  | 
| 3 3 |  | 
| 4 | 
            +
            require 'yaml'
         | 
| 4 5 | 
             
            require 'stringio'
         | 
| 5 6 | 
             
            real_stdout = STDOUT
         | 
| 6 7 | 
             
            real_stderr = STDERR
         | 
| @@ -14,5 +15,5 @@ at_exit do | |
| 14 15 | 
             
              $seeing_is_believing_current_result.stdout = fake_stdout.string
         | 
| 15 16 | 
             
              $seeing_is_believing_current_result.stderr = fake_stderr.string
         | 
| 16 17 |  | 
| 17 | 
            -
              real_stdout.write  | 
| 18 | 
            +
              real_stdout.write YAML.dump($seeing_is_believing_current_result).force_encoding("utf-8")
         | 
| 18 19 | 
             
            end
         | 
    
        data/spec/arg_parser_spec.rb
    CHANGED
    
    | @@ -40,9 +40,25 @@ describe SeeingIsBelieving::Binary::ArgParser do | |
| 40 40 | 
             
                end
         | 
| 41 41 | 
             
              end
         | 
| 42 42 |  | 
| 43 | 
            +
              shared_examples 'it requires a non-negative float or int' do |flags|
         | 
| 44 | 
            +
                it 'expects a non-negative float or int argument' do
         | 
| 45 | 
            +
                  flags.each do |flag|
         | 
| 46 | 
            +
                    parse([flag,   '1']).should_not have_error /#{flag}/
         | 
| 47 | 
            +
                    parse([flag,   '0']).should_not have_error /#{flag}/
         | 
| 48 | 
            +
                    parse([flag,  '-1']).should     have_error /#{flag}/
         | 
| 49 | 
            +
                    parse([flag,'-1.0']).should     have_error /#{flag}/
         | 
| 50 | 
            +
                    parse([flag, '1.0']).should_not have_error /#{flag}/
         | 
| 51 | 
            +
                    parse([flag,   'a']).should     have_error /#{flag}/
         | 
| 52 | 
            +
                    parse([flag,   '' ]).should     have_error /#{flag}/
         | 
| 53 | 
            +
                    parse([flag       ]).should     have_error /#{flag}/
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 43 58 | 
             
              specify 'unknown options set an error' do
         | 
| 44 59 | 
             
                parse(['--xyz']).should have_error 'Unknown option: "--xyz"'
         | 
| 45 60 | 
             
                parse(['-x']).should have_error 'Unknown option: "-x"'
         | 
| 61 | 
            +
                parse(['-x', 'b']).should have_error 'Unknown option: "-x"'
         | 
| 46 62 | 
             
              end
         | 
| 47 63 |  | 
| 48 64 | 
             
              example 'example: multiple args' do
         | 
| @@ -259,5 +275,41 @@ describe SeeingIsBelieving::Binary::ArgParser do | |
| 259 275 | 
             
                  parse(%w[--version])[:version].should == true
         | 
| 260 276 | 
             
                end
         | 
| 261 277 | 
             
              end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
              describe ':timeout' do
         | 
| 280 | 
            +
                it 'defaults to 0' do
         | 
| 281 | 
            +
                  parse([])[:timeout].should == 0
         | 
| 282 | 
            +
                end
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                it_behaves_like 'it requires a non-negative float or int', ['-t', '--timeout']
         | 
| 285 | 
            +
              end
         | 
| 286 | 
            +
             | 
| 287 | 
            +
              describe ':alignment_strategy' do
         | 
| 288 | 
            +
                AlignAll   = SeeingIsBelieving::Binary::AlignAll
         | 
| 289 | 
            +
                AlignLine  = SeeingIsBelieving::Binary::AlignLine
         | 
| 290 | 
            +
                AlignChunk = SeeingIsBelieving::Binary::AlignChunk
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                # maybe change the default?
         | 
| 293 | 
            +
                it 'defaults to AlignAll' do
         | 
| 294 | 
            +
                  parse([])[:alignment_strategy].should == AlignAll
         | 
| 295 | 
            +
                end
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                specify '-s and --alignment-strategy sets the alignment strategy' do
         | 
| 298 | 
            +
                  parse(['-s',                   'chunk'])[:alignment_strategy].should == AlignChunk
         | 
| 299 | 
            +
                  parse(['--alignment-strategy', 'chunk'])[:alignment_strategy].should == AlignChunk
         | 
| 300 | 
            +
                end
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                it 'accepts values: file, line, chunk' do
         | 
| 303 | 
            +
                  parse(['-s',  'file'])[:alignment_strategy].should == AlignAll
         | 
| 304 | 
            +
                  parse(['-s',  'line'])[:alignment_strategy].should == AlignLine
         | 
| 305 | 
            +
                  parse(['-s', 'chunk'])[:alignment_strategy].should == AlignChunk
         | 
| 306 | 
            +
                end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                it 'sets an error if not provided with a strategy, or if provided with an unknown strategy' do
         | 
| 309 | 
            +
                  parse(['-s', 'file']).should_not have_error /alignment-strategy/
         | 
| 310 | 
            +
                  parse(['-s',  'abc']).should     have_error /alignment-strategy/
         | 
| 311 | 
            +
                  parse(['-s'        ]).should     have_error /alignment-strategy/
         | 
| 312 | 
            +
                end
         | 
| 313 | 
            +
              end
         | 
| 262 314 | 
             
            end
         | 
| 263 315 |  | 
    
        metadata
    CHANGED
    
    | @@ -2,14 +2,14 @@ | |
| 2 2 | 
             
            name: seeing_is_believing
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 4 | 
             
              prerelease: 
         | 
| 5 | 
            -
              version: 0.0. | 
| 5 | 
            +
              version: 0.0.17
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| 8 8 | 
             
            - Josh Cheek
         | 
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-04- | 
| 12 | 
            +
            date: 2013-04-23 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -99,6 +99,9 @@ files: | |
| 99 99 | 
             
            - features/support/env.rb
         | 
| 100 100 | 
             
            - lib/seeing_is_believing.rb
         | 
| 101 101 | 
             
            - lib/seeing_is_believing/binary.rb
         | 
| 102 | 
            +
            - lib/seeing_is_believing/binary/align_all.rb
         | 
| 103 | 
            +
            - lib/seeing_is_believing/binary/align_chunk.rb
         | 
| 104 | 
            +
            - lib/seeing_is_believing/binary/align_line.rb
         | 
| 102 105 | 
             
            - lib/seeing_is_believing/binary/arg_parser.rb
         | 
| 103 106 | 
             
            - lib/seeing_is_believing/binary/line_formatter.rb
         | 
| 104 107 | 
             
            - lib/seeing_is_believing/binary/print_results_next_to_lines.rb
         |