ffi-hunspell 0.3.0 → 0.6.1
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 +7 -0
- data/.github/workflows/ruby.yml +34 -0
- data/.gitignore +1 -0
- data/ChangeLog.md +34 -1
- data/Gemfile +11 -0
- data/LICENSE.txt +1 -1
- data/README.md +47 -26
- data/Rakefile +9 -26
- data/ffi-hunspell.gemspec +1 -0
- data/gemspec.yml +8 -5
- data/lib/ffi/hunspell/dictionary.rb +60 -12
- data/lib/ffi/hunspell/hunspell.rb +33 -6
- data/lib/ffi/hunspell/version.rb +7 -0
- data/spec/dictionary_spec.rb +103 -50
- data/spec/fixtures/extra.dic +2 -0
- data/spec/hunspell_spec.rb +22 -12
- data/spec/spec_helper.rb +0 -2
- metadata +27 -59
- data/.travis.yml +0 -14
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 73c2a507e6fe1a6f34ff4a97f4db79c0518f5d352386c82cc69e6c35bfbe075a
|
|
4
|
+
data.tar.gz: dd5c8a8190a2cfa273f07a84fafea7c3422e1a3a4cdd4b6a1d629c465ced350e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: db867a438a0c6546d3175bf086ec999f905f27bbe663cc3a8758fd43516bb1968843f16800f6bf2f2322356005fd84e7c5915e2a964abb1b6cd8d7ce57f82d2b
|
|
7
|
+
data.tar.gz: 1af4a53d595bf279a43db1e1a3c5d8cdbe5439ef8853f4e829cc7b38115e1632a770c41af401645f427e5b85f7449257edc00f8434e205eee488d5c45cde7908
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on: [ push, pull_request ]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
tests:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
fail-fast: false
|
|
10
|
+
matrix:
|
|
11
|
+
ruby:
|
|
12
|
+
- 2.4
|
|
13
|
+
- 2.5
|
|
14
|
+
- 2.6
|
|
15
|
+
- 2.7
|
|
16
|
+
- 3.0
|
|
17
|
+
- jruby
|
|
18
|
+
name: Ruby ${{ matrix.ruby }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v2
|
|
21
|
+
- name: Set up Ruby
|
|
22
|
+
uses: ruby/setup-ruby@v1
|
|
23
|
+
with:
|
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
|
25
|
+
- name: Install libhunspell
|
|
26
|
+
run: |
|
|
27
|
+
sudo apt update -y && \
|
|
28
|
+
sudo apt install -y --no-install-recommends --no-install-suggests libhunspell-dev hunspell-en-us
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: bundle install --jobs 4 --retry 3
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bundle exec rake test
|
|
33
|
+
env:
|
|
34
|
+
LANG: en_US.UTF-8
|
data/.gitignore
CHANGED
data/ChangeLog.md
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
|
+
### 0.6.1 / 2021-02-12
|
|
2
|
+
|
|
3
|
+
* Fixed a possible memory leak in {FFI::Hunspell::Dictionary#stem} and
|
|
4
|
+
{FFI::Hunspell::Dictionary#suggest}.
|
|
5
|
+
* Prevent a possible memory leak if {FFI::Hunspell::Dictionary#close} is not
|
|
6
|
+
called, which deallocates the underlying libhunspell handler pointer,
|
|
7
|
+
before the dictionary is garbage collected. Note: if
|
|
8
|
+
{FFI::Hunspell::Dictionary.open} is called with a block, the dictionary object
|
|
9
|
+
will explicitly be closed once the block returns.
|
|
10
|
+
|
|
11
|
+
### 0.6.0 / 2020-11-28
|
|
12
|
+
|
|
13
|
+
* Added {FFI::Hunspell::Dictionary#add_dic} which adds an extra dictionary
|
|
14
|
+
file. (@cdchapman)
|
|
15
|
+
|
|
16
|
+
### 0.5.0 / 2019-10-24
|
|
17
|
+
|
|
18
|
+
* Added support for libhunspell-1.7 (@dorner).
|
|
19
|
+
* Added {FFI::Hunspell::VERSION}.
|
|
20
|
+
|
|
21
|
+
### 0.4.0 / 2017-04-21
|
|
22
|
+
|
|
23
|
+
* Added support for libhunspell-1.6.
|
|
24
|
+
* Added support for libhunspell-1.5 (@trench8891).
|
|
25
|
+
* Added support for libhunspell-1.4 (@willmoorefyi).
|
|
26
|
+
* Renamed `#add_affix` to {FFI::Hunspell::Dictionary#add_with_affix}
|
|
27
|
+
(@cdchapman).
|
|
28
|
+
|
|
29
|
+
### 0.3.1 / 2016-01-14
|
|
30
|
+
|
|
31
|
+
* Prefer loading hunspell-1.3 over hunspell-1.2, if both are installed.
|
|
32
|
+
* Support auto-detection of hunspell installed by homebrew (@forward3d).
|
|
33
|
+
|
|
1
34
|
### 0.3.0 / 2013-05-01
|
|
2
35
|
|
|
3
36
|
* Detect Ubuntu's hunspell directory (`/usr/share/hunspell`).
|
|
4
37
|
* {FFI::Hunspell::Dictionary#encoding} now returns an `Encoding` object.
|
|
5
38
|
* Encode Strings returned from {FFI::Hunspell::Dictionary#stem} and
|
|
6
|
-
{FFI::Hunspell::Dictionary#
|
|
39
|
+
{FFI::Hunspell::Dictionary#suggest} to match the dictionary's native
|
|
7
40
|
encoding.
|
|
8
41
|
|
|
9
42
|
### 0.2.6 / 2013-02-05
|
data/Gemfile
ADDED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
* [Source](https://github.com/postmodern/ffi-hunspell)
|
|
4
4
|
* [Issues](https://github.com/postmodern/ffi-hunspell/issues)
|
|
5
5
|
* [Documentation](http://rubydoc.info/gems/ffi-hunspell/frames)
|
|
6
|
-
* [Email](postmodern.mod3 at gmail.com)
|
|
7
|
-
|
|
8
|
-
[](https://travis-ci.org/postmodern/ffi-hunspell)
|
|
9
6
|
|
|
10
7
|
## Description
|
|
11
8
|
|
|
@@ -15,52 +12,76 @@ Ruby FFI bindings for [Hunspell][libhunspell].
|
|
|
15
12
|
|
|
16
13
|
Open a dictionary:
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
```rb
|
|
16
|
+
require 'ffi/hunspell'
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
FFI::Hunspell.dict do |dict|
|
|
19
|
+
# ...
|
|
20
|
+
end
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
FFI::Hunspell.dict('en_GB') do |dict|
|
|
23
|
+
# ...
|
|
24
|
+
end
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
dict = FFI::Hunspell.dict('en_GB')
|
|
27
|
+
# ...
|
|
28
|
+
dict.close
|
|
29
|
+
```
|
|
31
30
|
|
|
32
31
|
Check if a word is valid:
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
```rb
|
|
34
|
+
dict.check?('dog')
|
|
35
|
+
# => true
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
dict.check?('d0g')
|
|
38
|
+
# => false
|
|
39
|
+
```
|
|
39
40
|
|
|
40
41
|
Find the stems of a word:
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
```rb
|
|
44
|
+
dict.stem('dogs')
|
|
45
|
+
# => ["dog"]
|
|
46
|
+
```
|
|
44
47
|
|
|
45
48
|
Suggest alternate spellings for a word:
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
```rb
|
|
51
|
+
dict.suggest('arbitrage')
|
|
52
|
+
# => ["arbitrage", "arbitrages", "arbitrager", "arbitraged", "arbitrate"]
|
|
53
|
+
```
|
|
49
54
|
|
|
50
55
|
## Requirements
|
|
51
56
|
|
|
52
|
-
* [libhunspell] >= 1.2.0
|
|
57
|
+
* [libhunspell] >= 1.2.0, <= 1.7.0
|
|
53
58
|
* [ffi] ~> 1.0
|
|
54
59
|
|
|
55
60
|
## Install
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
```sh
|
|
63
|
+
$ gem install ffi-hunspell
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### libhunspell
|
|
67
|
+
|
|
68
|
+
* Debian / Ubuntu:
|
|
69
|
+
|
|
70
|
+
$ sudo apt install libhunspell-dev hunspell-en-us
|
|
71
|
+
|
|
72
|
+
* RedHat / Fedora:
|
|
73
|
+
|
|
74
|
+
$ sudo dnf install hunspell-devel hunspell-en
|
|
75
|
+
|
|
76
|
+
* macOS:
|
|
77
|
+
|
|
78
|
+
$ brew install hunspell
|
|
58
79
|
|
|
59
80
|
## License
|
|
60
81
|
|
|
61
|
-
Copyright (c) 2010-
|
|
82
|
+
Copyright (c) 2010-2021 Hal Brodigan
|
|
62
83
|
|
|
63
84
|
See {file:LICENSE.txt} for license information.
|
|
64
85
|
|
|
65
|
-
[libhunspell]: http://hunspell.
|
|
66
|
-
[ffi]: https://github.com/ffi/ffi
|
|
86
|
+
[libhunspell]: http://hunspell.github.io/
|
|
87
|
+
[ffi]: https://github.com/ffi/ffi#readme
|
data/Rakefile
CHANGED
|
@@ -1,36 +1,19 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
|
-
require 'rake'
|
|
3
2
|
|
|
4
3
|
begin
|
|
5
|
-
|
|
6
|
-
require 'rubygems/tasks'
|
|
7
|
-
|
|
8
|
-
Gem::Tasks.new
|
|
4
|
+
require 'bundler/setup'
|
|
9
5
|
rescue LoadError => e
|
|
10
|
-
|
|
11
|
-
warn "Run `gem install rubygems-tasks` to install 'rubygems/tasks'."
|
|
6
|
+
abort e.message
|
|
12
7
|
end
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
require 'rake'
|
|
10
|
+
require 'rubygems/tasks'
|
|
11
|
+
Gem::Tasks.new
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
task :spec do
|
|
21
|
-
abort "Please run `gem install rspec` to install RSpec."
|
|
22
|
-
end
|
|
23
|
-
end
|
|
13
|
+
require 'rspec/core/rake_task'
|
|
14
|
+
RSpec::Core::RakeTask.new
|
|
24
15
|
task :test => :spec
|
|
25
16
|
task :default => :spec
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
require 'yard'
|
|
30
|
-
|
|
31
|
-
YARD::Rake::YardocTask.new
|
|
32
|
-
rescue LoadError => e
|
|
33
|
-
task :yard do
|
|
34
|
-
abort "Please run `gem install yard` to install YARD."
|
|
35
|
-
end
|
|
36
|
-
end
|
|
18
|
+
require 'yard'
|
|
19
|
+
YARD::Rake::YardocTask.new
|
data/ffi-hunspell.gemspec
CHANGED
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
|
|
|
20
20
|
gem.authors = Array(gemspec['authors'])
|
|
21
21
|
gem.email = gemspec['email']
|
|
22
22
|
gem.homepage = gemspec['homepage']
|
|
23
|
+
gem.metadata = gemspec['metadata'] if gemspec['metadata']
|
|
23
24
|
|
|
24
25
|
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
|
25
26
|
|
data/gemspec.yml
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
name: ffi-hunspell
|
|
2
|
-
version: 0.3.0
|
|
3
2
|
summary: FFI bindings for Hunspell
|
|
4
3
|
description: Ruby FFI bindings for the Hunspell spell checker.
|
|
5
4
|
license: MIT
|
|
@@ -8,7 +7,13 @@ email: postmodern.mod3@gmail.com
|
|
|
8
7
|
homepage: https://github.com/postmodern/ffi-hunspell#readme
|
|
9
8
|
has_yard: true
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
metadata:
|
|
11
|
+
documentation_uri: https://rubydoc.info/gems/ffi-hunspell
|
|
12
|
+
source_code_uri: https://github.com/postmodern/ffi-hunspell
|
|
13
|
+
bug_tracker_uri: https://github.com/postmodern/ffi-hunspell/issues
|
|
14
|
+
changelog_uri: https://github.com/postmodern/ffi-hunspell/blob/master/ChangeLog.md
|
|
15
|
+
|
|
16
|
+
requirements: libhunspell >= 1.2.0, <= 1.7.0
|
|
12
17
|
|
|
13
18
|
required_ruby_version: ">= 1.9.1"
|
|
14
19
|
|
|
@@ -16,6 +21,4 @@ dependencies:
|
|
|
16
21
|
ffi: ~> 1.0
|
|
17
22
|
|
|
18
23
|
development_dependencies:
|
|
19
|
-
|
|
20
|
-
rspec: ~> 2.4
|
|
21
|
-
yard: ~> 0.7
|
|
24
|
+
bundler: ~> 2.0
|
|
@@ -37,9 +37,11 @@ module FFI
|
|
|
37
37
|
raise("invalid dic path #{dic_path.inspect}")
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
|
|
44
|
+
@ptr = FFI::AutoPointer.new(ptr,Hunspell.method(:Hunspell_destroy))
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
#
|
|
@@ -109,23 +111,63 @@ module FFI
|
|
|
109
111
|
#
|
|
110
112
|
# Adds a word to the dictionary.
|
|
111
113
|
#
|
|
112
|
-
# @param [
|
|
114
|
+
# @param [#to_s] word
|
|
113
115
|
# The word to add to the dictionary.
|
|
114
116
|
#
|
|
115
117
|
def add(word)
|
|
116
118
|
Hunspell.Hunspell_add(self,word.to_s)
|
|
117
119
|
end
|
|
118
120
|
|
|
121
|
+
alias << add
|
|
122
|
+
|
|
123
|
+
#
|
|
124
|
+
# Adds a word to the dictionary with affix flags.
|
|
125
|
+
#
|
|
126
|
+
# @param [#to_s] word
|
|
127
|
+
# The word to add to the dictionary.
|
|
128
|
+
#
|
|
129
|
+
# @param [#to_s] example
|
|
130
|
+
# Affix flags.
|
|
131
|
+
#
|
|
132
|
+
# @since 0.4.0
|
|
133
|
+
#
|
|
134
|
+
def add_with_affix(word,example)
|
|
135
|
+
Hunspell.Hunspell_add_with_affix(self,word.to_s,example.to_s)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# @deprecated Please use {#add_with_affix} instead.
|
|
140
|
+
#
|
|
119
141
|
def add_affix(word,example)
|
|
120
|
-
|
|
142
|
+
add_with_affix(word,example)
|
|
121
143
|
end
|
|
122
144
|
|
|
123
|
-
|
|
145
|
+
#
|
|
146
|
+
# Load an extra dictionary file. The extra dictionaries use the
|
|
147
|
+
# affix file of the allocated Hunspell object.
|
|
148
|
+
#
|
|
149
|
+
# Maximal number of extra dictionaries is limited in the source code (20)
|
|
150
|
+
#
|
|
151
|
+
# @param [String] dic_path
|
|
152
|
+
# The path to the extra `.dic` file.
|
|
153
|
+
#
|
|
154
|
+
# @raise [ArgumentError]
|
|
155
|
+
# The extra `.dic` file did not exist.
|
|
156
|
+
#
|
|
157
|
+
# @since 0.6.0
|
|
158
|
+
#
|
|
159
|
+
def add_dic(dic_path)
|
|
160
|
+
unless File.file?(dic_path)
|
|
161
|
+
raise(ArgumentError,"invalid extra dictionary path #{dic_path.inspect}")
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
Hunspell.Hunspell_add_dic(self,dic_path)
|
|
165
|
+
end
|
|
124
166
|
|
|
125
167
|
#
|
|
126
168
|
# Removes a word from the dictionary.
|
|
127
169
|
#
|
|
128
|
-
# @param [
|
|
170
|
+
# @param [#to_s] word
|
|
129
171
|
# The word to remove.
|
|
130
172
|
#
|
|
131
173
|
def remove(word)
|
|
@@ -137,7 +179,7 @@ module FFI
|
|
|
137
179
|
#
|
|
138
180
|
# Checks if the word is validate.
|
|
139
181
|
#
|
|
140
|
-
# @param [
|
|
182
|
+
# @param [#to_s] word
|
|
141
183
|
# The word in question.
|
|
142
184
|
#
|
|
143
185
|
# @return [Boolean]
|
|
@@ -152,7 +194,7 @@ module FFI
|
|
|
152
194
|
#
|
|
153
195
|
# Finds the stems of a word.
|
|
154
196
|
#
|
|
155
|
-
# @param [
|
|
197
|
+
# @param [#to_s] word
|
|
156
198
|
# The word in question.
|
|
157
199
|
#
|
|
158
200
|
# @return [Array<String>]
|
|
@@ -167,6 +209,8 @@ module FFI
|
|
|
167
209
|
|
|
168
210
|
if count > 0
|
|
169
211
|
stems = ptr.get_array_of_string(0,count)
|
|
212
|
+
|
|
213
|
+
Hunspell.Hunspell_free_list(self,output,count)
|
|
170
214
|
end
|
|
171
215
|
end
|
|
172
216
|
|
|
@@ -176,7 +220,7 @@ module FFI
|
|
|
176
220
|
#
|
|
177
221
|
# Suggests alternate spellings of a word.
|
|
178
222
|
#
|
|
179
|
-
# @param [
|
|
223
|
+
# @param [#to_s] word
|
|
180
224
|
# The word in question.
|
|
181
225
|
#
|
|
182
226
|
# @return [Array<String>]
|
|
@@ -191,6 +235,8 @@ module FFI
|
|
|
191
235
|
|
|
192
236
|
if count > 0
|
|
193
237
|
suggestions = ptr.get_array_of_string(0,count)
|
|
238
|
+
|
|
239
|
+
Hunspell.Hunspell_free_list(self,output,count)
|
|
194
240
|
end
|
|
195
241
|
end
|
|
196
242
|
|
|
@@ -203,9 +249,11 @@ module FFI
|
|
|
203
249
|
# @return [nil]
|
|
204
250
|
#
|
|
205
251
|
def close
|
|
206
|
-
|
|
252
|
+
if @ptr
|
|
253
|
+
@ptr.free
|
|
254
|
+
@ptr = nil
|
|
255
|
+
end
|
|
207
256
|
|
|
208
|
-
@ptr = nil
|
|
209
257
|
return nil
|
|
210
258
|
end
|
|
211
259
|
|
|
@@ -4,8 +4,15 @@ module FFI
|
|
|
4
4
|
module Hunspell
|
|
5
5
|
extend FFI::Library
|
|
6
6
|
|
|
7
|
-
ffi_lib [
|
|
8
|
-
|
|
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
|
+
|
|
9
16
|
|
|
10
17
|
attach_function :Hunspell_create, [:string, :string], :pointer
|
|
11
18
|
attach_function :Hunspell_create_key, [:string, :string, :string], :pointer
|
|
@@ -21,6 +28,19 @@ module FFI
|
|
|
21
28
|
attach_function :Hunspell_remove, [:pointer, :string], :int
|
|
22
29
|
attach_function :Hunspell_free_list, [:pointer, :pointer, :int], :void
|
|
23
30
|
|
|
31
|
+
begin
|
|
32
|
+
attach_function :Hunspell_add_dic, [:pointer, :string], :int
|
|
33
|
+
rescue FFI::NotFoundError
|
|
34
|
+
def self.method_missing(symbol,*arguments,&block)
|
|
35
|
+
if symbol == :Hunspell_add_dic
|
|
36
|
+
raise NotImplementedError,
|
|
37
|
+
"Hunspell_add_dic was not found in [#{ffi_libraries.map(&:name).join(", ")}]. You must install Hunspell 1.3.4 or later if you need this functionality."
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
super
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
24
44
|
#
|
|
25
45
|
# missing functions:
|
|
26
46
|
#
|
|
@@ -39,7 +59,7 @@ module FFI
|
|
|
39
59
|
#
|
|
40
60
|
# @since 0.2.0
|
|
41
61
|
#
|
|
42
|
-
def
|
|
62
|
+
def self.lang
|
|
43
63
|
@lang ||= DEFAULT_LANG
|
|
44
64
|
end
|
|
45
65
|
|
|
@@ -54,7 +74,7 @@ module FFI
|
|
|
54
74
|
#
|
|
55
75
|
# @since 0.2.0
|
|
56
76
|
#
|
|
57
|
-
def
|
|
77
|
+
def self.lang=(new_lang)
|
|
58
78
|
@lang = new_lang.to_s
|
|
59
79
|
end
|
|
60
80
|
|
|
@@ -65,6 +85,9 @@ module FFI
|
|
|
65
85
|
KNOWN_DIRECTORIES = [
|
|
66
86
|
# User
|
|
67
87
|
File.join(Gem.user_home,USER_DIR),
|
|
88
|
+
# OS X brew-instlled hunspell
|
|
89
|
+
File.join(Gem.user_home,'Library/Spelling'),
|
|
90
|
+
'/Library/Spelling',
|
|
68
91
|
# Debian
|
|
69
92
|
'/usr/local/share/myspell/dicts',
|
|
70
93
|
'/usr/share/myspell/dicts',
|
|
@@ -86,12 +109,16 @@ module FFI
|
|
|
86
109
|
#
|
|
87
110
|
# @since 0.2.0
|
|
88
111
|
#
|
|
89
|
-
def
|
|
112
|
+
def self.directories
|
|
90
113
|
@directories ||= KNOWN_DIRECTORIES.select do |path|
|
|
91
114
|
File.directory?(path)
|
|
92
115
|
end
|
|
93
116
|
end
|
|
94
117
|
|
|
118
|
+
def self.directories=(dirs)
|
|
119
|
+
@directories = dirs
|
|
120
|
+
end
|
|
121
|
+
|
|
95
122
|
#
|
|
96
123
|
# Opens a Hunspell dictionary.
|
|
97
124
|
#
|
|
@@ -106,7 +133,7 @@ module FFI
|
|
|
106
133
|
#
|
|
107
134
|
# @return [nil]
|
|
108
135
|
#
|
|
109
|
-
def
|
|
136
|
+
def self.dict(name=Hunspell.lang,&block)
|
|
110
137
|
Dictionary.open(name,&block)
|
|
111
138
|
end
|
|
112
139
|
end
|
data/spec/dictionary_spec.rb
CHANGED
|
@@ -2,30 +2,28 @@ require 'spec_helper'
|
|
|
2
2
|
require 'ffi/hunspell/dictionary'
|
|
3
3
|
|
|
4
4
|
describe Hunspell::Dictionary do
|
|
5
|
-
subject {
|
|
5
|
+
subject { described_class }
|
|
6
6
|
|
|
7
7
|
let(:lang) { 'en_US' }
|
|
8
|
-
|
|
9
8
|
let(:affix_path) { File.join(Hunspell.directories.last,"#{lang}.aff") }
|
|
10
|
-
let(:dic_path)
|
|
9
|
+
let(:dic_path) { File.join(Hunspell.directories.last,"#{lang}.dic") }
|
|
11
10
|
|
|
12
11
|
describe "#initialize" do
|
|
13
|
-
subject { described_class }
|
|
12
|
+
subject { described_class.new(affix_path,dic_path) }
|
|
14
13
|
|
|
15
14
|
it "should create a dictionary from '.aff' and '.dic' files" do
|
|
16
|
-
|
|
17
|
-
dict.should_not be_nil
|
|
18
|
-
|
|
19
|
-
dict.close
|
|
15
|
+
expect(subject.to_ptr).to_not be_nil
|
|
20
16
|
end
|
|
17
|
+
|
|
18
|
+
after { subject.close }
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
describe "open" do
|
|
21
|
+
describe ".open" do
|
|
24
22
|
subject { described_class }
|
|
25
23
|
|
|
26
24
|
it "should find and open a dictionary file for a given language" do
|
|
27
25
|
subject.open(lang) do |dict|
|
|
28
|
-
dict.
|
|
26
|
+
expect(dict).to_not be_nil
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
|
|
@@ -33,69 +31,124 @@ describe Hunspell::Dictionary do
|
|
|
33
31
|
dict = subject.open(lang)
|
|
34
32
|
dict.close
|
|
35
33
|
|
|
36
|
-
dict.
|
|
34
|
+
expect(dict).to be_closed
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
context "when given an unknown dictionary name" do
|
|
40
38
|
it "should raise an ArgumentError" do
|
|
41
|
-
|
|
39
|
+
expect {
|
|
42
40
|
subject.open('foo')
|
|
43
|
-
}.
|
|
41
|
+
}.to raise_error(ArgumentError)
|
|
44
42
|
end
|
|
45
43
|
end
|
|
46
44
|
end
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
context "when opened" do
|
|
47
|
+
subject { described_class.new(affix_path,dic_path) }
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
after { subject.close }
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
it "should check if a word is valid" do
|
|
57
|
-
subject.should be_valid('dog')
|
|
58
|
-
subject.should_not be_valid('dxg')
|
|
59
|
-
end
|
|
51
|
+
it "should provide the encoding of the dictionary files" do
|
|
52
|
+
expect(subject.encoding).to be_instance_of Encoding
|
|
53
|
+
end
|
|
60
54
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
subject.
|
|
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
|
|
64
58
|
end
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
describe "#add_dic" do
|
|
61
|
+
let(:fixtures_dir) { File.expand_path('../fixtures',__FILE__) }
|
|
62
|
+
let(:extra_dic) { File.join(fixtures_dir,'extra.dic') }
|
|
63
|
+
|
|
64
|
+
if FFI::Hunspell.respond_to?(:Hunspell_add_dic)
|
|
65
|
+
context "when libhunspell supports add_dic" do
|
|
66
|
+
before do
|
|
67
|
+
subject.add_dic(extra_dic)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should add an extra dictionary" do
|
|
71
|
+
expect(subject.add_dic(extra_dic)).to be 0
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "when the given extra dictionary file cannot be found" do
|
|
75
|
+
it do
|
|
76
|
+
expect { subject.add_dic('foo') }.to raise_error(ArgumentError)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should validate a word from the extra dictionary" do
|
|
81
|
+
expect(subject.valid?('dxg')).to be true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should validate an affixed word based on an affix flag from base affix file" do
|
|
85
|
+
expect(subject.valid?('dxgs')).to be true
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
context "when libhunspell does not support add_dic" do
|
|
90
|
+
it "should raise an error" do
|
|
91
|
+
expect {
|
|
92
|
+
subject.add_dic(extra_dic)
|
|
93
|
+
}.to raise_error(NotImplementedError)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
70
97
|
end
|
|
71
98
|
|
|
72
|
-
|
|
73
|
-
it "should
|
|
74
|
-
subject.
|
|
99
|
+
describe "#add" do
|
|
100
|
+
it "should add a word" do
|
|
101
|
+
expect(subject.add('cat')).to be 0
|
|
75
102
|
end
|
|
76
103
|
end
|
|
77
|
-
end
|
|
78
104
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
'
|
|
83
|
-
'
|
|
84
|
-
|
|
85
|
-
'arbitraged',
|
|
86
|
-
'arbitrate'
|
|
87
|
-
])
|
|
105
|
+
describe "#add_with_affix" do
|
|
106
|
+
it "should add a word with an example word" do
|
|
107
|
+
expect(subject.add_with_affix('cat', 'agree')).to be 0
|
|
108
|
+
expect(subject.valid?('disagreeable')).to be true
|
|
109
|
+
expect(subject.valid?('discatable')).to be true
|
|
110
|
+
end
|
|
88
111
|
end
|
|
89
112
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
113
|
+
describe "#stem" do
|
|
114
|
+
it "should find the stems of a word" do
|
|
115
|
+
expect(subject.stem('fishing')).to be == %w[fishing fish]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should force_encode all strings" do
|
|
119
|
+
expect(subject.suggest('fishing')).to all satisfy { |string|
|
|
120
|
+
string.encoding == subject.encoding
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "when there are no stems" do
|
|
125
|
+
it "should return []" do
|
|
126
|
+
expect(subject.stem("zzzzzzz")).to be == []
|
|
127
|
+
end
|
|
128
|
+
end
|
|
94
129
|
end
|
|
95
130
|
|
|
96
|
-
|
|
97
|
-
it "should
|
|
98
|
-
subject.suggest(
|
|
131
|
+
describe "#suggest" do
|
|
132
|
+
it "should suggest alternate spellings for words" do
|
|
133
|
+
expect(subject.suggest('arbitrage')).to include(
|
|
134
|
+
'arbitrage',
|
|
135
|
+
'arbitrages',
|
|
136
|
+
'arbitrager',
|
|
137
|
+
'arbitraged',
|
|
138
|
+
'arbitrate'
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should force_encode all strings" do
|
|
143
|
+
expect(subject.suggest('arbitrage')).to all satisfy { |string|
|
|
144
|
+
string.encoding == subject.encoding
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context "when there are no suggestions" do
|
|
149
|
+
it "should return []" do
|
|
150
|
+
expect(subject.suggest("________")).to be == []
|
|
151
|
+
end
|
|
99
152
|
end
|
|
100
153
|
end
|
|
101
154
|
end
|
data/spec/hunspell_spec.rb
CHANGED
|
@@ -2,24 +2,34 @@ require 'spec_helper'
|
|
|
2
2
|
require 'ffi/hunspell/hunspell'
|
|
3
3
|
|
|
4
4
|
describe Hunspell do
|
|
5
|
-
|
|
6
|
-
subject.lang
|
|
7
|
-
subject.lang.should_not be_empty
|
|
8
|
-
end
|
|
5
|
+
describe ".lang" do
|
|
6
|
+
subject { super().lang }
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
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
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
subject
|
|
16
|
-
|
|
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
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
dict
|
|
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
|
|
23
33
|
end
|
|
24
34
|
end
|
|
25
35
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,80 +1,43 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ffi-hunspell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.6.1
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Postmodern
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 2021-02-13 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: ffi
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
none: false
|
|
18
16
|
requirements:
|
|
19
|
-
- - ~>
|
|
17
|
+
- - "~>"
|
|
20
18
|
- !ruby/object:Gem::Version
|
|
21
19
|
version: '1.0'
|
|
22
20
|
type: :runtime
|
|
23
21
|
prerelease: false
|
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
none: false
|
|
26
23
|
requirements:
|
|
27
|
-
- - ~>
|
|
24
|
+
- - "~>"
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
26
|
version: '1.0'
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
|
31
|
-
name:
|
|
28
|
+
name: bundler
|
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
|
33
|
-
none: false
|
|
34
30
|
requirements:
|
|
35
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
36
32
|
- !ruby/object:Gem::Version
|
|
37
|
-
version: '0
|
|
33
|
+
version: '2.0'
|
|
38
34
|
type: :development
|
|
39
35
|
prerelease: false
|
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
-
none: false
|
|
42
37
|
requirements:
|
|
43
|
-
- - ~>
|
|
38
|
+
- - "~>"
|
|
44
39
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: '0
|
|
46
|
-
- !ruby/object:Gem::Dependency
|
|
47
|
-
name: rspec
|
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
|
49
|
-
none: false
|
|
50
|
-
requirements:
|
|
51
|
-
- - ~>
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '2.4'
|
|
54
|
-
type: :development
|
|
55
|
-
prerelease: false
|
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
-
none: false
|
|
58
|
-
requirements:
|
|
59
|
-
- - ~>
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '2.4'
|
|
62
|
-
- !ruby/object:Gem::Dependency
|
|
63
|
-
name: yard
|
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
|
65
|
-
none: false
|
|
66
|
-
requirements:
|
|
67
|
-
- - ~>
|
|
68
|
-
- !ruby/object:Gem::Version
|
|
69
|
-
version: '0.7'
|
|
70
|
-
type: :development
|
|
71
|
-
prerelease: false
|
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
-
none: false
|
|
74
|
-
requirements:
|
|
75
|
-
- - ~>
|
|
76
|
-
- !ruby/object:Gem::Version
|
|
77
|
-
version: '0.7'
|
|
40
|
+
version: '2.0'
|
|
78
41
|
description: Ruby FFI bindings for the Hunspell spell checker.
|
|
79
42
|
email: postmodern.mod3@gmail.com
|
|
80
43
|
executables: []
|
|
@@ -84,12 +47,13 @@ extra_rdoc_files:
|
|
|
84
47
|
- LICENSE.txt
|
|
85
48
|
- README.md
|
|
86
49
|
files:
|
|
87
|
-
- .gemtest
|
|
88
|
-
- .
|
|
89
|
-
- .
|
|
90
|
-
- .
|
|
91
|
-
- .yardopts
|
|
50
|
+
- ".gemtest"
|
|
51
|
+
- ".github/workflows/ruby.yml"
|
|
52
|
+
- ".gitignore"
|
|
53
|
+
- ".rspec"
|
|
54
|
+
- ".yardopts"
|
|
92
55
|
- ChangeLog.md
|
|
56
|
+
- Gemfile
|
|
93
57
|
- LICENSE.txt
|
|
94
58
|
- README.md
|
|
95
59
|
- Rakefile
|
|
@@ -98,33 +62,37 @@ files:
|
|
|
98
62
|
- lib/ffi/hunspell.rb
|
|
99
63
|
- lib/ffi/hunspell/dictionary.rb
|
|
100
64
|
- lib/ffi/hunspell/hunspell.rb
|
|
65
|
+
- lib/ffi/hunspell/version.rb
|
|
101
66
|
- spec/dictionary_spec.rb
|
|
67
|
+
- spec/fixtures/extra.dic
|
|
102
68
|
- spec/hunspell_spec.rb
|
|
103
69
|
- spec/spec_helper.rb
|
|
104
70
|
homepage: https://github.com/postmodern/ffi-hunspell#readme
|
|
105
71
|
licenses:
|
|
106
72
|
- MIT
|
|
73
|
+
metadata:
|
|
74
|
+
documentation_uri: https://rubydoc.info/gems/ffi-hunspell
|
|
75
|
+
source_code_uri: https://github.com/postmodern/ffi-hunspell
|
|
76
|
+
bug_tracker_uri: https://github.com/postmodern/ffi-hunspell/issues
|
|
77
|
+
changelog_uri: https://github.com/postmodern/ffi-hunspell/blob/master/ChangeLog.md
|
|
107
78
|
post_install_message:
|
|
108
79
|
rdoc_options: []
|
|
109
80
|
require_paths:
|
|
110
81
|
- lib
|
|
111
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
|
-
none: false
|
|
113
83
|
requirements:
|
|
114
|
-
- -
|
|
84
|
+
- - ">="
|
|
115
85
|
- !ruby/object:Gem::Version
|
|
116
86
|
version: 1.9.1
|
|
117
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
|
-
none: false
|
|
119
88
|
requirements:
|
|
120
|
-
- -
|
|
89
|
+
- - ">="
|
|
121
90
|
- !ruby/object:Gem::Version
|
|
122
91
|
version: '0'
|
|
123
92
|
requirements:
|
|
124
|
-
- libhunspell >= 1.2.0
|
|
125
|
-
|
|
126
|
-
rubygems_version: 1.8.25
|
|
93
|
+
- libhunspell >= 1.2.0, <= 1.7.0
|
|
94
|
+
rubygems_version: 3.1.4
|
|
127
95
|
signing_key:
|
|
128
|
-
specification_version:
|
|
96
|
+
specification_version: 4
|
|
129
97
|
summary: FFI bindings for Hunspell
|
|
130
98
|
test_files: []
|
data/.travis.yml
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
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.0.0
|
|
8
|
-
- jruby-19mode
|
|
9
|
-
- rbx-19mode
|
|
10
|
-
matrix:
|
|
11
|
-
allow_failures:
|
|
12
|
-
- rvm: rbx-18mode
|
|
13
|
-
- rvm: rbx-19mode
|
|
14
|
-
script: rake test
|