jruby-stemmer 0.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.bundle
2
+ *.gem
3
+ *.jar
4
+ *.o
5
+ *.rbc
6
+ *.so
7
+ .bundle
8
+ .config
9
+ .DS_Store
10
+ .yardoc
11
+ coverage
12
+ doc/
13
+ Gemfile.lock
14
+ InstalledFiles
15
+ lib/bundler/man
16
+ Makefile
17
+ pkg
18
+ rdoc
19
+ spec/reports
20
+ test/tmp
21
+ test/version_tmp
22
+ tmp
23
+ _yardoc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jruby-stemmer.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,27 @@
1
+ Excluding ext/java-stemmer/Stemmer.java -
2
+ see http://www.tartarus.org/~martin/PorterStemmer for that code
3
+
4
+
5
+
6
+ Copyright (c) 2013 Caius Durling
7
+
8
+ MIT License
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining
11
+ a copy of this software and associated documentation files (the
12
+ "Software"), to deal in the Software without restriction, including
13
+ without limitation the rights to use, copy, modify, merge, publish,
14
+ distribute, sublicense, and/or sell copies of the Software, and to
15
+ permit persons to whom the Software is furnished to do so, subject to
16
+ the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # JRuby::Stemmer
2
+
3
+ Easily stem words in ruby, using a native java implementation of the porter stemming algorithm for speed. (Java equivalent of the fast-stemmer gem for MRI.)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jruby-stemmer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jruby-stemmer
18
+
19
+ ## Usage
20
+
21
+ You can either call the wrapper method yourself, or use the mixed in helper method `String#stem`.
22
+
23
+ JRuby::Stemmer.stem("apple") # => "appl"
24
+ "apple".stem # => "appl"
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ spec = Gem::Specification.load("jruby-stemmer.gemspec")
2
+
3
+ require "rubygems/package_task"
4
+ Gem::PackageTask.new(spec) {}
5
+
6
+ require "rake/javaextensiontask"
7
+ Rake::JavaExtensionTask.new("java-stemmer", spec)
@@ -0,0 +1,427 @@
1
+ package org.tartarus.martin.porter_stemmer;
2
+
3
+ /*
4
+
5
+ Porter stemmer in Java. The original paper is in
6
+
7
+ Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
8
+ no. 3, pp 130-137,
9
+
10
+ See also http://www.tartarus.org/~martin/PorterStemmer
11
+
12
+ History:
13
+
14
+ Release 1
15
+
16
+ Bug 1 (reported by Gonzalo Parra 16/10/99) fixed as marked below.
17
+ The words 'aed', 'eed', 'oed' leave k at 'a' for step 3, and b[k-1]
18
+ is then out outside the bounds of b.
19
+
20
+ Release 2
21
+
22
+ Similarly,
23
+
24
+ Bug 2 (reported by Steve Dyrdahl 22/2/00) fixed as marked below.
25
+ 'ion' by itself leaves j = -1 in the test for 'ion' in step 5, and
26
+ b[j] is then outside the bounds of b.
27
+
28
+ Release 3
29
+
30
+ Considerably revised 4/9/00 in the light of many helpful suggestions
31
+ from Brian Goetz of Quiotix Corporation (brian@quiotix.com).
32
+
33
+ Release 4
34
+
35
+ */
36
+
37
+ import java.io.*;
38
+
39
+ /**
40
+ * Stemmer, implementing the Porter Stemming Algorithm
41
+ *
42
+ * The Stemmer class transforms a word into its root form. The input
43
+ * word can be provided a character at time (by calling add()), or at once
44
+ * by calling one of the various stem(something) methods.
45
+ */
46
+
47
+ public class Stemmer
48
+ { private char[] b;
49
+ private int i, /* offset into b */
50
+ i_end, /* offset to end of stemmed word */
51
+ j, k;
52
+ private static final int INC = 50;
53
+ /* unit of size whereby b is increased */
54
+ public Stemmer()
55
+ { b = new char[INC];
56
+ i = 0;
57
+ i_end = 0;
58
+ }
59
+
60
+ /**
61
+ * Add a character to the word being stemmed. When you are finished
62
+ * adding characters, you can call stem(void) to stem the word.
63
+ */
64
+
65
+ public void add(char ch)
66
+ { if (i == b.length)
67
+ { char[] new_b = new char[i+INC];
68
+ for (int c = 0; c < i; c++) new_b[c] = b[c];
69
+ b = new_b;
70
+ }
71
+ b[i++] = ch;
72
+ }
73
+
74
+
75
+ /** Adds wLen characters to the word being stemmed contained in a portion
76
+ * of a char[] array. This is like repeated calls of add(char ch), but
77
+ * faster.
78
+ */
79
+
80
+ public void add(char[] w, int wLen)
81
+ { if (i+wLen >= b.length)
82
+ { char[] new_b = new char[i+wLen+INC];
83
+ for (int c = 0; c < i; c++) new_b[c] = b[c];
84
+ b = new_b;
85
+ }
86
+ for (int c = 0; c < wLen; c++) b[i++] = w[c];
87
+ }
88
+
89
+ /**
90
+ * After a word has been stemmed, it can be retrieved by toString(),
91
+ * or a reference to the internal buffer can be retrieved by getResultBuffer
92
+ * and getResultLength (which is generally more efficient.)
93
+ */
94
+ public String toString() { return new String(b,0,i_end); }
95
+
96
+ /**
97
+ * Returns the length of the word resulting from the stemming process.
98
+ */
99
+ public int getResultLength() { return i_end; }
100
+
101
+ /**
102
+ * Returns a reference to a character buffer containing the results of
103
+ * the stemming process. You also need to consult getResultLength()
104
+ * to determine the length of the result.
105
+ */
106
+ public char[] getResultBuffer() { return b; }
107
+
108
+ /* cons(i) is true <=> b[i] is a consonant. */
109
+
110
+ private final boolean cons(int i)
111
+ { switch (b[i])
112
+ { case 'a': case 'e': case 'i': case 'o': case 'u': return false;
113
+ case 'y': return (i==0) ? true : !cons(i-1);
114
+ default: return true;
115
+ }
116
+ }
117
+
118
+ /* m() measures the number of consonant sequences between 0 and j. if c is
119
+ a consonant sequence and v a vowel sequence, and <..> indicates arbitrary
120
+ presence,
121
+
122
+ <c><v> gives 0
123
+ <c>vc<v> gives 1
124
+ <c>vcvc<v> gives 2
125
+ <c>vcvcvc<v> gives 3
126
+ ....
127
+ */
128
+
129
+ private final int m()
130
+ { int n = 0;
131
+ int i = 0;
132
+ while(true)
133
+ { if (i > j) return n;
134
+ if (! cons(i)) break; i++;
135
+ }
136
+ i++;
137
+ while(true)
138
+ { while(true)
139
+ { if (i > j) return n;
140
+ if (cons(i)) break;
141
+ i++;
142
+ }
143
+ i++;
144
+ n++;
145
+ while(true)
146
+ { if (i > j) return n;
147
+ if (! cons(i)) break;
148
+ i++;
149
+ }
150
+ i++;
151
+ }
152
+ }
153
+
154
+ /* vowelinstem() is true <=> 0,...j contains a vowel */
155
+
156
+ private final boolean vowelinstem()
157
+ { int i; for (i = 0; i <= j; i++) if (! cons(i)) return true;
158
+ return false;
159
+ }
160
+
161
+ /* doublec(j) is true <=> j,(j-1) contain a double consonant. */
162
+
163
+ private final boolean doublec(int j)
164
+ { if (j < 1) return false;
165
+ if (b[j] != b[j-1]) return false;
166
+ return cons(j);
167
+ }
168
+
169
+ /* cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant
170
+ and also if the second c is not w,x or y. this is used when trying to
171
+ restore an e at the end of a short word. e.g.
172
+
173
+ cav(e), lov(e), hop(e), crim(e), but
174
+ snow, box, tray.
175
+
176
+ */
177
+
178
+ private final boolean cvc(int i)
179
+ { if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false;
180
+ { int ch = b[i];
181
+ if (ch == 'w' || ch == 'x' || ch == 'y') return false;
182
+ }
183
+ return true;
184
+ }
185
+
186
+ private final boolean ends(String s)
187
+ { int l = s.length();
188
+ int o = k-l+1;
189
+ if (o < 0) return false;
190
+ for (int i = 0; i < l; i++) if (b[o+i] != s.charAt(i)) return false;
191
+ j = k-l;
192
+ return true;
193
+ }
194
+
195
+ /* setto(s) sets (j+1),...k to the characters in the string s, readjusting
196
+ k. */
197
+
198
+ private final void setto(String s)
199
+ { int l = s.length();
200
+ int o = j+1;
201
+ for (int i = 0; i < l; i++) b[o+i] = s.charAt(i);
202
+ k = j+l;
203
+ }
204
+
205
+ /* r(s) is used further down. */
206
+
207
+ private final void r(String s) { if (m() > 0) setto(s); }
208
+
209
+ /* step1() gets rid of plurals and -ed or -ing. e.g.
210
+
211
+ caresses -> caress
212
+ ponies -> poni
213
+ ties -> ti
214
+ caress -> caress
215
+ cats -> cat
216
+
217
+ feed -> feed
218
+ agreed -> agree
219
+ disabled -> disable
220
+
221
+ matting -> mat
222
+ mating -> mate
223
+ meeting -> meet
224
+ milling -> mill
225
+ messing -> mess
226
+
227
+ meetings -> meet
228
+
229
+ */
230
+
231
+ private final void step1()
232
+ { if (b[k] == 's')
233
+ { if (ends("sses")) k -= 2; else
234
+ if (ends("ies")) setto("i"); else
235
+ if (b[k-1] != 's') k--;
236
+ }
237
+ if (ends("eed")) { if (m() > 0) k--; } else
238
+ if ((ends("ed") || ends("ing")) && vowelinstem())
239
+ { k = j;
240
+ if (ends("at")) setto("ate"); else
241
+ if (ends("bl")) setto("ble"); else
242
+ if (ends("iz")) setto("ize"); else
243
+ if (doublec(k))
244
+ { k--;
245
+ { int ch = b[k];
246
+ if (ch == 'l' || ch == 's' || ch == 'z') k++;
247
+ }
248
+ }
249
+ else if (m() == 1 && cvc(k)) setto("e");
250
+ }
251
+ }
252
+
253
+ /* step2() turns terminal y to i when there is another vowel in the stem. */
254
+
255
+ private final void step2() { if (ends("y") && vowelinstem()) b[k] = 'i'; }
256
+
257
+ /* step3() maps double suffices to single ones. so -ization ( = -ize plus
258
+ -ation) maps to -ize etc. note that the string before the suffix must give
259
+ m() > 0. */
260
+
261
+ private final void step3() { if (k == 0) return; /* For Bug 1 */ switch (b[k-1])
262
+ {
263
+ case 'a': if (ends("ational")) { r("ate"); break; }
264
+ if (ends("tional")) { r("tion"); break; }
265
+ break;
266
+ case 'c': if (ends("enci")) { r("ence"); break; }
267
+ if (ends("anci")) { r("ance"); break; }
268
+ break;
269
+ case 'e': if (ends("izer")) { r("ize"); break; }
270
+ break;
271
+ case 'l': if (ends("bli")) { r("ble"); break; }
272
+ if (ends("alli")) { r("al"); break; }
273
+ if (ends("entli")) { r("ent"); break; }
274
+ if (ends("eli")) { r("e"); break; }
275
+ if (ends("ousli")) { r("ous"); break; }
276
+ break;
277
+ case 'o': if (ends("ization")) { r("ize"); break; }
278
+ if (ends("ation")) { r("ate"); break; }
279
+ if (ends("ator")) { r("ate"); break; }
280
+ break;
281
+ case 's': if (ends("alism")) { r("al"); break; }
282
+ if (ends("iveness")) { r("ive"); break; }
283
+ if (ends("fulness")) { r("ful"); break; }
284
+ if (ends("ousness")) { r("ous"); break; }
285
+ break;
286
+ case 't': if (ends("aliti")) { r("al"); break; }
287
+ if (ends("iviti")) { r("ive"); break; }
288
+ if (ends("biliti")) { r("ble"); break; }
289
+ break;
290
+ case 'g': if (ends("logi")) { r("log"); break; }
291
+ } }
292
+
293
+ /* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */
294
+
295
+ private final void step4() { switch (b[k])
296
+ {
297
+ case 'e': if (ends("icate")) { r("ic"); break; }
298
+ if (ends("ative")) { r(""); break; }
299
+ if (ends("alize")) { r("al"); break; }
300
+ break;
301
+ case 'i': if (ends("iciti")) { r("ic"); break; }
302
+ break;
303
+ case 'l': if (ends("ical")) { r("ic"); break; }
304
+ if (ends("ful")) { r(""); break; }
305
+ break;
306
+ case 's': if (ends("ness")) { r(""); break; }
307
+ break;
308
+ } }
309
+
310
+ /* step5() takes off -ant, -ence etc., in context <c>vcvc<v>. */
311
+
312
+ private final void step5()
313
+ { if (k == 0) return; /* for Bug 1 */ switch (b[k-1])
314
+ { case 'a': if (ends("al")) break; return;
315
+ case 'c': if (ends("ance")) break;
316
+ if (ends("ence")) break; return;
317
+ case 'e': if (ends("er")) break; return;
318
+ case 'i': if (ends("ic")) break; return;
319
+ case 'l': if (ends("able")) break;
320
+ if (ends("ible")) break; return;
321
+ case 'n': if (ends("ant")) break;
322
+ if (ends("ement")) break;
323
+ if (ends("ment")) break;
324
+ /* element etc. not stripped before the m */
325
+ if (ends("ent")) break; return;
326
+ case 'o': if (ends("ion") && j >= 0 && (b[j] == 's' || b[j] == 't')) break;
327
+ /* j >= 0 fixes Bug 2 */
328
+ if (ends("ou")) break; return;
329
+ /* takes care of -ous */
330
+ case 's': if (ends("ism")) break; return;
331
+ case 't': if (ends("ate")) break;
332
+ if (ends("iti")) break; return;
333
+ case 'u': if (ends("ous")) break; return;
334
+ case 'v': if (ends("ive")) break; return;
335
+ case 'z': if (ends("ize")) break; return;
336
+ default: return;
337
+ }
338
+ if (m() > 1) k = j;
339
+ }
340
+
341
+ /* step6() removes a final -e if m() > 1. */
342
+
343
+ private final void step6()
344
+ { j = k;
345
+ if (b[k] == 'e')
346
+ { int a = m();
347
+ if (a > 1 || a == 1 && !cvc(k-1)) k--;
348
+ }
349
+ if (b[k] == 'l' && doublec(k) && m() > 1) k--;
350
+ }
351
+
352
+ /** Stem the word placed into the Stemmer buffer through calls to add().
353
+ * Returns true if the stemming process resulted in a word different
354
+ * from the input. You can retrieve the result with
355
+ * getResultLength()/getResultBuffer() or toString().
356
+ */
357
+ public void stem()
358
+ { k = i - 1;
359
+ if (k > 1) { step1(); step2(); step3(); step4(); step5(); step6(); }
360
+ i_end = k+1; i = 0;
361
+ }
362
+
363
+ /** Test program for demonstrating the Stemmer. It reads text from a
364
+ * a list of files, stems each word, and writes the result to standard
365
+ * output. Note that the word stemmed is expected to be in lower case:
366
+ * forcing lower case must be done outside the Stemmer class.
367
+ * Usage: Stemmer file-name file-name ...
368
+ */
369
+ public static void main(String[] args)
370
+ {
371
+ char[] w = new char[501];
372
+ Stemmer s = new Stemmer();
373
+ for (int i = 0; i < args.length; i++)
374
+ try
375
+ {
376
+ FileInputStream in = new FileInputStream(args[i]);
377
+
378
+ try
379
+ { while(true)
380
+
381
+ { int ch = in.read();
382
+ if (Character.isLetter((char) ch))
383
+ {
384
+ int j = 0;
385
+ while(true)
386
+ { ch = Character.toLowerCase((char) ch);
387
+ w[j] = (char) ch;
388
+ if (j < 500) j++;
389
+ ch = in.read();
390
+ if (!Character.isLetter((char) ch))
391
+ {
392
+ /* to test add(char ch) */
393
+ for (int c = 0; c < j; c++) s.add(w[c]);
394
+
395
+ /* or, to test add(char[] w, int j) */
396
+ /* s.add(w, j); */
397
+
398
+ s.stem();
399
+ { String u;
400
+
401
+ /* and now, to test toString() : */
402
+ u = s.toString();
403
+
404
+ /* to test getResultBuffer(), getResultLength() : */
405
+ /* u = new String(s.getResultBuffer(), 0, s.getResultLength()); */
406
+
407
+ System.out.print(u);
408
+ }
409
+ break;
410
+ }
411
+ }
412
+ }
413
+ if (ch < 0) break;
414
+ System.out.print((char)ch);
415
+ }
416
+ }
417
+ catch (IOException e)
418
+ { System.out.println("error reading " + args[i]);
419
+ break;
420
+ }
421
+ }
422
+ catch (FileNotFoundException e)
423
+ { System.out.println("file " + args[i] + " not found");
424
+ break;
425
+ }
426
+ }
427
+ }
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jruby-stemmer/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "jruby-stemmer"
8
+ gem.version = JRuby::Stemmer::VERSION
9
+ gem.authors = ["Caius Durling"]
10
+ gem.email = ["dev@caius.name"]
11
+ gem.description = %q{Native java implementation of a string stemming algorithm. JRuby replacement for `fast-stemmer` gem under MRI.}
12
+ gem.summary = %q{Fast string stemming in JRuby}
13
+ gem.homepage = "https://github.com/caius/jruby-stemmer"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.platform = "java"
21
+ gem.files << "lib/java-stemmer.jar"
22
+
23
+ gem.add_development_dependency "rake-compiler"
24
+ gem.add_development_dependency "rspec"
25
+
26
+ end
Binary file
@@ -0,0 +1,5 @@
1
+ module JRuby
2
+ module Stemmer
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ require "jruby-stemmer/version"
2
+
3
+ # Mixes in String#stem using java implementation
4
+ module JRuby
5
+ module Stemmer
6
+ require "jruby"
7
+ # include_package 'org.tartarus.martin.porter_stemmer'
8
+ require_relative "java-stemmer"
9
+
10
+ def self.stem string
11
+ stemmer = Java::OrgTartarusMartinPorter_Stemmer::Stemmer.new
12
+ java_string = string.to_java_string
13
+ stemmer.add java_string.toCharArray, java_string.length
14
+ stemmer.stem
15
+ stemmer.to_string
16
+ end
17
+
18
+ module StringStem
19
+ def stem
20
+ JRuby::Stemmer.stem(self)
21
+ end
22
+ end
23
+ String.__send__ :include, StringStem
24
+
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ require "jruby-stemmer"
2
+
3
+ describe JRuby::Stemmer do
4
+ it "stems a string" do
5
+ result = JRuby::Stemmer.stem("apple")
6
+ expect(result).to be == "appl"
7
+ end
8
+ end
9
+
10
+ describe "String" do
11
+ it "has a #stem method" do
12
+ expect("").to respond_to(:stem)
13
+ end
14
+ it "stems a string" do
15
+ expect("apple".stem).to be == "appl"
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jruby-stemmer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: java
7
+ authors:
8
+ - Caius Durling
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake-compiler
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: !binary |-
21
+ MA==
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :development
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec
34
+ version_requirements: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: !binary |-
39
+ MA==
40
+ none: false
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: !binary |-
46
+ MA==
47
+ none: false
48
+ prerelease: false
49
+ type: :development
50
+ description: Native java implementation of a string stemming algorithm. JRuby replacement for `fast-stemmer` gem under MRI.
51
+ email:
52
+ - dev@caius.name
53
+ executables: []
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - ".gitignore"
58
+ - Gemfile
59
+ - LICENSE.txt
60
+ - README.md
61
+ - Rakefile
62
+ - ext/java-stemmer/Stemmer.java
63
+ - jruby-stemmer.gemspec
64
+ - lib/java-stemmer.jar
65
+ - lib/jruby-stemmer.rb
66
+ - lib/jruby-stemmer/version.rb
67
+ - spec/stemmer_spec.rb
68
+ homepage: https://github.com/caius/jruby-stemmer
69
+ licenses: []
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: !binary |-
79
+ MA==
80
+ none: false
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: !binary |-
86
+ MA==
87
+ none: false
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.24
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Fast string stemming in JRuby
94
+ test_files:
95
+ - spec/stemmer_spec.rb