forspell 0.0.6 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4dd2b546e45d6a2fab1fb824f628cc2f17d802ce
4
- data.tar.gz: e575a2f71a0968b33e715a153d535400dec007e6
3
+ metadata.gz: 67422b4f2942f8a061b0551a4fa837c0c0c93140
4
+ data.tar.gz: b56c34d10ecd2bee9dbfa14757ec7853d8a6fe17
5
5
  SHA512:
6
- metadata.gz: f8f3d245078e74f33da758e09f724d2c911655ee7e4d792e599bd11d7a073fa8ae2acf8972868552939b91a6567d703d3c8972a11adce97bd573fb3c2496a641
7
- data.tar.gz: 62826962163488488a5ce89fb72a608fd02a858fbec5e428ec96f8be4980208bc1349eca19d0800967241208b2b2cf833da6536591551f196c62f2df0d6b2885
6
+ metadata.gz: 1e2512ac8231b29ac095fdf2d71b426a82ba9365c6ae4d9cbf52f349f76b12bf7cdfe170b2001b4f0fe7b3fc4239175f59d8cec7f9742880c30d7a0bc8c88cff
7
+ data.tar.gz: 432eb94fcf818aba269b8292988956ba905964426e239ae35a9c3972813d6d1b7c19d9a1da2e4146d3f649bfbe13902359ba49fe532458e330e04c6cc4ad89b7
data/exe/clone_repos.sh CHANGED
@@ -43,7 +43,7 @@ array=( "https://github.com/rspec/rspec-core.git"
43
43
  "https://github.com/paper-trail-gem/paper_trail.git"
44
44
  "https://github.com/aasm/aasm.git"
45
45
  "https://github.com/rubysherpas/paranoia.git"
46
- ""
46
+ "https://github.com/rubocop-hq/rubocop.git"
47
47
  ""
48
48
  ""
49
49
  ""
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'yaml'
3
- require 'pry'
4
3
  require 'csv'
4
+ require 'pry'
5
5
 
6
6
  class DictionaryCreator
7
7
  attr_reader :result
8
8
 
9
- def initialize(path: '../test/popular_gems/json/')
9
+ def initialize(path: 'test/popular_gems/')
10
10
  @path = path
11
11
  @data = {}
12
12
  @result = {}
@@ -14,21 +14,20 @@ class DictionaryCreator
14
14
 
15
15
  def process
16
16
  (Dir.entries(@path) - ['.', '..']).each do |filename|
17
- # binding.pry
18
- @data[filename] = YAML.load_file("#{@path}#{filename}")
17
+ @data[filename] = File.read("#{@path}#{filename}")
19
18
  end
20
19
 
21
20
  @data.each_pair do |log_filename, data|
22
21
  next if data == false
23
22
 
24
23
  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
24
+ data.split(/\n/).each do |error_with_count|
25
+ error, count = error_with_count.split(' # ')
26
+ count = count.to_i
27
+ if @result[error]
28
+ @result[error] = @result[error].merge(count: @result.dig(error, :count) + count, gems: (@result.dig(error, :gems) + [gem_name]).uniq)
29
+ else
30
+ @result[error] = { count: count, gems: [gem_name] }
32
31
  end
33
32
  end
34
33
  end
@@ -37,11 +36,10 @@ class DictionaryCreator
37
36
  end
38
37
  end
39
38
 
40
- # DictionaryCreator.new.process.result
41
-
42
- CSV.open('../ruby_dict.csv', 'wb') do |csv|
39
+ CSV.open('ruby_dict_sort.csv', 'wb') do |csv|
43
40
  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]
41
+ res = DictionaryCreator.new.process.result
42
+ res.keys.sort.each do |word|
43
+ csv << [word, res[word][:count], res[word][:gems].join(', '), nil]
46
44
  end
47
45
  end
data/exe/generate_logs CHANGED
@@ -1,8 +1,11 @@
1
1
  #!/bin/bash
2
2
  cd ~/forspell
3
- rm ./test/popular_gems/json/*.log
3
+ rm ./test/popular_gems/*.dict
4
4
 
5
5
  for var in $(ls ../gem_src/)
6
6
  do
7
- ./bin/forspell ../gem_src/$var test/popular_gems/json/$var.log
7
+ cd ~/gem_src/$var
8
+ rm forspell.dict
9
+ ~/forspell/exe/forspell --gen-dictionary .
10
+ cp forspell.dict ~/forspell/test/popular_gems/$var.forspell.dict
8
11
  done
data/lib/forspell/cli.rb CHANGED
@@ -20,9 +20,12 @@ module Forspell
20
20
  o.string '-d', '--dictionary-path', 'Path to main hunspell dictionary to use (by default, forspell\'s en_US)', default: 'en_US'
21
21
  o.array '-c', '--custom-paths', 'Paths to custom dictionaries', default: []
22
22
  o.string '-f', '--format', 'Output formats: readable(default), JSON, YAML', default: 'readable'
23
- o.boolean '--gen-dictionary', 'Generate custom dictionary'
23
+ o.bool '--gen-dictionary', 'Generate custom dictionary', default: false
24
+ o.bool '--print-filepaths', 'Enable file paths in dictionary mode', default: false
24
25
  o.string '-l', '--logfile', 'Log to specified path'
25
- o.bool '-v', '--verbose', 'Verbose mode'
26
+ o.bool '-v', '--verbose', 'Verbose mode', default: false
27
+ o.bool '--no-suggest', 'Output without suggestions', default: false
28
+ o.integer '--suggestions-size', 'How many suggestions for each error should be returned', default: 3
26
29
  o.on '--help' do
27
30
  puts o
28
31
  exit
@@ -71,12 +74,14 @@ module Forspell
71
74
  end
72
75
 
73
76
  @opts[:custom_paths] << DEFAULT_CUSTOM_DICT if File.exist?(DEFAULT_CUSTOM_DICT)
77
+ suggestions_size = (@opts[:gen_dictionary] || @opts[:no_suggest]) ? 0 : @opts[:suggestions_size]
78
+ suggestions_size ||= 0
74
79
 
75
- @speller = Speller.new(@opts[:dictionary_path], *@opts[:custom_paths])
80
+ @speller = Speller.new(@opts[:dictionary_path], *@opts[:custom_paths], suggestions_size: suggestions_size)
76
81
  end
77
82
 
78
83
  def init_reporter
79
- @reporter = Reporter.new(**@opts.to_hash.slice(:logfile, :format, :verbose))
84
+ @reporter = Reporter.new(**@opts.to_hash.slice(:logfile, :format, :verbose, :print_filepaths))
80
85
  end
81
86
 
82
87
  def run
@@ -16,17 +16,21 @@ module Forspell
16
16
  def initialize(paths:, exclude_paths:)
17
17
  @paths = paths
18
18
  @exclude_paths = exclude_paths
19
- end
20
19
 
21
- def each(&block)
22
20
  to_process = @paths.flat_map(&method(:expand_paths))
23
-
24
21
  to_exclude = @exclude_paths.flat_map(&method(:expand_paths))
22
+ @files = to_process - to_exclude
23
+ end
25
24
 
26
- (to_process - to_exclude).map{ |path| path.gsub('//', '/')}
25
+ def each(&block)
26
+ @files.map{ |path| path.gsub('//', '/')}
27
27
  .each(&block)
28
28
  end
29
29
 
30
+ def size
31
+ @size ||= @files.size
32
+ end
33
+
30
34
  private
31
35
 
32
36
  def expand_paths(path)
@@ -45,8 +45,10 @@ module Forspell::Loaders
45
45
 
46
46
  group_by_location = chunks.group_by { |res| res[:location] }
47
47
  .transform_values do |lines|
48
- lines.map { |v| SPECIAL_CHARS_MAP[v[:value]] || v[:value] }.join.split(/\s|,|;|—/)
48
+ lines.map { |v| SPECIAL_CHARS_MAP[v[:value]] || v[:value] }
49
+ .join.split(%r{[[:punct:]]&&[^-'_./\\:]|\s})
49
50
  end
51
+
50
52
  group_by_location.each_pair do |location, words|
51
53
  words.reject(&:empty?)
52
54
  .each { |word| result << Word.new(@file, location || 0, word) }
@@ -2,20 +2,30 @@
2
2
 
3
3
  require 'yard'
4
4
  require 'yard/parser/ruby/ruby_parser'
5
+ require 'rdoc'
5
6
  require_relative 'source'
6
7
 
7
8
  module Forspell::Loaders
8
9
  class Ruby < Source
10
+ MAX_COMMENT_LENGTH = 777
11
+
12
+ def initialize(file: nil, text: nil)
13
+ super
14
+ @markup = RDoc::Markup.new
15
+ @formatter = RDoc::Markup::ToMarkdown.new
16
+ @formatter.width = MAX_COMMENT_LENGTH
17
+ end
18
+
9
19
  private
10
20
 
11
21
  def comments
12
22
  YARD::Parser::Ruby::RubyParser.new(@input, @file).parse
13
- .tokens.select{ |token| token.first == :comment }
14
- # example: [:comment, "# def loader_class path\n", [85, 2356]]
23
+ .tokens.select{ |type,| type == :comment }
24
+ .reject{ |_, text,| text.start_with?('# ') }
15
25
  end
16
26
 
17
27
  def text(comment)
18
- comment[1]
28
+ @markup.convert(comment[1], @formatter)
19
29
  end
20
30
 
21
31
  def line(comment)
@@ -4,18 +4,26 @@ require 'fileutils'
4
4
  require 'pastel'
5
5
  require 'logger'
6
6
  require 'json'
7
+ require 'highline'
8
+ require 'ruby-progressbar'
7
9
 
8
10
  module Forspell
9
11
  class Reporter
10
12
  SUCCESS_CODE = 0
11
13
  ERROR_CODE = 1
12
- ERROR_FORMAT = '%<file>s:%<line>i: %<text>s (suggestions: %<suggestions>s)'
14
+ DICT_PATH = File.join(Dir.pwd, 'forspell.dict')
15
+ DICT_OVERWRITE = 'Do you want to overwrite forspell.dict? (yN)'
16
+ SUGGEST_FORMAT = '(suggestions: %<suggestions>s)'
17
+ ERROR_FORMAT = '%<file>s:%<line>i: %<text>s %<suggest>s'
13
18
  SUMMARY = "Forspell inspects *.rb, *.c, *.cpp, *.md files\n"\
14
19
  '%<files>i inspected, %<errors>s detected'
15
20
 
21
+ attr_accessor :progress_bar
22
+
16
23
  def initialize(logfile:,
17
24
  verbose:,
18
- format:)
25
+ format:,
26
+ print_filepaths: false)
19
27
 
20
28
  FileUtils.touch(logfile) if logfile.is_a?(String)
21
29
  @logger = Logger.new(logfile || STDERR)
@@ -26,6 +34,7 @@ module Forspell
26
34
  @pastel = Pastel.new(enabled: $stdout.tty?)
27
35
  @errors = []
28
36
  @files = []
37
+ @print_filepaths = print_filepaths
29
38
  end
30
39
 
31
40
  def file(path)
@@ -35,7 +44,7 @@ module Forspell
35
44
 
36
45
  def error(word, suggestions)
37
46
  @errors << [word, suggestions]
38
- puts readable(word, suggestions) if @format == 'readable'
47
+ print(readable(word, suggestions)) if @format == 'readable'
39
48
  end
40
49
 
41
50
  def parsing_error(error)
@@ -64,17 +73,19 @@ module Forspell
64
73
  private
65
74
 
66
75
  def readable(word, suggestions)
76
+ suggest = format(SUGGEST_FORMAT, suggestions: suggestions.join(', ')) unless suggestions.empty?
77
+
67
78
  format(ERROR_FORMAT,
68
79
  file: word[:file],
69
80
  line: word[:line],
70
81
  text: @pastel.red(word[:text]),
71
- suggestions: suggestions.join(', '))
82
+ suggest: suggest)
72
83
  end
73
84
 
74
85
  def print_formatted
75
86
  @errors.map { |word, suggestions| word.to_h.merge(suggestions: suggestions) }
76
87
  .public_send("to_#{@format}")
77
- .tap { |res| puts res }
88
+ .tap { |res| print res }
78
89
  end
79
90
 
80
91
  def print_summary
@@ -82,18 +93,32 @@ module Forspell
82
93
  color = err_count.positive? ? :red : :green
83
94
  total_errors_colorized = @pastel.decorate(err_count.to_s, color)
84
95
 
85
- puts format(SUMMARY, files: @files.size, errors: total_errors_colorized)
96
+ print format(SUMMARY, files: @files.size, errors: total_errors_colorized)
86
97
  end
87
98
 
88
99
  def print_dictionary
100
+ puts DICT_PATH
101
+ if File.exist?(DICT_PATH)
102
+ cli = HighLine.new
103
+ answer = cli.ask(DICT_OVERWRITE)
104
+ out = answer.downcase == 'y' ? File.new(DICT_PATH, 'w') : exit(1)
105
+ else
106
+ out = File.new(DICT_PATH, 'w')
107
+ end
89
108
  @errors.map(&:first)
90
109
  .group_by(&:text)
91
110
  .transform_values { |v| v.map(&:file).uniq }
92
111
  .sort_by { |word, *| word.downcase }
93
112
  .each do |text, files|
94
- files.each { |file| puts "\# #{file}" }
95
- puts @pastel.decorate(text, :red)
113
+ files.each { |file| out.puts "\# #{file}" } if @print_filepaths
114
+ out.puts out.tty? ? @pastel.decorate(text, :red) : text
96
115
  end
97
116
  end
117
+
118
+ private
119
+
120
+ def print something
121
+ $stdout.tty? ? @progress_bar&.log(something) : puts(something)
122
+ end
98
123
  end
99
124
  end
@@ -1,77 +1,454 @@
1
+ Cianfrocca
1
2
  Gemfile: example
3
+ Hansson
4
+ Heinemeier
2
5
  Rakefile
6
+ aasm
3
7
  accessor: example
8
+ activerecord
9
+ activesupport
10
+ addon
4
11
  admin: example
5
- args
12
+ amongst
13
+ arel
14
+ arg: argument
15
+ arity
16
+ asciidoc
17
+ asciidoctor
6
18
  async
7
19
  attr: example
20
+ auth
21
+ authenticatable
22
+ autocorrect
23
+ autocorrected
24
+ autogenerated
25
+ autoload: load
26
+ autoloadable
27
+ autoloaded
28
+ autoloading
29
+ autosave
8
30
  backend: example
9
31
  backport: port
32
+ backtick
10
33
  backtrace: example
34
+ basecamp
35
+ basename: name
36
+ baseurl
37
+ bcrypt
38
+ behaviour: behavior
39
+ benchmarking
40
+ bigint
41
+ bignum
42
+ bing
43
+ binstubs
11
44
  bitwise
12
45
  boolean: example
46
+ broadcastings
47
+ bugfix: fix
48
+ bugfixes
13
49
  builtin
14
- bundler
50
+ bundler: example
51
+ byebug
52
+ bytesize: size
53
+ capybara: example
54
+ chainable
55
+ changelog: log
56
+ changeset: set
15
57
  charset: example
58
+ checkbox: box
59
+ checksum: gum
60
+ chmod
61
+ cli
62
+ cmd
63
+ codebase: base
16
64
  codepoint: example
65
+ coderay
66
+ colour: color
67
+ commandline: line
68
+ compat
69
+ compatability
17
70
  composable
18
- config
71
+ concat
72
+ config: example
73
+ confirmable
74
+ const
75
+ constantize
76
+ crossref
77
+ cryptographically
78
+ ctx
79
+ cukes
80
+ customizable
81
+ customizations
82
+ datagram
19
83
  dataset: set
84
+ datetime
85
+ declaratively
86
+ decrypt
87
+ dedupe
88
+ deferrable
89
+ defs
90
+ delegator
91
+ deprecations
92
+ deprecator
93
+ desc
94
+ deserialised
20
95
  deserialization
21
96
  deserialize: rise
22
- dir
97
+ deserialized
98
+ dest
99
+ destructor
100
+ destructuring
101
+ deterministically
102
+ dev
103
+ diff
104
+ diffable
105
+ dir: beer
106
+ docstring
107
+ docstrings
108
+ dogfoods
109
+ downcase
110
+ downcased
111
+ dup
112
+ dynamoid
113
+ eg
114
+ el
115
+ elsif
23
116
  encoding: example
117
+ endian
118
+ enqueue
119
+ enqueued
120
+ enqueues
121
+ enqueuing
24
122
  enum
123
+ enumerables
124
+ enums
125
+ env
126
+ epoll
127
+ erb
128
+ errback
129
+ erubi
130
+ erubis
131
+ erubis
132
+ etag
133
+ etag
134
+ eval
135
+ eval'd
136
+ evented
137
+ extensibility
138
+ extname
25
139
  fallback: example
140
+ falsey
141
+ falsy
142
+ favour
143
+ fieldset
26
144
  filesystem: system
145
+ fixnum
27
146
  formatter: example
147
+ freenode
148
+ frontend
149
+ gemspec: specification
150
+ geocode: code
151
+ geocoded
152
+ geocoder
153
+ geocoding
28
154
  geospatial
155
+ getter
156
+ gettext
157
+ gitter
158
+ globbing
159
+ gmail
160
+ grapheme
161
+ graphviz
162
+ gsub
163
+ gzip
164
+ gzipped
165
+ habtm
166
+ haml
167
+ hardcode
168
+ hardcoded
169
+ heredoc: document
170
+ highline
171
+ hiredis
172
+ hostname: name
173
+ href
174
+ hstore
175
+ https
29
176
  i18n
177
+ iconv
178
+ iframe
179
+ impl
180
+ incrementing
181
+ inflector
182
+ initialised
30
183
  initializer: example
31
184
  inline
185
+ instantiation
186
+ interdependencies
187
+ invoker
32
188
  io
189
+ irb
190
+ iteratively
191
+ ivar: variable
192
+ javascripts
193
+ jbuilder
194
+ jruby
195
+ jruby
196
+ js
197
+ json
198
+ klass
199
+ kqueue
200
+ kramdown
201
+ lcs
33
202
  lexer: example
34
203
  lib: rib
204
+ libxml
205
+ libxml-ruby
206
+ libxslt
35
207
  lifecycle: example
208
+ localhost
209
+ lookups
210
+ loopback
211
+ lua
212
+ markaby
213
+ maruku
214
+ matcher: catcher
215
+ mediawiki
216
+ memcache
36
217
  memoization
218
+ memoize
37
219
  memoized
220
+ merb
38
221
  metadata
222
+ metaprogramming
39
223
  middleware: example
224
+ minitest: example
225
+ mins
40
226
  mixin: toxin
227
+ modularity
228
+ mongo
229
+ mongoid
41
230
  monkeypatch: patch
42
231
  monkeypatching
232
+ mtime
233
+ multibyte
234
+ multiline
43
235
  multithreaded
44
236
  multithreading
237
+ mustermann
238
+ mutator
45
239
  mutex: class
240
+ namer
46
241
  namespace: example
242
+ natively
243
+ nginx
244
+ nginx
245
+ nils
246
+ nodoc
247
+ nokogiri: example
248
+ nonces
249
+ noop
250
+ npm
251
+ numericality
252
+ offence
253
+ openssl
254
+ overridable
47
255
  override: ride
256
+ overriden
257
+ pandoc
258
+ parallelize
48
259
  param: example
49
260
  parens
261
+ parseable
50
262
  parser: example
263
+ pathname
264
+ pathname
265
+ perf
266
+ performant
267
+ permalink: link
268
+ pid
269
+ pipelined
270
+ pipelining
271
+ plaintext
272
+ pluggable
51
273
  plugin: penguin
274
+ populator
275
+ postfix
276
+ postgres
52
277
  pre
278
+ precompile
279
+ precompiled
280
+ preload
281
+ preloaded
282
+ preloader
283
+ preloading
284
+ preloads
53
285
  prepend: append
54
- proc
286
+ preprocessing
287
+ prerelease
288
+ proc: example
289
+ profiler
290
+ programmatically
291
+ proxied
292
+ proxying
293
+ pubsub
294
+ pygments
295
+ rack-contrib
296
+ rackup
297
+ ragel
298
+ rails's
299
+ railtie
300
+ railties
301
+ rbenv
302
+ rbx
303
+ rdoc
304
+ readline
305
+ readme
306
+ readonly
307
+ rebase
308
+ reconfirmable
309
+ redcarpet
310
+ redistribution: distribution
55
311
  refactor
56
312
  refactoring
313
+ refactorings
57
314
  regex
58
315
  regexp
59
- repo
316
+ reloader: loader
317
+ rememberable
318
+ renderer: example
319
+ repl
320
+ repo: example
321
+ representable
322
+ representer
323
+ repro
324
+ reraise
325
+ resque
326
+ rhs
327
+ roadmap
328
+ rspec
329
+ rspec-dev
330
+ rspec-support
331
+ rubinius
332
+ rubocop
60
333
  rubygems
61
334
  runtime: example
335
+ sanitization
336
+ savepoint: point
337
+ scalability
338
+ schemas
339
+ scss
340
+ segv
341
+ sendmail
342
+ serializable
343
+ serializer: example
344
+ serializers
345
+ servlet
346
+ sexualized
347
+ sharding
348
+ sidekiq
349
+ signalling
350
+ simples
351
+ singularized
352
+ solaris
353
+ src
354
+ ssl
355
+ stabby
356
+ stateful
357
+ stdcall
62
358
  stderr
63
359
  stdin
64
360
  stdlib
361
+ stdlibs
65
362
  stdout
363
+ str
364
+ strftime
365
+ stringified
366
+ stringify
367
+ stringify
368
+ struct: structure
66
369
  stylesheet: sheet
67
370
  subclass: class
68
371
  subclassing
69
- subtype: example
372
+ subcommand: commnad
373
+ subdirectory: directory
374
+ subfolder: folder
375
+ sublicense: license
376
+ subpath: path
377
+ subprocess
378
+ substring: string
379
+ subtype: type
380
+ sudo
70
381
  superclass: class
382
+ symlink: link
383
+ symlinked
384
+ syntaxes
385
+ sysrandom
386
+ teardown
387
+ tempfile: file
388
+ templating
389
+ textarea: area
390
+ thoughtbot
391
+ threadsafe
71
392
  timestamp: stamp
393
+ timezone: zone
394
+ tmp
395
+ todo
396
+ tokenize
397
+ tokenized
72
398
  tokenizer: example
399
+ toplevel
400
+ trackable
401
+ tradeoff
402
+ transactional
403
+ transcoding
404
+ triaging
73
405
  truthy
406
+ tt
407
+ tty
408
+ turbolinks
409
+ typedef
410
+ tz
411
+ uglifier
412
+ unary
413
+ uncomment
74
414
  unescape
415
+ unescaped
416
+ unescapes
417
+ unescaping
418
+ unformatted
419
+ unhandled
75
420
  unicode
421
+ unindent
422
+ uniq
423
+ unlink: link
424
+ unlinked
425
+ unparenthesized
426
+ unreferenced
427
+ unregister
428
+ unscoped
429
+ untrusted
430
+ uri
431
+ usec
76
432
  username: example
433
+ uuid
434
+ valgrind
435
+ validator: predator
436
+ validators
437
+ vendored
438
+ vendoring
439
+ verifier
440
+ verifiers
441
+ viewport
442
+ webrick
443
+ webserver
77
444
  whitespace: example
445
+ wkhtmltopdf
446
+ writeable
447
+ wtf
448
+ xmlns
449
+ xpath
450
+ yajl
451
+ yaml
452
+ yardoc
453
+ yay
454
+ zoneinfo
@@ -10,8 +10,13 @@ module Forspell
10
10
  end
11
11
 
12
12
  def call
13
- @files.each do |path|
13
+ increment = (@files.size / 100.0).ceil
14
+ total = @files.size <= 100 ? @files.size : 100
15
+ @reporter.progress_bar = ProgressBar.create(total: total, output: $stderr)
16
+
17
+ @files.each_with_index do |path, index|
14
18
  process_file path
19
+ @reporter.progress_bar.increment if (index + 1) % increment == 0
15
20
  end
16
21
 
17
22
  @reporter.report
@@ -5,18 +5,12 @@ require 'cgi'
5
5
 
6
6
  module Forspell
7
7
  module Sanitizer
8
- REMOVE_PUNCT = /[[:punct:]&&[^\-\'\_\.]]$/.freeze
8
+ REMOVE_PUNCT = %r{[!|?|,|(|)|"|;]+}.freeze
9
9
 
10
10
  def self.sanitize(input)
11
11
 
12
- result = CGI.unescapeHTML(Sanitize.fragment(input,
13
- elements: [], remove_contents: true))
14
- .gsub(REMOVE_PUNCT, '').gsub(/[\!\.\?]{1}$/, '')
15
- if result.start_with?("'") && result.end_with?("'")
16
- result[1..-2]
17
- else
18
- result
12
+ CGI.unescapeHTML(Sanitize.fragment(input, elements: [], remove_contents: true))
13
+ .gsub(REMOVE_PUNCT, '').gsub(%r{[.:]+$}, '')
19
14
  end
20
- end
21
15
  end
22
16
  end
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ffi/hunspell'
4
+ require 'backports/2.5.0/enumerable/all'
4
5
 
5
6
  module Forspell
6
7
  class Speller
7
8
  attr_reader :dictionary
8
9
 
9
- SUGGESTIONS_SIZE = 3
10
10
  HUNSPELL_DIRS = [File.join(__dir__, 'dictionaries')]
11
11
  RUBY_DICT = File.join(__dir__, 'ruby.dict')
12
12
 
13
- def initialize(main_dictionary, *custom_dictionaries)
13
+ def initialize(main_dictionary, *custom_dictionaries, suggestions_size: 0)
14
+ @suggestions_size = suggestions_size
14
15
  FFI::Hunspell.directories = HUNSPELL_DIRS << File.dirname(main_dictionary)
15
16
  @dictionary = FFI::Hunspell.dict(File.basename(main_dictionary))
16
17
 
@@ -28,11 +29,20 @@ module Forspell
28
29
  end
29
30
 
30
31
  def correct?(word)
31
- dictionary.check?(word)
32
+ parts = word.split('-')
33
+ if parts.size == 1
34
+ alterations = [word]
35
+ alterations << word.capitalize unless word.capitalize == word
36
+ alterations << word.upcase unless word.upcase == word
37
+
38
+ alterations.any?{ |w| dictionary.check?(w) }
39
+ else
40
+ parts.all? { |part| correct?(part) }
41
+ end
32
42
  end
33
43
 
34
44
  def suggest(word)
35
- dictionary.suggest(word).first(SUGGESTIONS_SIZE)
45
+ @suggestions_size.positive? ? dictionary.suggest(word).first(@suggestions_size) : []
36
46
  end
37
47
  end
38
48
  end
@@ -3,12 +3,10 @@ require 'backports/2.4.0/regexp/match'
3
3
  module Forspell
4
4
  module WordMatcher
5
5
  WORD = %r{^
6
- \'? # could start with apostrophe
7
- ([a-z]|[A-Z])? # at least one letter,
8
- ([[:lower:]])+ # then any number of letters,
9
- ([\'\-])? # optional dash/apostrophe,
10
- ([[:lower:]])* # another bunch of letters
11
- \'? # could end with apostrophe
6
+ ([a-z]|[A-Z]) # at least one letter,
7
+ ([[:lower:]])* # then any number of letters,
8
+ ([\'\-][[:lower:]])? # optional dash/apostrophe, followed by letter
9
+ ([[:lower:]])* # another bunch of letters
12
10
  $}x
13
11
 
14
12
  def self.word? text
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forspell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Kuprikov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-05-26 00:00:00.000000000 Z
12
+ date: 2019-05-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: slop
@@ -137,6 +137,34 @@ dependencies:
137
137
  - - ">="
138
138
  - !ruby/object:Gem::Version
139
139
  version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: highline
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :runtime
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: ruby-progressbar
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :runtime
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
140
168
  - !ruby/object:Gem::Dependency
141
169
  name: rspec
142
170
  requirement: !ruby/object:Gem::Requirement