spellr 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +14 -14
- data/lib/.spellr.yml +2 -0
- data/lib/spellr/backports.rb +16 -6
- data/lib/spellr/base_reporter.rb +54 -0
- data/lib/spellr/check.rb +54 -20
- data/lib/spellr/cli.rb +13 -6
- data/lib/spellr/column_location.rb +1 -1
- data/lib/spellr/config.rb +6 -45
- data/lib/spellr/config_loader.rb +10 -6
- data/lib/spellr/file.rb +15 -2
- data/lib/spellr/file_list.rb +21 -17
- data/lib/spellr/interactive.rb +51 -116
- data/lib/spellr/interactive_add.rb +64 -0
- data/lib/spellr/interactive_replacement.rb +69 -0
- data/lib/spellr/key_tuner/naive_bayes.rb +49 -91
- data/lib/spellr/key_tuner/possible_key.rb +36 -32
- data/lib/spellr/key_tuner/stats.rb +26 -7
- data/lib/spellr/language.rb +28 -44
- data/lib/spellr/line_location.rb +13 -7
- data/lib/spellr/line_tokenizer.rb +35 -134
- data/lib/spellr/output.rb +62 -0
- data/lib/spellr/output_stubbed.rb +58 -0
- data/lib/spellr/quiet_reporter.rb +13 -0
- data/lib/spellr/reporter.rb +9 -13
- data/lib/spellr/token.rb +14 -16
- data/lib/spellr/token_regexps.rb +103 -0
- data/lib/spellr/tokenizer.rb +35 -14
- data/lib/spellr/version.rb +1 -1
- data/lib/spellr/wordlist.rb +29 -25
- data/lib/spellr/wordlist_reporter.rb +16 -8
- data/lib/spellr.rb +1 -0
- data/wordlists/ruby.txt +1046 -13
- metadata +9 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e2aaca19a62f3dafd26ff2948289fac3f12e83ca30660b2b17d5d97866b5c8c1
         | 
| 4 | 
            +
              data.tar.gz: fe0b3266121b748b26f1425a70c5b9d5e25a9d31a5a4befe66a84be8c6d1a9ee
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3b23613dee23ae8a8195d39a2abe55190a4b1b400174c197469391cb18d5d282a99920f5e3b7468030d7aa078ec0fe5d33bcf8b726e65e82dddd55cc9ba9f396
         | 
| 7 | 
            +
              data.tar.gz: 2ef4a3eb0f30574fc2b77564af37a0ef0fdc71b03c8377bab597d9fb81d978b49dda614366fe3cafe8d4d01d6e1f98307af7159391fc903c368cf1e0d8a3a493
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                spellr (0.5. | 
| 4 | 
            +
                spellr (0.5.1)
         | 
| 5 5 | 
             
                  fast_ignore (~> 0.4.0)
         | 
| 6 6 |  | 
| 7 7 | 
             
            GEM
         | 
| @@ -13,7 +13,7 @@ GEM | |
| 13 13 | 
             
                fast_ignore (0.4.1)
         | 
| 14 14 | 
             
                jaro_winkler (1.5.3)
         | 
| 15 15 | 
             
                method_source (0.9.2)
         | 
| 16 | 
            -
                parallel (1. | 
| 16 | 
            +
                parallel (1.18.0)
         | 
| 17 17 | 
             
                parser (2.6.5.0)
         | 
| 18 18 | 
             
                  ast (~> 2.4.0)
         | 
| 19 19 | 
             
                pry (0.12.2)
         | 
| @@ -21,21 +21,21 @@ GEM | |
| 21 21 | 
             
                  method_source (~> 0.9.0)
         | 
| 22 22 | 
             
                rainbow (3.0.0)
         | 
| 23 23 | 
             
                rake (10.5.0)
         | 
| 24 | 
            -
                rspec (3. | 
| 25 | 
            -
                  rspec-core (~> 3. | 
| 26 | 
            -
                  rspec-expectations (~> 3. | 
| 27 | 
            -
                  rspec-mocks (~> 3. | 
| 28 | 
            -
                rspec-core (3. | 
| 29 | 
            -
                  rspec-support (~> 3. | 
| 24 | 
            +
                rspec (3.9.0)
         | 
| 25 | 
            +
                  rspec-core (~> 3.9.0)
         | 
| 26 | 
            +
                  rspec-expectations (~> 3.9.0)
         | 
| 27 | 
            +
                  rspec-mocks (~> 3.9.0)
         | 
| 28 | 
            +
                rspec-core (3.9.0)
         | 
| 29 | 
            +
                  rspec-support (~> 3.9.0)
         | 
| 30 30 | 
             
                rspec-eventually (0.2.2)
         | 
| 31 | 
            -
                rspec-expectations (3. | 
| 31 | 
            +
                rspec-expectations (3.9.0)
         | 
| 32 32 | 
             
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 33 | 
            -
                  rspec-support (~> 3. | 
| 34 | 
            -
                rspec-mocks (3. | 
| 33 | 
            +
                  rspec-support (~> 3.9.0)
         | 
| 34 | 
            +
                rspec-mocks (3.9.0)
         | 
| 35 35 | 
             
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 36 | 
            -
                  rspec-support (~> 3. | 
| 37 | 
            -
                rspec-support (3. | 
| 38 | 
            -
                rubocop (0. | 
| 36 | 
            +
                  rspec-support (~> 3.9.0)
         | 
| 37 | 
            +
                rspec-support (3.9.0)
         | 
| 38 | 
            +
                rubocop (0.76.0)
         | 
| 39 39 | 
             
                  jaro_winkler (~> 1.5.1)
         | 
| 40 40 | 
             
                  parallel (~> 1.10)
         | 
| 41 41 | 
             
                  parser (>= 2.6)
         | 
    
        data/lib/.spellr.yml
    CHANGED
    
    
    
        data/lib/spellr/backports.rb
    CHANGED
    
    | @@ -3,12 +3,10 @@ | |
| 3 3 | 
             
            class Array
         | 
| 4 4 | 
             
              unless RUBY_VERSION >= '2.4'
         | 
| 5 5 | 
             
                def sum
         | 
| 6 | 
            -
                   | 
| 7 | 
            -
                    total +  | 
| 8 | 
            -
             | 
| 9 | 
            -
                     | 
| 10 | 
            -
                      value
         | 
| 11 | 
            -
                    end
         | 
| 6 | 
            +
                  if block_given?
         | 
| 7 | 
            +
                    reduce(0) { |total, value| total + yield(value) }
         | 
| 8 | 
            +
                  else
         | 
| 9 | 
            +
                    reduce(:+)
         | 
| 12 10 | 
             
                  end
         | 
| 13 11 | 
             
                end
         | 
| 14 12 | 
             
              end
         | 
| @@ -17,3 +15,15 @@ end | |
| 17 15 | 
             
            class String
         | 
| 18 16 | 
             
              alias_method :match?, :match unless RUBY_VERSION >= '2.4'
         | 
| 19 17 | 
             
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            class Hash
         | 
| 20 | 
            +
              unless RUBY_VERSION >= '2.5'
         | 
| 21 | 
            +
                def slice!(*keys)
         | 
| 22 | 
            +
                  delete_if { |k| !keys.include?(k) }
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def slice(*keys)
         | 
| 26 | 
            +
                  dup.slice!(*keys)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative 'string_format'
         | 
| 4 | 
            +
            require_relative 'output'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Spellr
         | 
| 7 | 
            +
              class BaseReporter
         | 
| 8 | 
            +
                include Spellr::StringFormat
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def parallel?
         | 
| 11 | 
            +
                  true
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def initialize(output = nil)
         | 
| 15 | 
            +
                  @output = output
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def finish
         | 
| 19 | 
            +
                  nil
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def call(token)
         | 
| 23 | 
            +
                  puts "#{aqua token.location} #{token.line.highlight(token.char_range).strip}"
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def increment(counter)
         | 
| 27 | 
            +
                  output.increment(counter)
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def puts(str)
         | 
| 31 | 
            +
                  output.puts(str)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def print(str)
         | 
| 35 | 
            +
                  output.print(str)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def warn(str)
         | 
| 39 | 
            +
                  output.warn(str)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def exit_code
         | 
| 43 | 
            +
                  output.exit_code
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def output
         | 
| 47 | 
            +
                  @output ||= Spellr::Output.new
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def counts
         | 
| 51 | 
            +
                  output.counts
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
    
        data/lib/spellr/check.rb
    CHANGED
    
    | @@ -5,6 +5,9 @@ require_relative 'tokenizer' | |
| 5 5 | 
             
            require_relative 'token'
         | 
| 6 6 | 
             
            require_relative 'column_location'
         | 
| 7 7 | 
             
            require_relative 'line_location'
         | 
| 8 | 
            +
            require_relative 'output_stubbed'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            require 'parallel'
         | 
| 8 11 |  | 
| 9 12 | 
             
            module Spellr
         | 
| 10 13 | 
             
              class InvalidByteSequence
         | 
| @@ -15,45 +18,76 @@ module Spellr | |
| 15 18 | 
             
              end
         | 
| 16 19 |  | 
| 17 20 | 
             
              class Check
         | 
| 18 | 
            -
                attr_reader :exit_code
         | 
| 19 21 | 
             
                attr_reader :files, :reporter
         | 
| 20 22 |  | 
| 23 | 
            +
                def exit_code
         | 
| 24 | 
            +
                  reporter.exit_code
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 21 27 | 
             
                def initialize(files: [], reporter: Spellr.config.reporter)
         | 
| 22 28 | 
             
                  @files = files
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  @ | 
| 29 | 
            +
             | 
| 30 | 
            +
                  @main_reporter = @reporter = reporter
         | 
| 25 31 | 
             
                end
         | 
| 26 32 |  | 
| 27 33 | 
             
                def check
         | 
| 28 | 
            -
                   | 
| 34 | 
            +
                  return check_parallel if reporter.parallel?
         | 
| 35 | 
            +
             | 
| 29 36 | 
             
                  files.each do |file|
         | 
| 30 | 
            -
                     | 
| 31 | 
            -
             | 
| 37 | 
            +
                    check_and_count_file(file)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  reporter.finish
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def check_parallel # rubocop:disable Metrics/MethodLength
         | 
| 44 | 
            +
                  acc_reporter = @reporter
         | 
| 45 | 
            +
                  Parallel.each(files, finish: ->(_, _, result) { acc_reporter.output << result }) do |file|
         | 
| 46 | 
            +
                    @reporter = acc_reporter.class.new(Spellr::OutputStubbed.new)
         | 
| 47 | 
            +
                    check_and_count_file(file)
         | 
| 48 | 
            +
                    reporter.output
         | 
| 32 49 | 
             
                  end
         | 
| 50 | 
            +
                  @reporter = acc_reporter
         | 
| 33 51 |  | 
| 34 | 
            -
                  reporter.finish | 
| 52 | 
            +
                  reporter.finish
         | 
| 35 53 | 
             
                end
         | 
| 36 54 |  | 
| 37 55 | 
             
                private
         | 
| 38 56 |  | 
| 39 | 
            -
                def  | 
| 40 | 
            -
                   | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 57 | 
            +
                def check_and_count_file(file)
         | 
| 58 | 
            +
                  check_file(file)
         | 
| 59 | 
            +
                  reporter.output.increment(:checked)
         | 
| 60 | 
            +
                rescue InvalidByteSequence
         | 
| 61 | 
            +
                  # sometimes files are binary
         | 
| 62 | 
            +
                  reporter.output.warn "Skipped unreadable file: #{file}"
         | 
| 63 | 
            +
                end
         | 
| 43 64 |  | 
| 44 | 
            -
             | 
| 65 | 
            +
                def check_tokens_in_file(file, start_at, wordlist_proc)
         | 
| 66 | 
            +
                  Spellr::Tokenizer.new(file, start_at: start_at)
         | 
| 67 | 
            +
                    .each_token(skip_term_proc: wordlist_proc) do |token|
         | 
| 45 68 | 
             
                      reporter.call(token)
         | 
| 46 | 
            -
                       | 
| 69 | 
            +
                      reporter.output.exit_code = 1
         | 
| 47 70 | 
             
                    end
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def wordlist_proc_for(file)
         | 
| 74 | 
            +
                  wordlists = Spellr.config.wordlists_for(file)
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  ->(term) { wordlists.any? { |w| w.include?(term) } }
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def check_file_from_restart(file, restart_token, wordlist_proc)
         | 
| 80 | 
            +
                  # new wordlist cache when adding a word
         | 
| 81 | 
            +
                  wordlist_proc = wordlist_proc_for(file) unless restart_token.replacement
         | 
| 82 | 
            +
                  check_file(file, start_at: restart_token.location, wordlist_proc: wordlist_proc)
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def check_file(file, start_at: nil, wordlist_proc: wordlist_proc_for(file))
         | 
| 86 | 
            +
                  restart_token = catch(:check_file_from) do
         | 
| 87 | 
            +
                    check_tokens_in_file(file, start_at, wordlist_proc)
         | 
| 48 88 | 
             
                    nil
         | 
| 49 89 | 
             
                  end
         | 
| 50 | 
            -
                  if restart_token
         | 
| 51 | 
            -
                    wordlist_arg = restart_token.replacement ? { wordlists: wordlists } : {} # new wordlist cache when adding a word
         | 
| 52 | 
            -
                    check_file(file, start_at: restart_token.location, **wordlist_arg)
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
                rescue InvalidByteSequence
         | 
| 55 | 
            -
                  # sometimes files are binary
         | 
| 56 | 
            -
                  warn "Skipped unreadable file: #{file}" unless Spellr.config.quiet?
         | 
| 90 | 
            +
                  check_file_from_restart(file, restart_token, wordlist_proc) if restart_token
         | 
| 57 91 | 
             
                end
         | 
| 58 92 | 
             
              end
         | 
| 59 93 | 
             
            end
         | 
    
        data/lib/spellr/cli.rb
    CHANGED
    
    | @@ -18,10 +18,8 @@ module Spellr | |
| 18 18 |  | 
| 19 19 | 
             
                def check
         | 
| 20 20 | 
             
                  require_relative 'check'
         | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                    exit 1
         | 
| 24 | 
            -
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  validate_config
         | 
| 25 23 |  | 
| 26 24 | 
             
                  checker = Spellr::Check.new(files: files)
         | 
| 27 25 | 
             
                  checker.check
         | 
| @@ -29,6 +27,13 @@ module Spellr | |
| 29 27 | 
             
                  exit checker.exit_code
         | 
| 30 28 | 
             
                end
         | 
| 31 29 |  | 
| 30 | 
            +
                def validate_config
         | 
| 31 | 
            +
                  return true if Spellr.config.valid?
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  Spellr.config.print_errors
         | 
| 34 | 
            +
                  exit 1
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 32 37 | 
             
                def files
         | 
| 33 38 | 
             
                  require_relative 'file_list'
         | 
| 34 39 | 
             
                  Spellr::FileList.new(*argv)
         | 
| @@ -41,7 +46,8 @@ module Spellr | |
| 41 46 |  | 
| 42 47 | 
             
                def quiet_option(_)
         | 
| 43 48 | 
             
                  Spellr.config.quiet = true
         | 
| 44 | 
            -
                   | 
| 49 | 
            +
                  require_relative 'quiet_reporter'
         | 
| 50 | 
            +
                  Spellr.config.reporter = Spellr::QuietReporter.new
         | 
| 45 51 | 
             
                end
         | 
| 46 52 |  | 
| 47 53 | 
             
                def interactive_option(_)
         | 
| @@ -89,7 +95,8 @@ module Spellr | |
| 89 95 | 
             
                    opts.separator('')
         | 
| 90 96 | 
             
                    opts.on('-w', '--wordlist', 'Outputs errors in wordlist format', &method(:wordlist_option))
         | 
| 91 97 | 
             
                    opts.on('-q', '--quiet', 'Silences output', &method(:quiet_option))
         | 
| 92 | 
            -
                    opts.on('-i', '--interactive', 'Runs the spell check interactively', | 
| 98 | 
            +
                    opts.on('-i', '--interactive', 'Runs the spell check interactively',
         | 
| 99 | 
            +
                            &method(:interactive_option))
         | 
| 93 100 | 
             
                    opts.separator('')
         | 
| 94 101 | 
             
                    opts.on('-d', '--dry-run', 'List files to be checked', &method(:dry_run_option))
         | 
| 95 102 | 
             
                    opts.separator('')
         | 
| @@ -4,9 +4,9 @@ require_relative 'line_location' | |
| 4 4 |  | 
| 5 5 | 
             
            module Spellr
         | 
| 6 6 | 
             
              class ColumnLocation
         | 
| 7 | 
            -
                attr_reader :line_location
         | 
| 8 7 | 
             
                attr_reader :char_offset
         | 
| 9 8 | 
             
                attr_reader :byte_offset
         | 
| 9 | 
            +
                attr_accessor :line_location
         | 
| 10 10 |  | 
| 11 11 | 
             
                def initialize(char_offset: 0, byte_offset: 0, line_location: LineLocation.new)
         | 
| 12 12 | 
             
                  @line_location = line_location
         | 
    
        data/lib/spellr/config.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ require_relative 'reporter' | |
| 7 7 | 
             
            require 'pathname'
         | 
| 8 8 |  | 
| 9 9 | 
             
            module Spellr
         | 
| 10 | 
            -
              class Config | 
| 10 | 
            +
              class Config
         | 
| 11 11 | 
             
                attr_writer :reporter
         | 
| 12 12 | 
             
                attr_reader :config_file
         | 
| 13 13 | 
             
                attr_accessor :quiet
         | 
| @@ -48,47 +48,17 @@ module Spellr | |
| 48 48 | 
             
                end
         | 
| 49 49 |  | 
| 50 50 | 
             
                def includes
         | 
| 51 | 
            -
                   | 
| 52 | 
            -
             | 
| 53 | 
            -
                  if @config[:only]
         | 
| 54 | 
            -
                    warn <<~WARNING
         | 
| 55 | 
            -
                      \e[33mSpellr: `only:` yaml key with a list of fnmatch rules is deprecated.
         | 
| 56 | 
            -
                      Please use `includes:` instead, which uses gitignore-inspired rules.
         | 
| 57 | 
            -
                      see github.com/robotdana/fast_ignore#using-an-includes-list for details\e[0m
         | 
| 58 | 
            -
                    WARNING
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  @includes = (@config[:includes] || []) + (@config[:only] || [])
         | 
| 51 | 
            +
                  @includes ||= @config[:includes] || []
         | 
| 62 52 | 
             
                end
         | 
| 63 53 |  | 
| 64 54 | 
             
                def excludes
         | 
| 65 | 
            -
                   | 
| 66 | 
            -
             | 
| 67 | 
            -
                  if @config[:ignore]
         | 
| 68 | 
            -
                    warn <<~WARNING
         | 
| 69 | 
            -
                      \e[33mSpellr: `ignore:` yaml key is deprecated.
         | 
| 70 | 
            -
                      Please use `excludes:` instead.\e[0m
         | 
| 71 | 
            -
                    WARNING
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                  @excludes = (@config[:excludes] || []) + (@config[:ignore] || [])
         | 
| 55 | 
            +
                  @excludes ||= @config[:excludes] || []
         | 
| 75 56 | 
             
                end
         | 
| 76 57 |  | 
| 77 58 | 
             
                def color
         | 
| 78 59 | 
             
                  @config[:color]
         | 
| 79 60 | 
             
                end
         | 
| 80 61 |  | 
| 81 | 
            -
                def clear_cache # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
         | 
| 82 | 
            -
                  remove_instance_variable(:@wordlists) if defined?(@wordlists)
         | 
| 83 | 
            -
                  remove_instance_variable(:@languages) if defined?(@languages)
         | 
| 84 | 
            -
                  remove_instance_variable(:@errors) if defined?(@errors)
         | 
| 85 | 
            -
                  remove_instance_variable(:@word_minimum_length) if defined?(@word_minimum_length)
         | 
| 86 | 
            -
                  remove_instance_variable(:@key_heuristic_weight) if defined?(@key_heuristic_weight)
         | 
| 87 | 
            -
                  remove_instance_variable(:@key_minimum_length) if defined?(@key_minimum_length)
         | 
| 88 | 
            -
                  remove_instance_variable(:@excludes) if defined?(@excludes)
         | 
| 89 | 
            -
                  remove_instance_variable(:@includes) if defined?(@includes)
         | 
| 90 | 
            -
                end
         | 
| 91 | 
            -
             | 
| 92 62 | 
             
                def languages
         | 
| 93 63 | 
             
                  @languages ||= @config[:languages].map do |key, args|
         | 
| 94 64 | 
             
                    Spellr::Language.new(key, args)
         | 
| @@ -103,10 +73,6 @@ module Spellr | |
| 103 73 | 
             
                  languages.select { |l| l.matches?(file) }
         | 
| 104 74 | 
             
                end
         | 
| 105 75 |  | 
| 106 | 
            -
                def wordlists
         | 
| 107 | 
            -
                  @wordlists ||= languages.flat_map(&:wordlists)
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
             | 
| 110 76 | 
             
                def wordlists_for(file)
         | 
| 111 77 | 
             
                  languages_for(file).flat_map(&:wordlists)
         | 
| 112 78 | 
             
                end
         | 
| @@ -123,21 +89,16 @@ module Spellr | |
| 123 89 | 
             
                private
         | 
| 124 90 |  | 
| 125 91 | 
             
                def only_has_one_key_per_language
         | 
| 126 | 
            -
                  conflicting_languages = languages
         | 
| 127 | 
            -
                    .group_by(&:key)
         | 
| 128 | 
            -
                    .values.select { |g| g.length > 1 }
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                  return if conflicting_languages.empty?
         | 
| 92 | 
            +
                  conflicting_languages = languages.group_by(&:key).values.select { |g| g.length > 1 }
         | 
| 131 93 |  | 
| 132 94 | 
             
                  conflicting_languages.each do |conflicts|
         | 
| 133 | 
            -
                    errors << "Error: #{conflicts.map(&:name).join(' & ')} share the same language key  | 
| 134 | 
            -
             | 
| 95 | 
            +
                    errors << "Error: #{conflicts.map(&:name).join(' & ')} share the same language key "\
         | 
| 96 | 
            +
                    "(#{conflicts.first.key}). Please define one to be different with `key:`"
         | 
| 135 97 | 
             
                  end
         | 
| 136 98 | 
             
                end
         | 
| 137 99 |  | 
| 138 100 | 
             
                def keys_are_single_characters
         | 
| 139 101 | 
             
                  bad_languages = languages.select { |l| l.key.length > 1 }
         | 
| 140 | 
            -
                  return if bad_languages.empty?
         | 
| 141 102 |  | 
| 142 103 | 
             
                  bad_languages.each do |language|
         | 
| 143 104 | 
             
                    errors << "Error: #{language.name} defines a key that is too long (#{language.key}). "\
         | 
    
        data/lib/spellr/config_loader.rb
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            require 'yaml'
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            module Spellr
         | 
| 4 6 | 
             
              class ConfigLoader
         | 
| 5 7 | 
             
                attr_reader :config_file
         | 
| @@ -9,6 +11,7 @@ module Spellr | |
| 9 11 | 
             
                end
         | 
| 10 12 |  | 
| 11 13 | 
             
                def config_file=(value)
         | 
| 14 | 
            +
                  # TODO: nicer error message
         | 
| 12 15 | 
             
                  ::File.read(value) # raise Errno::ENOENT if the file doesn't exist
         | 
| 13 16 | 
             
                  @config_file = value
         | 
| 14 17 | 
             
                  @config = nil
         | 
| @@ -29,10 +32,12 @@ module Spellr | |
| 29 32 | 
             
                end
         | 
| 30 33 |  | 
| 31 34 | 
             
                def load_yaml(path)
         | 
| 32 | 
            -
                  require 'yaml'
         | 
| 33 | 
            -
             | 
| 34 35 | 
             
                  return {} unless ::File.exist?(path)
         | 
| 35 36 |  | 
| 37 | 
            +
                  symbolize_yaml_safe_load(path)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def symbolize_yaml_safe_load(path)
         | 
| 36 41 | 
             
                  if RUBY_VERSION >= '2.5'
         | 
| 37 42 | 
             
                    YAML.safe_load(::File.read(path), symbolize_names: true)
         | 
| 38 43 | 
             
                  else
         | 
| @@ -40,12 +45,11 @@ module Spellr | |
| 40 45 | 
             
                  end
         | 
| 41 46 | 
             
                end
         | 
| 42 47 |  | 
| 43 | 
            -
                def symbolize_names!(obj)
         | 
| 48 | 
            +
                def symbolize_names!(obj) # rubocop:disable Metrics/MethodLength
         | 
| 44 49 | 
             
                  case obj
         | 
| 45 50 | 
             
                  when Hash
         | 
| 46 51 | 
             
                    obj.keys.each do |key|
         | 
| 47 | 
            -
                       | 
| 48 | 
            -
                      obj[key.to_sym] = symbolize_names!(value)
         | 
| 52 | 
            +
                      obj[key.to_sym] = symbolize_names!(obj.delete(key))
         | 
| 49 53 | 
             
                    end
         | 
| 50 54 | 
             
                  when Array
         | 
| 51 55 | 
             
                    obj.map! { |ea| symbolize_names!(ea) }
         | 
| @@ -53,7 +57,7 @@ module Spellr | |
| 53 57 | 
             
                  obj
         | 
| 54 58 | 
             
                end
         | 
| 55 59 |  | 
| 56 | 
            -
                def merge_config(default, project)
         | 
| 60 | 
            +
                def merge_config(default, project) # rubocop:disable Metrics/MethodLength
         | 
| 57 61 | 
             
                  if project.is_a?(Array) && default.is_a?(Array)
         | 
| 58 62 | 
             
                    default | project
         | 
| 59 63 | 
             
                  elsif project.is_a?(Hash) && default.is_a?(Hash)
         | 
    
        data/lib/spellr/file.rb
    CHANGED
    
    | @@ -2,8 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'pathname'
         | 
| 4 4 |  | 
| 5 | 
            -
            # TODO: maybe just extend pathname if you have to
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
            module Spellr
         | 
| 8 6 | 
             
              class File < Pathname
         | 
| 9 7 | 
             
                def self.wrap(file)
         | 
| @@ -22,5 +20,20 @@ module Spellr | |
| 22 20 | 
             
                def first_line
         | 
| 23 21 | 
             
                  @first_line ||= each_line.first
         | 
| 24 22 | 
             
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def relative_path
         | 
| 25 | 
            +
                  @relative_path ||= relative_path_from(Spellr.config.pwd)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def insert(string, range)
         | 
| 29 | 
            +
                  read_write do |body|
         | 
| 30 | 
            +
                    body[range] = string
         | 
| 31 | 
            +
                    body
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def read_write
         | 
| 36 | 
            +
                  write(yield read)
         | 
| 37 | 
            +
                end
         | 
| 25 38 | 
             
              end
         | 
| 26 39 | 
             
            end
         | 
    
        data/lib/spellr/file_list.rb
    CHANGED
    
    | @@ -12,34 +12,38 @@ module Spellr | |
| 12 12 | 
             
                  @patterns = patterns
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 | 
            +
                def each
         | 
| 16 | 
            +
                  fast_ignore.each do |file|
         | 
| 17 | 
            +
                    file = Spellr::File.new(file)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    yield(file)
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def to_a
         | 
| 24 | 
            +
                  enum_for(:each).to_a
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                private
         | 
| 28 | 
            +
             | 
| 15 29 | 
             
                # anchored patterns are significantly faster on large codebases
         | 
| 16 30 | 
             
                def cli_patterns
         | 
| 17 31 | 
             
                  @patterns.map do |pattern|
         | 
| 18 | 
            -
                     | 
| 19 | 
            -
                      pattern
         | 
| 20 | 
            -
                    else
         | 
| 21 | 
            -
                      "/#{pattern}"
         | 
| 22 | 
            -
                    end
         | 
| 32 | 
            +
                    pattern.sub(%r{^(?!(?:[/~*]|\.{1,2}/))}, '/')
         | 
| 23 33 | 
             
                  end
         | 
| 24 34 | 
             
                end
         | 
| 25 35 |  | 
| 26 | 
            -
                def  | 
| 36 | 
            +
                def gitignore_path
         | 
| 27 37 | 
             
                  gitignore = ::File.join(Dir.pwd, '.gitignore')
         | 
| 28 | 
            -
                  gitignore  | 
| 38 | 
            +
                  gitignore if ::File.exist?(gitignore)
         | 
| 39 | 
            +
                end
         | 
| 29 40 |  | 
| 41 | 
            +
                def fast_ignore
         | 
| 30 42 | 
             
                  FastIgnore.new(
         | 
| 31 43 | 
             
                    ignore_rules: Spellr.config.excludes,
         | 
| 32 44 | 
             
                    include_rules: Spellr.config.includes + cli_patterns,
         | 
| 33 | 
            -
                    gitignore:  | 
| 34 | 
            -
                  ) | 
| 35 | 
            -
                    file = Spellr::File.new(file)
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                    yield(file)
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                def to_a
         | 
| 42 | 
            -
                  enum_for(:each).to_a
         | 
| 45 | 
            +
                    gitignore: gitignore_path
         | 
| 46 | 
            +
                  )
         | 
| 43 47 | 
             
                end
         | 
| 44 48 | 
             
              end
         | 
| 45 49 | 
             
            end
         |