clausewitz-spelling 0.1.9 → 0.1.10
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/Gemfile.lock +1 -1
- data/bin/console +1 -0
- data/exe/clausewitz-spellcheck +5 -11
- data/lib/clausewitz/localisation.rb +64 -0
- data/lib/clausewitz/spelling.rb +0 -1
- data/lib/clausewitz/spelling/checker.rb +140 -127
- data/lib/clausewitz/spelling/results.rb +114 -77
- data/lib/clausewitz/spelling/version.rb +1 -1
- metadata +3 -3
- data/lib/clausewitz/spelling/formatter.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 928fb347a0cf9627f9d5fe15bf41cdcde863bfc6
|
4
|
+
data.tar.gz: c953a1f747632c9068f953fb49d6f849cff88c9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d3a8fac9a0f8600406a7d6a074eeee3620da864ed4f5bfc2c8e7b59431f88232959cb45858e6fa78cf27a7347a6d6b0c7753ba63da63a9e55d66a967ee70922
|
7
|
+
data.tar.gz: 564fc2d7c4b478b96bb18157fc27bbf67919d8d849bee0bad349376a28f911cb09f76f0014a2c969543a24156130198edd2964c76c7d3b72c57ad0e9a61324bf
|
data/Gemfile.lock
CHANGED
data/bin/console
CHANGED
data/exe/clausewitz-spellcheck
CHANGED
@@ -9,14 +9,8 @@ class Main
|
|
9
9
|
|
10
10
|
def parse_args(args)
|
11
11
|
opts = Optimist::options(args) do
|
12
|
-
opt :
|
13
|
-
"
|
14
|
-
type: :string
|
15
|
-
opt :english_dialect,
|
16
|
-
"Two-letter code indicating dialect of English to use",
|
17
|
-
type: :string
|
18
|
-
opt :spanish_dialect,
|
19
|
-
"Two-letter code indicating dialect of Spanish to use",
|
12
|
+
opt :dictionary_root,
|
13
|
+
"Directory containing per-language custom word lists",
|
20
14
|
type: :string
|
21
15
|
opt :suggestion_count,
|
22
16
|
"How many suggestions to display",
|
@@ -27,9 +21,9 @@ class Main
|
|
27
21
|
|
28
22
|
def run
|
29
23
|
spellchecker = Clausewitz::Spelling::Checker.new(@opts)
|
30
|
-
results = spellchecker.
|
31
|
-
results.
|
32
|
-
!results.failed?
|
24
|
+
results = @args.map { |arg| spellchecker.check_file(arg) }
|
25
|
+
results.each { |r| puts r }
|
26
|
+
!results.any?(&:failed?)
|
33
27
|
end
|
34
28
|
end
|
35
29
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Clausewitz
|
4
|
+
module Localisation
|
5
|
+
LANG_MAP = {
|
6
|
+
'english' => {
|
7
|
+
base: 'en'
|
8
|
+
},
|
9
|
+
'french' => {
|
10
|
+
base: 'fr'
|
11
|
+
},
|
12
|
+
'german' => {
|
13
|
+
base: 'de'
|
14
|
+
},
|
15
|
+
'portuguese' => {
|
16
|
+
base: 'pt'
|
17
|
+
},
|
18
|
+
'russian' => {
|
19
|
+
base: 'ru'
|
20
|
+
},
|
21
|
+
'spanish' => {
|
22
|
+
base: 'es'
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
def self.parse(text)
|
27
|
+
smudged_text = text.lines.map do |line|
|
28
|
+
self.smudge_key(line)
|
29
|
+
end
|
30
|
+
contents = YAML.load(smudged_text.join("\n"))
|
31
|
+
self.validate_localisation!(contents)
|
32
|
+
contents.each do |lang, entries|
|
33
|
+
entry_keys = entries ? entries.keys : []
|
34
|
+
entry_keys.each do |key|
|
35
|
+
entries[unsmudge_key(key)] = entries.delete(key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
contents
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse_file(filepath)
|
42
|
+
self.parse(File.read(filepath))
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.smudge_key(line)
|
46
|
+
line.sub(/\:([0-9]+) /, '!!!\1: ')
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.validate_localisation!(contents)
|
50
|
+
fail("Unknown language keys!") unless contents.keys.all? do |lang|
|
51
|
+
self.valid_lang?(lang)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
VALID_LANG_REGEX = /^l_(#{LANG_MAP.keys.join('|')})/
|
56
|
+
def self.valid_lang?(lang)
|
57
|
+
lang =~ VALID_LANG_REGEX
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.unsmudge_key(line)
|
61
|
+
line.sub(/!!!([0-9]+)$/, ':\1')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/clausewitz/spelling.rb
CHANGED
@@ -1,140 +1,149 @@
|
|
1
1
|
require 'ffi/aspell'
|
2
2
|
require 'open3'
|
3
|
+
require 'pathname'
|
3
4
|
require 'set'
|
4
5
|
require 'tmpdir'
|
5
6
|
require 'yaml'
|
6
7
|
require 'damerau-levenshtein'
|
8
|
+
require 'clausewitz/localisation'
|
7
9
|
require 'clausewitz/spelling/results'
|
8
10
|
|
9
11
|
module Clausewitz; module Spelling
|
10
12
|
class Checker
|
11
13
|
attr_accessor :dict_words
|
12
14
|
def initialize(opts = {})
|
13
|
-
|
15
|
+
@dictionary_root = opts[:dictionary_root]
|
14
16
|
@suggestion_count = opts[:suggestion_count] || 3
|
15
17
|
|
16
|
-
@
|
17
|
-
|
18
|
-
@en_speller = FFI::Aspell::Speller.new(
|
19
|
-
@english_dialect,
|
20
|
-
encoding: 'UTF-8'
|
21
|
-
)
|
22
|
-
|
23
|
-
@spanish_dialect = opts[:spanish_dialect] || 'es'
|
24
|
-
@spanish_dialect = "es_#{@spanish_dialect}" if opts[:spanish_dialect]
|
25
|
-
@es_speller = FFI::Aspell::Speller.new(
|
26
|
-
@spanish_dialect,
|
27
|
-
encoding: 'UTF-8'
|
28
|
-
)
|
29
|
-
|
30
|
-
dict_path = opts[:custom_wordlist]
|
31
|
-
|
32
|
-
if dict_path
|
33
|
-
fail("No such file #{dict_path}!") unless File.exist?(dict_path)
|
34
|
-
@dict_words = Set.new(File.read(dict_path).lines.map(&:chomp).to_a)
|
35
|
-
@custom_words_filepath = generate_word_list
|
36
|
-
@en_speller.set('extra-dicts', @custom_words_filepath)
|
37
|
-
@en_speller.set('ignore-accents', true)
|
38
|
-
else
|
39
|
-
@dict_words = Set.new([])
|
40
|
-
@en_speller.set('ignore-accents', true)
|
18
|
+
if @dictionary_root
|
19
|
+
@dictionary_root = Pathname.new(@dictionary_root)
|
41
20
|
end
|
21
|
+
|
22
|
+
@loaded_spellcheckers = {}
|
23
|
+
@loaded_wordlists = {}
|
42
24
|
end
|
43
25
|
|
44
|
-
def check_file(
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
bad_keys.map! { |key| unsmudge_key(key) }
|
52
|
-
if !bad_keys.empty?
|
53
|
-
UnknownLangsFileResult.new(file_path, bad_keys)
|
54
|
-
else
|
55
|
-
results = loc.map do |lang, entries|
|
56
|
-
check_entries(lang, entries)
|
57
|
-
end
|
58
|
-
FileResults.new(file_path, results)
|
26
|
+
def check_file(filepath)
|
27
|
+
results = []
|
28
|
+
begin
|
29
|
+
filepath = Pathname.new(filepath)
|
30
|
+
validate_filepath!(filepath)
|
31
|
+
rescue => e
|
32
|
+
return InvalidFilepathResult.new(filepath, e)
|
59
33
|
end
|
60
|
-
rescue Psych::SyntaxError => e
|
61
|
-
# If we fail to load the file it's probably busted.
|
62
|
-
BadFormatFileResult.new(file_path, e)
|
63
|
-
end
|
64
34
|
|
65
|
-
|
66
|
-
|
67
|
-
|
35
|
+
$stderr.puts "Skipping #{filepath}..." if filepath.directory?
|
36
|
+
|
37
|
+
begin
|
38
|
+
contents = Clausewitz::Localisation.parse_file(filepath)
|
39
|
+
rescue => e
|
40
|
+
return UnparseableFileResult.new(filepath, e)
|
68
41
|
end
|
69
|
-
OverallResults.new(results.compact)
|
70
|
-
end
|
71
42
|
|
72
|
-
|
73
|
-
|
74
|
-
if entries && !entries.empty?
|
75
|
-
entries.each do |key, text|
|
76
|
-
result = check_entry(key, text)
|
77
|
-
misspellings << result unless result.check_results.empty?
|
78
|
-
end
|
43
|
+
checks = contents.map do |lang, entries|
|
44
|
+
check_entries(lang, entries)
|
79
45
|
end
|
80
|
-
|
46
|
+
FileResults.new(filepath, checks)
|
81
47
|
end
|
82
48
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
49
|
+
private
|
50
|
+
|
51
|
+
def check_entries(lang, entries)
|
52
|
+
wordlist = load_wordlist(lang)
|
53
|
+
aspell_checker = load_aspell_checker(lang)
|
54
|
+
spellcheck_ignore = entries&.delete('spellcheck_ignore')
|
55
|
+
ignored_keys = spellcheck_ignore ? spellcheck_ignore.split(',') : []
|
56
|
+
return IgnoredLangResult.new(lang) if ignored_keys.include?('all')
|
57
|
+
return LangResults.new(lang, []) unless entries
|
58
|
+
checks = entries.map do |key, entry|
|
59
|
+
if ignored_keys.include?(key)
|
60
|
+
IgnoredEntryResult.new(key)
|
61
|
+
else
|
62
|
+
check_entry(aspell_checker, wordlist, key, entry)
|
89
63
|
end
|
90
64
|
end
|
91
|
-
|
92
|
-
end
|
65
|
+
LangResults.new(lang, checks)
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_entry(checker, wordlist, key, entry)
|
69
|
+
# We don't want to pay attention to scripted localisation, so we'll strip
|
70
|
+
# it out before we start.
|
71
|
+
# TODO: Look into supporting escaped square brackets as part of the
|
72
|
+
# string.
|
73
|
+
entry.gsub!(/\[.+\]/, '')
|
74
|
+
|
75
|
+
# Remove other localisation bits we don't care about.
|
76
|
+
entry.gsub!(/§(%|\*|=|\d|W|G|R|B|Y|b|M|g|T|l|H|\+|-|!)/, '')
|
77
|
+
|
78
|
+
# We should also remove punctuation that is never part of words, like
|
79
|
+
# exclamation points, commas, semi-colons, and question marks.
|
80
|
+
# We should be using proper apostrophes for possessives in our loc.
|
81
|
+
entry.gsub!(/(!|;|\?|'|"|“|”|:|\$|\(|\))/, '')
|
82
|
+
|
83
|
+
# If a word has one full stop at the end with no other full stops
|
84
|
+
# elsewhere in the word, it's probably an acronym or initialism like
|
85
|
+
# U.S.A. and so we should avoid stripping it. Otherwise, it's probably
|
86
|
+
# the end of a sentence and can be ignored.
|
87
|
+
words = entry.split(/\s|—/)
|
88
|
+
words.map! do |word|
|
89
|
+
if word.end_with?('...')
|
90
|
+
word.sub(/\.\.\.$/, '')
|
91
|
+
elsif word =~ /\.$/ && word.chars.count('.') == 1
|
92
|
+
word.sub(/\.$/, '')
|
93
|
+
elsif word =~ /,$/
|
94
|
+
word.sub(/,$/, '')
|
95
|
+
else
|
96
|
+
word
|
97
|
+
end
|
98
|
+
end.join(" ")
|
93
99
|
|
94
|
-
|
95
|
-
|
96
|
-
return true if word.chars.count('.') > 1
|
97
|
-
word.gsub!(/^(#{SQUIGGLE}.|[[:punct:]])+/, '')
|
98
|
-
word.gsub!(/(#{SQUIGGLE}.|[[:punct:]])+$/, '')
|
99
|
-
not_word?(word) ||
|
100
|
-
@dict_words.include?(word) ||
|
101
|
-
@en_speller.correct?(word) ||
|
102
|
-
@es_speller.correct?(word)
|
100
|
+
checks = words.map { |word| check_word(checker, wordlist, word) }.compact
|
101
|
+
EntryResults.new(key, checks)
|
103
102
|
end
|
104
103
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
def check_word(checker, wordlist, word)
|
105
|
+
return if is_number?(word)
|
106
|
+
return if is_ordinal?(word)
|
107
|
+
return if is_percentage?(word)
|
108
|
+
return if is_icon?(word)
|
109
|
+
return if wordlist.include?(word)
|
110
|
+
|
111
|
+
if !checker.correct?(word)
|
112
|
+
MisspelledWordResult.new(word, suggest_words(checker, wordlist, word))
|
109
113
|
end
|
110
|
-
contents = contents.lines.map do |line|
|
111
|
-
smudge_key(line)
|
112
|
-
end.join("\n")
|
113
|
-
YAML.load(contents)
|
114
114
|
end
|
115
115
|
|
116
|
-
def
|
117
|
-
|
118
|
-
is_number?(word) ||
|
119
|
-
is_ordinal?(word) ||
|
120
|
-
word =~ /^£/
|
121
|
-
end
|
116
|
+
def suggest_words(checker, wordlist, word)
|
117
|
+
return [] if word.size < 3
|
122
118
|
|
123
|
-
|
119
|
+
suggestions = Set.new
|
120
|
+
|
121
|
+
aspell_suggestions = checker.suggestions(word)
|
122
|
+
|
123
|
+
custom_suggestions = wordlist.select do |dict_word|
|
124
|
+
DamerauLevenshtein.distance(word, dict_word) < word.size
|
125
|
+
end
|
126
|
+
|
127
|
+
aspell_suggestions.each { |sug| suggestions.add(sug) }
|
128
|
+
custom_suggestions.each { |sug| suggestions.add(sug) }
|
124
129
|
|
125
|
-
|
126
|
-
|
130
|
+
suggestions.to_a.sort_by do |sug|
|
131
|
+
DamerauLevenshtein.distance(sug, word)
|
132
|
+
end.first(@suggestion_count)
|
127
133
|
end
|
128
134
|
|
129
|
-
def
|
130
|
-
word =~
|
135
|
+
def is_icon?(word)
|
136
|
+
word =~ /^£\w+/
|
131
137
|
end
|
132
138
|
|
133
139
|
def is_number?(word)
|
134
140
|
Float(word) != nil rescue false
|
135
141
|
end
|
136
142
|
|
137
|
-
|
143
|
+
def is_ordinal?(word)
|
144
|
+
word =~ /[0-9]+(th|st|nd|rd)/
|
145
|
+
end
|
146
|
+
|
138
147
|
def is_percentage?(word)
|
139
148
|
word =~ /(-|\+)?[0-9]+(\.[0-9]+)?%/ ||
|
140
149
|
word =~ /%(-|\+)?[0-9]+(\.[0-9]+)?/
|
@@ -143,55 +152,59 @@ module Clausewitz; module Spelling
|
|
143
152
|
# Loads our custom wordlist into a temporary Aspell dictionary.
|
144
153
|
# This way Aspell won't yell at us for custom words and will also
|
145
154
|
# potentially select from this list as suggestions for misspelled words.
|
146
|
-
def
|
147
|
-
dir = Dir.mktmpdir(
|
148
|
-
output = File.join(dir,
|
155
|
+
def load_custom_dictionary(lang)
|
156
|
+
dir = Dir.mktmpdir("custom-wordlist-#{lang}-")
|
157
|
+
output = File.join(dir, "#{lang}-custom.wlst")
|
149
158
|
cmd = %W[
|
150
159
|
aspell --lang=en --encoding=UTF-8 create master #{output}
|
151
160
|
]
|
152
161
|
value = nil
|
153
162
|
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
|
154
|
-
|
163
|
+
contents = File.read(File.join(@dictionary_root, lang, 'dict.txt'))
|
164
|
+
words = contents.lines.map(&:chomp)
|
165
|
+
words.each do |word|
|
155
166
|
stdin.puts(word)
|
156
167
|
end
|
157
168
|
stdin.close
|
158
169
|
value = wait_thr.value
|
159
170
|
end
|
160
|
-
|
171
|
+
unless value.success?
|
172
|
+
fail("Could not generate custom word list for #{lang}!")
|
173
|
+
end
|
161
174
|
output
|
162
175
|
end
|
163
176
|
|
164
|
-
def
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
177
|
+
def load_aspell_checker(lang)
|
178
|
+
return @loaded_spellcheckers[lang] if @loaded_spellcheckers[lang]
|
179
|
+
aspell_lang_config = Localisation::LANG_MAP.select do |config_key, _|
|
180
|
+
lang.sub(/^l_/, '') == config_key
|
181
|
+
end.first
|
182
|
+
lang_code = aspell_lang_config.last[:base]
|
183
|
+
aspell_checker = FFI::Aspell::Speller.new(lang_code, encoding: 'UTF-8')
|
184
|
+
aspell_checker.set('ignore-accents', true)
|
185
|
+
if @dictionary_root && @dictionary_root.join(lang_code).exist?
|
186
|
+
custom_words = load_custom_dictionary(lang_code)
|
187
|
+
aspell_checker.set('extra-dicts', custom_words)
|
188
|
+
end
|
189
|
+
@loaded_spellcheckers[lang] = aspell_checker
|
170
190
|
end
|
171
191
|
|
172
|
-
def
|
173
|
-
return [] if
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
custom_suggestions = @dict_words.select do |dict_word|
|
182
|
-
DamerauLevenshtein.distance(word, dict_word) < word.size
|
192
|
+
def load_wordlist(lang)
|
193
|
+
return @loaded_wordlists[lang] if @loaded_wordlists[lang]
|
194
|
+
aspell_lang_config = Localisation::LANG_MAP.select do |config_key, _|
|
195
|
+
lang.sub(/^l_/, '') == config_key
|
196
|
+
end.first
|
197
|
+
lang_code = aspell_lang_config.last[:base]
|
198
|
+
if @dictionary_root && @dictionary_root.join(lang_code).exist?
|
199
|
+
contents = File.read(@dictionary_root.join(lang_code, 'dict.txt'))
|
183
200
|
end
|
184
|
-
|
185
|
-
aspell_suggestions.each { |sug| suggestions.add(sug) }
|
186
|
-
custom_suggestions.each { |sug| suggestions.add(sug) }
|
187
|
-
|
188
|
-
suggestions.to_a.sort_by do |sug|
|
189
|
-
DamerauLevenshtein.distance(sug, word)
|
190
|
-
end.first(@suggestion_count)
|
201
|
+
@loaded_wordlists[lang] = Set.new(contents.lines.to_a.map(&:chomp))
|
191
202
|
end
|
192
203
|
|
193
|
-
|
194
|
-
|
204
|
+
# Make sure a file to be checked is actually present and readable.
|
205
|
+
def validate_filepath!(filepath)
|
206
|
+
fail("No such file #{filepath}!") unless filepath.exist?
|
207
|
+
fail("Cannot read #{filepath}!") unless filepath.readable?
|
195
208
|
end
|
196
209
|
end
|
197
|
-
end; end
|
210
|
+
end; end
|
@@ -1,137 +1,174 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
|
3
3
|
module Clausewitz; module Spelling
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@file_results = file_results
|
4
|
+
class FileResults
|
5
|
+
def initialize(filepath, lang_results)
|
6
|
+
@filepath = filepath
|
7
|
+
@lang_results = lang_results
|
9
8
|
end
|
10
9
|
|
11
10
|
def failed?
|
12
|
-
@
|
11
|
+
@lang_results.any?(&:failed?)
|
13
12
|
end
|
14
13
|
|
15
|
-
def
|
16
|
-
@
|
14
|
+
def to_s
|
15
|
+
outfile = failed? ? @filepath.to_s.red : "#{@filepath} passed".green
|
16
|
+
failures = @lang_results.select(&:failed?)
|
17
|
+
"#{outfile}\n" + failures.map { |l| " #{l}" }.join("\n")
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
class
|
21
|
-
|
22
|
-
|
23
|
-
@
|
24
|
-
@lang_results = lang_results
|
21
|
+
class LangResults
|
22
|
+
def initialize(lang, entry_results)
|
23
|
+
@lang = lang
|
24
|
+
@entry_results = entry_results
|
25
25
|
end
|
26
26
|
|
27
27
|
def failed?
|
28
|
-
@
|
28
|
+
@entry_results.any?(&:failed?)
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
31
|
+
def to_s
|
32
|
+
to_str
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_str(indent = 0)
|
36
|
+
firstspacer = ' ' * indent
|
37
|
+
spacer = ' ' * (indent + 2)
|
38
|
+
failures = @entry_results.select(&:failed?)
|
39
|
+
outlines = failures.map { |e| "#{spacer}#{e.to_str(indent + 2)}" }
|
40
|
+
outlines = outlines.join("\n")
|
41
|
+
outlang = failed? ? @lang.red : @lang.green
|
42
|
+
out = "#{firstspacer}#{outlang}\n#{outlines}"
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
class
|
47
|
-
|
48
|
-
|
49
|
-
@file_path = file_path
|
50
|
-
@error = error
|
46
|
+
class IgnoredLangResult
|
47
|
+
def initialize(lang)
|
48
|
+
@lang = lang
|
51
49
|
end
|
52
50
|
|
53
51
|
def failed?
|
54
|
-
|
52
|
+
false
|
55
53
|
end
|
56
54
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
55
|
+
def to_s
|
56
|
+
to_str
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_str(indent = 0)
|
60
|
+
firstspacer = ' ' * indent
|
61
|
+
"#{firstspacer}#{@lang} ignored".yellow
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
class
|
64
|
-
|
65
|
-
|
66
|
-
@
|
67
|
-
@bad_langs = bad_langs
|
65
|
+
class EntryResults
|
66
|
+
def initialize(key, word_results)
|
67
|
+
@key = key
|
68
|
+
@word_results = word_results
|
68
69
|
end
|
69
70
|
|
70
71
|
def failed?
|
71
|
-
|
72
|
+
!@word_results.empty?
|
72
73
|
end
|
73
74
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
75
|
+
def to_s
|
76
|
+
to_str
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_str(indent = 0)
|
80
|
+
spacer = ' ' * indent
|
81
|
+
if failed?
|
82
|
+
outlines = @word_results.map { |w| "#{spacer}#{w.to_str(indent + 2)}" }
|
83
|
+
outlines = outlines.join("\n")
|
84
|
+
"#{spacer}#{@key.red}\n#{outlines}"
|
85
|
+
else
|
86
|
+
"#{spacer}#{@key} passed".green
|
87
|
+
end
|
77
88
|
end
|
78
89
|
end
|
79
90
|
|
80
|
-
class
|
81
|
-
|
82
|
-
|
83
|
-
@lang = lang
|
84
|
-
@key_results = key_results
|
91
|
+
class IgnoredEntryResult
|
92
|
+
def initialize(key)
|
93
|
+
@key = key
|
85
94
|
end
|
86
95
|
|
87
96
|
def failed?
|
88
|
-
|
97
|
+
false
|
89
98
|
end
|
90
99
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
100
|
+
def to_s
|
101
|
+
to_str
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_str(indent = 0)
|
105
|
+
firstspacer = ' ' * indent
|
106
|
+
"#{firstspacer}#{@key} ignored".yellow
|
94
107
|
end
|
95
108
|
end
|
96
109
|
|
97
|
-
class
|
98
|
-
|
99
|
-
|
100
|
-
@
|
101
|
-
@check_results = check_results
|
110
|
+
class MisspelledWordResult
|
111
|
+
def initialize(word, suggestions)
|
112
|
+
@word = word
|
113
|
+
@suggestions = suggestions
|
102
114
|
end
|
103
115
|
|
104
116
|
def failed?
|
105
|
-
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_s
|
121
|
+
to_str
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_str(indent = 0)
|
125
|
+
spacer = ' ' * indent
|
126
|
+
msg = "#{spacer}#{@word}".red
|
127
|
+
|
128
|
+
if @suggestions && !@suggestions.empty?
|
129
|
+
msg += " (#{@suggestions.join(', ')})".yellow
|
130
|
+
else
|
131
|
+
msg += " (-- no suggestions --)".yellow
|
132
|
+
end
|
133
|
+
|
134
|
+
msg
|
106
135
|
end
|
136
|
+
end
|
107
137
|
|
108
|
-
|
109
|
-
|
110
|
-
|
138
|
+
# Result capturing basic problems interacting with the file before parsing.
|
139
|
+
class InvalidFilepathResult
|
140
|
+
attr_reader :filepath, :error
|
141
|
+
def initialize(filepath, error)
|
142
|
+
@filepath = filepath
|
143
|
+
@error = error
|
144
|
+
end
|
145
|
+
|
146
|
+
def failed?
|
147
|
+
true
|
111
148
|
end
|
112
149
|
end
|
113
150
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
@
|
151
|
+
# Result capturing problems parsing a readable file.
|
152
|
+
class UnparseableFileResult
|
153
|
+
attr_reader :filepath, :error
|
154
|
+
def initialize(filepath, error)
|
155
|
+
@filepath = filepath
|
156
|
+
@error = error
|
119
157
|
end
|
120
158
|
|
121
159
|
def failed?
|
122
160
|
true
|
123
161
|
end
|
124
162
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
163
|
+
def to_s
|
164
|
+
to_str
|
165
|
+
end
|
166
|
+
|
167
|
+
def to_str(indent = 0)
|
168
|
+
spacer = ' ' * indent
|
169
|
+
secondspacer = ' ' * (indent + 2)
|
170
|
+
"#{spacer}#{@filepath} could not be parsed\n".red +
|
171
|
+
"#{secondspacer}#{@error.message}".red
|
135
172
|
end
|
136
173
|
end
|
137
174
|
end; end # Clausewitz::Spelling
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clausewitz-spelling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Chappell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -144,9 +144,9 @@ files:
|
|
144
144
|
- bin/setup
|
145
145
|
- clausewitz-spelling.gemspec
|
146
146
|
- exe/clausewitz-spellcheck
|
147
|
+
- lib/clausewitz/localisation.rb
|
147
148
|
- lib/clausewitz/spelling.rb
|
148
149
|
- lib/clausewitz/spelling/checker.rb
|
149
|
-
- lib/clausewitz/spelling/formatter.rb
|
150
150
|
- lib/clausewitz/spelling/results.rb
|
151
151
|
- lib/clausewitz/spelling/version.rb
|
152
152
|
homepage: http://github.com/wtchappell/clausewitz-spelling
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Clausewitz; module Spelling
|
2
|
-
class Formatter
|
3
|
-
def render(overall_results)
|
4
|
-
render_overall_results(overall_results)
|
5
|
-
end
|
6
|
-
|
7
|
-
private
|
8
|
-
|
9
|
-
def render_overall_results(overall_results)
|
10
|
-
overall_results.files.each do |file_results|
|
11
|
-
render_file_results(file_results)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def render_file_results(file_results)
|
16
|
-
file_results.langs.each do |lang_results|
|
17
|
-
render_lang_results(lang_results)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def render_lang_results(lang_results)
|
22
|
-
lang_results.keys.each do |key_results|
|
23
|
-
render_key_results(key_results)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def render_key_results(key_results)
|
28
|
-
key_results.spellchecks.each do |spellcheck_result|
|
29
|
-
render_spellcheck_result(spellcheck_result)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def render_spellcheck_result(spellcheck_result)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end; end # Clausewitz::Spelling
|