rdoc-spellcheck 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.
- data.tar.gz.sig +0 -0
- data/.autotest +17 -0
- data/.gemtest +0 -0
- data/History.rdoc +5 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +80 -0
- data/Rakefile +23 -0
- data/lib/rdoc/discover.rb +2 -0
- data/lib/rdoc/generator/spellcheck.rb +714 -0
- data/test/test_rdoc_generator_spellcheck.rb +655 -0
- metadata +162 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
Binary file
|
data/.autotest
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
Autotest.add_hook :initialize do |at|
|
6
|
+
at.testlib = 'minitest/autorun'
|
7
|
+
at.add_exception '.git'
|
8
|
+
|
9
|
+
def at.path_to_classname s
|
10
|
+
sep = File::SEPARATOR
|
11
|
+
f = s.sub(/^test#{sep}/, '').sub(/\.rb$/, '').split(sep)
|
12
|
+
f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
|
13
|
+
f = f.map { |path| path =~ /^Test/ ? path : "Test#{path}" }
|
14
|
+
f.join('::').gsub('Rdoc', 'RDoc')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
data/.gemtest
ADDED
File without changes
|
data/History.rdoc
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
= rdoc-spellcheck
|
2
|
+
|
3
|
+
home :: https://github.com/drbrain/rdoc-spellcheck
|
4
|
+
rdoc :: http://docs.seattlerb.org/rdoc-spellcheck
|
5
|
+
bugs :: https://github.com/drbrain/rdoc-spellcheck/issues
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
rdoc-spellcheck checks your documentation for spelling errors. File, class,
|
10
|
+
and method names are automatically excluded from the results and you can add
|
11
|
+
your own words to the default word list.
|
12
|
+
|
13
|
+
== Features
|
14
|
+
|
15
|
+
* Checks documentation for pages, classes, modules, methods, constants, etc.
|
16
|
+
* Prints a report showing each misspelled word and correction suggestions
|
17
|
+
|
18
|
+
== Problems
|
19
|
+
|
20
|
+
rdoc-spellcheck depends on aspell for which development has ceased despite
|
21
|
+
messages to the contrary. I've submitted two pull requests to the
|
22
|
+
hunspell-ffi gem that should allow it to become a usable replacement for the
|
23
|
+
raspell gem. (The currently released hunspell-ffi does not appear to support
|
24
|
+
private or session dictionaries.)
|
25
|
+
|
26
|
+
For some projects it seems there are too many false positives for names and
|
27
|
+
programming words. I've reduced this somewhat by automatically including many
|
28
|
+
programming words in the session dictionary. One solution involves switching
|
29
|
+
to hunspell which appears to have better-maintained word dictionaries. The
|
30
|
+
other involves exploring an upper threshold for the edit distance between a
|
31
|
+
given word and its suggestion.
|
32
|
+
|
33
|
+
== Synopsis
|
34
|
+
|
35
|
+
$ rdoc -f spellcheck lib *.rdoc
|
36
|
+
|
37
|
+
== Requirements
|
38
|
+
|
39
|
+
* rdoc
|
40
|
+
* libaspell -- See https://github.com/evan/raspell/blob/master/README.rdoc for
|
41
|
+
installation instructions for aspell
|
42
|
+
|
43
|
+
== Install
|
44
|
+
|
45
|
+
sudo gem install rdoc-spellcheck
|
46
|
+
|
47
|
+
== Developers
|
48
|
+
|
49
|
+
After checking out the source, run:
|
50
|
+
|
51
|
+
$ rake newb
|
52
|
+
|
53
|
+
This task will install any missing dependencies, run the tests/specs,
|
54
|
+
and generate the RDoc.
|
55
|
+
|
56
|
+
== License
|
57
|
+
|
58
|
+
(The MIT License)
|
59
|
+
|
60
|
+
Copyright (c) Eric Hodel
|
61
|
+
|
62
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
63
|
+
a copy of this software and associated documentation files (the
|
64
|
+
'Software'), to deal in the Software without restriction, including
|
65
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
66
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
67
|
+
permit persons to whom the Software is furnished to do so, subject to
|
68
|
+
the following conditions:
|
69
|
+
|
70
|
+
The above copyright notice and this permission notice shall be
|
71
|
+
included in all copies or substantial portions of the Software.
|
72
|
+
|
73
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
74
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
75
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
76
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
77
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
78
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
79
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
80
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
Hoe.plugin :minitest
|
7
|
+
Hoe.plugin :git
|
8
|
+
Hoe.plugin :travis
|
9
|
+
|
10
|
+
Hoe.spec 'rdoc-spellcheck' do
|
11
|
+
developer 'Eric Hodel', 'drbrain@segment7.net'
|
12
|
+
|
13
|
+
rdoc_locations <<
|
14
|
+
'docs.seattlerb.org:/data/www/docs.seattlerb.org/rdoc-spellcheck/'
|
15
|
+
|
16
|
+
# Too lazy to make Unicode Regexps work on Ruby 1.8 and 1.9
|
17
|
+
spec_extras['required_ruby_version'] = '>= 1.9.2'
|
18
|
+
|
19
|
+
dependency 'raspell', '~> 1.3'
|
20
|
+
dependency 'rdoc', '~> 3.12'
|
21
|
+
end
|
22
|
+
|
23
|
+
# vim: syntax=ruby
|
@@ -0,0 +1,714 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require 'raspell'
|
4
|
+
|
5
|
+
##
|
6
|
+
# A spell checking generator for RDoc.
|
7
|
+
#
|
8
|
+
# This generator creates a report of misspelled words. You can use it to find
|
9
|
+
# when you acidentally make a typo. For example, this line contains one.
|
10
|
+
|
11
|
+
class RDoc::Generator::Spellcheck
|
12
|
+
|
13
|
+
RDoc::RDoc.add_generator self
|
14
|
+
|
15
|
+
##
|
16
|
+
# This version of rdoc-spellcheck
|
17
|
+
|
18
|
+
VERSION = '1.0'
|
19
|
+
|
20
|
+
##
|
21
|
+
# A list of common words that aspell may not include, but are commonly used
|
22
|
+
# in ruby programs.
|
23
|
+
#--
|
24
|
+
# Please keep this list sorted in your pull requests
|
25
|
+
|
26
|
+
DEFAULT_WORDS = %w[
|
27
|
+
API
|
28
|
+
ArgumentError
|
29
|
+
CGI
|
30
|
+
DES
|
31
|
+
ECDSA
|
32
|
+
EOFError
|
33
|
+
ERb
|
34
|
+
Encoding::CompatibilityError
|
35
|
+
Encoding::ConverterNotFoundError
|
36
|
+
Encoding::InvalidByteSequenceError
|
37
|
+
Encoding::UndefinedConversionError
|
38
|
+
EncodingError
|
39
|
+
Errno::E2BIG
|
40
|
+
Errno::EACCES
|
41
|
+
Errno::EADDRINUSE
|
42
|
+
Errno::EADDRNOTAVAIL
|
43
|
+
Errno::EAFNOSUPPORT
|
44
|
+
Errno::EAGAIN
|
45
|
+
Errno::EALREADY
|
46
|
+
Errno::EAUTH
|
47
|
+
Errno::EBADF
|
48
|
+
Errno::EBADMSG
|
49
|
+
Errno::EBADRPC
|
50
|
+
Errno::EBUSY
|
51
|
+
Errno::ECANCELED
|
52
|
+
Errno::ECHILD
|
53
|
+
Errno::ECONNABORTED
|
54
|
+
Errno::ECONNREFUSED
|
55
|
+
Errno::ECONNRESET
|
56
|
+
Errno::EDEADLK
|
57
|
+
Errno::EDESTADDRREQ
|
58
|
+
Errno::EDOM
|
59
|
+
Errno::EDQUOT
|
60
|
+
Errno::EEXIST
|
61
|
+
Errno::EFAULT
|
62
|
+
Errno::EFBIG
|
63
|
+
Errno::EFTYPE
|
64
|
+
Errno::EHOSTDOWN
|
65
|
+
Errno::EHOSTUNREACH
|
66
|
+
Errno::EIDRM
|
67
|
+
Errno::EILSEQ
|
68
|
+
Errno::EINPROGRESS
|
69
|
+
Errno::EINTR
|
70
|
+
Errno::EINVAL
|
71
|
+
Errno::EIO
|
72
|
+
Errno::EISCONN
|
73
|
+
Errno::EISDIR
|
74
|
+
Errno::ELOOP
|
75
|
+
Errno::EMFILE
|
76
|
+
Errno::EMLINK
|
77
|
+
Errno::EMSGSIZE
|
78
|
+
Errno::EMULTIHOP
|
79
|
+
Errno::ENAMETOOLONG
|
80
|
+
Errno::ENEEDAUTH
|
81
|
+
Errno::ENETDOWN
|
82
|
+
Errno::ENETRESET
|
83
|
+
Errno::ENETUNREACH
|
84
|
+
Errno::ENFILE
|
85
|
+
Errno::ENOATTR
|
86
|
+
Errno::ENOBUFS
|
87
|
+
Errno::ENODATA
|
88
|
+
Errno::ENODEV
|
89
|
+
Errno::ENOENT
|
90
|
+
Errno::ENOEXEC
|
91
|
+
Errno::ENOLCK
|
92
|
+
Errno::ENOLINK
|
93
|
+
Errno::ENOMEM
|
94
|
+
Errno::ENOMSG
|
95
|
+
Errno::ENOPROTOOPT
|
96
|
+
Errno::ENOSPC
|
97
|
+
Errno::ENOSR
|
98
|
+
Errno::ENOSTR
|
99
|
+
Errno::ENOSYS
|
100
|
+
Errno::ENOTBLK
|
101
|
+
Errno::ENOTCONN
|
102
|
+
Errno::ENOTDIR
|
103
|
+
Errno::ENOTEMPTY
|
104
|
+
Errno::ENOTRECOVERABLE
|
105
|
+
Errno::ENOTSOCK
|
106
|
+
Errno::ENOTSUP
|
107
|
+
Errno::ENOTTY
|
108
|
+
Errno::ENXIO
|
109
|
+
Errno::EOPNOTSUPP
|
110
|
+
Errno::EOVERFLOW
|
111
|
+
Errno::EOWNERDEAD
|
112
|
+
Errno::EPERM
|
113
|
+
Errno::EPFNOSUPPORT
|
114
|
+
Errno::EPIPE
|
115
|
+
Errno::EPROCLIM
|
116
|
+
Errno::EPROCUNAVAIL
|
117
|
+
Errno::EPROGMISMATCH
|
118
|
+
Errno::EPROGUNAVAIL
|
119
|
+
Errno::EPROTO
|
120
|
+
Errno::EPROTONOSUPPORT
|
121
|
+
Errno::EPROTOTYPE
|
122
|
+
Errno::ERANGE
|
123
|
+
Errno::EREMOTE
|
124
|
+
Errno::EROFS
|
125
|
+
Errno::ERPCMISMATCH
|
126
|
+
Errno::ESHUTDOWN
|
127
|
+
Errno::ESOCKTNOSUPPORT
|
128
|
+
Errno::ESPIPE
|
129
|
+
Errno::ESRCH
|
130
|
+
Errno::ESTALE
|
131
|
+
Errno::ETIME
|
132
|
+
Errno::ETIMEDOUT
|
133
|
+
Errno::ETOOMANYREFS
|
134
|
+
Errno::ETXTBSY
|
135
|
+
Errno::EUSERS
|
136
|
+
Errno::EXDEV
|
137
|
+
Errno::NOERROR
|
138
|
+
Exception
|
139
|
+
FIXME
|
140
|
+
FQDN
|
141
|
+
FiberError
|
142
|
+
FileUtils
|
143
|
+
FloatDomainError
|
144
|
+
GPL
|
145
|
+
IETF
|
146
|
+
IOError
|
147
|
+
IndexError
|
148
|
+
Interrupt
|
149
|
+
KeyError
|
150
|
+
LoadError
|
151
|
+
LocalJumpError
|
152
|
+
MSDN
|
153
|
+
Math::DomainError
|
154
|
+
NTFS
|
155
|
+
NUL
|
156
|
+
NameError
|
157
|
+
NoMemoryError
|
158
|
+
NoMethodError
|
159
|
+
NoMethodError
|
160
|
+
NotImplementedError
|
161
|
+
O'Reilly
|
162
|
+
PHP
|
163
|
+
PNG
|
164
|
+
POSIX
|
165
|
+
PRNG
|
166
|
+
README
|
167
|
+
RangeError
|
168
|
+
RegexpError
|
169
|
+
RuntimeError
|
170
|
+
SIGABRT
|
171
|
+
SIGALRM
|
172
|
+
SIGBUS
|
173
|
+
SIGCHLD
|
174
|
+
SIGCLD
|
175
|
+
SIGCONT
|
176
|
+
SIGEMT
|
177
|
+
SIGEXIT
|
178
|
+
SIGFPE
|
179
|
+
SIGHUP
|
180
|
+
SIGILL
|
181
|
+
SIGINFO
|
182
|
+
SIGINT
|
183
|
+
SIGIO
|
184
|
+
SIGIOT
|
185
|
+
SIGKILL
|
186
|
+
SIGPIPE
|
187
|
+
SIGPROF
|
188
|
+
SIGQUIT
|
189
|
+
SIGSEGV
|
190
|
+
SIGSTOP
|
191
|
+
SIGSYS
|
192
|
+
SIGTERM
|
193
|
+
SIGTRAP
|
194
|
+
SIGTSTP
|
195
|
+
SIGTTIN
|
196
|
+
SIGTTOU
|
197
|
+
SIGURG
|
198
|
+
SIGUSR1
|
199
|
+
SIGUSR2
|
200
|
+
SIGVTALRM
|
201
|
+
SIGWINCH
|
202
|
+
SIGXCPU
|
203
|
+
SIGXFSZ
|
204
|
+
SMTP
|
205
|
+
SMTPS
|
206
|
+
ScriptError
|
207
|
+
SecurityError
|
208
|
+
SignalException
|
209
|
+
StandardError
|
210
|
+
StopIteration
|
211
|
+
StringIO
|
212
|
+
SyntaxError
|
213
|
+
SystemCallError
|
214
|
+
SystemExit
|
215
|
+
SystemStackError
|
216
|
+
ThreadError
|
217
|
+
TypeError
|
218
|
+
URI
|
219
|
+
UUCP
|
220
|
+
VCS
|
221
|
+
Wikipedia
|
222
|
+
XHTML
|
223
|
+
ZeroDivisionError
|
224
|
+
Zlib
|
225
|
+
accessor
|
226
|
+
accessors
|
227
|
+
argf
|
228
|
+
argv
|
229
|
+
ary
|
230
|
+
authenticators
|
231
|
+
baz
|
232
|
+
bom
|
233
|
+
bzip
|
234
|
+
canonicalization
|
235
|
+
cfg
|
236
|
+
cpp
|
237
|
+
crlf
|
238
|
+
cryptographic
|
239
|
+
csh
|
240
|
+
daemonizing
|
241
|
+
decrypt
|
242
|
+
decrypted
|
243
|
+
decrypter
|
244
|
+
decrypting
|
245
|
+
decrypts
|
246
|
+
deprecations
|
247
|
+
dereferenced
|
248
|
+
deserialization
|
249
|
+
deserialize
|
250
|
+
deserialized
|
251
|
+
deserializes
|
252
|
+
deserializing
|
253
|
+
dev
|
254
|
+
druby
|
255
|
+
dRuby
|
256
|
+
dup
|
257
|
+
duplexed
|
258
|
+
elsif
|
259
|
+
emacs
|
260
|
+
encodings
|
261
|
+
encrypter
|
262
|
+
endian
|
263
|
+
env
|
264
|
+
erb
|
265
|
+
finalized
|
266
|
+
finalizer
|
267
|
+
finalizers
|
268
|
+
globals
|
269
|
+
gsub
|
270
|
+
gzip
|
271
|
+
gzipped
|
272
|
+
http
|
273
|
+
https
|
274
|
+
img
|
275
|
+
incrementing
|
276
|
+
initializer
|
277
|
+
inlining
|
278
|
+
instantiation
|
279
|
+
irb
|
280
|
+
iso
|
281
|
+
ivar
|
282
|
+
kbd
|
283
|
+
klass
|
284
|
+
klasses
|
285
|
+
lang
|
286
|
+
lexing
|
287
|
+
lookup
|
288
|
+
lossy
|
289
|
+
mailto
|
290
|
+
matz
|
291
|
+
mktmpdir
|
292
|
+
natively
|
293
|
+
newb
|
294
|
+
nonces
|
295
|
+
perl
|
296
|
+
popup
|
297
|
+
proleptic
|
298
|
+
proxied
|
299
|
+
pwd
|
300
|
+
racc
|
301
|
+
radian
|
302
|
+
radians
|
303
|
+
radix
|
304
|
+
rbw
|
305
|
+
redistributions
|
306
|
+
refactor
|
307
|
+
refactored
|
308
|
+
reinitializes
|
309
|
+
resized
|
310
|
+
rhtml
|
311
|
+
rsync
|
312
|
+
serializable
|
313
|
+
startup
|
314
|
+
stderr
|
315
|
+
stdin
|
316
|
+
stdout
|
317
|
+
struct
|
318
|
+
succ
|
319
|
+
sudo
|
320
|
+
tmpdir
|
321
|
+
tokenizer
|
322
|
+
tokenizes
|
323
|
+
txt
|
324
|
+
unbuffered
|
325
|
+
unescape
|
326
|
+
unescapes
|
327
|
+
uniq
|
328
|
+
unmaintained
|
329
|
+
unmarshal
|
330
|
+
unmarshalled
|
331
|
+
unmarshalling
|
332
|
+
unordered
|
333
|
+
untagged
|
334
|
+
untrusted
|
335
|
+
utf
|
336
|
+
validator
|
337
|
+
validators
|
338
|
+
versioning
|
339
|
+
visibilities
|
340
|
+
www
|
341
|
+
yacc
|
342
|
+
]
|
343
|
+
|
344
|
+
##
|
345
|
+
# OptionParser validator for Aspell language dictionaries
|
346
|
+
|
347
|
+
SpellLanguage = Object.new
|
348
|
+
|
349
|
+
attr_accessor :minimum_word_length # :nodoc:
|
350
|
+
|
351
|
+
attr_reader :spell # :nodoc:
|
352
|
+
|
353
|
+
##
|
354
|
+
# Adds rdoc-spellcheck options to the rdoc command
|
355
|
+
|
356
|
+
def self.setup_options options
|
357
|
+
default_language, = ENV['LANG'].split '.'
|
358
|
+
|
359
|
+
options.spell_add_words = false
|
360
|
+
options.spell_language = default_language
|
361
|
+
options.spell_minimum_word_length = 4
|
362
|
+
options.spell_source_dir = Dir.pwd
|
363
|
+
options.quiet = true # suppress statistics
|
364
|
+
|
365
|
+
op = options.option_parser
|
366
|
+
|
367
|
+
op.accept SpellLanguage do |language|
|
368
|
+
found = Aspell.list_dicts.find do |dict|
|
369
|
+
dict.name == language
|
370
|
+
end
|
371
|
+
|
372
|
+
raise OptionParser::InvalidArgument,
|
373
|
+
"dictionary #{language} not installed" unless found
|
374
|
+
|
375
|
+
language
|
376
|
+
end
|
377
|
+
|
378
|
+
op.separator nil
|
379
|
+
op.separator 'Spellcheck options:'
|
380
|
+
op.separator nil
|
381
|
+
|
382
|
+
op.on('--spell-add-words [WORDLIST]',
|
383
|
+
'Adds words to the aspell personal wordlist.',
|
384
|
+
'The word list may be a comma-separated',
|
385
|
+
'list of words which must contain multiple',
|
386
|
+
'words, a file or empty to read words from',
|
387
|
+
'stdin') do |wordlist|
|
388
|
+
words = if wordlist.nil? then
|
389
|
+
$stdin.read.split
|
390
|
+
elsif wordlist =~ /,/ then
|
391
|
+
wordlist.split ','
|
392
|
+
else
|
393
|
+
open wordlist do |io|
|
394
|
+
io.read.split
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
options.spell_add_words = words
|
399
|
+
end
|
400
|
+
|
401
|
+
op.separator nil
|
402
|
+
|
403
|
+
op.on('--[no-]spell-aggregate-all',
|
404
|
+
'Show aggregate counts for all misspellings.') do |aggregate_all|
|
405
|
+
options.spell_aggregate_all = aggregate_all
|
406
|
+
end
|
407
|
+
|
408
|
+
op.separator nil
|
409
|
+
|
410
|
+
op.on('--spell-language=LANGUAGE', SpellLanguage,
|
411
|
+
'Language to use for spell checking.',
|
412
|
+
"The default language is #{default_language}") do |language|
|
413
|
+
options.spell_language = language
|
414
|
+
end
|
415
|
+
|
416
|
+
op.separator nil
|
417
|
+
|
418
|
+
op.on('--spell-minimum-word-length=LENGTH', Integer,
|
419
|
+
'Minimum length of a word to spell check.',
|
420
|
+
"The default is #{options.spell_minimum_word_length}") do |length|
|
421
|
+
options.spell_minimum_word_length = length
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
def initialize options # :not-new:
|
426
|
+
@options = options
|
427
|
+
|
428
|
+
@encoding = @options.encoding
|
429
|
+
@aggregate_all = @options.spell_aggregate_all
|
430
|
+
@minimum_word_length = @options.spell_minimum_word_length
|
431
|
+
@source_dir = @options.spell_source_dir
|
432
|
+
|
433
|
+
@misspellings = Hash.new 0
|
434
|
+
|
435
|
+
@spell = Aspell.new @options.spell_language, nil, nil, @encoding.name
|
436
|
+
@spell.suggestion_mode = Aspell::NORMAL
|
437
|
+
@spell.set_option 'run-together', 'true'
|
438
|
+
|
439
|
+
if words = @options.spell_add_words then
|
440
|
+
words.each do |word|
|
441
|
+
@spell.add_to_personal word
|
442
|
+
end
|
443
|
+
|
444
|
+
@spell.save_all_word_lists
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
##
|
449
|
+
# Adds +name+ to the dictionary, splitting the word on '_' (a character
|
450
|
+
# Aspell does not allow)
|
451
|
+
|
452
|
+
def add_name name
|
453
|
+
name.scan(/[a-z]+/i) do |part|
|
454
|
+
@spell.add_to_session part
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
##
|
459
|
+
# Returns a report of misspelled words in +comment+. The report contains
|
460
|
+
# each misspelled word and its offset in the comment's text.
|
461
|
+
|
462
|
+
def find_misspelled comment
|
463
|
+
report = []
|
464
|
+
|
465
|
+
comment.text.scan(/\p{L}[\p{L}']+\p{L}/i) do |word|
|
466
|
+
next if $&.length < @minimum_word_length
|
467
|
+
offset = $`.length # store
|
468
|
+
|
469
|
+
word = $` if word =~ /'s$/i
|
470
|
+
|
471
|
+
next if @spell.check word
|
472
|
+
|
473
|
+
offset = offset.zero? ? 0 : offset + 1
|
474
|
+
|
475
|
+
report << [word, offset]
|
476
|
+
|
477
|
+
@misspellings[word] += 1
|
478
|
+
end
|
479
|
+
|
480
|
+
report
|
481
|
+
end
|
482
|
+
|
483
|
+
##
|
484
|
+
# Creates the spelling report
|
485
|
+
|
486
|
+
def generate files
|
487
|
+
setup_dictionary
|
488
|
+
|
489
|
+
report = []
|
490
|
+
|
491
|
+
RDoc::TopLevel.all_classes_and_modules.each do |mod|
|
492
|
+
mod.comment_location.each do |comment, location|
|
493
|
+
report.concat misspellings_for(mod.definition, comment, location)
|
494
|
+
end
|
495
|
+
|
496
|
+
mod.each_include do |incl|
|
497
|
+
name = "#{incl.parent.full_name}.include #{incl.name}"
|
498
|
+
|
499
|
+
report.concat misspellings_for(name, incl.comment, incl.file)
|
500
|
+
end
|
501
|
+
|
502
|
+
mod.each_constant do |const|
|
503
|
+
# TODO add missing RDoc::Constant#full_name
|
504
|
+
name = const.parent ? const.parent.full_name : '(unknown)'
|
505
|
+
name = "#{name}::#{const.name}"
|
506
|
+
|
507
|
+
report.concat misspellings_for(name, const.comment, const.file)
|
508
|
+
end
|
509
|
+
|
510
|
+
mod.each_attribute do |attr|
|
511
|
+
name = "#{attr.parent.full_name}.#{attr.definition} :#{attr.name}"
|
512
|
+
|
513
|
+
report.concat misspellings_for(name, attr.comment, attr.file)
|
514
|
+
end
|
515
|
+
|
516
|
+
mod.each_method do |meth|
|
517
|
+
report.concat misspellings_for(meth.full_name, meth.comment, meth.file)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
RDoc::TopLevel.all_files.each do |file|
|
522
|
+
report.concat misspellings_for(nil, file.comment, file)
|
523
|
+
end
|
524
|
+
|
525
|
+
if @misspellings.empty? then
|
526
|
+
puts 'No misspellings found'
|
527
|
+
else
|
528
|
+
puts report.join "\n"
|
529
|
+
puts
|
530
|
+
|
531
|
+
num_width = @misspellings.values.max.to_s.length
|
532
|
+
order = @misspellings.sort_by do |word, count|
|
533
|
+
[-count, word]
|
534
|
+
end
|
535
|
+
|
536
|
+
order = order.first 10 unless @aggregate_all
|
537
|
+
|
538
|
+
puts 'Aggregate misspellings:'
|
539
|
+
order.each do |word, count|
|
540
|
+
puts "%*d %s" % [num_width, count, word]
|
541
|
+
end
|
542
|
+
|
543
|
+
total = @misspellings.values.inject :+
|
544
|
+
|
545
|
+
puts
|
546
|
+
puts "Total misspellings: #{total}"
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
##
|
551
|
+
# Determines the line and column of the misspelling in +comment+ at +offset+
|
552
|
+
# in the +file+.
|
553
|
+
|
554
|
+
def location_of text, offset, file
|
555
|
+
last_newline = text[0, offset].rindex "\n"
|
556
|
+
start_of_line = last_newline ? last_newline + 1 : 0
|
557
|
+
|
558
|
+
line_text = text[start_of_line..offset]
|
559
|
+
|
560
|
+
full_path = File.expand_path file.absolute_name, @source_dir
|
561
|
+
|
562
|
+
file_content = RDoc::Encoding.read_file full_path, @encoding
|
563
|
+
|
564
|
+
raise "[bug] Unable to read #{full_path}" unless file_content
|
565
|
+
|
566
|
+
file_content.each_line.with_index do |line, index|
|
567
|
+
if line =~ /#{Regexp.escape line_text}/ then
|
568
|
+
column = $`.length + line_text.length
|
569
|
+
return index, column
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# TODO typos in include file
|
574
|
+
|
575
|
+
nil
|
576
|
+
end
|
577
|
+
|
578
|
+
##
|
579
|
+
# Returns a report of misspellings the +comment+ at +location+ for
|
580
|
+
# documentation item +name+
|
581
|
+
|
582
|
+
def misspellings_for name, comment, location
|
583
|
+
out = []
|
584
|
+
|
585
|
+
return out if comment.empty?
|
586
|
+
|
587
|
+
misspelled = find_misspelled comment
|
588
|
+
|
589
|
+
return out if misspelled.empty?
|
590
|
+
|
591
|
+
if name then
|
592
|
+
out << "#{name} in #{location.full_name}:"
|
593
|
+
else
|
594
|
+
out << "In #{location.full_name}:"
|
595
|
+
end
|
596
|
+
|
597
|
+
out << nil
|
598
|
+
|
599
|
+
out.concat misspelled.flat_map { |word, offset|
|
600
|
+
suggestion = suggestion_text comment.text, word, offset
|
601
|
+
line, column = location_of word, offset, location
|
602
|
+
|
603
|
+
if line then
|
604
|
+
["#{location.absolute_name}:#{line}:#{column}", suggestion]
|
605
|
+
else
|
606
|
+
["(via include)", suggestion]
|
607
|
+
end
|
608
|
+
}
|
609
|
+
|
610
|
+
out
|
611
|
+
end
|
612
|
+
|
613
|
+
##
|
614
|
+
# Adds file names, class names, module names, method names, etc. from the
|
615
|
+
# documentation tree to the session spelling dictionary.
|
616
|
+
|
617
|
+
def setup_dictionary
|
618
|
+
DEFAULT_WORDS.each do |word|
|
619
|
+
add_name word
|
620
|
+
end
|
621
|
+
|
622
|
+
RDoc::TopLevel.all_classes_and_modules.each do |mod|
|
623
|
+
add_name mod.name
|
624
|
+
|
625
|
+
mod.each_include do |incl|
|
626
|
+
add_name incl.name
|
627
|
+
end
|
628
|
+
|
629
|
+
mod.each_constant do |const|
|
630
|
+
add_name const.name
|
631
|
+
end
|
632
|
+
|
633
|
+
mod.each_attribute do |attr|
|
634
|
+
add_name attr.name
|
635
|
+
end
|
636
|
+
|
637
|
+
mod.each_method do |meth|
|
638
|
+
add_name meth.name
|
639
|
+
add_name meth.params if meth.params
|
640
|
+
add_name meth.block_params if meth.block_params
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
RDoc::TopLevel.all_files.each do |file|
|
645
|
+
file.absolute_name.split(%r%[/\\.]%).each do |part|
|
646
|
+
add_name part
|
647
|
+
end
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
651
|
+
##
|
652
|
+
# Creates suggestion text for the misspelled +word+ at +offset+ in +text+
|
653
|
+
|
654
|
+
def suggestion_text text, word, offset
|
655
|
+
prefix = offset - 10
|
656
|
+
prefix = 0 if prefix < 0
|
657
|
+
|
658
|
+
text =~ /\A.{#{prefix}}(.{0,10})#{Regexp.escape word}(.{0,10})/m
|
659
|
+
|
660
|
+
before = "#{prefix.zero? ? nil : '...'}#{$1}"
|
661
|
+
after = "#{$2}#{$2.length < 10 ? nil : '...'}"
|
662
|
+
|
663
|
+
highlight = "\e[1;31m#{word}\e[m"
|
664
|
+
|
665
|
+
suggestions = @spell.suggest(word).first 5
|
666
|
+
|
667
|
+
<<-TEXT
|
668
|
+
"#{before}#{highlight}#{after}"
|
669
|
+
|
670
|
+
"#{word}" suggestions:
|
671
|
+
\t#{suggestions.join ', '}
|
672
|
+
|
673
|
+
TEXT
|
674
|
+
rescue => e
|
675
|
+
$stderr.puts "[bug] #{e.class}: #{e.message}"
|
676
|
+
$stderr.puts
|
677
|
+
$stderr.puts "word: #{word}"
|
678
|
+
$stderr.puts "offset: #{offset}"
|
679
|
+
$stderr.puts ">>>> start text <<<<\n#{text}\n>>>>> end text <<<<<"
|
680
|
+
raise
|
681
|
+
end
|
682
|
+
|
683
|
+
end
|
684
|
+
|
685
|
+
class RDoc::Options
|
686
|
+
|
687
|
+
##
|
688
|
+
# Enables addition of words to the personal wordlist
|
689
|
+
|
690
|
+
attr_accessor :spell_add_words
|
691
|
+
|
692
|
+
##
|
693
|
+
# Display all found misspellings instead of the top ten.
|
694
|
+
|
695
|
+
attr_accessor :spell_aggregate_all
|
696
|
+
|
697
|
+
##
|
698
|
+
# The Aspell dictionary language to use. Defaults to the language in the
|
699
|
+
# LANG environment variable.
|
700
|
+
|
701
|
+
attr_accessor :spell_language
|
702
|
+
|
703
|
+
##
|
704
|
+
# The minimum length of a word for spell checking.
|
705
|
+
|
706
|
+
attr_accessor :spell_minimum_word_length
|
707
|
+
|
708
|
+
##
|
709
|
+
# The directory spellcheck was run from which contains all the source files.
|
710
|
+
|
711
|
+
attr_accessor :spell_source_dir
|
712
|
+
|
713
|
+
end
|
714
|
+
|