glossa 1.0.1 → 1.0.3

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/glossa/language.rb +314 -0
  3. data/lib/glossa.rb +2 -312
  4. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d95abe526ac1d302f6a15983c96abb8abd8513a
4
- data.tar.gz: 7a16c7b7576caa1a7652300af8b8f1be063abb21
3
+ metadata.gz: 2b406d8728b2b832e70c3aefc528020eb5489c53
4
+ data.tar.gz: 6ad10f3b86df8dc9d899618e2c4c8635e9ba4230
5
5
  SHA512:
6
- metadata.gz: 61489793e6306cd7a57c5cfefc7405f552b7a005ff88db37ac22682e3bd44b3b9108e727c1e4b66565c6c1ec07dbc76d7f983bdd6af6e85b0907599a8d3d358f
7
- data.tar.gz: a3461b9ad1c714787180f340eae82f676bd6d08263f9baa83c6ae251d9bdaf7d368a7e675610f23aa6b8b76aba280cf25b45dee02937f7f9b2e3560a62a17224
6
+ metadata.gz: 04e73fdf24aa45f3faf3b1c93c53296e5aaeccb4be50085bfcbd13801032402c9afad2feb7300a59a904afeb2da5df9be24f99b9fabc107c9b8f07d1179f69cd
7
+ data.tar.gz: cc25218879756c1abe1bfa35cea4d5b24a022f6e0520e1a7d6bb5fd08099be14e944f9dfae2d4bc595814f0ac99e78daec13834f312ca4c94126898d74954c57
@@ -0,0 +1,314 @@
1
+ class Glossa::Language
2
+ attr_accessor :phonemes, :structure, :exponent, :restricts, :cortho, :vortho, :noortho, :nomorph, :nowordpool, :minsyll, :maxsyll, :morphemes, :words, :names, :genitive, :definitive, :joiner, :maxchar, :minchar
3
+
4
+ def initialize(random = false, options = nil)
5
+ if random
6
+ @phonemes = {
7
+ "C" => shuffle(choose(Glossa::CON_SETS, 2)[:C]),
8
+ "V" => shuffle(choose(Glossa::VOW_SETS, 2)[:V]),
9
+ "L" => shuffle(choose(Glossa::L_SETS, 2)[:L]),
10
+ "S" => shuffle(choose(Glossa::S_SETS, 2)[:S]),
11
+ "F" => shuffle(choose(Glossa::F_SETS, 2)[:F])
12
+ }
13
+ @noortho = false
14
+ @nomorph = false
15
+ @nowordpool = false
16
+ @structure = choose(Glossa::SYLL_STRUCTS)
17
+ @exponent = rand(1..3) # a larger exponent means less variation when randomly choosing some elements
18
+ @restricts = Glossa::RESTRICT_SETS[2][:res]
19
+ @cortho = choose(Glossa::C_ORTH_SETS, 2)[:orth]
20
+ @vortho = choose(Glossa::V_ORTH_SETS, 2)[:orth]
21
+ @morphemes = {}
22
+ @words = {}
23
+ @names = []
24
+ @joiner = choose(' -')
25
+ @maxchar = rand(10...15)
26
+ @minchar = rand(3...5)
27
+ @minsyll = rand(1...3)
28
+ @maxsyll = rand(@minsyll + 1...7)
29
+
30
+ if @structure.length < 3
31
+ @minsyll += 1;
32
+ end
33
+ else
34
+ options ||= {}
35
+ @phonemes = options[:phonemes] || {
36
+ "C" => "ptkmnls",
37
+ "V" => "aeiou",
38
+ "S" => "s",
39
+ "F" => "mn",
40
+ "L" => "rl"
41
+ }
42
+ @structure = options[:structure] || "CVC"
43
+ @exponent = options[:exponent] || 2
44
+ @restricts = options[:restricts] || []
45
+ @cortho = options[:cortho] || {}
46
+ @vortho = options[:vortho] || {}
47
+ @noortho = options[:noortho] || true
48
+ @nomorph = options[:nomorph] || true
49
+ @nowordpool = options[:nowordpool] || true
50
+ @minsyll = options[:minsyll] || 1
51
+ @maxsyll = options[:maxsyll] || 1
52
+ @morphemes = options[:morphemes] || {}
53
+ @words = options[:words] || {}
54
+ @names = options[:names] || []
55
+ @joiner = options[:joiner] || ' '
56
+ @maxchar = options[:maxchar] || 12
57
+ @minchar = options[:minchar] || 5
58
+ end
59
+
60
+ @genitive = get_morpheme('of')
61
+ @definitive = get_morpheme('the')
62
+ end
63
+
64
+ ##
65
+ # Takes an array and picks a semi-random element, with the first
66
+ # elements weighted more frequently the the last elements by using
67
+ # the power of a given exponent.
68
+ def choose(list, exponent = 1)
69
+ listIndex = ((rand ** exponent) * list.length).floor
70
+
71
+ list[listIndex]
72
+ end
73
+
74
+ ##
75
+ # Takes an array or string and shuffles it into a random order.
76
+ def shuffle(list)
77
+ is_string = list.is_a? String
78
+ l = is_string ? list.chars : list
79
+ new_list = l.dup
80
+
81
+ i = 0;
82
+ l.each do |item|
83
+ tmp = item
84
+ rand_index = rand(i)
85
+ new_list[i] = new_list[rand_index]
86
+ new_list[rand_index] = tmp
87
+ i += 1;
88
+ end
89
+
90
+ if is_string
91
+ return new_list.join
92
+ else
93
+ return new_list
94
+ end
95
+ end
96
+
97
+ ##
98
+ # Takes an array of strings and an optional joiner string
99
+ # and concatenates them into a single string
100
+ def join(list, sep = '')
101
+ return '' if list.length == 0
102
+ first_word = list.shift
103
+ list.each do |item|
104
+ first_word << sep << item
105
+ end
106
+
107
+ first_word
108
+ end
109
+
110
+ ##
111
+ # Takes an array of phonetic syllables, and spells them using the languages orthography
112
+ def spell(syllables)
113
+ return syllables if self.noortho
114
+ s = syllables.chars
115
+ word = ''
116
+ s.each do |syllable|
117
+ if self.cortho[syllable]
118
+ word << self.cortho[syllable]
119
+ elsif self.vortho[syllable]
120
+ word << self.vortho[syllable]
121
+ elsif Glossa::DEFAULT_ORTHO[syllable]
122
+ word << Glossa::DEFAULT_ORTHO[syllable]
123
+ else
124
+ word << syllable
125
+ end
126
+ end
127
+ word
128
+ end
129
+
130
+ ##
131
+ # Creates a spelled (see the spell() method) syllable, according to
132
+ # the language's syllable structure. It does this by selecting a semi-random
133
+ # phonetic letter for the appropriate phoneme type in the structure, making sure
134
+ # that it doesn't conflict with a restricted pattern, and then spells the
135
+ # phonetic word according to the language's orthography.
136
+ def make_syllable
137
+ structure = self.structure.chars
138
+ while true
139
+ syll = ''
140
+ structure.each do |ptype|
141
+ # If the char is '?', skip with 50% chance to remove last character
142
+ # (think RegEx usage of '?')
143
+ if ptype == '?'
144
+ if rand < 0.5
145
+ syll = syll[0...syll.length - 1]
146
+ end
147
+ next
148
+ end
149
+
150
+ syll << choose(self.phonemes[ptype], self.exponent)
151
+ end
152
+
153
+ # Make sure this syllable doesn't violate a restriction
154
+ bad = false
155
+ self.restricts.each do |regex|
156
+ if regex =~ syll
157
+ bad = true
158
+ break
159
+ end
160
+ end
161
+ next if bad
162
+
163
+ return spell(syll)
164
+ end
165
+ end
166
+
167
+ ##
168
+ # The lowest common-denominator "word" that we will store for our language.
169
+ # Morphemes are the smallest unit of language that has a meaning.
170
+ # A "morpheme," in this sense, is a unique syllable (spelled according to our orthography)
171
+ # with a type (key). Whenever a morpheme is created, we store it in the class instance,
172
+ # so as to make sure we don't create duplicates. Morphemes comprise words.
173
+ def get_morpheme(key = '')
174
+ return make_syllable if self.nomorph
175
+
176
+ # make_word will sometimes pass in nil
177
+ if key.nil?
178
+ key = ''
179
+ end
180
+
181
+ # Use the morphemes we've already made for this kind of word if possible
182
+ list = self.morphemes[key] || []
183
+
184
+ # If a key is not specified, make 10 generic morphemes
185
+ # otherwise, just make one new one
186
+ extras = key == '' ? 10 : 1
187
+
188
+ while true
189
+ # As more morphemes are created, there is a
190
+ # diminishing chance that a new one will be created.
191
+ n = rand(list.length + extras)
192
+ return list[n] if list[n]
193
+
194
+ # An existing morpheme was not selected, so create a new one
195
+ morph = make_syllable
196
+
197
+ # No duplicates!
198
+ bad = false
199
+ self.morphemes.each do |k|
200
+ next if self.morphemes[k].nil?
201
+ if self.morphemes[k].include? morph
202
+ bad = true
203
+ break
204
+ end
205
+ end
206
+ next if bad
207
+ list << morph
208
+ self.morphemes[key] = list
209
+
210
+ return morph
211
+ end
212
+ end
213
+
214
+ ##
215
+ # Given the min- and max-syllables for our language, create a new
216
+ # word out of a random number of morphemes.
217
+ def make_word(key)
218
+ num_sylls = rand(self.minsyll..self.maxsyll)
219
+ word = ''
220
+ keys = []
221
+
222
+ # If a key is defined, then select one of the syllables
223
+ # to have a morpheme of that type.
224
+ keys[rand(num_sylls)] = key
225
+ num_sylls.times { |i| word << get_morpheme(keys[i]) }
226
+
227
+ word
228
+ end
229
+
230
+ ##
231
+ # This method has a chance to use an existing word, or create a new
232
+ # one of the type (key) specified using the make_word method. If a
233
+ # new word is created, it will make sure that it is not duplicating
234
+ # an existing word, and then add it to the list of stored words.
235
+ def get_word(key = '')
236
+ words = self.words[key] || []
237
+ extras = key == '' ? 2 : 3
238
+
239
+ while true
240
+ n = rand(words.length + extras)
241
+ existing_word = words[n]
242
+ return existing_word if existing_word
243
+
244
+ new_word = make_word(key)
245
+ bad = false
246
+ self.words.each do |word|
247
+ if word.include? new_word
248
+ bad = true
249
+ break
250
+ end
251
+ end
252
+ next if bad
253
+ words << new_word
254
+ self.words[key] = words
255
+
256
+ return new_word
257
+ end
258
+ end
259
+
260
+ ##
261
+ # A wrapper with some additional logic around the get_word method.
262
+ # make_name will create a name, using get_word (so the words created
263
+ # to make up the name will be saved by the specified key), and have
264
+ # a 50% chance to add an additional word, and potentially the genitive
265
+ # and definitive words. After checking to make sure that it's an ok size
266
+ # and isn't already used, it saves and returns the name
267
+ def make_name(key = '')
268
+ ## If you don't dup these, words will get concatenated onto them during the join process
269
+ genitive = self.genitive.dup
270
+ definitive = self.definitive.dup
271
+
272
+ while true
273
+ # 50% chance that the name will be a single word, 50% chance that it will be two words combined somehow
274
+ name = rand < 0.5 ? get_word(key) : nil
275
+ if name.nil?
276
+ # 60% chance that each word will use the same key as invoked
277
+ w1_key = rand < 0.6 ? key : ''
278
+ w1 = get_word(w1_key).capitalize
279
+ w2_key = rand < 0.6 ? key : ''
280
+ w2 = get_word(w2_key).capitalize
281
+
282
+ # 50% chance to be joined without the lang's genitive word
283
+ if rand > 0.5
284
+ name = join([w1, w2], self.joiner)
285
+ else
286
+ name = join([w1, genitive, w2], self.joiner)
287
+ end
288
+ end
289
+
290
+ # 10% to prefix with definitive
291
+ name = join([definitive, name], self.joiner) if rand < 0.1
292
+
293
+ # Generate another one if this doesn't meet the min- or maxchar reqs
294
+ next if (name.length < self.minchar) || (name.length > self.maxchar)
295
+
296
+ name.capitalize!
297
+
298
+ # Check to see if this string has already been generated
299
+ used = false
300
+ self.names.each do |lang_name|
301
+ if (name.include? lang_name) || (lang_name.include? name)
302
+ used = true
303
+ break
304
+ end
305
+ end
306
+
307
+ # Start over if this name exists already
308
+ next if used
309
+
310
+ self.names << name
311
+ return name
312
+ end
313
+ end
314
+ end
data/lib/glossa.rb CHANGED
@@ -256,316 +256,6 @@ module Glossa
256
256
  :res => [/[sʃf][sʃ]/, /(.)\1/, /[rl][rl]/]
257
257
  }
258
258
  ]
259
+ end
259
260
 
260
- class Language
261
- attr_accessor :phonemes, :structure, :exponent, :restricts, :cortho, :vortho, :noortho, :nomorph, :nowordpool, :minsyll, :maxsyll, :morphemes, :words, :names, :genitive, :definitive, :joiner, :maxchar, :minchar
262
-
263
- def initialize(random = false, options = nil)
264
- if random
265
- @phonemes = {
266
- "C" => shuffle(choose(CON_SETS, 2)[:C]),
267
- "V" => shuffle(choose(VOW_SETS, 2)[:V]),
268
- "L" => shuffle(choose(L_SETS, 2)[:L]),
269
- "S" => shuffle(choose(S_SETS, 2)[:S]),
270
- "F" => shuffle(choose(F_SETS, 2)[:F])
271
- }
272
- @noortho = false
273
- @nomorph = false
274
- @nowordpool = false
275
- @structure = choose(SYLL_STRUCTS)
276
- @exponent = rand(1..3)
277
- @restricts = RESTRICT_SETS[2][:res]
278
- @cortho = choose(C_ORTH_SETS, 2)[:orth]
279
- @vortho = choose(V_ORTH_SETS, 2)[:orth]
280
- @morphemes = {}
281
- @words = {}
282
- @names = []
283
- @joiner = choose(' -')
284
- @maxchar = rand(10...15)
285
- @minchar = rand(3...5)
286
- @minsyll = rand(1...3)
287
- @maxsyll = rand(@minsyll + 1...7)
288
-
289
- if @structure.length < 3
290
- @minsyll += 1;
291
- end
292
- else
293
- options ||= {}
294
- @phonemes = options[:phonemes] || {
295
- "C" => "ptkmnls",
296
- "V" => "aeiou",
297
- "S" => "s",
298
- "F" => "mn",
299
- "L" => "rl"
300
- }
301
- @structure = options[:structure] || "CVC"
302
- @exponent = options[:exponent] || 2
303
- @restricts = options[:restricts] || []
304
- @cortho = options[:cortho] || {}
305
- @vortho = options[:vortho] || {}
306
- @noortho = options[:noortho] || true
307
- @nomorph = options[:nomorph] || true
308
- @nowordpool = options[:nowordpool] || true
309
- @minsyll = options[:minsyll] || 1
310
- @maxsyll = options[:maxsyll] || 1
311
- @morphemes = options[:morphemes] || {}
312
- @words = options[:words] || {}
313
- @names = options[:names] || []
314
- @joiner = options[:joiner] || ' '
315
- @maxchar = options[:maxchar] || 12
316
- @minchar = options[:minchar] || 5
317
- end
318
-
319
- @genitive = get_morpheme('of')
320
- @definitive = get_morpheme('the')
321
- end
322
-
323
- ##
324
- # Takes an array and picks a semi-random element, with the first
325
- # elements weighted more frequently the the last elements by using
326
- # the power of a given exponent.
327
- def choose(list, exponent = 1)
328
- listIndex = ((rand ** exponent) * list.length).floor
329
-
330
- list[listIndex]
331
- end
332
-
333
- ##
334
- # This is already how rand works? Need to verify
335
- def rand_range(lo, hi = nil)
336
- if hi.nil?
337
- hi = lo
338
- lo = 0
339
- end
340
-
341
- (rand * (hi - lo) + lo).floor
342
- end
343
-
344
- ##
345
- # Takes an array or string and shuffles it into a random order.
346
- def shuffle(list)
347
- is_string = list.is_a? String
348
- l = is_string ? list.chars : list
349
- new_list = l.dup
350
-
351
- i = 0;
352
- l.each do |item|
353
- tmp = item
354
- rand_index = rand(i)
355
- new_list[i] = new_list[rand_index]
356
- new_list[rand_index] = tmp
357
- i += 1;
358
- end
359
-
360
- if is_string
361
- return new_list.join
362
- else
363
- return new_list
364
- end
365
- end
366
-
367
- ##
368
- # Takes an array of strings and an optional joiner string
369
- # and concatenates them into a single string
370
- def join(list, sep = '')
371
- return '' if list.length == 0
372
- first_word = list.shift
373
- list.each do |item|
374
- first_word << sep << item
375
- end
376
-
377
- first_word
378
- end
379
-
380
- ##
381
- # Takes an array of phonetic syllables, and spells it using the languages orthography
382
- def spell(syllables)
383
- return syllables if self.noortho
384
- s = syllables.chars
385
- word = ''
386
- s.each do |syllable|
387
- if self.cortho[syllable]
388
- word << self.cortho[syllable]
389
- elsif self.vortho[syllable]
390
- word << self.vortho[syllable]
391
- elsif DEFAULT_ORTHO[syllable]
392
- word << DEFAULT_ORTHO[syllable]
393
- else
394
- word << syllable
395
- end
396
- end
397
- word
398
- end
399
-
400
- ##
401
- # Creates a spelled (see the spell() method) syllable, according to
402
- # the language's syllable structure. It does this by selecting a semi-random
403
- # phonetic letter for the appropriate phoneme type in the structure, making sure
404
- # that it doesn't conflict with a restricted pattern, and then spells the
405
- # phonetic word according to the language's orthography.
406
- def make_syllable
407
- structure = self.structure.chars
408
- while true
409
- syll = ''
410
- structure.each do |ptype|
411
- # If the char is '?', skip with 50% chance to remove last character
412
- if ptype == '?'
413
- if rand < 0.5
414
- syll = syll[0...syll.length - 1]
415
- end
416
- next
417
- end
418
-
419
- syll << choose(self.phonemes[ptype], self.exponent)
420
- end
421
- bad = false
422
- self.restricts.each do |regex|
423
- if regex =~ syll
424
- bad = true
425
- break
426
- end
427
- end
428
- next if bad
429
-
430
- return spell(syll)
431
- end
432
- end
433
-
434
- ##
435
- # The lowest common-denominator "word" that we will store for our language.
436
- # Morphemes are the smallest unit of language that has a meaning.
437
- # A "morpheme," in this sense, is a unique syllable (spelled according to our orthography)
438
- # with a type (key). Whenever a morpheme is created, we store it in the class instance,
439
- # so as to make sure we don't create duplicates. Morphemes comprise words.
440
- def get_morpheme(key = '')
441
- return make_syllable if self.nomorph
442
-
443
- # Use the morphemes we've already made for this kind of word if possible
444
- list = self.morphemes[key] || []
445
-
446
- # If a key is not specified, make 10 generic morphemes
447
- # otherwise, just make one new one
448
- extras = key == '' ? 10 : 1
449
-
450
- while true
451
- # As more morphemes are created, there is a
452
- # diminishing chance that a new one will be created.
453
- n = rand_range(list.length + extras)
454
- return list[n] if list[n]
455
-
456
- morph = make_syllable
457
-
458
- # No duplicates!
459
- bad = false
460
- self.morphemes.each do |k|
461
- next if self.morphemes[k].nil?
462
- if self.morphemes[k].include? morph
463
- bad = true
464
- break
465
- end
466
- end
467
- next if bad
468
- list << morph
469
- self.morphemes[key] = list
470
-
471
- return morph
472
- end
473
- end
474
-
475
- ##
476
- # Given the min- and max-syllables for our language, create a new
477
- # word out of a random number of morphemes.
478
- def make_word(key)
479
- num_sylls = rand_range(self.minsyll, self.maxsyll + 1)
480
- word = ''
481
- keys = []
482
-
483
- # If a key is defined, then select one of the syllables
484
- # to have a morpheme of that type.
485
- keys[rand_range(num_sylls)] = key
486
- num_sylls.times { |i| word << get_morpheme(keys[i]) }
487
-
488
- word
489
- end
490
-
491
- ##
492
- # This method has a chance to use an existing word, or create a new
493
- # one of the type (key) specified using the make_word method. If a
494
- # new word is created, it will make sure that it is not duplicating
495
- # an existing word, and then add it to the list of stored words.
496
- def get_word(key = '')
497
- words = self.words[key] || []
498
- extras = key == '' ? 2 : 3
499
-
500
- while true
501
- n = rand_range(words.length + extras)
502
- existing_word = words[n]
503
- return existing_word if existing_word
504
-
505
- new_word = make_word(key)
506
- bad = false
507
- self.words.each do |word|
508
- if word.include? new_word
509
- bad = true
510
- break
511
- end
512
- end
513
- next if bad
514
- words << new_word
515
- self.words[key] = words
516
-
517
- return new_word
518
- end
519
- end
520
-
521
- ##
522
- # A wrapper with some additional logic around the get_word method.
523
- # make_name will create a name, using get_word (so the words created
524
- # to make up the name will be saved by the specified key), and have
525
- # a 50% chance to add an additional word, and potentially the genitive
526
- # and definitive words. After checking to make sure that it's an ok size
527
- # and isn't already used, it saves and returns the name
528
- def make_name(key = '')
529
- ## If you don't dup these, words will get concatenated onto them during the join process
530
- genitive = self.genitive.dup
531
- definitive = self.definitive.dup
532
- puts self.definitive
533
- while true
534
- # 50% chance that the name will be a single word, 50% chance that it will be two words combined somehow
535
- name = rand < 0.5 ? get_word(key) : nil
536
- if name.nil?
537
- # 60% chance that each word will use the same key as invoked
538
- w1_key = rand < 0.6 ? key : ''
539
- w1 = get_word(w1_key).capitalize
540
- w2_key = rand < 0.6 ? key : ''
541
- w2 = get_word(w2_key).capitalize
542
-
543
- # 50% chance to be joined without the lang's genitive word
544
- if rand > 0.5
545
- name = join([w1, w2], self.joiner)
546
- else
547
- name = join([w1, genitive, w2], self.joiner)
548
- end
549
- end
550
-
551
- # 10% to prefix with definitive
552
- name = join([definitive, name], self.joiner) if rand < 0.1
553
- puts self.definitive
554
- next if (name.length < self.minchar) || (name.length > self.maxchar)
555
-
556
- used = false
557
- self.names.each do |lang_name|
558
- if (name.include? lang_name) || (lang_name.include? name)
559
- used = true
560
- break
561
- end
562
- end
563
-
564
- next if used
565
-
566
- self.names << name.capitalize
567
- return name.capitalize
568
- end
569
- end
570
- end
571
- end
261
+ require "glossa/language"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glossa
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Franklin
@@ -10,14 +10,17 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2017-03-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: glossa is a tool for creating simple naming language generators (which
14
- can in turn generate names)
13
+ description: |-
14
+ Glossa is a tool for creating simple naming language generators (which can in turn generate names).
15
+
16
+ Note: Version 1.0.0 is an (almost) direct port of [mewo2's JavaScript naming-language generator](https://github.com/mewo2/naming-language). These initial ideas are his, and I have changed very little of the actual inner-workings (other than basically turn it into a class). I would _*highly*_ encourage everybody to go and checkout his original repo (link above), [read his documentation on how the language generator works](http://mewo2.com/notes/naming-language/), and [follow @unchartedatlas](https://twitter.com/unchartedatlas)
15
17
  email: jacob.d.franklin@gmail.com
16
18
  executables: []
17
19
  extensions: []
18
20
  extra_rdoc_files: []
19
21
  files:
20
22
  - lib/glossa.rb
23
+ - lib/glossa/language.rb
21
24
  homepage: http://rubygems.org/gems/glossa
22
25
  licenses:
23
26
  - MIT
@@ -41,5 +44,5 @@ rubyforge_project:
41
44
  rubygems_version: 2.6.8
42
45
  signing_key:
43
46
  specification_version: 4
44
- summary: A random naming language generator generator
47
+ summary: A random naming language generator
45
48
  test_files: []