ffi-aspell 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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