patrickod-raspell 1.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.
data/ext/raspell.c ADDED
@@ -0,0 +1,726 @@
1
+
2
+ #include "raspell.h"
3
+
4
+ extern void Init_dictinfo();
5
+ extern void Init_aspell();
6
+
7
+ void Init_raspell() {
8
+ cAspellError = rb_define_class("AspellError", rb_eStandardError);
9
+ Init_dictinfo();
10
+ Init_aspell();
11
+ }
12
+
13
+ static AspellDictInfo* get_info(VALUE info) {
14
+ AspellDictInfo *result;
15
+ Data_Get_Struct(info, AspellDictInfo, result);
16
+ return result;
17
+ }
18
+
19
+ static VALUE dictinfo_s_new(int argc, VALUE *argv, VALUE klass) {
20
+ rb_raise(rb_eException, "not instantiable");
21
+ }
22
+
23
+ static VALUE dictinfo_name(VALUE self) {
24
+ return rb_str_new2(get_info(self)->name);
25
+ }
26
+
27
+ static VALUE dictinfo_code(VALUE self) {
28
+ return rb_str_new2(get_info(self)->code);
29
+ }
30
+
31
+ static VALUE dictinfo_jargon(VALUE self) {
32
+ return rb_str_new2(get_info(self)->jargon);
33
+ }
34
+
35
+ static VALUE dictinfo_size(VALUE self) {
36
+ return INT2FIX(get_info(self)->size);
37
+ }
38
+
39
+ static VALUE dictinfo_size_str(VALUE self) {
40
+ return rb_str_new2(get_info(self)->size_str);
41
+ }
42
+
43
+ void Init_dictinfo() {
44
+ //CLASS DEFINITION=========================================================
45
+ cDictInfo = rb_define_class("AspellDictInfo", rb_cObject);
46
+
47
+ //CLASS METHODS============================================================
48
+ rb_define_singleton_method(cDictInfo, "new", dictinfo_s_new, 0);
49
+
50
+ //METHODS =================================================================
51
+ rb_define_method(cDictInfo, "name", dictinfo_name, 0);
52
+ rb_define_method(cDictInfo, "code", dictinfo_code, 0);
53
+ rb_define_method(cDictInfo, "jargon", dictinfo_jargon, 0);
54
+ rb_define_method(cDictInfo, "size", dictinfo_size, 0);
55
+ rb_define_method(cDictInfo, "size_str", dictinfo_size_str, 0);
56
+ }
57
+
58
+ extern VALUE rb_cFile;
59
+
60
+ /**
61
+ * This method is called from the garbage collector during finalization.
62
+ * @param p pointer to spellchecker-object.
63
+ */
64
+ static void aspell_free(void *p) {
65
+ delete_aspell_speller(p);
66
+ }
67
+
68
+ /**
69
+ * Check for an error - raise exception if so.
70
+ * @param speller the spellchecker-object.
71
+ * @return void
72
+ * @exception Exception if there was an error.
73
+ */
74
+ static void check_for_error(AspellSpeller * speller) {
75
+ if (aspell_speller_error(speller) != 0) {
76
+ rb_raise(cAspellError, aspell_speller_error_message(speller));
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Set a specific option, that is known by aspell.
82
+ * @param config the config object of a specific spellchecker.
83
+ * @param key the option to set (eg: lang).
84
+ * @param value the value of the option to set (eg: "us_US").
85
+ * @exception Exception if key not known, or value undefined.
86
+ */
87
+ static void set_option(AspellConfig *config, char *key, char *value) {
88
+ //printf("set option: %s = %s\n", key, value);
89
+ if (aspell_config_replace(config, key, value) == 0) {
90
+ rb_raise(cAspellError, aspell_config_error_message(config));
91
+ }
92
+ //check config:
93
+ if (aspell_config_error(config) != 0) {
94
+ rb_raise(cAspellError, aspell_config_error_message(config));
95
+ }
96
+ }
97
+
98
+ static void set_options(AspellConfig *config, VALUE hash) {
99
+ VALUE options = rb_funcall(hash, rb_intern("keys"), 0);
100
+ int count=RARRAY_LEN(options);
101
+ int c = 0;
102
+ //set all values
103
+ while(c<count) {
104
+ //fetch option
105
+ VALUE option = RARRAY_PTR(options)[c];
106
+ VALUE value = rb_funcall(hash, rb_intern("fetch"), 1, option);
107
+ if (TYPE(option)!=T_STRING) rb_raise(cAspellError, "Given key must be a string.");
108
+ if (TYPE(value )!=T_STRING) rb_raise(cAspellError, "Given value must be a string.");
109
+ set_option(config, STR2CSTR(option), STR2CSTR(value));
110
+ c++;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Extract c-struct speller from ruby object.
116
+ * @param speller the speller as ruby object.
117
+ * @return the speller as c-struct.
118
+ */
119
+ static AspellSpeller* get_speller(VALUE speller) {
120
+ AspellSpeller *result;
121
+ Data_Get_Struct(speller, AspellSpeller, result);
122
+ return result;
123
+ }
124
+
125
+ /**
126
+ * Generate a document checker object from a given speller.
127
+ * @param speller the speller that shall chech a document.
128
+ * @return a fresh document checker.
129
+ */
130
+ static AspellDocumentChecker* get_checker(AspellSpeller *speller) {
131
+ AspellCanHaveError * ret;
132
+ AspellDocumentChecker * checker;
133
+ ret = new_aspell_document_checker(speller);
134
+ if (aspell_error(ret) != 0)
135
+ rb_raise(cAspellError, aspell_error_message(ret));
136
+ checker = to_aspell_document_checker(ret);
137
+ return checker;
138
+ }
139
+
140
+ /**
141
+ * Utility function that wraps a list of words as ruby array of ruby strings.
142
+ * @param list an aspell wordlist.
143
+ * @return an ruby array, containing all words as ruby strings.
144
+ */
145
+ static VALUE get_list(const AspellWordList *list) {
146
+ VALUE result = rb_ary_new2(aspell_word_list_size(list));
147
+ if (list != 0) {
148
+ AspellStringEnumeration * els = aspell_word_list_elements(list);
149
+ const char * word;
150
+ while ( (word = aspell_string_enumeration_next(els)) != 0) {
151
+ rb_ary_push(result, rb_str_new2(word));
152
+ }
153
+ delete_aspell_string_enumeration(els);
154
+ }
155
+ return result;
156
+ }
157
+
158
+ /**
159
+ * Generate a regexp from the given word with word boundaries.
160
+ * @param word the word to match.
161
+ * @return regular expression, matching exactly the word as whole.
162
+ */
163
+ static VALUE get_wordregexp(VALUE word) {
164
+ char *cword = STR2CSTR(word);
165
+ char *result = malloc((strlen(cword)+5)*sizeof(char));
166
+ *result='\0';
167
+ strcat(result, "\\b");
168
+ strcat(result, cword);
169
+ strcat(result, "\\b");
170
+ word = rb_reg_new(result, strlen(result), 0);
171
+ free(result);
172
+ return word;
173
+ }
174
+
175
+
176
+ /**
177
+ * Ctor for aspell objects:
178
+ * Aspell.new(language, jargon, size, encoding)
179
+ * Please note: All parameters are optional. If a parameter is omitted, a default value is assumed from
180
+ * the environment (eg lang from $LANG). To retain default values, you can use nil
181
+ * as value: to set only size: Aspell.new(nil, nil, "80")
182
+ * @param language ISO639 language code plus optional ISO 3166 counry code as string (eg: "de" or "us_US")
183
+ * @param jargon a special jargon of the selected language
184
+ * @param size the size of the dictionary to chose (if there are options)
185
+ * @param encoding the encoding to use
186
+ * @exception Exception if the specified dictionary is not found.
187
+ */
188
+ static VALUE aspell_s_new(int argc, VALUE *argv, VALUE klass) {
189
+ VALUE vlang, vjargon, vsize, vencoding;
190
+ const char *tmp;
191
+ //aspell values
192
+ AspellCanHaveError * ret;
193
+ AspellSpeller * speller;
194
+ AspellConfig * config;
195
+
196
+ //create new config
197
+ config = new_aspell_config();
198
+
199
+ //extract values
200
+ rb_scan_args(argc, argv, "04", &vlang, &vjargon, &vsize, &vencoding);
201
+
202
+ //language:
203
+ if (RTEST(vlang)) set_option(config, "lang", STR2CSTR(vlang));
204
+ //jargon:
205
+ if (RTEST(vjargon)) set_option(config, "jargon", STR2CSTR(vjargon));
206
+ //size:
207
+ if (RTEST(vsize)) set_option(config, "size", STR2CSTR(vsize));
208
+ //encoding:
209
+ if (RTEST(vencoding)) set_option(config, "encoding", STR2CSTR(vencoding));
210
+
211
+ //create speller:
212
+ ret = new_aspell_speller(config);
213
+ delete_aspell_config(config);
214
+ if (aspell_error(ret) != 0) {
215
+ tmp = strdup(aspell_error_message(ret));
216
+ delete_aspell_can_have_error(ret);
217
+ rb_raise(cAspellError, tmp);
218
+ }
219
+
220
+ speller = to_aspell_speller(ret);
221
+
222
+ //wrap pointer
223
+ return Data_Wrap_Struct(klass, 0, aspell_free, speller);
224
+ }
225
+
226
+
227
+
228
+ /**
229
+ * Ctor for aspell objects.
230
+ * This is a custom constructor and takes a hash of config options: key, value pairs.
231
+ * Common use:
232
+ *
233
+ * a = Aspell.new({"lang"=>"de", "jargon"=>"berlin"})
234
+ *
235
+ * For a list of config options, see aspell manual.
236
+ * @param options hash of options
237
+ */
238
+ static VALUE aspell_s_new1(VALUE klass, VALUE options) {
239
+ //aspell values
240
+ AspellCanHaveError * ret;
241
+ AspellSpeller * speller;
242
+ AspellConfig * config;
243
+
244
+ //create new config
245
+ config = new_aspell_config();
246
+
247
+ //set options
248
+ set_options(config, options);
249
+
250
+ //create speller:
251
+ ret = new_aspell_speller(config);
252
+ delete_aspell_config(config);
253
+ if (aspell_error(ret) != 0) {
254
+ const char *tmp = strdup(aspell_error_message(ret));
255
+ delete_aspell_can_have_error(ret);
256
+ rb_raise(cAspellError, tmp);
257
+ }
258
+
259
+ speller = to_aspell_speller(ret);
260
+
261
+ //wrap pointer
262
+ return Data_Wrap_Struct(klass, 0, aspell_free, speller);
263
+ }
264
+
265
+ /**
266
+ * List all available dictionaries.
267
+ * @param class object
268
+ * @return array of AspellDictInfo objects.
269
+ */
270
+ static VALUE aspell_s_list_dicts(VALUE klass) {
271
+ AspellConfig * config;
272
+ AspellDictInfoList * dlist;
273
+ AspellDictInfoEnumeration * dels;
274
+ const AspellDictInfo * entry;
275
+ VALUE result = rb_ary_new();
276
+
277
+ //get a list of dictionaries
278
+ config = new_aspell_config();
279
+ dlist = get_aspell_dict_info_list(config);
280
+ delete_aspell_config(config);
281
+
282
+ //iterate over list - fill ruby array
283
+ dels = aspell_dict_info_list_elements(dlist);
284
+ while ( (entry = aspell_dict_info_enumeration_next(dels)) != 0) {
285
+ rb_ary_push(result, Data_Wrap_Struct(cDictInfo, 0, 0, (AspellDictInfo *)entry));
286
+ }
287
+ delete_aspell_dict_info_enumeration(dels);
288
+ return result;
289
+ }
290
+
291
+ /**
292
+ * @see set_option.
293
+ */
294
+ static VALUE aspell_set_option(VALUE self, VALUE option, VALUE value) {
295
+ AspellSpeller *speller = get_speller(self);
296
+ set_option(aspell_speller_config(speller), STR2CSTR(option), STR2CSTR(value));
297
+ return self;
298
+ }
299
+
300
+
301
+ /**
302
+ * Delete an option.
303
+ * @param option optionstring to remove from the options.
304
+ */
305
+ static VALUE aspell_remove_option(VALUE self, VALUE option) {
306
+ AspellSpeller *speller = get_speller(self);
307
+ aspell_config_remove(aspell_speller_config(speller), STR2CSTR(option));
308
+ return self;
309
+ }
310
+
311
+ /**
312
+ * To set the mode, words are suggested.
313
+ * @param one of Aspell::[ULTRA|FAST|NORMAL|BADSPELLERS]
314
+ */
315
+ static VALUE aspell_set_suggestion_mode(VALUE self, VALUE value) {
316
+ AspellSpeller *speller = get_speller(self);
317
+ set_option(aspell_speller_config(speller), "sug-mode", STR2CSTR(value));
318
+ return self;
319
+ }
320
+
321
+ /**
322
+ * Returns the personal wordlist as array of strings.
323
+ * @return array of strings
324
+ */
325
+ static VALUE aspell_personal_wordlist(VALUE self) {
326
+ AspellSpeller *speller = get_speller(self);
327
+ return get_list(aspell_speller_personal_word_list(speller));
328
+ }
329
+
330
+ /**
331
+ * Returns the session wordlist as array of strings.
332
+ * @return array of strings
333
+ */
334
+ static VALUE aspell_session_wordlist(VALUE self) {
335
+ AspellSpeller *speller = get_speller(self);
336
+ return get_list(aspell_speller_session_word_list(speller));
337
+ }
338
+
339
+ /**
340
+ * Returns the main wordlist as array of strings.
341
+ * @return array of strings
342
+ */
343
+ static VALUE aspell_main_wordlist(VALUE self) {
344
+ AspellSpeller *speller = get_speller(self);
345
+ return get_list(aspell_speller_main_word_list(speller));
346
+ }
347
+
348
+ /**
349
+ * Synchronize all wordlists with the current session.
350
+ */
351
+ static VALUE aspell_save_all_wordlists(VALUE self) {
352
+ AspellSpeller *speller = get_speller(self);
353
+ aspell_speller_save_all_word_lists(speller);
354
+ check_for_error(speller);
355
+ return self;
356
+ }
357
+
358
+ /**
359
+ * Remove all words inside session.
360
+ */
361
+ static VALUE aspell_clear_session(VALUE self) {
362
+ AspellSpeller *speller = get_speller(self);
363
+ aspell_speller_clear_session(speller);
364
+ check_for_error(speller);
365
+ return self;
366
+ }
367
+
368
+ /**
369
+ * Suggest words for the given misspelled word.
370
+ * @param word the misspelled word.
371
+ * @return array of strings.
372
+ */
373
+ static VALUE aspell_suggest(VALUE self, VALUE word) {
374
+ AspellSpeller *speller = get_speller(self);
375
+ return get_list(aspell_speller_suggest(speller, STR2CSTR(word), -1));
376
+ }
377
+
378
+ /**
379
+ * Add a given word to the list of known words inside my private dictionary.
380
+ * You have to call aspell_save_all_wordlists to make sure the list gets persistent.
381
+ * @param word the word to add.
382
+ */
383
+ static VALUE aspell_add_to_personal(VALUE self, VALUE word) {
384
+ AspellSpeller *speller = get_speller(self);
385
+ aspell_speller_add_to_personal(speller, STR2CSTR(word), -1);
386
+ check_for_error(speller);
387
+ return self;
388
+ }
389
+
390
+ /**
391
+ * Add a given word to the list of known words just for the lifetime of this object.
392
+ * @param word the word to add.
393
+ */
394
+ static VALUE aspell_add_to_session(VALUE self, VALUE word) {
395
+ AspellSpeller *speller = get_speller(self);
396
+ aspell_speller_add_to_session(speller, STR2CSTR(word), -1);
397
+ check_for_error(speller);
398
+ return self;
399
+ }
400
+
401
+ /**
402
+ * Retrieve the value of a specific option.
403
+ * The options are listed inside
404
+ * Aspell::[DictionaryOptions|CheckerOptions|FilterOptions|RunTogetherOptions|MiscOptions|UtilityOptions]
405
+ * @param word the option as string.
406
+ */
407
+ static VALUE aspell_conf_retrieve(VALUE self, VALUE key) {
408
+ AspellSpeller *speller = get_speller(self);
409
+ AspellConfig *config = aspell_speller_config(speller);
410
+ VALUE result = rb_str_new2(aspell_config_retrieve(config, STR2CSTR(key)));
411
+ if (aspell_config_error(config) != 0) {
412
+ rb_raise(cAspellError, aspell_config_error_message(config));
413
+ }
414
+ return result;
415
+ }
416
+
417
+ /**
418
+ * Retrieve the value of a specific option as list.
419
+ * @param word the option as string.
420
+ */
421
+ static VALUE aspell_conf_retrieve_list(VALUE self, VALUE key) {
422
+ AspellSpeller *speller = get_speller(self);
423
+ AspellConfig *config = aspell_speller_config(speller);
424
+ AspellStringList * list = new_aspell_string_list();
425
+ AspellMutableContainer * container = aspell_string_list_to_mutable_container(list);
426
+ AspellStringEnumeration * els;
427
+ VALUE result = rb_ary_new();
428
+ const char *option_value;
429
+
430
+ //retrieve list
431
+ aspell_config_retrieve_list(config, STR2CSTR(key), container);
432
+ //check for error
433
+ if (aspell_config_error(config) != 0) {
434
+ char *tmp = strdup(aspell_config_error_message(config));
435
+ delete_aspell_string_list(list);
436
+ rb_raise( cAspellError, tmp);
437
+ }
438
+
439
+ //iterate over list
440
+ els = aspell_string_list_elements(list);
441
+ while ( (option_value = aspell_string_enumeration_next(els)) != 0) {
442
+ //push the option value to result
443
+ rb_ary_push(result, rb_str_new2(option_value));
444
+ }
445
+ //free list
446
+ delete_aspell_string_enumeration(els);
447
+ delete_aspell_string_list(list);
448
+
449
+ return result;
450
+ }
451
+
452
+ /**
453
+ * Simply dump config.
454
+ * Not very useful at all.
455
+ */
456
+ static VALUE aspell_dump_config(VALUE self) {
457
+ AspellSpeller *speller = get_speller(self);
458
+ AspellConfig *config = aspell_speller_config(speller);
459
+ AspellKeyInfoEnumeration * key_list = aspell_config_possible_elements( config, 0 );
460
+ const AspellKeyInfo * entry;
461
+
462
+ while ( (entry = aspell_key_info_enumeration_next(key_list) ) ) {
463
+ printf("%20s: %s\n", entry->name, aspell_config_retrieve(config, entry->name) );
464
+ }
465
+ delete_aspell_key_info_enumeration(key_list);
466
+ return self;
467
+ }
468
+
469
+ /**
470
+ * Check a given word for correctness.
471
+ * @param word the word to check
472
+ * @return true if the word is correct, otherwise false.
473
+ */
474
+ static VALUE aspell_check(VALUE self, VALUE word) {
475
+ AspellSpeller *speller = get_speller(self);
476
+ VALUE result = Qfalse;
477
+ int code = aspell_speller_check(speller, STR2CSTR(word), -1);
478
+ if (code == 1)
479
+ result = Qtrue;
480
+ else if (code == 0)
481
+ result = Qfalse;
482
+ else
483
+ rb_raise( cAspellError, aspell_speller_error_message(speller));
484
+ return result;
485
+ }
486
+
487
+ /**
488
+ * This method will check an array of strings for misspelled words.
489
+ * This method needs a block to work proper. Each misspelled word is yielded,
490
+ * a correct word as result from the block is assumed.
491
+ * Common use:
492
+ *
493
+ * a = Aspell.new(...)
494
+ * text = ...
495
+ * a.correct_lines(text) { |badword|
496
+ * puts "Error: #{badword}\n"
497
+ * puts a.suggest(badword).join(" | ")
498
+ * gets #the input is returned as right word
499
+ * }
500
+ *
501
+ * @param ary the array of strings to check.
502
+ * @result an array holding all lines with corrected words.
503
+ */
504
+ static VALUE aspell_correct_lines(VALUE self, VALUE ary) {
505
+ VALUE result = ary;
506
+ if (rb_block_given_p()) {
507
+ //create checker
508
+ AspellSpeller *speller = get_speller(self);
509
+ AspellDocumentChecker * checker = get_checker(speller);
510
+ AspellToken token;
511
+ //some tmp values
512
+ VALUE vline, sline;
513
+ VALUE word, rword;
514
+ char *line;
515
+ int count=RARRAY_LEN(ary);
516
+ int c=0;
517
+ //create new result array
518
+ result = rb_ary_new();
519
+ //iterate over array
520
+ while(c<count) {
521
+ int offset=0;
522
+ //fetch line
523
+ vline = RARRAY_PTR(ary)[c];
524
+ //save line
525
+ sline = rb_funcall(vline, rb_intern("dup"), 0);
526
+ //c representation
527
+ line = STR2CSTR(vline);
528
+ //process line
529
+ aspell_document_checker_process(checker, line, -1);
530
+ //iterate over all misspelled words
531
+ while (token = aspell_document_checker_next_misspelling(checker), token.len != 0) {
532
+ //extract word by start/length qualifier
533
+ word = rb_funcall(vline, rb_intern("[]"), 2, INT2FIX(token.offset), INT2FIX(token.len));
534
+ //get the right word from the block
535
+ rword = rb_yield(word);
536
+ //nil -> do nothing
537
+ if(rword == Qnil) continue;
538
+ //check for string
539
+ if (TYPE(rword) != T_STRING) rb_raise(cAspellError, "Need a String to substitute");
540
+ //chomp the string
541
+ rb_funcall(rword, rb_intern("chomp!"), 0);
542
+ //empty string -> do nothing
543
+ if(strlen(STR2CSTR(rword)) == 0) continue;
544
+ //remember word for later suggestion
545
+ aspell_speller_store_replacement(speller, STR2CSTR(word), -1, STR2CSTR(rword), -1);
546
+ //substitute the word by replacement
547
+ rb_funcall(sline, rb_intern("[]="), 3, INT2FIX(token.offset+offset), INT2FIX(token.len), rword);
548
+ //adjust offset
549
+ offset += strlen(STR2CSTR(rword))-strlen(STR2CSTR(word));
550
+ //printf("replace >%s< with >%s< (offset now %d)\n", STR2CSTR(word), STR2CSTR(rword), offset);
551
+ }
552
+ //push the substituted line to result
553
+ rb_ary_push(result, sline);
554
+ c++;
555
+ }
556
+ //free checker
557
+ delete_aspell_document_checker(checker);
558
+ } else {
559
+ rb_raise(cAspellError, "No block given. How to correct?");
560
+ }
561
+ return result;
562
+ }
563
+
564
+ /**
565
+ * Remember a correction.
566
+ * This affects the suggestion of other words to fit this correction.
567
+ * @param badword the bad spelled word as string.
568
+ * @param badword the correction of the bad spelled word as string.
569
+ * @result self
570
+ */
571
+ static VALUE aspell_store_replacement(VALUE self, VALUE badword, VALUE rightword) {
572
+ AspellSpeller *speller = get_speller(self);
573
+ aspell_speller_store_replacement(speller, STR2CSTR(badword), -1, STR2CSTR(rightword), -1);
574
+ return self;
575
+ }
576
+
577
+ /**
578
+ * Simple utility function to correct a file.
579
+ * The file gets read, content will be checked and write back.
580
+ * Please note: This method will change the file! - no backup and of course: no warranty!
581
+ * @param filename the name of the file as String.
582
+ * @exception Exception due to lack of read/write permissions.
583
+ */
584
+ static VALUE aspell_correct_file(VALUE self, VALUE filename) {
585
+ if (rb_block_given_p()) {
586
+ VALUE content = rb_funcall(rb_cFile, rb_intern("readlines"), 1, filename);
587
+ VALUE newcontent = aspell_correct_lines(self, content);
588
+ VALUE file = rb_file_open(STR2CSTR(filename), "w+");
589
+ rb_funcall(file, rb_intern("write"), 1, newcontent);
590
+ rb_funcall(file, rb_intern("close"), 0);
591
+ } else {
592
+ rb_raise(cAspellError, "No block given. How to correct?");
593
+ }
594
+ return self;
595
+
596
+ }
597
+
598
+ /**
599
+ * Return a list of all misspelled words inside a given array of strings.
600
+ * @param ary an array of strings to check for.
601
+ * @return array of strings: words that are misspelled.
602
+ */
603
+ static VALUE aspell_list_misspelled(VALUE self, VALUE ary) {
604
+ VALUE result = rb_hash_new();
605
+ //create checker
606
+ AspellSpeller *speller = get_speller(self);
607
+ AspellDocumentChecker * checker = get_checker(speller);
608
+ AspellToken token;
609
+ VALUE word, vline;
610
+ int count=RARRAY_LEN(ary);
611
+ int c=0;
612
+ //iterate over array
613
+ while(c<count) {
614
+ //process line
615
+ vline = RARRAY_PTR(ary)[c];
616
+ aspell_document_checker_process(checker, STR2CSTR(vline), -1);
617
+ //iterate over all misspelled words
618
+ while (token = aspell_document_checker_next_misspelling(checker), token.len != 0) {
619
+ //extract word by start/length qualifier
620
+ word = rb_funcall(vline, rb_intern("[]"), 2, INT2FIX(token.offset), INT2FIX(token.len));
621
+ rb_hash_aset(result, word, Qnil);
622
+ //yield block, if given
623
+ if (rb_block_given_p())
624
+ rb_yield(word);
625
+ }
626
+ c++;
627
+ }
628
+ //free checker
629
+ delete_aspell_document_checker(checker);
630
+ result = rb_funcall(result, rb_intern("keys"), 0);
631
+ return result;
632
+ }
633
+
634
+ void Init_aspell() {
635
+ //CLASS DEFINITION=========================================================
636
+ cAspell = rb_define_class("Aspell", rb_cObject);
637
+
638
+ //CONSTANTS================================================================
639
+ rb_define_const(cAspell, "ULTRA", rb_str_new2("ultra"));
640
+ rb_define_const(cAspell, "FAST", rb_str_new2("fast"));
641
+ rb_define_const(cAspell, "NORMAL", rb_str_new2("normal"));
642
+ rb_define_const(cAspell, "BADSPELLERS", rb_str_new2("bad-spellers"));
643
+ rb_define_const(cAspell, "DictionaryOptions", rb_ary_new3( 11,
644
+ rb_str_new2("master"),
645
+ rb_str_new2("dict-dir"),
646
+ rb_str_new2("lang"),
647
+ rb_str_new2("size"),
648
+ rb_str_new2("jargon"),
649
+ rb_str_new2("word-list-path"),
650
+ rb_str_new2("module-search-order"),
651
+ rb_str_new2("personal"),
652
+ rb_str_new2("repl"),
653
+ rb_str_new2("extra-dicts"),
654
+ rb_str_new2("strip-accents")));
655
+ rb_define_const(cAspell, "CheckerOptions", rb_ary_new3( 11,
656
+ rb_str_new2("ignore"),
657
+ rb_str_new2("ignore-case"),
658
+ rb_str_new2("ignore-accents"),
659
+ rb_str_new2("ignore-repl"),
660
+ rb_str_new2("save-repl"),
661
+ rb_str_new2("sug-mode"),
662
+ rb_str_new2("module-search-order"),
663
+ rb_str_new2("personal"),
664
+ rb_str_new2("repl"),
665
+ rb_str_new2("extra-dicts"),
666
+ rb_str_new2("strip-accents")));
667
+ rb_define_const(cAspell, "FilterOptions", rb_ary_new3( 10,
668
+ rb_str_new2("filter"),
669
+ rb_str_new2("mode"),
670
+ rb_str_new2("encoding"),
671
+ rb_str_new2("add-email-quote"),
672
+ rb_str_new2("rem-email-quote"),
673
+ rb_str_new2("email-margin"),
674
+ rb_str_new2("sgml-check"),
675
+ rb_str_new2("sgml-extension"),
676
+ rb_str_new2("tex-command"),
677
+ rb_str_new2("tex-check-command")));
678
+ rb_define_const(cAspell, "RunTogetherOptions", rb_ary_new3( 3,
679
+ rb_str_new2("run-together"),
680
+ rb_str_new2("run-together-limit"),
681
+ rb_str_new2("run-together-min")));
682
+ rb_define_const(cAspell, "MiscOptions", rb_ary_new3( 8,
683
+ rb_str_new2("conf"),
684
+ rb_str_new2("conf-dir"),
685
+ rb_str_new2("data-dir"),
686
+ rb_str_new2("local-data-dir"),
687
+ rb_str_new2("home-dir"),
688
+ rb_str_new2("per-conf"),
689
+ rb_str_new2("prefix"),
690
+ rb_str_new2("set-prefix")));
691
+
692
+ rb_define_const(cAspell, "UtilityOptions", rb_ary_new3( 4,
693
+ rb_str_new2("backup"),
694
+ rb_str_new2("time"),
695
+ rb_str_new2("reverse"),
696
+ rb_str_new2("keymapping")));
697
+
698
+ //CLASS METHODS============================================================
699
+ rb_define_singleton_method(cAspell, "new", aspell_s_new, -1);
700
+ rb_define_singleton_method(cAspell, "new1", aspell_s_new1, 1);
701
+ rb_define_singleton_method(cAspell, "list_dicts", aspell_s_list_dicts, 0);
702
+
703
+ //METHODS =================================================================
704
+ rb_define_method(cAspell, "add_to_personal", aspell_add_to_personal, 1);
705
+ rb_define_method(cAspell, "add_to_session", aspell_add_to_personal, 1);
706
+ rb_define_method(cAspell, "check", aspell_check, 1);
707
+ rb_define_method(cAspell, "correct_lines", aspell_correct_lines, 1);
708
+ rb_define_method(cAspell, "correct_file", aspell_correct_file, 1);
709
+ rb_define_method(cAspell, "clear_session", aspell_clear_session, 0);
710
+ rb_define_method(cAspell, "dump_config", aspell_dump_config, 0);
711
+ rb_define_method(cAspell, "list_misspelled", aspell_list_misspelled, 1);
712
+ //This seems not to be very useful ...
713
+ //rb_define_method(cAspell, "main_wordlist", aspell_main_wordlist, 0);
714
+ rb_define_method(cAspell, "personal_wordlist", aspell_personal_wordlist, 0);
715
+ rb_define_method(cAspell, "save_all_word_lists", aspell_save_all_wordlists, 0);
716
+ rb_define_method(cAspell, "session_wordlist", aspell_session_wordlist, 0);
717
+ rb_define_method(cAspell, "set_option", aspell_set_option, 2);
718
+ rb_define_method(cAspell, "store_replacement", aspell_store_replacement, 2);
719
+ rb_define_method(cAspell, "remove_option", aspell_remove_option, 1);
720
+ rb_define_method(cAspell, "get_option", aspell_conf_retrieve, 1);
721
+ rb_define_method(cAspell, "get_option_as_list", aspell_conf_retrieve_list, 1);
722
+ rb_define_method(cAspell, "suggest", aspell_suggest, 1);
723
+ rb_define_method(cAspell, "suggestion_mode=", aspell_set_suggestion_mode, 1);
724
+ }
725
+
726
+