forspell 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9ec99d8b67f987cb0cb0305b2af98796b971ea1a6fd61fe946ffe8685e5cacaf
4
+ data.tar.gz: 85cce6671e87533b82551377270fc4bf665b854e764a6c4358595d4cfd7622b7
5
+ SHA512:
6
+ metadata.gz: 25c10c8d9218fd566ae1847f3d66aac56f183099459cd467239bb63f82fecfabce77e5da39b0edaf8c647b97a5db65f33e2021a9580d229fe9d3d42a4fffbfa7
7
+ data.tar.gz: e9034da3163e853dfcb3dad1a90be1ae3f6fcd8990b8d1a0e6aecddaf692c9f748ba3bca993de3333695181a1b8b730688bfefa1830ff73582884155c519f588
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Forspell
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/forspell.svg)](http://badge.fury.io/rb/forspell)
4
+ [![Build Status](https://travis-ci.org/kkuprikov/forspell.svg?branch=master)](https://travis-ci.org/kkuprikov/forspell)
5
+
6
+ **Forspell** is spellchecker for code and documentation. It uses well-known [hunspell](https://en.wikipedia.org/wiki/Hunspell) tool and dictionary, provides customizable output, and could be easily integrated into CI pipeline.
7
+
8
+ Example of output:
9
+
10
+ ![](https://user-images.githubusercontent.com/713419/55152630-d775a600-5161-11e9-9c56-d9fb45d8a3a4.png)
11
+
12
+ ## Features
13
+
14
+ * Able to check Markdown files and comments inside Ruby, C and C++ source code;
15
+ * Correctly skips over code examples and identifiers inside comments and Markdown most of the time;
16
+ * Distributed with latest en-US hunspell dictionaries, but can be set to use any other dictionary;
17
+ * Includes by default custom Ruby ecosystem-related dictionary (so it will not report as misspelled words like "Gemfile", "args", "middleware" and alike);
18
+ * It is easy to create custom dictionary for your project, so your internal terms would not be reported as misspellings;
19
+ * Option to auto-generate initial custom dictionary;
20
+ * Several output formats, including pretty colorized human-readable, YAML and JSON.
21
+
22
+ ## Installation
23
+
24
+ ```
25
+ gem install forspell
26
+ ```
27
+
28
+ `forspell` requires `libhunspell` >= 1.2.0 to be installed, see [hunspell site](https://github.com/hunspell/hunspell) for installation instructions (it is probably as easy as `<yourpackagemanager> install hunspell` on most of Linuxes and MacOS).
29
+
30
+ ## Usage
31
+
32
+ ```
33
+ $ forspell --help
34
+ Usage: forspell [list of files and folders] [options]
35
+
36
+ Options:
37
+ -e, --exclude pathes List of pathes to exclude
38
+ -d, --dictionary path Path to main hunspell dictionary to use (by default, forspell's en_US)
39
+ -c, --custom pathes Pathes to custom dictionaries
40
+ -f, --format format_name Output formats: readable (default), json, yaml
41
+ --gen-dictionary Generate custom dictionary
42
+ -l, --logfile path Log to specified path
43
+ -v, --verbose Verbose mode
44
+ --help
45
+ ```
46
+
47
+ forspell automatically loads command-line arguments from `.forspell` file in current folder, if it is present.
48
+
49
+ ### Dictionaries
50
+
51
+ As already said, forspell uses hunspell dictionaries to check spelling. By default, it is `en_US` modern dictionary, distributed with forspell itself, but you can specify any other with `-d` option. If you have `/some/custom/path/fr_FR.aff` and `/some/custom/path/fr_FR.dic`, than you can use it instead of `en_US` with `-d /some/custom/path/fr_FR`.
52
+
53
+ In addition to the main dictionary, forspell also includes (and always uses) small auxiliary dictionary with words specific for Ruby ecosystem, you can review it in [forspell repo](https://github.com/kkuprikov/forspell/blob/master/lib/forspell/ruby.dict).
54
+
55
+ You can also add your project's **custom dictionary** with internal terms, for them not to obstruct spellchecker's output. Custom dictionary (or several) can be passed with `-c` option. Also, `forspell.dict` would be automatically read, if present in current directory. Format of custom dictionary:
56
+
57
+ * Each word on its own line.
58
+ * Line contains either just `word` (means only this word in this form).
59
+ * ...or `word: example` -- in this case, "example" should be existing word from the main dictionary, and it means your custom term can have the same forms as example word. For example, "subclass: class" will mean that "subclass", "subclasses" and "subclass'" should be considered correct.
60
+ * `#` marks comments.
61
+
62
+ For larger projects, it is handy to generate custom dictionary with `forspell your,project,pathes --gen-dictionary`. This will create `forspell.dict` with all misspelling found in your project, you can proceed by deleting genuine errors and leave what should be considered correct internal terms.
63
+
64
+ ## Integration with CI
65
+
66
+ Forspell return codes:
67
+
68
+ * 0 - when no errors found
69
+ * 1 - when there are any errors
70
+ * 2 - when it could not process with provided options, i.e. no dictionary found, no directories for checking supplied.
71
+
72
+ To integrate forspell with, say, TravisCI, you would add to `.travis.yml`:
73
+
74
+ * `sudo apt-get install hunspell` into `before_install` section
75
+ * Just `forspell` into `script` section (given you have proper `.forspell` file with all options what to check and how to output)
76
+
77
+ ## Authors
78
+
79
+ * [Kirill Kuprikov](https://github.com/kkuprikov)
80
+ * [Victor Shepelev](https://github.com/zverok)
81
+
82
+ ## License
83
+
84
+ MIT
85
+
86
+ ## Contributing
87
+
88
+ Feel free to create an issue or open a pull request!
@@ -0,0 +1,72 @@
1
+ #!/bin/sh
2
+
3
+ # Clone multiple repositories.
4
+
5
+ echo "=== CLONENATOR ==="
6
+
7
+ array=( "https://github.com/rspec/rspec-core.git"
8
+ "https://github.com/halostatue/diff-lcs/"
9
+ "https://github.com/rspec/rspec-expectations.git"
10
+ "https://github.com/rspec/rspec-mocks.git"
11
+ "https://github.com/rspec/rspec.git"
12
+ "https://github.com/rspec/rspec-support.git"
13
+ "https://github.com/erikhuda/thor.git"
14
+ "https://github.com/tzinfo/tzinfo.git"
15
+ "https://github.com/rtomayko/tilt.git"
16
+ "https://github.com/ruby-concurrency/thread_safe.git"
17
+ "https://github.com/rack-test/rack-test.git"
18
+ "https://github.com/seattlerb/minitest.git"
19
+ "https://github.com/sparklemotion/nokogiri.git"
20
+ "https://github.com/mikel/mail.git"
21
+ "https://github.com/ffi/ffi.git"
22
+ "https://github.com/lostisland/faraday.git"
23
+ "https://github.com/lautis/uglifier.git"
24
+ "https://github.com/rest-client/rest-client.git"
25
+ "https://github.com/pry/pry.git"
26
+ "https://github.com/eventmachine/eventmachine.git"
27
+ "https://github.com/redis/redis-rb.git"
28
+ "https://github.com/sinatra/sinatra.git"
29
+ "https://github.com/rails/jbuilder.git"
30
+ "https://github.com/ruby/rdoc.git"
31
+ "https://github.com/sparklemotion/http-cookie.git"
32
+ "https://github.com/mileszs/wicked_pdf.git"
33
+ "https://github.com/kjvarga/sitemap_generator.git"
34
+ "https://github.com/oivoodoo/devise_masquerade.git"
35
+ "https://github.com/norman/friendly_id.git"
36
+ "https://github.com/alexreisner/geocoder.git"
37
+ "https://github.com/RubyMoney/money-rails.git"
38
+ "https://github.com/ryanb/letter_opener.git"
39
+ "https://github.com/varvet/pundit.git"
40
+ "https://github.com/plataformatec/devise.git"
41
+ "https://github.com/thoughtbot/factory_bot.git"
42
+ "https://github.com/teamcapybara/capybara.git"
43
+ "https://github.com/paper-trail-gem/paper_trail.git"
44
+ "https://github.com/aasm/aasm.git"
45
+ "https://github.com/rubysherpas/paranoia.git"
46
+ ""
47
+ ""
48
+ ""
49
+ ""
50
+ ""
51
+ ""
52
+ ""
53
+ ""
54
+ ""
55
+ ""
56
+ ""
57
+ ""
58
+ ""
59
+ ""
60
+ ""
61
+ ""
62
+ )
63
+
64
+ cd ~/gem_src
65
+
66
+ for element in ${array[@]}
67
+ do
68
+ echo "clonning $element"
69
+ git clone $element
70
+ done
71
+
72
+ echo "=== DONE ==="
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ require 'yaml'
3
+ require 'pry'
4
+ require 'csv'
5
+
6
+ class DictionaryCreator
7
+ attr_reader :result
8
+
9
+ def initialize(path: '../test/popular_gems/json/')
10
+ @path = path
11
+ @data = {}
12
+ @result = {}
13
+ end
14
+
15
+ def process
16
+ (Dir.entries(@path) - ['.', '..']).each do |filename|
17
+ # binding.pry
18
+ @data[filename] = YAML.load_file("#{@path}#{filename}")
19
+ end
20
+
21
+ @data.each_pair do |log_filename, data|
22
+ next if data == false
23
+
24
+ gem_name = log_filename.split('.').first
25
+ data.each do |data_entry|
26
+ data_entry[:errors].each do |error|
27
+ if @result[error]
28
+ @result[error] = @result[error].merge(count: @result.dig(error, :count) + 1, gems: (@result.dig(error, :gems) + [gem_name]).uniq)
29
+ else
30
+ @result[error] = { count: 1, gems: [gem_name] }
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ self
37
+ end
38
+ end
39
+
40
+ # DictionaryCreator.new.process.result
41
+
42
+ CSV.open('../ruby_dict.csv', 'wb') do |csv|
43
+ csv << ['word', 'count', 'gems', 'should_include?']
44
+ DictionaryCreator.new.process.result.each_pair do |word, data|
45
+ csv << [word, data[:count], data[:gems].join(', '), nil]
46
+ end
47
+ end
data/exe/forspell ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/forspell/cli'
3
+
4
+ Forspell::CLI.new(ARGV).call
data/exe/generate_logs ADDED
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ cd ~/forspell
3
+ rm ./test/popular_gems/json/*.log
4
+
5
+ for var in $(ls ../gem_src/)
6
+ do
7
+ ./bin/forspell ../gem_src/$var test/popular_gems/json/$var.log
8
+ done
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slop'
4
+ require 'backports/2.5.0/hash/slice'
5
+ require_relative 'runner'
6
+ require_relative 'speller'
7
+ require_relative 'reporter'
8
+ require_relative 'file_list'
9
+
10
+ module Forspell
11
+ class CLI
12
+ ERROR_CODE = 2
13
+ CONFIG_PATH = File.join(Dir.pwd, '.forspell')
14
+ DEFAULT_CUSTOM_DICT = File.join(Dir.pwd, 'forspell.dict')
15
+
16
+ FORMATS = %w[readable yaml json].freeze
17
+ FORMAT_ERR = "must be one of the following: #{FORMATS.join(', ')}"
18
+ DEFINITIONS = proc do |o|
19
+ o.array '-e', '--exclude-paths', 'List of paths to exclude'
20
+ o.string '-d', '--dictionary-path', 'Path to main hunspell dictionary to use (by default, forspell\'s en_US)', default: 'en_US'
21
+ o.array '-c', '--custom-paths', 'Paths to custom dictionaries', default: []
22
+ o.string '-f', '--format', 'Output formats: readable(default), JSON, YAML', default: 'readable'
23
+ o.boolean '--gen-dictionary', 'Generate custom dictionary'
24
+ o.string '-l', '--logfile', 'Log to specified path'
25
+ o.bool '-v', '--verbose', 'Verbose mode'
26
+ o.on '--help' do
27
+ puts o
28
+ exit
29
+ end
30
+ end
31
+
32
+ def initialize options
33
+ @options = options
34
+ end
35
+
36
+ def call
37
+ init_options
38
+ create_files_list
39
+ init_speller
40
+ init_reporter
41
+ run
42
+ end
43
+
44
+ private
45
+
46
+ def create_files_list
47
+ @files = FileList.new(paths: @opts.arguments, exclude_paths: @opts[:exclude_paths])
48
+ end
49
+
50
+ def init_options
51
+ @options += File.read(CONFIG_PATH).tr("\n", ' ').split(' ') if File.exist?(CONFIG_PATH)
52
+
53
+ @opts = Slop.parse(@options, &DEFINITIONS)
54
+
55
+ if @opts.arguments.empty?
56
+ puts 'Usage: forspell paths to check [options]'
57
+ puts 'Type --help for more info'
58
+ exit(ERROR_CODE)
59
+ end
60
+
61
+ @opts[:format] = 'dictionary' if @opts[:gen_dictionary]
62
+ @opts[:format] = @opts[:format]&.downcase
63
+ end
64
+
65
+ def init_speller
66
+ @opts[:custom_paths].each do |path|
67
+ next if File.exist?(path)
68
+
69
+ puts "Custom dictionary not found: #{path}"
70
+ exit(ERROR_CODE)
71
+ end
72
+
73
+ @opts[:custom_paths] << DEFAULT_CUSTOM_DICT if File.exist?(DEFAULT_CUSTOM_DICT)
74
+
75
+ @speller = Speller.new(@opts[:dictionary_path], *@opts[:custom_paths])
76
+ end
77
+
78
+ def init_reporter
79
+ @reporter = Reporter.new(**@opts.to_hash.slice(:logfile, :format, :verbose))
80
+ end
81
+
82
+ def run
83
+ runner = Forspell::Runner.new(files: @files, speller: @speller, reporter: @reporter)
84
+ runner.call
85
+ exit @reporter.finalize
86
+ rescue Forspell::FileList::PathLoadError => path
87
+ @reporter.path_load_error path
88
+ exit ERROR_CODE
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,205 @@
1
+ SET UTF-8
2
+ TRY esianrtolcdugmphbyfvkwzESIANRTOLCDUGMPHBYFVKWZ'
3
+ ICONV 1
4
+ ICONV ’ '
5
+ NOSUGGEST !
6
+
7
+ # ordinal numbers
8
+ COMPOUNDMIN 1
9
+ # only in compounds: 1th, 2th, 3th
10
+ ONLYINCOMPOUND c
11
+ # compound rules:
12
+ # 1. [0-9]*1[0-9]th (10th, 11th, 12th, 56714th, etc.)
13
+ # 2. [0-9]*[02-9](1st|2nd|3rd|[4-9]th) (21st, 22nd, 123rd, 1234th, etc.)
14
+ COMPOUNDRULE 2
15
+ COMPOUNDRULE n*1t
16
+ COMPOUNDRULE n*mp
17
+ WORDCHARS 0123456789
18
+
19
+ PFX A Y 1
20
+ PFX A 0 re .
21
+
22
+ PFX I Y 1
23
+ PFX I 0 in .
24
+
25
+ PFX U Y 1
26
+ PFX U 0 un .
27
+
28
+ PFX C Y 1
29
+ PFX C 0 de .
30
+
31
+ PFX E Y 1
32
+ PFX E 0 dis .
33
+
34
+ PFX F Y 1
35
+ PFX F 0 con .
36
+
37
+ PFX K Y 1
38
+ PFX K 0 pro .
39
+
40
+ SFX V N 2
41
+ SFX V e ive e
42
+ SFX V 0 ive [^e]
43
+
44
+ SFX N Y 3
45
+ SFX N e ion e
46
+ SFX N y ication y
47
+ SFX N 0 en [^ey]
48
+
49
+ SFX X Y 3
50
+ SFX X e ions e
51
+ SFX X y ications y
52
+ SFX X 0 ens [^ey]
53
+
54
+ SFX H N 2
55
+ SFX H y ieth y
56
+ SFX H 0 th [^y]
57
+
58
+ SFX Y Y 1
59
+ SFX Y 0 ly .
60
+
61
+ SFX G Y 2
62
+ SFX G e ing e
63
+ SFX G 0 ing [^e]
64
+
65
+ SFX J Y 2
66
+ SFX J e ings e
67
+ SFX J 0 ings [^e]
68
+
69
+ SFX D Y 4
70
+ SFX D 0 d e
71
+ SFX D y ied [^aeiou]y
72
+ SFX D 0 ed [^ey]
73
+ SFX D 0 ed [aeiou]y
74
+
75
+ SFX T N 4
76
+ SFX T 0 st e
77
+ SFX T y iest [^aeiou]y
78
+ SFX T 0 est [aeiou]y
79
+ SFX T 0 est [^ey]
80
+
81
+ SFX R Y 4
82
+ SFX R 0 r e
83
+ SFX R y ier [^aeiou]y
84
+ SFX R 0 er [aeiou]y
85
+ SFX R 0 er [^ey]
86
+
87
+ SFX Z Y 4
88
+ SFX Z 0 rs e
89
+ SFX Z y iers [^aeiou]y
90
+ SFX Z 0 ers [aeiou]y
91
+ SFX Z 0 ers [^ey]
92
+
93
+ SFX S Y 4
94
+ SFX S y ies [^aeiou]y
95
+ SFX S 0 s [aeiou]y
96
+ SFX S 0 es [sxzh]
97
+ SFX S 0 s [^sxzhy]
98
+
99
+ SFX P Y 3
100
+ SFX P y iness [^aeiou]y
101
+ SFX P 0 ness [aeiou]y
102
+ SFX P 0 ness [^y]
103
+
104
+ SFX M Y 1
105
+ SFX M 0 's .
106
+
107
+ SFX B Y 3
108
+ SFX B 0 able [^aeiou]
109
+ SFX B 0 able ee
110
+ SFX B e able [^aeiou]e
111
+
112
+ SFX L Y 1
113
+ SFX L 0 ment .
114
+
115
+ REP 90
116
+ REP a ei
117
+ REP ei a
118
+ REP a ey
119
+ REP ey a
120
+ REP ai ie
121
+ REP ie ai
122
+ REP alot a_lot
123
+ REP are air
124
+ REP are ear
125
+ REP are eir
126
+ REP air are
127
+ REP air ere
128
+ REP ere air
129
+ REP ere ear
130
+ REP ere eir
131
+ REP ear are
132
+ REP ear air
133
+ REP ear ere
134
+ REP eir are
135
+ REP eir ere
136
+ REP ch te
137
+ REP te ch
138
+ REP ch ti
139
+ REP ti ch
140
+ REP ch tu
141
+ REP tu ch
142
+ REP ch s
143
+ REP s ch
144
+ REP ch k
145
+ REP k ch
146
+ REP f ph
147
+ REP ph f
148
+ REP gh f
149
+ REP f gh
150
+ REP i igh
151
+ REP igh i
152
+ REP i uy
153
+ REP uy i
154
+ REP i ee
155
+ REP ee i
156
+ REP j di
157
+ REP di j
158
+ REP j gg
159
+ REP gg j
160
+ REP j ge
161
+ REP ge j
162
+ REP s ti
163
+ REP ti s
164
+ REP s ci
165
+ REP ci s
166
+ REP k cc
167
+ REP cc k
168
+ REP k qu
169
+ REP qu k
170
+ REP kw qu
171
+ REP o eau
172
+ REP eau o
173
+ REP o ew
174
+ REP ew o
175
+ REP oo ew
176
+ REP ew oo
177
+ REP ew ui
178
+ REP ui ew
179
+ REP oo ui
180
+ REP ui oo
181
+ REP ew u
182
+ REP u ew
183
+ REP oo u
184
+ REP u oo
185
+ REP u oe
186
+ REP oe u
187
+ REP u ieu
188
+ REP ieu u
189
+ REP ue ew
190
+ REP ew ue
191
+ REP uff ough
192
+ REP oo ieu
193
+ REP ieu oo
194
+ REP ier ear
195
+ REP ear ier
196
+ REP ear air
197
+ REP air ear
198
+ REP w qu
199
+ REP qu w
200
+ REP z ss
201
+ REP ss z
202
+ REP shun tion
203
+ REP shun sion
204
+ REP shun cion
205
+ REP size cise