random-words 1.0.4

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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/.irbrc +4 -0
  3. data/.rspec +4 -0
  4. data/.rspec_status +39 -0
  5. data/.rubocop.yml +64 -0
  6. data/CHANGELOG.md +29 -0
  7. data/Gemfile +18 -0
  8. data/Gemfile.lock +111 -0
  9. data/README.md +90 -0
  10. data/Rakefile +85 -0
  11. data/bin/randw +334 -0
  12. data/lib/random-words/generator.rb +533 -0
  13. data/lib/random-words/string.rb +56 -0
  14. data/lib/random-words/version.rb +4 -0
  15. data/lib/random-words/words/bacon/adjectives.txt +329 -0
  16. data/lib/random-words/words/bacon/adverbs.txt +69 -0
  17. data/lib/random-words/words/bacon/articles-plural.txt +10 -0
  18. data/lib/random-words/words/bacon/articles-singular.txt +10 -0
  19. data/lib/random-words/words/bacon/clauses.txt +639 -0
  20. data/lib/random-words/words/bacon/conjunctions-subordinate.txt +29 -0
  21. data/lib/random-words/words/bacon/nouns-plural.txt +168 -0
  22. data/lib/random-words/words/bacon/nouns-singular.txt +200 -0
  23. data/lib/random-words/words/bacon/numbers.txt +21 -0
  24. data/lib/random-words/words/bacon/verbs-passive.txt +105 -0
  25. data/lib/random-words/words/bacon/verbs-plural.txt +154 -0
  26. data/lib/random-words/words/bacon/verbs-singular.txt +106 -0
  27. data/lib/random-words/words/corporate/adjectives.txt +196 -0
  28. data/lib/random-words/words/corporate/adverbs.txt +462 -0
  29. data/lib/random-words/words/corporate/articles-plural.txt +10 -0
  30. data/lib/random-words/words/corporate/articles-singular.txt +10 -0
  31. data/lib/random-words/words/corporate/clauses.txt +101 -0
  32. data/lib/random-words/words/corporate/conjunctions-subordinate.txt +29 -0
  33. data/lib/random-words/words/corporate/nouns-plural.txt +321 -0
  34. data/lib/random-words/words/corporate/nouns-singular.txt +474 -0
  35. data/lib/random-words/words/corporate/numbers.txt +21 -0
  36. data/lib/random-words/words/corporate/verbs-passive.txt +495 -0
  37. data/lib/random-words/words/corporate/verbs-plural.txt +173 -0
  38. data/lib/random-words/words/corporate/verbs-singular.txt +146 -0
  39. data/lib/random-words/words/english/adjectives.txt +325 -0
  40. data/lib/random-words/words/english/adverbs.txt +462 -0
  41. data/lib/random-words/words/english/articles-plural.txt +10 -0
  42. data/lib/random-words/words/english/articles-singular.txt +10 -0
  43. data/lib/random-words/words/english/clauses.txt +639 -0
  44. data/lib/random-words/words/english/conjunctions-subordinate.txt +29 -0
  45. data/lib/random-words/words/english/nouns-plural.txt +524 -0
  46. data/lib/random-words/words/english/nouns-singular.txt +530 -0
  47. data/lib/random-words/words/english/numbers.txt +21 -0
  48. data/lib/random-words/words/english/verbs-passive.txt +495 -0
  49. data/lib/random-words/words/english/verbs-plural.txt +325 -0
  50. data/lib/random-words/words/english/verbs-singular.txt +350 -0
  51. data/lib/random-words/words/latin/adjectives.txt +188 -0
  52. data/lib/random-words/words/latin/adverbs.txt +212 -0
  53. data/lib/random-words/words/latin/articles-plural.txt +122 -0
  54. data/lib/random-words/words/latin/articles-singular.txt +19 -0
  55. data/lib/random-words/words/latin/clauses.txt +89 -0
  56. data/lib/random-words/words/latin/conjunctions-subordinate.txt +104 -0
  57. data/lib/random-words/words/latin/nouns-plural.txt +190 -0
  58. data/lib/random-words/words/latin/nouns-singular.txt +193 -0
  59. data/lib/random-words/words/latin/numbers.txt +21 -0
  60. data/lib/random-words/words/latin/verbs-passive.txt +171 -0
  61. data/lib/random-words/words/latin/verbs-plural.txt +177 -0
  62. data/lib/random-words/words/latin/verbs-singular.txt +218 -0
  63. data/lib/random-words.rb +6 -0
  64. data/random-words.gemspec +36 -0
  65. data/src/_README.md +92 -0
  66. metadata +119 -0
@@ -0,0 +1,533 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Random Sentence Generator
5
+ # This script generates random sentences using a variety of words and structures.
6
+ # It includes nouns, verbs, adjectives, adverbs, articles, clauses, and more.
7
+ module RandomWords
8
+ # Random character, word, and sentence generator
9
+ class Generator
10
+ # @return [Array<String>] arrays of elements of speech
11
+ attr_accessor :nouns, :verbs, :passive_verbs, :adverbs, :adjectives, :articles, :clauses, :subordinate_conjunctions,
12
+ :terminators, :numbers, :plural_nouns, :plural_verbs, :plural_articles
13
+
14
+ # @return [Integer] Number of sentences in paragraphs
15
+ attr_reader :paragraph_length
16
+
17
+ # @return [Symbol] Sentence length (:short, :medium, :long, :very_long)
18
+ attr_reader :sentence_length
19
+
20
+ # @return [Symbol] Dictionary in use
21
+ attr_reader :source
22
+
23
+ # @return [Boolean] Testing mode
24
+ attr_accessor :testing
25
+
26
+ # Define the default sentence parts
27
+ # These parts will be used to generate random sentences and character strings
28
+ SENTENCE_PARTS = %w[random_article random_adjective random_noun random_adverb random_verb random_adjective
29
+ random_verb random_adverb].freeze
30
+
31
+ # Initialize the generator with a source and options
32
+ # @param source [Symbol] The source of the words (e.g., :english)
33
+ # @param _options [Hash] Options for the generator (e.g., length, paragraph_length)
34
+ # @example
35
+ # generator = RandomWords::Generator.new(:english, sentence_length: :medium, paragraph_length: 5)
36
+ # generator.source = :french
37
+ # generator.lengths = { short: 50, medium: 150 }
38
+ # generator.sentence_length = :long
39
+ # generator.paragraph_length = 3
40
+ def initialize(source = :english, options = {})
41
+ @source = source
42
+ @nouns = from_file('nouns-singular.txt')
43
+ @plural_nouns = from_file('nouns-plural.txt')
44
+ @verbs = from_file('verbs-singular.txt')
45
+ @plural_verbs = from_file('verbs-plural.txt')
46
+ @passive_verbs = from_file('verbs-passive.txt')
47
+ @adverbs = from_file('adverbs.txt')
48
+ @adjectives = from_file('adjectives.txt')
49
+ @articles = from_file('articles-singular.txt')
50
+ @plural_articles = from_file('articles-plural.txt')
51
+ @clauses = from_file('clauses.txt')
52
+ @subordinate_conjunctions = from_file('conjunctions-subordinate.txt')
53
+
54
+ @numbers = from_file('numbers.txt')
55
+
56
+ @options = {
57
+ sentence_length: :medium,
58
+ paragraph_length: 5
59
+ }
60
+ @options.merge!(options) if options.is_a?(Hash)
61
+ @sentence_length = @options[:sentence_length]
62
+ @paragraph_length = @options[:paragraph_length]
63
+ lengths
64
+ end
65
+
66
+ # Define number of sentences in paragraphs
67
+ # @param length [Integer] The number of sentences in the paragraph
68
+ def paragraph_length=(length)
69
+ raise ArgumentError, 'Paragraph length must be a positive integer' unless length.is_a?(Integer) && length.positive?
70
+
71
+ @paragraph_length = length
72
+ end
73
+
74
+ # Define sentence length
75
+ # @param length [Symbol] :short, :medium, :long, or :very_long
76
+ def sentence_length=(length)
77
+ to_set = case length.to_s
78
+ when /^s/
79
+ :short
80
+ when /^m/
81
+ :medium
82
+ when /^l/
83
+ :long
84
+ when /^v/
85
+ :very_long
86
+ else
87
+ raise ArgumentError, "Invalid length: #{length}. Use :short, :medium, :long, or :very_long."
88
+ end
89
+ @sentence_length = to_set
90
+ end
91
+
92
+ # Bad init method for testing purposes
93
+ # @!visibility private
94
+ def bad_init
95
+ @nouns = from_file('nouns-noent.txt')
96
+ end
97
+
98
+ # define all lengths for testing purposes
99
+ # @!visibility private
100
+ def define_all_lengths
101
+ @lengths = {
102
+ short: 60,
103
+ medium: 200,
104
+ long: 300,
105
+ very_long: 500
106
+ }
107
+ res = []
108
+ res << define_length(:short)
109
+ res << define_length(:medium)
110
+ res << define_length(:long)
111
+ res << define_length(:very_long)
112
+ res
113
+ end
114
+
115
+ # Define a bad length for testing purposes
116
+ # @!visibility private
117
+ def bad_length
118
+ define_length(:bad_length)
119
+ end
120
+
121
+ # Test random generators
122
+ # These methods are used to test the random generation of words and sentences
123
+ # @!visibility private
124
+ def test_random
125
+ @testing = true
126
+ res = []
127
+ res << random_noun
128
+ res << random_verb
129
+ res << random_adjective
130
+ res << random_adverb
131
+ res << random_article
132
+ res << random_article_for_noun('apple')
133
+ res << random_article_for_noun('apples')
134
+ res << random_article_for_noun('banana')
135
+ res << random_article_for_noun('bananas')
136
+ res << random_plural_article
137
+ res << random_clause
138
+ res << random_subordinate_conjunction
139
+ res << random_number_with_plural
140
+ res << random_conjunction
141
+ res << random_passive_verb
142
+ res << random_plural_noun
143
+ res << random_plural_verb
144
+ res << generate_additional_clauses.join(' ')
145
+ res
146
+ end
147
+
148
+ # Define a new source dictionary and re-initialize
149
+ def source=(new_source)
150
+ initialize(new_source)
151
+ end
152
+
153
+ # Refactored lengths and lengths= methods
154
+ # This method returns the lengths of sentences
155
+ # The default lengths are set to the following values:
156
+ # short: 60, medium: 200, long: 300, very_long: 500
157
+ def lengths
158
+ @lengths ||= { short: 60, medium: 200, long: 300, very_long: 500 }
159
+ end
160
+
161
+ # This method allows you to set new lengths for the sentences
162
+ # It merges the new lengths with the existing ones
163
+ # Example: lengths = { short: 50, medium: 150 }
164
+ # @param new_lengths [Hash] A hash containing the new lengths for the sentences
165
+ # @return [Hash] The updated lengths hash
166
+ # @example
167
+ # lengths = { short: 50, medium: 150 }
168
+ def lengths=(new_lengths)
169
+ @lengths = lengths.merge(new_lengths)
170
+ end
171
+
172
+ # Generate a random word
173
+ # @return [String] A randomly generated word
174
+ def word
175
+ generate_word
176
+ end
177
+
178
+ # Generate a set number of random words
179
+ # @param number [Integer] The number of words to generate
180
+ def words(number)
181
+ result = SENTENCE_PARTS.cycle.take(number).map { |part| send(part.to_sym) }.take(number)
182
+ result.map do |word|
183
+ word.split(/ /).last
184
+ end.join(' ').compress
185
+ end
186
+
187
+ # Generate a series of random words up to a specified length
188
+ # @param min [Integer] The minimum length of the generated string
189
+ # @param max [Integer] (Optional) The maximum length of the generated string
190
+ # @param whole_words [Boolean] (Optional) Whether to generate whole words or not
191
+ # @param dead_switch [Integer] (Optional) A counter to prevent infinite loops
192
+ # @return [String] The generated string of random words
193
+ # @example
194
+ # characters(50) # Generates a string with at least 50 characters
195
+ # characters(50, 100) # Generates a string with between 50 and 100 characters
196
+ # characters(50, whole_words: false) # Generates a string with 50 characters allowing word truncation
197
+ def characters(min, max = nil, whole_words: true, whitespace: true, dead_switch: 0)
198
+ result = ''
199
+ max ||= min
200
+ raise ArgumentError, 'Infinite loop detected' if dead_switch > 20
201
+
202
+ whole_words = false if dead_switch > 15
203
+
204
+ space = whitespace ? ' ' : ''
205
+ current_part = 0
206
+ while result.length < max && result.length < min
207
+ word = send(SENTENCE_PARTS[current_part].to_sym)
208
+ word.gsub!(/ +/, '') unless whitespace
209
+ current_part = (current_part + 1) % SENTENCE_PARTS.length
210
+ new_result = "#{result}#{space}#{word}".compress
211
+
212
+ if new_result.length > max
213
+ return handle_overflow(OverflowConfig.new(new_result, result, min, max, whole_words, whitespace,
214
+ dead_switch))
215
+ end
216
+ return new_result if new_result.length == max
217
+
218
+ result = new_result
219
+ end
220
+
221
+ result.strip
222
+ end
223
+
224
+ # Generate a random sentence
225
+ # @param length [Integer] The desired length of the sentence in characters
226
+ # @return [String] A randomly generated sentence
227
+ def sentence(length = nil)
228
+ generate_combined_sentence(length)
229
+ end
230
+
231
+ # Generate a specified number of random sentences
232
+ # @param number [Integer] The number of sentences to generate
233
+ # @return [Array] An array of generated sentences
234
+ # @example
235
+ # sentences(5) # Generates an array of 5 random sentences
236
+ def sentences(number)
237
+ Array.new(number) { generate_combined_sentence }
238
+ end
239
+
240
+ # Generate a random sentence, combining multiple sentences if necessary
241
+ # @param length [Symbol] The desired length of the sentence, :short, :medium, :long, or :very_long
242
+ # @return [String] A randomly generated sentence
243
+ # This method generates a random sentence and checks its length.
244
+ # If the length is less than the defined length, it combines it with another sentence.
245
+ # The final sentence is returned with proper capitalization and termination.
246
+ # @example
247
+ # generate_combined_sentence # Generates a combined sentence
248
+ def generate_combined_sentence(length = nil)
249
+ length ||= define_length(@sentence_length)
250
+ sentence = generate_sentence
251
+ return sentence.capitalize.compress.terminate if sentence.length > length
252
+
253
+ while sentence.length < length
254
+ # Generate a random number of sentences to combine
255
+ new_sentence = generate_sentence(length / 2)
256
+
257
+ # Combine the sentences with random conjunctions
258
+ sentence = "#{sentence.strip.no_term}, #{random_conjunction} #{new_sentence}"
259
+ end
260
+
261
+ sentence.capitalize.compress.terminate
262
+ end
263
+
264
+ # Generate a random paragraph
265
+ # @param length [Integer] The desired number of sentences in the paragraph
266
+ # @return [String] A randomly generated paragraph
267
+ # This method generates a random paragraph by combining multiple sentences.
268
+ # It uses the generate_combined_sentence method to create each sentence.
269
+ # @see #generate_combined_sentence
270
+ def paragraph(length = @paragraph_length)
271
+ sentences = []
272
+ length.times do
273
+ sentences << generate_combined_sentence
274
+ end
275
+ sentences.join(' ').strip.compress
276
+ end
277
+
278
+ private
279
+
280
+ # Handle overflow when the new result exceeds the maximum length
281
+ OverflowConfig = Struct.new(:new_result, :result, :min, :max, :whole_words, :whitespace, :dead_switch)
282
+
283
+ def handle_overflow(config)
284
+ space = config.whitespace ? ' ' : ''
285
+ needed = config.max - config.result.compress.length - space.length
286
+ config.min = config.max if config.min > config.max
287
+
288
+ if needed > 1
289
+ options = nouns_of_length(needed)
290
+ return "#{config.result}#{space}#{options.sample}".compress unless options.empty?
291
+ end
292
+
293
+ if config.whole_words
294
+ return characters(config.min, config.max, whole_words: config.whole_words, whitespace: config.whitespace,
295
+ dead_switch: config.dead_switch + 1)
296
+ end
297
+
298
+ truncated = config.new_result.compress[0...config.max]
299
+ truncated.strip if truncated.strip.length.between?(config.min, config.max)
300
+ end
301
+
302
+ # Generate a random sentence with a specified length
303
+ # @param length [Integer] The desired length of the sentence
304
+ # @return [String] A randomly generated sentence
305
+ # This method generates a random sentence with a specified length.
306
+ # It has a 20% chance of including a random number with a plural noun and a main clause.
307
+ # The sentence is constructed using various components such as nouns, verbs, adjectives, and adverbs.
308
+ # @example
309
+ # generate_sentence(100) # Generates a sentence with a length of 100 characters
310
+ # generate_sentence # Generates a sentence with the default length
311
+ def generate_sentence(length = nil)
312
+ length ||= define_length(@sentence_length)
313
+ sentence_components = []
314
+
315
+ # Randomly decide if we include a plural noun with a number
316
+ sentence_components << random_number_with_plural if roll(20) # 20% chance to include a plural noun
317
+
318
+ # Construct main clause
319
+ sentence_components << generate_main_clause
320
+
321
+ # Include any additional clauses
322
+ # sentence_components.concat(generate_additional_clauses)
323
+
324
+ # while sentence_components.join(' ').strip.length < length
325
+ # # Randomly include a subordinate conjunction
326
+ # additional_clauses = generate_additional_clauses
327
+ # sentence_components.concat(additional_clauses)
328
+ # sentence_components.map!(&:strip)
329
+ # break if sentence_components.join(' ').length >= length
330
+
331
+ # conjunction = random_subordinate_conjunction.strip
332
+ # sentence_components.unshift(conjunction.capitalize) # Place conjunction at the start
333
+ # end
334
+
335
+ # Join all parts into a single sentence
336
+ sentence_components.join(' ').strip.compress
337
+ end
338
+
339
+ # Load words from a dictionary file
340
+ # Files are plain text with one word or phrase per line
341
+ # The @source variable defines which dictionary to be used and should be defined before calling this method
342
+ # @param filename [String] The name of the file to load
343
+ # @return [Array] An array of words loaded from the file
344
+ # @example
345
+ # from_file('nouns.txt') # Loads words from words/[source]/nouns.txt
346
+ def from_file(filename)
347
+ filename = "#{filename.sub(/\.txt$/, '')}.txt"
348
+ path = File.join(__dir__, 'words', @source.to_s, filename)
349
+
350
+ path = File.join(__dir__, 'words', 'english', filename) unless File.exist?(path)
351
+
352
+ File.read(path).split("\n").map(&:strip) # Changed from split_lines to split("\n")
353
+ rescue Errno::ENOENT
354
+ warn "File not found: #{filename}"
355
+ []
356
+ end
357
+
358
+ # Convert a length symbol to a specific length value
359
+ # @param length [Symbol] The length symbol (:short, :medium, :long, or :very_long)
360
+ # @return [Integer] The corresponding length value
361
+ # @example
362
+ # define_length(:short) # Returns the length for :short
363
+ def define_length(length)
364
+ case length
365
+ when :short
366
+ @lengths[:short] || 60
367
+ when :medium
368
+ @lengths[:medium] || 200
369
+ when :long
370
+ @lengths[:long] || 300
371
+ when :very_long
372
+ @lengths[:very_long] || 500
373
+ else
374
+ raise ArgumentError, "Invalid length: #{length}. Use :short, :medium, or :long."
375
+ end
376
+ end
377
+
378
+ # Get a list of nouns matching a specific length
379
+ # @param length [Integer] The desired length of the nouns
380
+ # @return [Array] An array of nouns with the specified length
381
+ # @example
382
+ # nouns_of_length(5) # Returns an array of nouns with a length of 5 characters
383
+ def nouns_of_length(length)
384
+ nouns.select { |word| word.length == length }
385
+ end
386
+
387
+ # Generate a random conjunction
388
+ # @return [String] A randomly selected conjunction
389
+ # @example
390
+ # random_conjunction # Returns a random conjunction
391
+ def random_conjunction
392
+ %w[and or but].sample
393
+ end
394
+
395
+ # Generate a random number with a plural noun
396
+ # @return [String] A string containing a number and a plural noun
397
+ # Number names will be sourced from the numbers.txt file and provided in written not numeric form
398
+ # @example
399
+ # random_number_with_plural # Returns a string like "three cats"
400
+ def random_number_with_plural
401
+ number = numbers.sample
402
+ "#{number} #{random_plural_noun}"
403
+ end
404
+
405
+ # Generate a random noun
406
+ # @return [String] A randomly selected noun
407
+ def random_noun
408
+ nouns.sample
409
+ end
410
+
411
+ # Generate a random plural noun
412
+ # @return [String] A randomly selected plural noun
413
+ def random_plural_noun
414
+ plural_nouns.sample
415
+ end
416
+
417
+ # Generate a random verb
418
+ # @return [String] A randomly selected verb
419
+ def random_verb
420
+ verbs.sample
421
+ end
422
+
423
+ # Generate a random plural verb
424
+ # @return [String] A randomly selected plural verb
425
+ def random_plural_verb
426
+ plural_verbs.sample
427
+ end
428
+
429
+ # Generate a random passive verb
430
+ # @return [String] A randomly selected passive verb
431
+ def random_passive_verb
432
+ passive_verbs.sample
433
+ end
434
+
435
+ # Generate a random adverb
436
+ # @return [String] A randomly selected adverb
437
+ def random_adverb
438
+ adverbs.sample
439
+ end
440
+
441
+ # Generate a random adjective
442
+ # @return [String] A randomly selected adjective
443
+ def random_adjective
444
+ adjectives.sample
445
+ end
446
+
447
+ # Generate a random article
448
+ # @return [String] A randomly selected article
449
+ def random_article
450
+ articles.sample
451
+ end
452
+
453
+ # Generate a random article for a noun
454
+ # @param noun [String] The noun for which to generate an article
455
+ # @return [String] A randomly selected article for the given noun
456
+ # This method checks if the noun is plural and selects an appropriate article.
457
+ # If the noun starts with a vowel, it uses 'an' instead of 'a'.
458
+ # @example
459
+ # random_article_for_noun('apple') # Returns 'an'
460
+ def random_article_for_noun(noun)
461
+ article = plural_nouns.include?(noun) ? random_plural_article : random_article
462
+ article = 'an' if @testing
463
+ if noun.start_with?(/[aeiou]/i) && article =~ /^an?$/
464
+ article = 'an' if article == 'a'
465
+ elsif article == 'an'
466
+ article = 'a'
467
+ end
468
+ article
469
+ end
470
+
471
+ # Generate a random plural article
472
+ # @return [String] A randomly selected plural article
473
+ def random_plural_article
474
+ plural_articles.sample
475
+ end
476
+
477
+ # Generate a random clause
478
+ # @return [String] A randomly selected clause
479
+ def random_clause
480
+ clauses.sample
481
+ end
482
+
483
+ # Generate a random subordinate conjunction
484
+ # @return [String] A randomly selected subordinate conjunction
485
+ def random_subordinate_conjunction
486
+ subordinate_conjunctions.sample
487
+ end
488
+
489
+ # Generate a random main clause
490
+ # @return [String] A randomly generated main clause
491
+ # This method constructs a main clause using a random number of words.
492
+ # It randomly selects a noun, verb, adjective, and adverb to create a "coherent" sentence.
493
+ # It has a 50% chance of including a random number with a plural noun.
494
+ # It has a 20% chance of including a random clause at the end.
495
+ # @example
496
+ # generate_main_clause # Returns a random main clause
497
+ def generate_main_clause
498
+ beginning = if roll(50)
499
+ "#{random_number_with_plural} #{random_adverb} #{random_plural_verb}"
500
+ else
501
+ noun = random_noun
502
+ "#{random_article_for_noun(noun)} #{random_adjective} #{noun} #{random_adverb} #{random_verb}"
503
+ end
504
+
505
+ tail = roll(20) ? ", #{random_clause}" : ''
506
+ "#{beginning.strip}#{tail.strip}"
507
+ end
508
+
509
+ # Simplified generate_additional_clauses
510
+ def generate_additional_clauses
511
+ Array.new(rand(1..2)) { random_clause }
512
+ end
513
+
514
+ # Roll a random number to determine if an action should occur
515
+ # @param percent [Integer] 1-100 percent chance of the action occurring (1-100)
516
+ # @return [Boolean] True if the action occurs, false otherwise
517
+ # @example
518
+ # roll(50) # 50% chance of returning true
519
+ def roll(percent)
520
+ rand(1..100) <= percent
521
+ end
522
+
523
+ # Generate a random word
524
+ # @return [String] A randomly generated word
525
+ # This method constructs a random word using various components such as articles, adjectives, nouns, verbs, and adverbs.
526
+ # It randomly decides whether to include each component based on a 50% chance.
527
+ # @example
528
+ # generate_word # Returns a random word
529
+ def generate_word
530
+ send(SENTENCE_PARTS.sample)
531
+ end
532
+ end
533
+ end
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # String extensions for RandomWords
5
+ # This module extends the String class with additional methods for cleaning,
6
+ # compressing, and manipulating strings.
7
+ #
8
+ # @example
9
+ # str = " Hello, World! "
10
+ # str.clean # => "Hello World"
11
+ # str.compress # => "Hello World"
12
+ # str.terminate # => "Hello World."
13
+ #
14
+ class ::String
15
+ # Remove unwanted characters and whitespace from a string.
16
+ # @return [String] The string with unwanted characters removed.
17
+ # @example
18
+ # "Hello, World!".clean # => "Hello World"
19
+ #
20
+ # @return [String] The cleaned string.
21
+ def clean
22
+ gsub(/[^-a-zA-Z0-9\s]/, '').strip
23
+ end
24
+
25
+ # Split a string by newlines, clean each line, and remove empty lines.
26
+ # @return [Array<String>] The string split into lines, cleaned, and empty lines removed.
27
+ # @example
28
+ # "Hello, World!\n\nThis is a test.".split_lines # => ["Hello World", "This is a test"]
29
+ #
30
+ def split_lines
31
+ strip.split("\n").map(&:clean).reject(&:empty?)
32
+ end
33
+
34
+ # Compress multiple spaces into a single space and remove leading/trailing spaces.
35
+ # @return [String] The string with extra spaces compressed.
36
+ def compress
37
+ gsub(/\s+/, ' ').strip
38
+ end
39
+
40
+ # Terminate a string with a random punctuation mark.
41
+ # @return [String] The string with a random punctuation mark at the end.
42
+ # @example
43
+ # "Hello World".terminate # => "Hello World."
44
+ #
45
+ def terminate
46
+ terminators = %w[. . . ! ! ?]
47
+ terminator = terminators.sample
48
+ sub(/[.!?;,-]*$/, terminator)
49
+ end
50
+
51
+ # Remove any punctuation mark from the end of a string.
52
+ # @return [String] The string with the last punctuation mark removed.
53
+ def no_term
54
+ sub(/[.!?;,-]*$/, '')
55
+ end
56
+ end
@@ -0,0 +1,4 @@
1
+ module RandomWords
2
+ # The version of the RandomWords gem.
3
+ VERSION = '1.0.4'
4
+ end