tolq-ffi-hunspell 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3ba672292b48ce7c197aba99a62971ac5e2355b1ff168058169c0edfcb25415f
4
+ data.tar.gz: 6d4193fe3895ee9fd2c94a02e712af29e4529ffa35c276926172fa3131b3d6d1
5
+ SHA512:
6
+ metadata.gz: e80a32d978a7e641c99ef69119fabf4f3921c41e043db9aee8a132499b75e101e0a815310e43619896ab2537d0109dcf6135f8dabb912f583f536023986bc79d
7
+ data.tar.gz: 74c0273375c0681c5c466438366d9a86db9e0e9c01625b2caec4694f94b43548e667623360334f01bb04f22d6a2bebf9264f22c445a0cac11ab911b94ea2c0e2
data/.gemtest ADDED
File without changes
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ doc
2
+ pkg
3
+ .bundle
4
+ .yardoc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ before_install:
3
+ - sudo apt-get install libhunspell-dev hunspell-en-us
4
+ - gem install ffi rubygems-tasks rspec yard
5
+ rvm:
6
+ - 1.9.3
7
+ - 2.3.0
8
+ - jruby
9
+ - rbx
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: rbx
13
+ script: rake spec
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title 'FFI Hunspell Documentation' --protected --files ChangeLog.md,LICENSE.txt
data/ChangeLog.md ADDED
@@ -0,0 +1,71 @@
1
+ ### 0.4.0 / 2017-04-21
2
+
3
+ * Added support for libhunspell-1.6.
4
+ * Added support for libhunspell-1.5 (@trench8891).
5
+ * Added support for libhunspell-1.4 (@willmoorefyi).
6
+ * Renamed `#add_affix` to {FFI::Hunspell::Dictionary#add_with_affix}
7
+ (@cdchapman).
8
+
9
+ ### 0.3.1 / 2016-01-14
10
+
11
+ * Prefer loading hunspell-1.3 over hunspell-1.2, if both are installed.
12
+ * Support auto-detection of hunspell installed by homebrew (@forward3d).
13
+
14
+ ### 0.3.0 / 2013-05-01
15
+
16
+ * Detect Ubuntu's hunspell directory (`/usr/share/hunspell`).
17
+ * {FFI::Hunspell::Dictionary#encoding} now returns an `Encoding` object.
18
+ * Encode Strings returned from {FFI::Hunspell::Dictionary#stem} and
19
+ {FFI::Hunspell::Dictionary#suggest} to match the dictionary's native
20
+ encoding.
21
+
22
+ ### 0.2.6 / 2013-02-05
23
+
24
+ * Removed the env dependency.
25
+ * Check the returned count from `Hunsepll_stem` in
26
+ {FFI::Hunspell::Dictionary#stem}.
27
+ * Check the returned count from `Hunspell_suggest` in
28
+ {FFI::Hunspell::Dictionary#suggest}.
29
+
30
+ ### 0.2.5 / 2012-05-11
31
+
32
+ * Load `libhunspell-1.2.so.0` if `libhunspell-1.2.so` cannot be found.
33
+ * Load `libhunspell-1.3.so.0` if `libhunspell-1.3.so` cannot be found.
34
+
35
+ ### 0.2.4 / 2012-04-27
36
+
37
+ * Require ffi ~> 1.0.
38
+ * Attempt loading `libhunspell-1.2` and `libhunspell-1.3`.
39
+
40
+ ### 0.2.3 / 2011-02-02
41
+
42
+ * Require ffi >= 0.6.0 and <= 1.1.0:
43
+ * JRuby requires ffi >= 1.0.0.
44
+ * A lot of projects still require ffi ~> 0.6.0.
45
+
46
+ ### 0.2.2 / 2011-01-25
47
+
48
+ * Added {FFI::Hunspell::USER_DIR}.
49
+ * Added {FFI::Hunspell::KNOWN_DIRECTORIES}, containing known dictionary
50
+ directories used by Debian, Fedora and Mac Ports.
51
+ * Have {FFI::Hunspell.directories} return the dictionary directories found
52
+ on the system.
53
+
54
+ ### 0.2.1 / 2011-01-23
55
+
56
+ * Require env ~> 0.1.2.
57
+ * Use `Env.lang` to get the default language.
58
+ * Updated the Copyright years.
59
+
60
+ ### 0.2.0 / 2011-01-22
61
+
62
+ * Added {FFI::Hunspell.lang}.
63
+ * Added {FFI::Hunspell.lang=}.
64
+ * Added {FFI::Hunspell.directories}.
65
+ * Have {FFI::Hunspell::Dictionary.open} accept a language name, and search
66
+ {FFI::Hunspell.directories} for the dictionary files.
67
+
68
+ ### 0.1.0 / 2010-10-05
69
+
70
+ * Initial release.
71
+
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010-2016 Hal Brodigan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # ffi-hunspell
2
+
3
+ * [Source](https://github.com/postmodern/ffi-hunspell)
4
+ * [Issues](https://github.com/postmodern/ffi-hunspell/issues)
5
+ * [Documentation](http://rubydoc.info/gems/ffi-hunspell/frames)
6
+ * [Email](postmodern.mod3 at gmail.com)
7
+
8
+ [![Build Status](https://secure.travis-ci.org/postmodern/ffi-hunspell.png?branch=master)](https://travis-ci.org/postmodern/ffi-hunspell)
9
+
10
+ ## Description
11
+
12
+ Ruby FFI bindings for [Hunspell][libhunspell].
13
+
14
+ ## Examples
15
+
16
+ Open a dictionary:
17
+ ```rb
18
+ require 'ffi/hunspell'
19
+
20
+ FFI::Hunspell.dict do |dict|
21
+ # ...
22
+ end
23
+
24
+ FFI::Hunspell.dict('en_GB') do |dict|
25
+ # ...
26
+ end
27
+
28
+ dict = FFI::Hunspell.dict('en_GB')
29
+ # ...
30
+ dict.close
31
+ ```
32
+
33
+ Check if a word is valid:
34
+ ```rb
35
+ dict.check?('dog')
36
+ # => true
37
+
38
+ dict.check?('d0g')
39
+ # => false
40
+ ```
41
+ Find the stems of a word:
42
+ ```rb
43
+ dict.stem('dogs')
44
+ # => ["dog"]
45
+ ```
46
+ Suggest alternate spellings for a word:
47
+ ```rb
48
+ dict.suggest('arbitrage')
49
+ # => ["arbitrage", "arbitrages", "arbitrager", "arbitraged", "arbitrate"]
50
+ ```
51
+ ## Requirements
52
+
53
+ * [libhunspell] >= 1.2.0
54
+ * [ffi] ~> 1.0
55
+
56
+ ## Install
57
+ ```sh
58
+ $ gem install ffi-hunspell
59
+ ```
60
+ ## License
61
+
62
+ Copyright (c) 2010-2016 Hal Brodigan
63
+
64
+ See {file:LICENSE.txt} for license information.
65
+
66
+ [libhunspell]: http://hunspell.sourceforge.net/
67
+ [ffi]: https://github.com/ffi/ffi
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'rubygems/tasks'
6
+
7
+ Gem::Tasks.new
8
+ rescue LoadError => e
9
+ warn e.message
10
+ warn "Run `gem install rubygems-tasks` to install 'rubygems/tasks'."
11
+ end
12
+
13
+ begin
14
+ require 'rspec/core/rake_task'
15
+
16
+ RSpec::Core::RakeTask.new
17
+ rescue LoadError => e
18
+ task :spec do
19
+ abort "Please run `gem install rspec` to install RSpec."
20
+ end
21
+ end
22
+ task :test => :spec
23
+ task :default => :spec
24
+
25
+ begin
26
+ require 'yard'
27
+
28
+ YARD::Rake::YardocTask.new
29
+ rescue LoadError => e
30
+ task :yard do
31
+ abort "Please run `gem install yard` to install YARD."
32
+ end
33
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gemspec = YAML.load_file('gemspec.yml')
7
+
8
+ gem.name = gemspec.fetch('name')
9
+ gem.version = gemspec.fetch('version') do
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'ffi/hunspell/version'
14
+ FFI::Hunspell::VERSION
15
+ end
16
+
17
+ gem.summary = gemspec['summary']
18
+ gem.description = gemspec['description']
19
+ gem.licenses = Array(gemspec['license'])
20
+ gem.authors = Array(gemspec['authors'])
21
+ gem.email = gemspec['email']
22
+ gem.homepage = gemspec['homepage']
23
+
24
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
+
26
+ gem.files = `git ls-files`.split($/)
27
+ gem.files = glob[gemspec['files']] if gemspec['files']
28
+
29
+ gem.executables = gemspec.fetch('executables') do
30
+ glob['bin/*'].map { |path| File.basename(path) }
31
+ end
32
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
33
+
34
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
35
+ gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
36
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
37
+
38
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
39
+ %w[ext lib].select { |dir| File.directory?(dir) }
40
+ })
41
+
42
+ gem.requirements = gemspec['requirements']
43
+ gem.required_ruby_version = gemspec['required_ruby_version']
44
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
45
+ gem.post_install_message = gemspec['post_install_message']
46
+
47
+ split = lambda { |string| string.split(/,\s*/) }
48
+
49
+ if gemspec['dependencies']
50
+ gemspec['dependencies'].each do |name,versions|
51
+ gem.add_dependency(name,split[versions])
52
+ end
53
+ end
54
+
55
+ if gemspec['development_dependencies']
56
+ gemspec['development_dependencies'].each do |name,versions|
57
+ gem.add_development_dependency(name,split[versions])
58
+ end
59
+ end
60
+ end
data/gemspec.yml ADDED
@@ -0,0 +1,21 @@
1
+ name: tolq-ffi-hunspell
2
+ version: 0.5.0
3
+ summary: FFI bindings for Hunspell
4
+ description: Ruby FFI bindings for the Hunspell spell checker.
5
+ license: MIT
6
+ authors: Postmodern
7
+ email: postmodern.mod3@gmail.com
8
+ homepage: https://github.com/postmodern/ffi-hunspell#readme
9
+ has_yard: true
10
+
11
+ requirements: libhunspell >= 1.2.0
12
+
13
+ required_ruby_version: ">= 1.9.1"
14
+
15
+ dependencies:
16
+ ffi: ~> 1.0
17
+
18
+ development_dependencies:
19
+ rubygems-tasks: ~> 0.1
20
+ rspec: ~> 3.0
21
+ yard: ~> 0.7
@@ -0,0 +1,2 @@
1
+ require 'ffi/hunspell/hunspell'
2
+ require 'ffi/hunspell/dictionary'
@@ -0,0 +1,257 @@
1
+ require 'ffi/hunspell/hunspell'
2
+
3
+ module FFI
4
+ module Hunspell
5
+ #
6
+ # Represents a dictionary for a specific language.
7
+ #
8
+ class Dictionary
9
+
10
+ # The affix file extension
11
+ AFF_EXT = 'aff'
12
+
13
+ # The dictionary file extension
14
+ DIC_EXT = 'dic'
15
+
16
+ #
17
+ # Creates a new dictionary.
18
+ #
19
+ # @param [String] affix_path
20
+ # The path to the `.aff` file.
21
+ #
22
+ # @param [String] dic_path
23
+ # The path to the `.dic` file.
24
+ #
25
+ # @param [String] key
26
+ # The optional key for encrypted dictionary files.
27
+ #
28
+ # @raise [RuntimeError]
29
+ # Either the `.aff` or `.dic` files did not exist.
30
+ #
31
+ def initialize(affix_path,dic_path,key=nil)
32
+ unless File.file?(affix_path)
33
+ raise("invalid affix path #{affix_path.inspect}")
34
+ end
35
+
36
+ unless File.file?(dic_path)
37
+ raise("invalid dic path #{dic_path.inspect}")
38
+ end
39
+
40
+ @ptr = if key then Hunspell.Hunspell_create_key(affix_path,dic_path,key)
41
+ else Hunspell.Hunspell_create(affix_path,dic_path)
42
+ end
43
+ end
44
+
45
+ #
46
+ # Opens a Hunspell dictionary.
47
+ #
48
+ # @param [Symbol, String] name
49
+ # The name of the dictionary to open.
50
+ #
51
+ # @yield [dict]
52
+ # The given block will be passed the Hunspell dictionary.
53
+ #
54
+ # @yieldparam [Dictionary] dict
55
+ # The opened dictionary.
56
+ #
57
+ # @return [Dictionary]
58
+ # If no block is given, the open dictionary will be returned.
59
+ #
60
+ # @raise [ArgumentError]
61
+ # The dictionary files could not be found in any of the directories.
62
+ #
63
+ def self.open(name)
64
+ name = name.to_s
65
+
66
+ Hunspell.directories.each do |dir|
67
+ affix_path = File.join(dir,"#{name}.#{AFF_EXT}")
68
+ dic_path = File.join(dir,"#{name}.#{DIC_EXT}")
69
+
70
+ if (File.file?(affix_path) && File.file?(dic_path))
71
+ dict = self.new(affix_path,dic_path)
72
+
73
+ if block_given?
74
+ yield dict
75
+
76
+ dict.close
77
+ return nil
78
+ else
79
+ return dict
80
+ end
81
+ end
82
+ end
83
+
84
+ raise(ArgumentError,"unable to find the dictionary #{name.dump} in any of the directories")
85
+ end
86
+
87
+ #
88
+ # Determines if the dictionary is closed.
89
+ #
90
+ # @return [Boolean]
91
+ # Specifies whether the dictionary was closed.
92
+ #
93
+ def closed?
94
+ @ptr.nil?
95
+ end
96
+
97
+ #
98
+ # The encoding of the dictionary file.
99
+ #
100
+ # @return [Encoding]
101
+ # The encoding of the dictionary file.
102
+ #
103
+ def encoding
104
+ @encoding ||= Encoding.const_get(
105
+ Hunspell.Hunspell_get_dic_encoding(self).gsub('-','_')
106
+ )
107
+ end
108
+
109
+ #
110
+ # Adds a word to the dictionary.
111
+ #
112
+ # @param [#to_s] word
113
+ # The word to add to the dictionary.
114
+ #
115
+ def add(word)
116
+ Hunspell.Hunspell_add(self,word.to_s)
117
+ end
118
+
119
+ #
120
+ # Adds a word to the dictionary with affix flags.
121
+ #
122
+ # @param [#to_s] word
123
+ # The word to add to the dictionary.
124
+ #
125
+ # @param [#to_s] example
126
+ # Affix flags.
127
+ #
128
+ # @since 0.4.0
129
+ #
130
+ def add_with_affix(word,example)
131
+ Hunspell.Hunspell_add_with_affix(self,word.to_s,example.to_s)
132
+ end
133
+
134
+ #
135
+ # @deprecated Please use {#add_with_affix} instead.
136
+ #
137
+ def add_affix(word,example)
138
+ add_with_affix(word,example)
139
+ end
140
+
141
+ alias << add
142
+
143
+ #
144
+ # Removes a word from the dictionary.
145
+ #
146
+ # @param [#to_s] word
147
+ # The word to remove.
148
+ #
149
+ def remove(word)
150
+ Hunspell.Hunspell_remove(self,word.to_s)
151
+ end
152
+
153
+ alias delete remove
154
+
155
+ #
156
+ # Checks if the word is validate.
157
+ #
158
+ # @param [#to_s] word
159
+ # The word in question.
160
+ #
161
+ # @return [Boolean]
162
+ # Specifies whether the word is valid.
163
+ #
164
+ def check?(word)
165
+ Hunspell.Hunspell_spell(self,word.to_s) != 0
166
+ end
167
+
168
+ alias valid? check?
169
+
170
+ #
171
+ # Finds the stems of a word.
172
+ #
173
+ # @param [#to_s] word
174
+ # The word in question.
175
+ #
176
+ # @return [Array<String>]
177
+ # The stems of the word.
178
+ #
179
+ def stem(word)
180
+ stems = []
181
+
182
+ FFI::MemoryPointer.new(:pointer) do |output|
183
+ count = Hunspell.Hunspell_stem(self,output,word.to_s)
184
+ ptr = output.get_pointer(0)
185
+
186
+ if count > 0
187
+ stems = ptr.get_array_of_string(0,count)
188
+ end
189
+ end
190
+
191
+ return stems.map { |word| force_encoding(word) }
192
+ end
193
+
194
+ #
195
+ # Suggests alternate spellings of a word.
196
+ #
197
+ # @param [#to_s] word
198
+ # The word in question.
199
+ #
200
+ # @return [Array<String>]
201
+ # The suggestions for the word.
202
+ #
203
+ def suggest(word)
204
+ suggestions = []
205
+
206
+ FFI::MemoryPointer.new(:pointer) do |output|
207
+ count = Hunspell.Hunspell_suggest(self,output,word.to_s)
208
+ ptr = output.get_pointer(0)
209
+
210
+ if count > 0
211
+ suggestions = ptr.get_array_of_string(0,count)
212
+ end
213
+ end
214
+
215
+ return suggestions.map { |word| force_encoding(word) }
216
+ end
217
+
218
+ #
219
+ # Closes the dictionary.
220
+ #
221
+ # @return [nil]
222
+ #
223
+ def close
224
+ Hunspell.Hunspell_destroy(self)
225
+
226
+ @ptr = nil
227
+ return nil
228
+ end
229
+
230
+ #
231
+ # Converts the dictionary to a pointer.
232
+ #
233
+ # @return [FFI::Pointer]
234
+ # The pointer for the dictionary.
235
+ #
236
+ def to_ptr
237
+ @ptr
238
+ end
239
+
240
+ protected
241
+
242
+ #
243
+ # Encodes a String into the dictionary's encoding.
244
+ #
245
+ # @param [String] string
246
+ # The unencoded String.
247
+ #
248
+ # @return [String]
249
+ # The encoded String.
250
+ #
251
+ def force_encoding(string)
252
+ string.force_encoding(encoding)
253
+ end
254
+
255
+ end
256
+ end
257
+ end
@@ -0,0 +1,127 @@
1
+ require 'ffi'
2
+
3
+ module FFI
4
+ module Hunspell
5
+ extend FFI::Library
6
+
7
+ ffi_lib [
8
+ 'hunspell-1.7', 'libhunspell-1.7.so.0',
9
+ 'hunspell-1.6', 'libhunspell-1.6.so.0',
10
+ 'hunspell-1.5', 'libhunspell-1.5.so.0',
11
+ 'hunspell-1.4', 'libhunspell-1.4.so.0',
12
+ 'hunspell-1.3', 'libhunspell-1.3.so.0',
13
+ 'hunspell-1.2', 'libhunspell-1.2.so.0'
14
+ ]
15
+
16
+
17
+ attach_function :Hunspell_create, [:string, :string], :pointer
18
+ attach_function :Hunspell_create_key, [:string, :string, :string], :pointer
19
+ attach_function :Hunspell_destroy, [:pointer], :void
20
+ attach_function :Hunspell_spell, [:pointer, :string], :int
21
+ attach_function :Hunspell_get_dic_encoding, [:pointer], :string
22
+ attach_function :Hunspell_suggest, [:pointer, :pointer, :string], :int
23
+ attach_function :Hunspell_analyze, [:pointer, :pointer, :string], :int
24
+ attach_function :Hunspell_stem, [:pointer, :pointer, :string], :int
25
+ attach_function :Hunspell_generate, [:pointer, :pointer, :string, :string], :int
26
+ attach_function :Hunspell_add, [:pointer, :string], :int
27
+ attach_function :Hunspell_add_with_affix, [:pointer, :string, :string], :int
28
+ attach_function :Hunspell_remove, [:pointer, :string], :int
29
+ attach_function :Hunspell_free_list, [:pointer, :pointer, :int], :void
30
+
31
+ #
32
+ # missing functions:
33
+ #
34
+ # attach_function :Hunspell_stem2, [:pointer, :pointer, :pointer, :int], :int
35
+ # attach_function :Hunspell_generate2, [:pointer, :pointer, :string, :pointer, :int], :int
36
+ #
37
+
38
+ # The language to default to, if no 'LANG' env variable was set.
39
+ DEFAULT_LANG = ENV.fetch('LANG','en_US.UTF-8').split('.',2).first
40
+
41
+ #
42
+ # The default language.
43
+ #
44
+ # @return [String]
45
+ # The name of the default language.
46
+ #
47
+ # @since 0.2.0
48
+ #
49
+ def self.lang
50
+ @lang ||= DEFAULT_LANG
51
+ end
52
+
53
+ #
54
+ # Sets the default language.
55
+ #
56
+ # @param [String] new_lang
57
+ # The new language name.
58
+ #
59
+ # @return [String]
60
+ # The name of the new default language.
61
+ #
62
+ # @since 0.2.0
63
+ #
64
+ def self.lang=(new_lang)
65
+ @lang = new_lang.to_s
66
+ end
67
+
68
+ # The directory name used to store user installed dictionaries.
69
+ USER_DIR = '.hunspell_default'
70
+
71
+ # Known directories to search within for dictionaries.
72
+ KNOWN_DIRECTORIES = [
73
+ # User
74
+ File.join(Gem.user_home,USER_DIR),
75
+ # OS X brew-instlled hunspell
76
+ File.join(Gem.user_home,'Library/Spelling'),
77
+ '/Library/Spelling',
78
+ # Debian
79
+ '/usr/local/share/myspell/dicts',
80
+ '/usr/share/myspell/dicts',
81
+ # Ubuntu
82
+ '/usr/share/hunspell',
83
+ # Fedora
84
+ '/usr/local/share/myspell',
85
+ '/usr/share/myspell',
86
+ # Mac Ports
87
+ '/opt/local/share/hunspell',
88
+ '/opt/share/hunspell'
89
+ ]
90
+
91
+ #
92
+ # The dictionary directories to search for dictionary files.
93
+ #
94
+ # @return [Array<String, Pathname>]
95
+ # The directory paths.
96
+ #
97
+ # @since 0.2.0
98
+ #
99
+ def self.directories
100
+ @directories ||= KNOWN_DIRECTORIES.select do |path|
101
+ File.directory?(path)
102
+ end
103
+ end
104
+
105
+ def self.directories=(dirs)
106
+ @directories = dirs
107
+ end
108
+
109
+ #
110
+ # Opens a Hunspell dictionary.
111
+ #
112
+ # @param [Symbol, String] name
113
+ # The name of the dictionary to open.
114
+ #
115
+ # @yield [dict]
116
+ # The given block will be passed the Hunspell dictionary.
117
+ #
118
+ # @yieldparam [Dictionary] dict
119
+ # The opened dictionary.
120
+ #
121
+ # @return [nil]
122
+ #
123
+ def self.dict(name=Hunspell.lang,&block)
124
+ Dictionary.open(name,&block)
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+ require 'ffi/hunspell/dictionary'
3
+
4
+ describe Hunspell::Dictionary do
5
+ subject { described_class }
6
+
7
+ let(:lang) { 'en_US' }
8
+ let(:affix_path) { File.join(Hunspell.directories.last,"#{lang}.aff") }
9
+ let(:dic_path) { File.join(Hunspell.directories.last,"#{lang}.dic") }
10
+
11
+ describe "#initialize" do
12
+ subject { described_class.new(affix_path,dic_path) }
13
+
14
+ it "should create a dictionary from '.aff' and '.dic' files" do
15
+ expect(subject.to_ptr).to_not be_nil
16
+ end
17
+
18
+ after { subject.close }
19
+ end
20
+
21
+ describe ".open" do
22
+ subject { described_class }
23
+
24
+ it "should find and open a dictionary file for a given language" do
25
+ subject.open(lang) do |dict|
26
+ expect(dict).to_not be_nil
27
+ end
28
+ end
29
+
30
+ it "should close the dictionary" do
31
+ dict = subject.open(lang)
32
+ dict.close
33
+
34
+ expect(dict).to be_closed
35
+ end
36
+
37
+ context "when given an unknown dictionary name" do
38
+ it "should raise an ArgumentError" do
39
+ expect {
40
+ subject.open('foo')
41
+ }.to raise_error(ArgumentError)
42
+ end
43
+ end
44
+ end
45
+
46
+ context "when opened" do
47
+ subject { described_class.new(affix_path,dic_path) }
48
+
49
+ after { subject.close }
50
+
51
+ it "should provide the encoding of the dictionary files" do
52
+ expect(subject.encoding).to be Encoding::ISO_8859_1
53
+ end
54
+
55
+ it "should check if a word is valid" do
56
+ expect(subject.valid?('dog')).to be true
57
+ expect(subject.valid?('dxg')).to be false
58
+ end
59
+
60
+ describe "#add" do
61
+ it "should add a word" do
62
+ expect(subject.add('cat')).to be 0
63
+ end
64
+ end
65
+
66
+ describe "#add_with_affix" do
67
+ it "should add a word with an example word" do
68
+ expect(subject.add_with_affix('cat', 'agree')).to be 0
69
+ expect(subject.valid?('disagreeable')).to be true
70
+ expect(subject.valid?('discatable')).to be true
71
+ end
72
+ end
73
+
74
+ describe "#stem" do
75
+ it "should find the stems of a word" do
76
+ expect(subject.stem('fishing')).to be == %w[fishing fish]
77
+ end
78
+
79
+ it "should force_encode all strings" do
80
+ expect(subject.suggest('fishing')).to all satisfy { |string|
81
+ string.encoding == subject.encoding
82
+ }
83
+ end
84
+
85
+ context "when there are no stems" do
86
+ it "should return []" do
87
+ expect(subject.stem("zzzzzzz")).to be == []
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "#suggest" do
93
+ it "should suggest alternate spellings for words" do
94
+ expect(subject.suggest('arbitrage')).to include(
95
+ 'arbitrage',
96
+ 'arbitrages',
97
+ 'arbitrager',
98
+ 'arbitraged',
99
+ 'arbitrate'
100
+ )
101
+ end
102
+
103
+ it "should force_encode all strings" do
104
+ expect(subject.suggest('arbitrage')).to all satisfy { |string|
105
+ string.encoding == subject.encoding
106
+ }
107
+ end
108
+
109
+ context "when there are no suggestions" do
110
+ it "should return []" do
111
+ expect(subject.suggest("________")).to be == []
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'ffi/hunspell/hunspell'
3
+
4
+ describe Hunspell do
5
+ describe ".lang" do
6
+ subject { super().lang }
7
+
8
+ it "should have a default language" do
9
+ expect(subject).to_not be_nil
10
+ expect(subject).to_not be_empty
11
+ end
12
+ end
13
+
14
+ describe ".directories" do
15
+ subject { super().directories }
16
+
17
+ it "should have directories to search within" do
18
+ expect(subject).to_not be_empty
19
+ end
20
+ end
21
+
22
+ describe ".dict" do
23
+ it "should open a dictionary file" do
24
+ subject.dict('en_US') do |dict|
25
+ expect(dict).to_not be_nil
26
+ end
27
+ end
28
+
29
+ it "should open the dictionary file for the default language" do
30
+ subject.dict do |dict|
31
+ expect(dict).to_not be_nil
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ require 'rspec'
2
+ require 'ffi/hunspell'
3
+
4
+ include FFI
5
+
6
+ RSpec.configure do |specs|
7
+ specs.before(:suite) do
8
+ if ENV['HUNSPELL_ROOT']
9
+ Hunspell.directories << ENV['HUNSPELL_ROOT']
10
+ end
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tolq-ffi-hunspell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Postmodern
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubygems-tasks
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.7'
69
+ description: Ruby FFI bindings for the Hunspell spell checker.
70
+ email: postmodern.mod3@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files:
74
+ - ChangeLog.md
75
+ - LICENSE.txt
76
+ - README.md
77
+ files:
78
+ - ".gemtest"
79
+ - ".gitignore"
80
+ - ".rspec"
81
+ - ".travis.yml"
82
+ - ".yardopts"
83
+ - ChangeLog.md
84
+ - LICENSE.txt
85
+ - README.md
86
+ - Rakefile
87
+ - ffi-hunspell.gemspec
88
+ - gemspec.yml
89
+ - lib/ffi/hunspell.rb
90
+ - lib/ffi/hunspell/dictionary.rb
91
+ - lib/ffi/hunspell/hunspell.rb
92
+ - spec/dictionary_spec.rb
93
+ - spec/hunspell_spec.rb
94
+ - spec/spec_helper.rb
95
+ homepage: https://github.com/postmodern/ffi-hunspell#readme
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 1.9.1
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements:
114
+ - libhunspell >= 1.2.0
115
+ rubygems_version: 3.0.2
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: FFI bindings for Hunspell
119
+ test_files: []