ffi-aspell 0.0.3 → 1.0.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.
@@ -4,8 +4,6 @@ module FFI
4
4
  # Error class used by methods such as {FFI::Aspell::Speller#get} and
5
5
  # {FFI::Aspell::Speller#set}.
6
6
  #
7
- # @since 13-04-2012
8
- #
9
7
  class ConfigError < StandardError; end
10
8
  end # Aspell
11
9
  end # FFI
@@ -72,28 +72,83 @@ module FFI
72
72
  #
73
73
  # speller.suggestions('cookei') # => ["cookie", ...]
74
74
  #
75
+ # ### Cleaning up
76
+ #
77
+ # When you're finished with the `Speller` object, you can let the finalizer
78
+ # automatically free resources, otherwise, call {#close} to explicitly free
79
+ # the underlying resources:
80
+ #
81
+ # speller = FFI::Aspell::Speller.new
82
+ # speller.correct?('cookie') # => true
83
+ # speller.close
84
+ #
85
+ # Alternatively, you can use the block form of {.open} to automatically
86
+ # free the resources:
87
+ #
88
+ # FFI::Aspell::Speller.open do |speller|
89
+ # puts speller.correct?('cookie') # => prints "true"
90
+ # end
91
+ #
92
+ # {.open} takes the same parameters as {Speller#initialize Speller.new}.
93
+ #
75
94
  # For more information see the documentation of the individual methods in
76
95
  # this class.
77
96
  #
78
- # @since 13-04-2012
79
- # @todo Currently this class creates a new speller object every time
80
- # {FFI::Aspell::Speller#correct?} and similar methods are called. I'm not
81
- # entirely sure if this is needed, if not it should be modified.
82
- #
83
97
  class Speller
84
98
  ##
85
99
  # Array containing the possible suggestion modes to use.
86
100
  #
87
- # @since 18-04-2012
101
+ # @return [Array]
88
102
  #
89
103
  SUGGESTION_MODES = ['ultra', 'fast', 'normal', 'bad-spellers']
90
104
 
105
+ ##
106
+ # Creates a new instance of the class. If a block is given, the instance
107
+ # is yielded and automatically closed when exiting the block.
108
+ #
109
+ # @yield If a block is given, the speller instance is yielded.
110
+ #
111
+ # @yieldparam [Speller] speller The created speller. {Speller#close} is
112
+ # automatically called when exiting the block.
113
+ #
114
+ # @return [Speller]
115
+ #
116
+ # @see [#initialize]
117
+ #
118
+ def self.open(*args)
119
+ speller = self.new(*args)
120
+
121
+ if block_given?
122
+ begin
123
+ yield speller
124
+ ensure
125
+ speller.close
126
+ end
127
+ end
128
+
129
+ return speller
130
+ end
131
+
132
+ ##
133
+ # Returns a proc for a finalizer, used for cleaning up native resources.
134
+ #
135
+ # @param [FFI::Pointer] config
136
+ # @param [FFI::Pointer] speller
137
+ # @return [Proc]
138
+ #
139
+ def self.finalizer(config, speller)
140
+ return proc {
141
+ Aspell.config_delete(config)
142
+ Aspell.speller_delete(speller)
143
+ }
144
+ end
145
+
91
146
  ##
92
147
  # Creates a new instance of the class, sets the language as well as the
93
148
  # options specified in the `options` hash.
94
149
  #
95
- # @since 13-04-2012
96
150
  # @param [String] language The language to use.
151
+ #
97
152
  # @param [Hash] options A hash containing extra configuration options,
98
153
  # such as the "personal" option to set.
99
154
  #
@@ -103,29 +158,61 @@ module FFI
103
158
  options['lang'] = language if language
104
159
 
105
160
  options.each { |k, v| set(k, v) }
161
+
162
+ update_speller
163
+ end
164
+
165
+ ##
166
+ # Closes the speller and frees underlying resources. Calling this is not
167
+ # absolutely required as the resources will eventually be freed by the
168
+ # finalizer.
169
+ #
170
+ # @raise [RuntimeError] Raised if the speller is closed.
171
+ #
172
+ def close
173
+ check_closed
174
+
175
+ # Remove finalizer since we're manually freeing resources.
176
+ ObjectSpace.undefine_finalizer(self)
177
+
178
+ Aspell.config_delete(@config)
179
+
180
+ @config = nil
181
+
182
+ Aspell.speller_delete(@speller)
183
+
184
+ @speller = nil
185
+ end
186
+
187
+ ##
188
+ # Checks if the speller is closed or not.
189
+ #
190
+ # @return [TrueClass|FalseClass]
191
+ #
192
+ def closed?
193
+ return @config.nil?
106
194
  end
107
195
 
108
196
  ##
109
197
  # Checks if the given word is correct or not.
110
198
  #
111
- # @since 13-04-2012
112
199
  # @param [String] word The word to check.
200
+ # @raise [RuntimeError] Raised if the speller is closed.
113
201
  # @return [TrueClass|FalseClass]
114
202
  #
115
203
  def correct?(word)
204
+ check_closed
205
+
116
206
  unless word.is_a?(String)
117
207
  raise(TypeError, "Expected String but got #{word.class} instead")
118
208
  end
119
209
 
120
- speller = Aspell.speller_new(@config)
121
210
  correct = Aspell.speller_check(
122
- speller,
211
+ @speller,
123
212
  handle_input(word.to_s),
124
213
  word.bytesize
125
214
  )
126
215
 
127
- Aspell.speller_delete(speller)
128
-
129
216
  return correct
130
217
  end
131
218
 
@@ -133,21 +220,23 @@ module FFI
133
220
  # Returns an array containing words suggested as an alternative to the
134
221
  # specified word.
135
222
  #
136
- # @since 13-04-2012
137
223
  # @param [String] word The word for which to generate a suggestion list.
224
+ # @raise [RuntimeError] Raised if the speller is closed.
138
225
  # @return [Array]
139
226
  #
140
227
  def suggestions(word)
228
+ check_closed
229
+
141
230
  unless word.is_a?(String)
142
231
  raise(TypeError, "Expected String but got #{word.class} instead")
143
232
  end
144
233
 
145
- speller = Aspell.speller_new(@config)
146
- list = Aspell.speller_suggest(
147
- speller,
234
+ list = Aspell.speller_suggest(
235
+ @speller,
148
236
  handle_input(word),
149
237
  word.bytesize
150
238
  )
239
+
151
240
  suggestions = []
152
241
  elements = Aspell.word_list_elements(list)
153
242
 
@@ -156,7 +245,6 @@ module FFI
156
245
  end
157
246
 
158
247
  Aspell.string_enumeration_delete(elements)
159
- Aspell.speller_delete(speller)
160
248
 
161
249
  return suggestions
162
250
  end
@@ -164,40 +252,38 @@ module FFI
164
252
  ##
165
253
  # Sets the suggestion mode for {FFI::Aspell::Speller#suggestions}.
166
254
  #
167
- # @since 13-04-2012
168
255
  # @param [String] mode The suggestion mode to use.
256
+ # @raise [RuntimeError] Raised if the speller is closed.
169
257
  #
170
258
  def suggestion_mode=(mode)
259
+ check_closed
260
+
171
261
  set('sug-mode', mode)
172
262
  end
173
263
 
174
264
  ##
175
265
  # Returns the suggestion mode that's currently used.
176
266
  #
177
- # @since 13-04-2012
267
+ # @raise [RuntimeError] Raised if the speller is closed.
178
268
  # @return [String]
179
269
  #
180
270
  def suggestion_mode
271
+ check_closed
272
+
181
273
  return get('sug-mode')
182
274
  end
183
275
 
184
276
  ##
185
277
  # Sets a configuration option.
186
278
  #
187
- # @since 13-04-2012
188
279
  # @param [#to_s] key The configuration key to set.
189
280
  # @param [#to_s] value The value of the configuration key.
281
+ # @raise [RuntimeError] Raised if the speller is closed.
190
282
  # @raise [FFI::Aspell::ConfigError] Raised when the configuration value
191
283
  # could not be set or when an incorrect suggestion mode was given.
192
284
  #
193
285
  def set(key, value)
194
- unless key.respond_to?(:to_s)
195
- raise(TypeError, 'Configuration keys should respond to #to_s()')
196
- end
197
-
198
- unless value.respond_to?(:to_s)
199
- raise(TypeError, 'Configuration values should respond to #to_s()')
200
- end
286
+ check_closed
201
287
 
202
288
  if key == 'sug-mode' and !SUGGESTION_MODES.include?(value)
203
289
  raise(ConfigError, "The suggestion mode #{value} is invalid")
@@ -206,21 +292,21 @@ module FFI
206
292
  unless Aspell.config_replace(@config, key.to_s, value.to_s)
207
293
  raise(ConfigError, "Failed to set the configuration item #{key}")
208
294
  end
295
+
296
+ update_speller
209
297
  end
210
298
 
211
299
  ##
212
300
  # Retrieves the value of the specified configuration item.
213
301
  #
214
- # @since 13-04-2012
215
302
  # @param [#to_s] key The configuration key to retrieve.
216
303
  # @return [String]
304
+ # @raise [RuntimeError] Raised if the speller is closed.
217
305
  # @raise [FFI::Aspell::ConfigError] Raised when the configuration item
218
306
  # does not exist.
219
307
  #
220
308
  def get(key)
221
- unless key.respond_to?(:to_s)
222
- raise(TypeError, 'Configuration keys should respond to #to_s()')
223
- end
309
+ check_closed
224
310
 
225
311
  value = Aspell.config_retrieve(@config, key.to_s)
226
312
 
@@ -234,16 +320,14 @@ module FFI
234
320
  ##
235
321
  # Retrieves the default value for the given configuration key.
236
322
  #
237
- # @since 13-04-2012
238
323
  # @param [#to_s] key The name of the configuration key.
239
324
  # @return [String]
325
+ # @raise [RuntimeError] Raised if the speller is closed.
240
326
  # @raise [FFI::Aspell::ConfigError] Raised when the configuration item
241
327
  # does not exist.
242
328
  #
243
329
  def get_default(key)
244
- unless key.respond_to?(:to_s)
245
- raise(TypeError, 'Configuration keys should respond to #to_s()')
246
- end
330
+ check_closed
247
331
 
248
332
  value = Aspell.config_retrieve_default(@config, key.to_s)
249
333
 
@@ -257,15 +341,13 @@ module FFI
257
341
  ##
258
342
  # Resets a configuration item to its default value.
259
343
  #
260
- # @since 13-04-2012
261
344
  # @param [#to_s] key The name of the configuration item to reset.
345
+ # @raise [RuntimeError] Raised if the speller is closed.
262
346
  # @raise [FFI::Aspell::ConfigError] Raised when the configuration item
263
347
  # could not be reset.
264
348
  #
265
349
  def reset(key)
266
- unless key.respond_to?(:to_s)
267
- raise(TypeError, 'Configuration keys should respond to #to_s()')
268
- end
350
+ check_closed
269
351
 
270
352
  unless Aspell.config_remove(@config, key.to_s)
271
353
  raise(
@@ -274,41 +356,64 @@ module FFI
274
356
  "it doesn't exist"
275
357
  )
276
358
  end
359
+
360
+ update_speller
277
361
  end
278
362
 
363
+ private
364
+
279
365
  ##
280
366
  # Converts word to encoding expected in aspell
281
367
  # from current ruby encoding
282
368
  #
283
- # @param [String] word The word to convert
284
- # return [String] word
369
+ # @param [String] word The word to convert
370
+ # @return [String] word
285
371
  #
286
372
  def handle_input(word)
287
- if defined?(Encoding)
288
- enc = get('encoding')
289
- word.encode!(enc)
290
- end
373
+ enc = get('encoding')
291
374
 
292
- word
375
+ return word.encode(enc)
293
376
  end
294
- private :handle_input
295
377
 
296
378
  ##
297
379
  # Converts word from aspell encoding to what ruby expects
298
380
  #
299
- # @param [String] word The word to convert
300
- # return [String] word
381
+ # @param [String] word The word to convert
382
+ # @return [String] word
301
383
  #
302
384
  def handle_output(word)
303
- if defined?(Encoding)
304
- enc = get('encoding')
305
- word.force_encoding(enc).encode!
306
- end
385
+ enc = get('encoding')
307
386
 
308
- word
387
+ return word.force_encoding(enc).encode
388
+ end
389
+
390
+ ##
391
+ # Raises error if speller is closed.
392
+ #
393
+ # @raise [RuntimeError] Raised if the speller is closed.
394
+ # @return [nil]
395
+ #
396
+ def check_closed
397
+ if closed?
398
+ raise(RuntimeError, 'This Speller object has already been closed')
399
+ end
309
400
  end
310
- private :handle_output
311
401
 
402
+ ##
403
+ # Updates the internal speller object to use the current config.
404
+ #
405
+ def update_speller
406
+ ObjectSpace.undefine_finalizer(self)
407
+
408
+ Aspell.speller_delete(@speller)
409
+
410
+ @speller = Aspell.speller_new(@config)
411
+
412
+ ObjectSpace.define_finalizer(
413
+ self,
414
+ self.class.finalizer(@config, @speller)
415
+ )
416
+ end
312
417
  end # Speller
313
418
  end # Aspell
314
419
  end # FFI
@@ -1,5 +1,5 @@
1
1
  module FFI
2
2
  module Aspell
3
- VERSION = '0.0.3'
3
+ VERSION = '1.0.0'
4
4
  end # Aspell
5
5
  end # FFI
metadata CHANGED
@@ -1,146 +1,123 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-aspell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Yorick Peterse
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-07 00:00:00.000000000 Z
11
+ date: 2014-09-10 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
- version: 1.0.11
19
+ version: '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
- version: 1.0.11
26
+ version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
- version: 0.9.2.2
33
+ version: '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.9.2.2
40
+ version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: yard
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
- version: 0.7.5
47
+ version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
- version: 0.7.5
54
+ version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
- name: redcarpet
56
+ name: kramdown
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - ">="
68
60
  - !ruby/object:Gem::Version
69
- version: 2.1.1
61
+ version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - ">="
76
67
  - !ruby/object:Gem::Version
77
- version: 2.1.1
68
+ version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
- name: bacon
70
+ name: rspec
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - ">="
84
74
  - !ruby/object:Gem::Version
85
- version: 1.1.0
75
+ version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - ">="
92
81
  - !ruby/object:Gem::Version
93
- version: 1.1.0
82
+ version: '0'
94
83
  description: FFI bindings for Aspell
95
84
  email: yorickpeterse@gmail.com
96
85
  executables: []
97
86
  extensions: []
98
87
  extra_rdoc_files: []
99
88
  files:
100
- - .gitignore
101
- - .ruby-version
102
- - .yardopts
103
- - Gemfile
89
+ - ".yardopts"
104
90
  - LICENSE
105
- - README.md
106
- - Rakefile
107
- - ffi-aspell.gemspec
91
+ - doc/DCO.md
92
+ - doc/changelog.md
93
+ - doc/css/common.css
108
94
  - lib/ffi/aspell.rb
95
+ - lib/ffi/aspell/aspell.rb
109
96
  - lib/ffi/aspell/error.rb
110
97
  - lib/ffi/aspell/speller.rb
111
98
  - lib/ffi/aspell/version.rb
112
- - pkg/.gitkeep
113
- - spec/ffi/aspell/speller.rb
114
- - spec/ffi/aspell/suggestions.rb
115
- - spec/fixtures/personal.en.pws
116
- - spec/fixtures/personal.nl.pws
117
- - spec/helper.rb
118
- - task/build.rake
119
- - task/memory.rake
120
- - task/test.rake
121
- homepage: https://github.com/YorickPeterse/ffi-aspell
99
+ homepage: https://github.com/yorickpeterse/ffi-aspell
122
100
  licenses: []
101
+ metadata: {}
123
102
  post_install_message:
124
103
  rdoc_options: []
125
104
  require_paths:
126
105
  - lib
127
106
  required_ruby_version: !ruby/object:Gem::Requirement
128
- none: false
129
107
  requirements:
130
- - - ! '>='
108
+ - - ">="
131
109
  - !ruby/object:Gem::Version
132
- version: '0'
110
+ version: 1.9.3
133
111
  required_rubygems_version: !ruby/object:Gem::Requirement
134
- none: false
135
112
  requirements:
136
- - - ! '>='
113
+ - - ">="
137
114
  - !ruby/object:Gem::Version
138
115
  version: '0'
139
116
  requirements: []
140
117
  rubyforge_project:
141
- rubygems_version: 1.8.23
118
+ rubygems_version: 2.4.1
142
119
  signing_key:
143
- specification_version: 3
120
+ specification_version: 4
144
121
  summary: FFI bindings for Aspell
145
122
  test_files: []
146
123
  has_rdoc: yard