spellr 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +186 -0
  5. data/.ruby-version +1 -0
  6. data/.spellr.yml +23 -0
  7. data/.spellr_wordlists/dictionary.txt +120 -0
  8. data/.spellr_wordlists/english.txt +3 -0
  9. data/.spellr_wordlists/lorem.txt +4 -0
  10. data/.spellr_wordlists/ruby.txt +2 -0
  11. data/.travis.yml +7 -0
  12. data/Gemfile +8 -0
  13. data/Gemfile.lock +67 -0
  14. data/LICENSE.txt +21 -0
  15. data/README.md +64 -0
  16. data/Rakefile +8 -0
  17. data/bin/console +8 -0
  18. data/bin/fetch_wordlist/english +65 -0
  19. data/bin/fetch_wordlist/ruby +150 -0
  20. data/bin/setup +3 -0
  21. data/exe/spellr +5 -0
  22. data/lib/.spellr.yml +93 -0
  23. data/lib/spellr.rb +26 -0
  24. data/lib/spellr/check.rb +56 -0
  25. data/lib/spellr/cli.rb +205 -0
  26. data/lib/spellr/column_location.rb +49 -0
  27. data/lib/spellr/config.rb +105 -0
  28. data/lib/spellr/file.rb +27 -0
  29. data/lib/spellr/file_list.rb +45 -0
  30. data/lib/spellr/interactive.rb +191 -0
  31. data/lib/spellr/language.rb +104 -0
  32. data/lib/spellr/line_location.rb +29 -0
  33. data/lib/spellr/line_tokenizer.rb +181 -0
  34. data/lib/spellr/reporter.rb +27 -0
  35. data/lib/spellr/string_format.rb +43 -0
  36. data/lib/spellr/token.rb +83 -0
  37. data/lib/spellr/tokenizer.rb +72 -0
  38. data/lib/spellr/version.rb +5 -0
  39. data/lib/spellr/wordlist.rb +100 -0
  40. data/lib/spellr/wordlist_reporter.rb +21 -0
  41. data/spellr.gemspec +35 -0
  42. data/wordlist +2 -0
  43. data/wordlists/dockerfile.txt +21 -0
  44. data/wordlists/html.txt +340 -0
  45. data/wordlists/javascript.txt +64 -0
  46. data/wordlists/ruby.txt +2344 -0
  47. data/wordlists/shell.txt +2 -0
  48. metadata +217 -0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Dana Sherson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Spellr
2
+
3
+ Spell check your source code for fun and occasionally finding bugs
4
+
5
+ This is inspired by https://github.com/myint/scspell but i wanted a ruby gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'spellr', require: false
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install spellr
22
+
23
+ ## Usage
24
+
25
+ To start an interactive spell checking session
26
+ ```
27
+ spellr --interactive
28
+ ```
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
35
+
36
+ ## Contributing
37
+
38
+ Bug reports and pull requests are welcome on GitHub at https://github.com/robotdana/spellr.
39
+
40
+ ## License
41
+
42
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
43
+
44
+ ## TODO Before release
45
+
46
+ - [x] handle interactive add
47
+ - [x] handling wordlists per language better
48
+ - [x] global wordlists
49
+ - [x] dynamic wordlist (e.g. built from ruby and YOUR Gemfile and stdlib packages)
50
+ - [x] gem committed semi-dynamic wordlist
51
+ - [x] gem committed static wordlist
52
+ - [x] enable/disable
53
+ - [x] get marketplacer codebase green
54
+ - [x] escape
55
+ - [ ] remove default dynamic wordlist nonsense
56
+ - [x] fix bugs, have specs
57
+ - [x] attempt key recognition
58
+ ## TODO after release
59
+ - [ ] throw instead of raise for flow control
60
+ - [ ] attempt subwords again
61
+ - [ ] (semi)dynamic js wordlist
62
+ - [ ] (semi)dynamic html wordlist
63
+ - [ ] (semi)dynamic bash wordlist
64
+ - [ ] editor plugins
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'spellr'
6
+ require 'pry'
7
+
8
+ Pry.start
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'net/http'
5
+ require 'optparse'
6
+
7
+ class SCOWLDownloader
8
+ SIZE_OPTIONS = %w{10 20 35 40 50 55 60 70 80 95}.freeze
9
+ VARIANT_OPTIONS = %w{none common acceptable seldom-used}.freeze
10
+ DIACRITIC_OPTIONS = %w{strip keep both}.freeze
11
+ SPELLING_LANGUAGE_OPTIONS = %w{US GBs GBz CA AU}.freeze
12
+
13
+ def initialize
14
+ set_default_options
15
+ parse_options
16
+ puts Net::HTTP.get_response(uri).body
17
+ end
18
+
19
+ private
20
+
21
+ def set_default_options
22
+ @options = {
23
+ max_size: 50,
24
+ spelling: :US,
25
+ max_variant: 0,
26
+ diacritic: :both,
27
+ hacker: true
28
+ }
29
+ end
30
+
31
+ def parse_options # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
32
+ # rubocop:disable Metrics/LineLength
33
+ OptionParser.new do |opts|
34
+ opts.banner = 'Usage: spellr [options] fetch english [wordlist options]'
35
+ opts.on('-s', '--max-size', '=SIZE', String, SIZE_OPTIONS, 'Wordlist size. Options: 10 (~5,000 words), 20, 35, 40, 50 (default), 60, 70 (~170,000 words)') { |i| @options[:max_size] = i }
36
+ opts.on('-v', '--max-variants', '=VARIANTS', String, VARIANT_OPTIONS, 'Spelling variants. Options: none (default), common, acceptable, seldom-used') { |i| @options[:max_variant] = VARIANT_OPTIONS.index(i) }
37
+ opts.on('-d', '--diacritic', '=DIACRITIC', String, DIACRITIC_OPTIONS, 'Include diacritics in words. Options: strip (café becomes cafe), keep, both (default. cafe & café)') { |s| @options[:diacritic] = s }
38
+ opts.on('-l', '--language=x,y,z', Array, 'Comma separated list of English variations. Options: US (default), GBs (GB with -ise), GBz (GB with -ize), CA, AU') do |a|
39
+ raise ArgumentError unless (a - SPELLING_LANGUAGE_OPTIONS).empty?
40
+
41
+ @options[:spelling] = a
42
+ end
43
+ opts.on('-p', '--[no-]programming', 'include common programming terms like grep (default true)') { |h| @options[:special] = :hacker if h }
44
+ opts.on_tail('-h', '--help') do
45
+ warn opts.to_s
46
+ exit 1
47
+ end
48
+ end.parse!
49
+ # rubocop:enable Metrics/LineLength
50
+ end
51
+
52
+ attr_reader :options
53
+
54
+ def uri
55
+ query = URI.encode_www_form(
56
+ **options,
57
+ download: :wordlist,
58
+ encoding: :'utf-8',
59
+ format: :inline
60
+ )
61
+ URI.parse("http://app.aspell.net/create?#{query}")
62
+ end
63
+ end
64
+
65
+ SCOWLDownloader.new
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+ class RubyWords # rubocop:disable Metrics/ClassLength
6
+ def initialize
7
+ @strings = []
8
+ prepare_excluded_classes
9
+
10
+ parse_options
11
+
12
+ prepare_post_excluded_classes
13
+
14
+ puts generate_words
15
+ end
16
+
17
+ private
18
+
19
+ def prepare_excluded_classes
20
+ @looked_at = []
21
+ @looked_at << RubyWords.__id__
22
+ @looked_at << OptionParser.__id__ # because we're including it here
23
+ end
24
+
25
+ def generate_words
26
+ $VERBOSE = nil
27
+ @strings = []
28
+ generate_words_for(Module)
29
+ generate_keywords
30
+ generate_convention_words
31
+ end
32
+
33
+ def generate_words_for(constant)
34
+ return if @looked_at.include?(constant.__id__) # to prevent endless loops
35
+
36
+ @looked_at << constant.__id__
37
+
38
+ generate_methods_for(constant)
39
+ generate_child_constants_for(constant)
40
+ end
41
+
42
+ def generate_methods_for(constant)
43
+ @strings |= constant.public_instance_methods(false) if constant.respond_to?(:public_instance_methods)
44
+ @strings |= constant.public_methods(false) if constant.respond_to?(:public_methods)
45
+ end
46
+
47
+ def generate_child_constants_for(constant) # rubocop:disable Metrics/MethodLength
48
+ return unless constant.respond_to?(:constants)
49
+
50
+ constant.constants.each do |child|
51
+ if autoload?(child)
52
+ warn "Skipping autoload constant #{constant}::#{child}"
53
+ next
54
+ end
55
+
56
+ @strings |= [child]
57
+ child = constant.const_get(child)
58
+ generate_words_for(child)
59
+ rescue StandardError, LoadError => e
60
+ warn "Error loading #{constant}::#{child} => #{e.message}"
61
+ end
62
+ end
63
+
64
+ def generate_keywords
65
+ @strings |= %w{
66
+ __ENCODING__ __LINE__ __FILE__ BEGIN END alias and begin break case class def
67
+ defined? do else elsif end ensure false for if in module next nil not or redo
68
+ rescue retry return self super then true undef unless until when while yield
69
+ }
70
+ end
71
+
72
+ def generate_convention_words
73
+ @strings |= %w{
74
+ klass
75
+ }
76
+ end
77
+
78
+ # badly behaved classes that I'll always have to exclude
79
+ # TODO: use the full class name rather than __id__ so i don't have to load anything
80
+ def prepare_post_excluded_classes
81
+ %w{RSpec::Core::Runner I18n::Tests}.each do |exclude|
82
+ @looked_at << Module.const_get(exclude).__id__
83
+ rescue StandardError, LoadError # rubocop:disable Lint/HandleExceptions
84
+ end
85
+ end
86
+
87
+ def exclude_option(excludes, quiet: false)
88
+ excludes.each do |exclude|
89
+ @looked_at << Module.const_get(exclude).__id__
90
+ rescue StandardError, LoadError => e
91
+ warn "Error excluding #{exclude} => #{e.message}" unless quiet
92
+ end
93
+ end
94
+
95
+ def bundler_option(_)
96
+ require 'bundler/setup'
97
+ require_each Bundler.setup.requires.values.flatten(1)
98
+ end
99
+
100
+ def require_each(requirables)
101
+ requirables.each(&method(:soft_require))
102
+ end
103
+
104
+ def soft_require(requireable)
105
+ require requireable
106
+ rescue LoadError => e
107
+ warn "Error requiring #{requireable} => #{e.message}"
108
+ end
109
+
110
+ def require_option(gems)
111
+ soft_require 'bundler/setup'
112
+ require_each(gems)
113
+ end
114
+
115
+ def available_stdlibs
116
+ %w{
117
+ abbrev base64 benchmark bigdecimal cgi cmath coverage csv date delegate digest
118
+ drb/drb e2mmap English erb etc expect fcntl fiddle fileutils find forwardable
119
+ getoptlong io/console io/nonblock io/wait ipaddr irb json logger matrix mkmf
120
+ monitor mutex_m net/ftp net/http net/imap net/pop net/smtp net/telnet nkf
121
+ objspace observer open-uri open3 openssl optionparser optparse ostruct pathname
122
+ pp prettyprint prime pstore psych pty racc/parser readline resolv ripper rss scanf
123
+ sdbm securerandom set shell shellwords singleton socket stringio strscan sync syslog
124
+ tempfile thwait time timeout tmpdir tracer tsort uri weakref webrick yaml zlib
125
+ }
126
+ end
127
+
128
+ def stdlib_option(stdlibs)
129
+ stdlibs &= available_stdlibs
130
+ stdlibs.each { |p| require p }
131
+ @strings += stdlibs
132
+ @looked_at -= [OptionParser.__id__] if stdlibs.include?('optparse') # because they might want it too
133
+ end
134
+
135
+ def parse_options # rubocop:disable Metrics/MethodLength
136
+ OptionParser.new do |opts|
137
+ opts.set_program_name 'spellr --fetch ruby'
138
+ opts.on('-r', '--require=x,y,z', Array, 'requires the specified gems', &method(:require_option))
139
+ opts.on('-s', '--stdlib=x,y,z', Array, 'requires the specified stdlib packages', &method(:stdlib_option))
140
+ opts.on('-b', '--bundler', 'includes methods and constants required by emfile', &method(:bundler_option))
141
+ opts.on('-x', '--exclude=x,y,z', Array, 'exclude listing these constants and their methods', &method(:exclude_option)) # rubocop:disable Metrics/LineLength
142
+ opts.on_tail('-h', '--help', 'Shows this message') do
143
+ warn opts
144
+ exit 1
145
+ end
146
+ end.parse!
147
+ end
148
+ end
149
+
150
+ RubyWords.new
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ bundle install
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/spellr/cli'
5
+ Spellr::CLI.new(ARGV)
@@ -0,0 +1,93 @@
1
+ ---
2
+ word_minimum_length: 3
3
+
4
+ ignore: # this list is parsed with the .gitignore format
5
+ - /.git/
6
+ - .DS_Store
7
+ - Gemfile.lock
8
+ - .rspec_status
9
+ - '*.png'
10
+ - '*.jpg'
11
+ - '*.gif'
12
+ - '*.ico'
13
+ - .gitkeep
14
+ - .keep
15
+ - '*.svg'
16
+ - '*.eot'
17
+ - '*.ttf'
18
+ - '*.woff'
19
+ - '*.woff2'
20
+ - '*.zip'
21
+ - '*.pdf'
22
+ - '*.xlsx'
23
+ - '*.gz'
24
+
25
+ languages:
26
+ english:
27
+ generate: "fetch english"
28
+ # TODO: don't generate the ruby file until you actually need one
29
+ ruby:
30
+ only: # Filtered using File.fn_match
31
+ - '*.rb'
32
+ - '*.rake'
33
+ - '*.gemspec'
34
+ - '*.erb'
35
+ - '*.haml'
36
+ - '*.jbuilder'
37
+ - '*.builder'
38
+ - Gemfile
39
+ - Rakefile
40
+ - config.ru
41
+ hashbangs:
42
+ - ruby
43
+ html:
44
+ only:
45
+ - '*.html'
46
+ - '*.hml'
47
+ - '*.jsx'
48
+ - '*.tsx'
49
+ - '*.js'
50
+ - '*.ts'
51
+ - '*.coffee'
52
+ - '*.haml'
53
+ - '*.erb'
54
+ - '*.rb'
55
+ - '*.builder'
56
+ - '*.css'
57
+ - '*.scss'
58
+ - '*.sass'
59
+ - '*.less'
60
+ js:
61
+ only:
62
+ - '*.html'
63
+ - '*.hml'
64
+ - '*.jsx'
65
+ - '*.tsx'
66
+ - '*.js'
67
+ - '*.ts'
68
+ - '*.coffee'
69
+ - '*.haml'
70
+ - '*.erb'
71
+ - '*.json'
72
+ shell:
73
+ only:
74
+ - '*.sh'
75
+ - Dockerfile
76
+ hashbangs:
77
+ - bash
78
+ - sh
79
+ dockerfile:
80
+ only:
81
+ - Dockerfile
82
+ css:
83
+ only:
84
+ - '*.css'
85
+ - '*.sass'
86
+ - '*.scss'
87
+ xml:
88
+ only:
89
+ - '*.xml'
90
+ - '*.html'
91
+ - '*.haml'
92
+ - '*.hml'
93
+ - '*.svg'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spellr
4
+ class Error < StandardError; end
5
+ class DidReplacement < Spellr::Error
6
+ attr_reader :token
7
+
8
+ def initialize(token = nil)
9
+ @token = token
10
+ end
11
+ end
12
+ class DidAdd < Spellr::Error
13
+ attr_reader :token
14
+
15
+ def initialize(token = nil)
16
+ @token = token
17
+ end
18
+ end
19
+
20
+ module_function
21
+
22
+ def config
23
+ require_relative 'spellr/config'
24
+ @config ||= Spellr::Config.new
25
+ end
26
+ end