random-words 1.0.5 → 1.0.7

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec_status +166 -39
  3. data/.rubocop.yml +4 -0
  4. data/.rubocop_todo.yml +313 -0
  5. data/CHANGELOG.md +67 -0
  6. data/Gemfile +15 -12
  7. data/Gemfile.lock +46 -26
  8. data/README.md +208 -15
  9. data/bin/randw +258 -92
  10. data/lib/random-words/array.rb +71 -0
  11. data/lib/random-words/config.rb +254 -0
  12. data/lib/random-words/generator.rb +257 -94
  13. data/lib/random-words/hash.rb +16 -0
  14. data/lib/random-words/html2markdown.rb +205 -0
  15. data/lib/random-words/lorem-markdown.rb +397 -0
  16. data/lib/random-words/number-to-word.rb +139 -0
  17. data/lib/random-words/source.rb +106 -0
  18. data/lib/random-words/string.rb +224 -45
  19. data/lib/random-words/table-cleanup.rb +210 -0
  20. data/lib/random-words/version.rb +1 -1
  21. data/lib/random-words/words/1984/adjectives.txt +103 -0
  22. data/lib/random-words/words/1984/adverbs.txt +92 -0
  23. data/lib/random-words/words/1984/articles-plural.txt +10 -0
  24. data/lib/random-words/words/1984/articles-singular.txt +10 -0
  25. data/lib/random-words/words/1984/clauses.txt +79 -0
  26. data/lib/random-words/words/1984/config.yml +4 -0
  27. data/lib/random-words/words/1984/conjunctions-coordinating.txt +20 -0
  28. data/lib/random-words/words/1984/conjunctions-subordinate.txt +29 -0
  29. data/lib/random-words/words/1984/names.txt +12 -0
  30. data/lib/random-words/words/1984/nouns-plural.txt +89 -0
  31. data/lib/random-words/words/1984/nouns-singular.txt +74 -0
  32. data/lib/random-words/words/1984/numbers.yml +5 -0
  33. data/lib/random-words/words/1984/phrases.txt +16 -0
  34. data/lib/random-words/words/1984/prepositions.txt +89 -0
  35. data/lib/random-words/words/1984/terminators.txt +16 -0
  36. data/lib/random-words/words/1984/verbs-passive.txt +83 -0
  37. data/lib/random-words/words/1984/verbs-plural.txt +91 -0
  38. data/lib/random-words/words/1984/verbs-singular.txt +110 -0
  39. data/lib/random-words/words/alice/adjectives.txt +80 -0
  40. data/lib/random-words/words/alice/adverbs.txt +87 -0
  41. data/lib/random-words/words/alice/articles-plural.txt +10 -0
  42. data/lib/random-words/words/alice/articles-singular.txt +10 -0
  43. data/lib/random-words/words/alice/clauses.txt +81 -0
  44. data/lib/random-words/words/alice/config.yml +4 -0
  45. data/lib/random-words/words/alice/conjunctions-coordinating.txt +20 -0
  46. data/lib/random-words/words/alice/conjunctions-subordinate.txt +29 -0
  47. data/lib/random-words/words/alice/names.txt +10 -0
  48. data/lib/random-words/words/alice/nouns-plural.txt +95 -0
  49. data/lib/random-words/words/alice/nouns-singular.txt +82 -0
  50. data/lib/random-words/words/alice/numbers.yml +5 -0
  51. data/lib/random-words/words/alice/phrases.txt +16 -0
  52. data/lib/random-words/words/alice/prepositions.txt +45 -0
  53. data/lib/random-words/words/alice/terminators.txt +16 -0
  54. data/lib/random-words/words/alice/verbs-passive.txt +495 -0
  55. data/lib/random-words/words/alice/verbs-plural.txt +115 -0
  56. data/lib/random-words/words/alice/verbs-singular.txt +97 -0
  57. data/lib/random-words/words/bacon/clauses.txt +592 -592
  58. data/lib/random-words/words/bacon/config.yml +4 -0
  59. data/lib/random-words/words/bacon/conjunctions-coordinating.txt +20 -0
  60. data/lib/random-words/words/bacon/names.txt +54 -0
  61. data/lib/random-words/words/bacon/numbers.yml +5 -0
  62. data/lib/random-words/words/bacon/phrases.txt +20 -0
  63. data/lib/random-words/words/bacon/prepositions.txt +45 -0
  64. data/lib/random-words/words/bacon/terminators.txt +16 -0
  65. data/lib/random-words/words/corporate/config.yml +4 -0
  66. data/lib/random-words/words/corporate/conjunctions-coordinating.txt +20 -0
  67. data/lib/random-words/words/corporate/names.txt +74 -0
  68. data/lib/random-words/words/corporate/numbers.yml +5 -0
  69. data/lib/random-words/words/corporate/phrases.txt +29 -0
  70. data/lib/random-words/words/corporate/prepositions.txt +45 -0
  71. data/lib/random-words/words/corporate/terminators.txt +16 -0
  72. data/lib/random-words/words/doctor/adjectives.txt +92 -0
  73. data/lib/random-words/words/doctor/adverbs.txt +92 -0
  74. data/lib/random-words/words/doctor/articles-plural.txt +10 -0
  75. data/lib/random-words/words/doctor/articles-singular.txt +10 -0
  76. data/lib/random-words/words/doctor/clauses.txt +83 -0
  77. data/lib/random-words/words/doctor/config.yml +10 -0
  78. data/lib/random-words/words/doctor/conjunctions-coordinating.txt +20 -0
  79. data/lib/random-words/words/doctor/conjunctions-subordinate.txt +29 -0
  80. data/lib/random-words/words/doctor/names.txt +74 -0
  81. data/lib/random-words/words/doctor/nouns-plural.txt +84 -0
  82. data/lib/random-words/words/doctor/nouns-singular.txt +84 -0
  83. data/lib/random-words/words/doctor/numbers.yml +5 -0
  84. data/lib/random-words/words/doctor/phrases.txt +29 -0
  85. data/lib/random-words/words/doctor/prepositions.txt +45 -0
  86. data/lib/random-words/words/doctor/terminators.txt +16 -0
  87. data/lib/random-words/words/doctor/verbs-passive.txt +83 -0
  88. data/lib/random-words/words/doctor/verbs-plural.txt +88 -0
  89. data/lib/random-words/words/doctor/verbs-singular.txt +83 -0
  90. data/lib/random-words/words/english/clauses.txt +592 -592
  91. data/lib/random-words/words/english/config.yml +4 -0
  92. data/lib/random-words/words/english/conjunctions-coordinating.txt +20 -0
  93. data/lib/random-words/words/english/names.txt +74 -0
  94. data/lib/random-words/words/english/numbers.yml +5 -0
  95. data/lib/random-words/words/english/phrases.txt +29 -0
  96. data/lib/random-words/words/english/prepositions.txt +45 -0
  97. data/lib/random-words/words/english/terminators.txt +16 -0
  98. data/lib/random-words/words/english/verbs-plural.txt +1 -0
  99. data/lib/random-words/words/english/verbs-singular.txt +1 -0
  100. data/lib/random-words/words/foulmouth/adjectives.txt +89 -0
  101. data/lib/random-words/words/foulmouth/adverbs.txt +97 -0
  102. data/lib/random-words/words/foulmouth/articles-plural.txt +12 -0
  103. data/lib/random-words/words/foulmouth/articles-singular.txt +11 -0
  104. data/lib/random-words/words/foulmouth/clauses.txt +74 -0
  105. data/lib/random-words/words/foulmouth/config.yml +4 -0
  106. data/lib/random-words/words/foulmouth/conjunctions-coordinating.txt +20 -0
  107. data/lib/random-words/words/foulmouth/conjunctions-subordinate.txt +29 -0
  108. data/lib/random-words/words/foulmouth/names.txt +81 -0
  109. data/lib/random-words/words/foulmouth/nouns-plural.txt +96 -0
  110. data/lib/random-words/words/foulmouth/nouns-singular.txt +99 -0
  111. data/lib/random-words/words/foulmouth/numbers.yml +5 -0
  112. data/lib/random-words/words/foulmouth/phrases.txt +30 -0
  113. data/lib/random-words/words/foulmouth/prepositions.txt +35 -0
  114. data/lib/random-words/words/foulmouth/terminators.txt +16 -0
  115. data/lib/random-words/words/foulmouth/verbs-passive.txt +143 -0
  116. data/lib/random-words/words/foulmouth/verbs-plural.txt +91 -0
  117. data/lib/random-words/words/foulmouth/verbs-singular.txt +104 -0
  118. data/lib/random-words/words/hipster/adjectives.txt +100 -0
  119. data/lib/random-words/words/hipster/adverbs.txt +89 -0
  120. data/lib/random-words/words/hipster/articles-plural.txt +10 -0
  121. data/lib/random-words/words/hipster/articles-singular.txt +10 -0
  122. data/lib/random-words/words/hipster/clauses.txt +180 -0
  123. data/lib/random-words/words/hipster/config.yml +4 -0
  124. data/lib/random-words/words/hipster/conjunctions-coordinating.txt +20 -0
  125. data/lib/random-words/words/hipster/conjunctions-subordinate.txt +29 -0
  126. data/lib/random-words/words/hipster/names.txt +73 -0
  127. data/lib/random-words/words/hipster/nouns-plural.txt +96 -0
  128. data/lib/random-words/words/hipster/nouns-singular.txt +100 -0
  129. data/lib/random-words/words/hipster/numbers.yml +5 -0
  130. data/lib/random-words/words/hipster/phrases.txt +21 -0
  131. data/lib/random-words/words/hipster/prepositions.txt +45 -0
  132. data/lib/random-words/words/hipster/terminators.txt +16 -0
  133. data/lib/random-words/words/hipster/verbs-passive.txt +88 -0
  134. data/lib/random-words/words/hipster/verbs-plural.txt +106 -0
  135. data/lib/random-words/words/hipster/verbs-singular.txt +114 -0
  136. data/lib/random-words/words/latin/config.yml +4 -0
  137. data/lib/random-words/words/latin/conjunctions-coordinating.txt +15 -0
  138. data/lib/random-words/words/latin/names.txt +93 -0
  139. data/lib/random-words/words/latin/numbers.yml +5 -0
  140. data/lib/random-words/words/latin/phrases.txt +16 -0
  141. data/lib/random-words/words/latin/prepositions.txt +18 -0
  142. data/lib/random-words/words/latin/terminators.txt +16 -0
  143. data/lib/random-words/words/spanish/adjectives.txt +81 -0
  144. data/lib/random-words/words/spanish/adverbs.txt +87 -0
  145. data/lib/random-words/words/spanish/articles-plural.txt +4 -0
  146. data/lib/random-words/words/spanish/articles-singular.txt +4 -0
  147. data/lib/random-words/words/spanish/clauses.txt +74 -0
  148. data/lib/random-words/words/spanish/config.yml +4 -0
  149. data/lib/random-words/words/spanish/conjunctions-coordinating.txt +8 -0
  150. data/lib/random-words/words/spanish/conjunctions-subordinate.txt +16 -0
  151. data/lib/random-words/words/spanish/names.txt +61 -0
  152. data/lib/random-words/words/spanish/nouns-plural.txt +92 -0
  153. data/lib/random-words/words/spanish/nouns-singular.txt +125 -0
  154. data/lib/random-words/words/spanish/numbers.yml +5 -0
  155. data/lib/random-words/words/spanish/phrases.txt +31 -0
  156. data/lib/random-words/words/spanish/prepositions.txt +31 -0
  157. data/lib/random-words/words/spanish/terminators.txt +17 -0
  158. data/lib/random-words/words/spanish/verbs-passive.txt +495 -0
  159. data/lib/random-words/words/spanish/verbs-plural.txt +326 -0
  160. data/lib/random-words/words/spanish/verbs-singular.txt +351 -0
  161. data/lib/random-words/words/veggie/adjectives.txt +111 -0
  162. data/lib/random-words/words/veggie/adverbs.txt +81 -0
  163. data/lib/random-words/words/veggie/articles-plural.txt +10 -0
  164. data/lib/random-words/words/veggie/articles-singular.txt +10 -0
  165. data/lib/random-words/words/veggie/clauses.txt +57 -0
  166. data/lib/random-words/words/veggie/config.yml +4 -0
  167. data/lib/random-words/words/veggie/conjunctions-coordinating.txt +20 -0
  168. data/lib/random-words/words/veggie/conjunctions-subordinate.txt +29 -0
  169. data/lib/random-words/words/veggie/names.txt +93 -0
  170. data/lib/random-words/words/veggie/nouns-plural.txt +78 -0
  171. data/lib/random-words/words/veggie/nouns-singular.txt +105 -0
  172. data/lib/random-words/words/veggie/numbers.yml +5 -0
  173. data/lib/random-words/words/veggie/phrases.txt +20 -0
  174. data/lib/random-words/words/veggie/prepositions.txt +45 -0
  175. data/lib/random-words/words/veggie/terminators.txt +16 -0
  176. data/lib/random-words/words/veggie/verbs-passive.txt +56 -0
  177. data/lib/random-words/words/veggie/verbs-plural.txt +79 -0
  178. data/lib/random-words/words/veggie/verbs-singular.txt +79 -0
  179. data/lib/random-words.rb +28 -0
  180. data/random-words.gemspec +3 -1
  181. data/src/_README.md +208 -15
  182. metadata +181 -9
  183. data/lib/random-words/words/bacon/numbers.txt +0 -21
  184. data/lib/random-words/words/corporate/numbers.txt +0 -21
  185. data/lib/random-words/words/english/numbers.txt +0 -21
  186. data/lib/random-words/words/latin/numbers.txt +0 -21
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Original code by Mike Burns
4
+
5
+ # Copyright 2007 Mike Burns
6
+
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+
21
+ module RandomWords
22
+ # This class extends the Integer class with methods to convert numbers
23
+ # into their word representations. It provides methods for converting
24
+ # numbers to words in various languages, including English.
25
+ #
26
+ # @example
27
+ # 1.to_word # => "one"
28
+ # 126620.to_word # => "one hundred twenty six thousand six hundred twenty"
29
+ #
30
+ class ::Integer
31
+ # Turn a number into the word representation of that number.
32
+ # 1.to_word # => "one"
33
+ # 126620.to_word # => "one hundred twenty six thousand six hundred twenty"
34
+ def to_word(numbers)
35
+ tmp = self / 1000
36
+ final = (self % 1000).hundred_to_word(2, numbers)
37
+ place = 3 # special-case the tens and below
38
+ until tmp.zero?
39
+ final = (tmp % 1000).hundred_to_word(place, numbers) + ' ' + final
40
+ place += 1
41
+ tmp /= 1000
42
+ end
43
+ final == '' ? 'zero' : final.sub(/\s+$/, '')
44
+ end
45
+
46
+ # For testing edge cases
47
+ def additional_tests(numbers)
48
+ teen_to_word(numbers)
49
+ digit_to_word(numbers)
50
+ tens_place_to_word(numbers)
51
+ true
52
+ end
53
+
54
+ protected
55
+
56
+ # Convert a number to its word representation for the hundreds place.
57
+ def hundred_to_word(place = 0, numbers)
58
+ if zero?
59
+ ''
60
+ elsif self < 10
61
+ append_place(digit_to_word(numbers), place, numbers)
62
+ elsif self < 20
63
+ append_place(teen_to_word(numbers), place, numbers)
64
+ elsif self < 100
65
+ append_place(tens_place_to_word(numbers), place, numbers)
66
+ else
67
+ hundreds = self / 100
68
+ tens = self % 100
69
+ if tens.zero?
70
+ append_place(hundreds.digit_to_word(numbers) + " #{numbers[:places][2]}", place, numbers)
71
+ else
72
+ append_place(hundreds.digit_to_word(numbers) + " #{numbers[:places][2]} " + tens.tens_place_to_word(numbers), place,
73
+ numbers)
74
+ end
75
+ end
76
+ end
77
+
78
+ # Append the appropriate place value to a word based on its position.
79
+ # @param word [String] The word representation of the number.
80
+ # @param place [Integer] The place value (e.g., hundreds, thousands).
81
+ # @param numbers [Hash] A hash containing number words.
82
+ # @return [String] The word with the appropriate place value appended.
83
+ def append_place(word, place, numbers)
84
+ places = numbers[:places]
85
+ if place > 2
86
+ word + ' ' + places[place]
87
+ else
88
+ word
89
+ end
90
+ end
91
+
92
+ # Convert a number to its word representation for the tens place.
93
+ # This is a special case for numbers 20-99.
94
+ # @param numbers [Hash] A hash containing number words.
95
+ # @return [String] The word representation of the number.
96
+ # @example
97
+ # 45.tens_place_to_word(numbers) # => "forty five"
98
+ def tens_place_to_word(numbers)
99
+ if self > 19
100
+ tens = self / 10
101
+ ones = self % 10
102
+ ten = numbers[:tens][tens - 2]
103
+ ten + (ones.zero? ? '' : ' ' + ones.digit_to_word(numbers))
104
+ else
105
+ teen_to_word(numbers)
106
+ end
107
+ end
108
+
109
+ # Convert a number to its word representation for the teens place.
110
+ # This is a special case for numbers 10-19.
111
+ # @param numbers [Hash] A hash containing number words.
112
+ # @return [String] The word representation of the number.
113
+ # @example
114
+ # 12.teen_to_word(numbers) # => "twelve"
115
+ def teen_to_word(numbers)
116
+ if self < 10
117
+ digit_to_word(numbers)
118
+ elsif self < 20
119
+ numbers[:teens][self - 10]
120
+ else
121
+ tens_place_to_word(numbers)
122
+ end
123
+ end
124
+
125
+ # Convert a number to its word representation for the digits place.
126
+ # This is a special case for numbers 0-9.
127
+ # @param numbers [Hash] A hash containing number words.
128
+ # @return [String] The word representation of the number.
129
+ # @example
130
+ # 5.digit_to_word(numbers) # => "five"
131
+ def digit_to_word(numbers)
132
+ if zero?
133
+ ''
134
+ else
135
+ numbers[:digits][self]
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ module RandomWords
5
+ # A class representing a source of words for the RandomWords library.
6
+ class Source
7
+ attr_reader :name, :names, :config, :dictionary, :description
8
+
9
+ # Initializes a new Source instance.
10
+ # @param name [Symbol] The name of the source
11
+ # @param path [String] The path to the source directory
12
+ def initialize(name, path)
13
+ @name = name.to_sym
14
+ @path = path
15
+ config = IO.read(File.join(path, 'config.yml'))
16
+ @config = YAML.safe_load(config, aliases: true)
17
+ @names = @config['triggers'] || [name]
18
+ @description = @config['description'] || 'No description available'
19
+ @dictionary = from_files
20
+ @dictionary[:all_words] = @dictionary.values.flatten.uniq
21
+ @dictionary[:terminators], @dictionary[:extended_punctuation] = from_file('terminators').split_terminators
22
+ @dictionary[:first_names], @dictionary[:last_names], @dictionary[:full_names] = from_file('names').split_names
23
+ rescue StandardError
24
+ @name = name.to_sym
25
+ @config = {}
26
+ @names = [name]
27
+ @description = 'No description available'
28
+ @dictionary = from_files
29
+ @dictionary[:all_words] = @dictionary.values.flatten.uniq
30
+ @dictionary[:terminators], @dictionary[:extended_punctuation] = from_file('terminators').split_terminators
31
+ @dictionary[:first_names], @dictionary[:last_names], @dictionary[:full_names] = from_file('names').split_names
32
+ end
33
+
34
+ # def to_sym
35
+ # name.to_sym
36
+ # end
37
+
38
+ # Bad init method for testing purposes
39
+ # @!visibility private
40
+ def bad_init
41
+ from_file('nouns-noent.txt')
42
+ end
43
+
44
+ private
45
+
46
+ # Load words from all dictionary files
47
+ # @return [Hash] A hash containing arrays of words for each part of speech
48
+ # @example
49
+ # from_files # Loads words from all dictionary files
50
+ def from_files
51
+ {
52
+ nouns: from_file('nouns-singular'),
53
+ plural_nouns: from_file('nouns-plural'),
54
+ verbs: from_file('verbs-singular'),
55
+ plural_verbs: from_file('verbs-plural'),
56
+ passive_verbs: from_file('verbs-passive'),
57
+ adverbs: from_file('adverbs'),
58
+ adjectives: from_file('adjectives'),
59
+ articles: from_file('articles-singular'),
60
+ plural_articles: from_file('articles-plural'),
61
+ prepositions: from_file('prepositions'),
62
+ clauses: from_file('clauses'),
63
+ coordinating_conjunctions: from_file('conjunctions-coordinating'),
64
+ subordinate_conjunctions: from_file('conjunctions-subordinate'),
65
+ numbers: from_yaml('numbers'),
66
+ phrases: from_file('phrases')
67
+ }
68
+ end
69
+
70
+ # Load words from a dictionary file
71
+ # Files are plain text with one word or phrase per line
72
+ # The @source variable defines which dictionary to be used and should be defined before calling this method
73
+ # @param filename [String] The name of the file to load
74
+ # @return [Array] An array of words loaded from the file
75
+ # @example
76
+ # from_file('nouns.txt') # Loads words from words/[source]/nouns.txt
77
+ def from_file(filename)
78
+ filename = "#{filename.sub(/\.txt$/, '')}.txt"
79
+ path = File.join(@path, filename)
80
+
81
+ File.read(path).strip.split("\n").map(&:strip) # Changed from split_lines to split("\n")
82
+ rescue Errno::ENOENT
83
+ warn "File not found: #{path}"
84
+ []
85
+ end
86
+
87
+ # Load words from a YAML file
88
+ # @param filename [String] The name of the YAML file to load
89
+ # @return [Hash] A hash of words loaded from the YAML file
90
+ def from_yaml(filename)
91
+ path = File.join(@path, "#{filename}.yml")
92
+ return {} unless File.exist?(path)
93
+
94
+ begin
95
+ nums = YAML.safe_load(File.read(path), aliases: true).symbolize_keys
96
+ nums.keys.each do |key|
97
+ nums[key] = nums[key].split(' ').map(&:strip) if nums[key].is_a?(String)
98
+ end
99
+ nums
100
+ rescue Psych::SyntaxError => e
101
+ warn "YAML syntax error in #{path}: #{e.message}"
102
+ {}
103
+ end
104
+ end
105
+ end
106
+ end
@@ -1,56 +1,235 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
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"
4
+ module RandomWords
5
+ # String extensions for RandomWords
6
+ # This module extends the String class with additional methods for cleaning,
7
+ # compressing, and manipulating strings.
19
8
  #
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
9
  # @example
28
- # "Hello, World!\n\nThis is a test.".split_lines # => ["Hello World", "This is a test"]
10
+ # str = " Hello, World! "
11
+ # str.clean # => "Hello World"
12
+ # str.compress # => "Hello World"
13
+ # str.terminate # => "Hello World."
29
14
  #
30
- def split_lines
31
- strip.split("\n").map(&:clean).reject(&:empty?)
32
- end
15
+ class ::String
16
+ # Remove unwanted characters and whitespace from a string.
17
+ # @return [String] The string with unwanted characters removed.
18
+ # @example
19
+ # "Hello, World!".clean # => "Hello World"
20
+ #
21
+ # @return [String] The cleaned string.
22
+ def clean
23
+ gsub(/[^-a-zA-Z0-9\s]/, '').strip
24
+ end
33
25
 
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
26
+ # Captialize instances of "i" in a string.
27
+ # @return [String] The string with "i" capitalized.
28
+ # @example
29
+ # "this is an i".capitalize_i # => "this is an I"
30
+ # @example
31
+ # "this is an iPhone".capitalize_i # => "this is an iPhone"
32
+ #
33
+ def capitalize_i
34
+ gsub(/\bi\b/, 'I')
35
+ end
39
36
 
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
37
+ # Capitalize the first letter of a string, respcting punctuation.
38
+ # @return [String] The string with the first letter capitalized.
39
+ # @example
40
+ # "hello world".capitalize # => "Hello world"
41
+ def capitalize
42
+ return self if empty?
43
+
44
+ letters = split('')
45
+ string = []
46
+ string << letters.shift while letters[0] !~ /[[:word:]]/
47
+ string << letters.shift.upcase
48
+ string.concat(letters)
49
+ string.join('')
50
+ end
51
+
52
+ # Downcase the first letter of a string, respecting punctuation.
53
+ # @return [String] The string with the first letter downcased.
54
+ def downcase_first
55
+ return self if empty?
56
+
57
+ letters = split('')
58
+ string = []
59
+ string << letters.shift while letters[0] !~ /[[:word:]]/
60
+ string << letters.shift.downcase
61
+ string.concat(letters)
62
+ string.join('')
63
+ end
64
+
65
+ # Capitalize the first letter of each sentence in a string.
66
+ # Scans for all known terminators followed by a space and capitalizes the next letter.
67
+ # @param terminators [Array<Array>] An array of beginning and ending punctuation mark arrays.
68
+ # @return [String] The string with the first letter of each sentence capitalized.
69
+ # @example
70
+ # "hello world. this is a test.".fix_caps([[".", "."]]) # => "Hello world. This is a test."
71
+ #
72
+ def fix_caps(terminators)
73
+ return self if empty?
74
+
75
+ terminator_ends = terminators.map { |t| t[1].split('').last }.delete_if(&:empty?)
76
+ return capitalize if terminator_ends.empty?
77
+
78
+ terminator_regex = Regexp.new("[#{Regexp.escape(terminator_ends.join)}]")
79
+ return capitalize unless self =~ terminator_regex
80
+
81
+ split(/(?<=#{terminator_regex}) /).map do |sentence|
82
+ sentence.capitalize
83
+ end.join(' ')
84
+ end
85
+
86
+ # Remove duplicate commas
87
+ # @return [String] The string with duplicate commas removed.
88
+ # @example
89
+ # "Hello, , World!".remove_duplicate_commas # => "Hello, World!"
90
+ def dedup_commas
91
+ gsub(/(, *)+/, ',').gsub(',', ', ')
92
+ end
93
+
94
+ # Generate a sentence with capitalization and terminator
95
+ # @param terminator [Array<String>] An array of beginning and ending punctuation marks.
96
+ # @return [String] The string with a random punctuation mark at the end.
97
+ def to_sent(terminator)
98
+ capitalize.compress.capitalize_i.dedup_commas.terminate(terminator)
99
+ end
100
+
101
+ # Split a string by newlines, clean each line, and remove empty lines.
102
+ # @return [Array<String>] The string split into lines, cleaned, and empty lines removed.
103
+ # @example
104
+ # "Hello, World!\n\nThis is a test.".split_lines # => ["Hello World", "This is a test"]
105
+ #
106
+ def split_lines
107
+ strip.split("\n").map(&:clean).reject(&:empty?)
108
+ end
109
+
110
+ # Compress multiple spaces into a single space and remove leading/trailing spaces.
111
+ # @return [String] The string with extra spaces compressed.
112
+ def compress
113
+ gsub(/\s+/, ' ').strip
114
+ end
115
+
116
+ # Terminate a string with a random punctuation mark.
117
+ # @param terminator [Array<String>] An array of beginning and ending punctuation marks.
118
+ # @return [String] The string with a random punctuation mark at the end.
119
+ # @example
120
+ # "Hello World".terminate(["", "."]) # => "Hello World."
121
+ #
122
+ def terminate(terminator)
123
+ sub(/^/, terminator[0]).sub(/[^a-zA-Z0-9]*$/, terminator[1])
124
+ end
125
+
126
+ # Remove any punctuation mark from the end of a string.
127
+ # @return [String] The string with the last punctuation mark removed.
128
+ def no_term(terminators)
129
+ str = dup
130
+ leading = terminators.map { |t| t[0] }.delete_if(&:empty?).join
131
+ trailing = terminators.map { |t| t[1] }.delete_if(&:empty?).join
132
+ return self if leading.empty? && trailing.empty?
133
+
134
+ str.sub!(/^[#{Regexp.escape(leading)}]/, '') unless leading.empty?
135
+
136
+ str.sub!(/[#{Regexp.escape(trailing)}]+$/, '') unless trailing.empty?
137
+
138
+ str
139
+ end
140
+
141
+ # Indent every line in a string with a specified string.
142
+ # @param [String] string The string to indent with.
143
+ # @return [String] The indented string.
144
+ def indent(string)
145
+ gsub(/^/, string)
146
+ end
147
+
148
+ # Capitalize the first letter of a string.
149
+ # @return [String] The string with the first letter capitalized.
150
+ def cap_first
151
+ # Capitalizes the first letter of a string.
152
+ self[0] = self[0].upcase
153
+ self
154
+ end
155
+
156
+ # Add a specified character to the end of a string, avoiding repeated punctuation.
157
+ # @param [String] char The character to add (default: '.').
158
+ # @return [String] The string with the specified character at the end.
159
+ def term(char = '.')
160
+ # Adds a specified character to the end of a string.
161
+ sub(/[.?!,;]?$/, "#{char}")
162
+ end
163
+
164
+ # Remove extra newlines from the output.
165
+ # @return [String] The string with extra newlines removed.
166
+ def compress_newlines
167
+ # Removes extra newlines from the output.
168
+ gsub(/\n{2,}/, "\n\n").strip
169
+ end
170
+
171
+ # Compress newlines in the output, destructive.
172
+ # @see #compress_newlines
173
+ # @return [String] The string with newlines compressed.
174
+ def compress_newlines!
175
+ # Removes extra newlines from the output.
176
+ replace compress_newlines
177
+ end
178
+
179
+ # Preserve spaces in the output by replacing multiple spaces with %%.
180
+ # @return [String] The string with spaces preserved.
181
+ def preserve_spaces
182
+ # Preserves spaces in the output.
183
+ gsub(/ +/, '%%')
184
+ end
185
+
186
+ # Restore spaces in the output by replacing %% with spaces.
187
+ # @return [String] The string with spaces restored.
188
+ def restore_spaces
189
+ # Restores spaces in the output.
190
+ gsub('%%', ' ')
191
+ end
192
+
193
+ # Check if the string is trueish (starts with 't', 'y', or '1').
194
+ # @return [Boolean] true if the string is trueish, false otherwise.
195
+ def trueish?
196
+ to_s =~ /^[ty1]/i
197
+ end
198
+
199
+ # Convert the string to a source symbol based on its name.
200
+ # @return [Symbol] The symbolized name of the source.
201
+ def to_source
202
+ new_source = nil
203
+ sources = RandomWords::Generator.new.sources
204
+
205
+ sources.each do |_k, v|
206
+ v.names.each do |name|
207
+ next unless name.to_s =~ /^#{self}/i
208
+
209
+ new_source = v.name
210
+ break
211
+ end
212
+ break if new_source
213
+ end
214
+
215
+ new_source || :latin
216
+ end
50
217
 
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(/[.!?;,-]*$/, '')
218
+ # Convert the string to a length symbol based on its name.
219
+ # @return [Symbol] The symbolized length of the string.
220
+ def to_length
221
+ case self
222
+ when /^s/i
223
+ :short
224
+ when /^m/i
225
+ :medium
226
+ when /^l/i
227
+ :long
228
+ when /^v/i
229
+ :very_long
230
+ else
231
+ :medium
232
+ end
233
+ end
55
234
  end
56
235
  end